/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+#if __i386__
+
+// Only used by the intel implementation of
+// IOService::requireMaxBusStall(UInt32 __unused ns)
+struct BusStallEntry
+{
+ const IOService *fService;
+ UInt32 fMaxDelay;
+};
+
+static OSData *sBusStall = OSData::withCapacity(8 * sizeof(BusStallEntry));
+static IOLock *sBusStallLock = IOLockAlloc();
+#endif /* __i386__ */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
void IOService::initialize( void )
{
kern_return_t err;
void IOService::free( void )
{
+ requireMaxBusStall(0);
if( getPropertyTable())
unregisterAllInterest();
PMfree();
|| ((provider = getProvider())
&& (provider->__state[1] & kIOServiceSynchronousState));
+ if ( options & kIOServiceAsynchronous )
+ sync = false;
needConfig = (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState)))
&& (0 == (__state[0] & kIOServiceInactiveState));
return( ret );
}
-void IOService::applyToInterested( const OSSymbol * typeOfInterest,
- OSObjectApplierFunction applier,
- void * context )
+static void
+applyToInterestNotifiers(const IORegistryEntry *target,
+ const OSSymbol * typeOfInterest,
+ OSObjectApplierFunction applier,
+ void * context )
{
OSArray * copyArray = 0;
- applyToClients( (IOServiceApplierFunction) applier, context );
-
LOCKREADNOTIFY();
IOCommand *notifyList =
- OSDynamicCast( IOCommand, getProperty( typeOfInterest ));
+ OSDynamicCast( IOCommand, target->getProperty( typeOfInterest ));
if( notifyList) {
copyArray = OSArray::withCapacity(1);
}
}
+void IOService::applyToInterested( const OSSymbol * typeOfInterest,
+ OSObjectApplierFunction applier,
+ void * context )
+{
+ applyToClients( (IOServiceApplierFunction) applier, context );
+ applyToInterestNotifiers(this, typeOfInterest, applier, context);
+}
+
struct MessageClientsContext {
IOService * service;
UInt32 type;
next->unlockForArbitration();
if( (wasQuiet || nowQuiet) ) {
- OSArray * array;
- unsigned int index;
- OSObject * interested;
-
- array = OSDynamicCast( OSArray, next->getProperty( gIOBusyInterest ));
- if( array) {
- LOCKREADNOTIFY();
- for( index = 0;
- (interested = array->getObject( index ));
- index++) {
- next->messageClient(kIOMessageServiceBusyStateChange,
- interested, (void *) wasQuiet /* busy now */);
- }
- UNLOCKNOTIFY();
- }
+ MessageClientsContext context;
+
+ context.service = next;
+ context.type = kIOMessageServiceBusyStateChange;
+ context.argument = (void *) wasQuiet; // busy now
+ context.argSize = 0;
+
+ applyToInterestNotifiers( next, gIOBusyInterest,
+ &messageClientsApplier, &context );
if( nowQuiet && (next == gIOServiceRoot))
OSMetaClass::considerUnloads();
IOUserClient *client;
OSObject *temp;
+ if (kIOReturnSuccess == newUserClient( owningTask, securityID, type, handler ))
+ return kIOReturnSuccess;
+
// First try my own properties for a user client class name
temp = getProperty(gIOUserClientClassKey);
if (temp) {
if (!userClientClass)
return kIOReturnUnsupported;
+ // This reference is consumed by the IOServiceOpen call
temp = OSMetaClass::allocClassWithName(userClientClass);
if (!temp)
return kIOReturnNoMemory;
IOReturn IOService::newUserClient( task_t owningTask, void * securityID,
UInt32 type, IOUserClient ** handler )
{
- return( newUserClient( owningTask, securityID, type, 0, handler ));
+ return( kIOReturnUnsupported );
}
IOReturn IOService::requestProbe( IOOptionBits options )
setProperty( gIODeviceMemoryKey, array);
}
+/*
+ * For machines where the transfers on an I/O bus can stall because
+ * the CPU is in an idle mode, These APIs allow a driver to specify
+ * the maximum bus stall that they can handle. 0 indicates no limit.
+ */
+void IOService::
+setCPUSnoopDelay(UInt32 __unused ns)
+{
+#if __i386__
+ ml_set_maxsnoop(ns);
+#endif /* __i386__ */
+}
+
+UInt32 IOService::
+getCPUSnoopDelay()
+{
+#if __i386__
+ return ml_get_maxsnoop();
+#else
+ return 0;
+#endif /* __i386__ */
+}
+
+void IOService::
+requireMaxBusStall(UInt32 __unused ns)
+{
+#if __i386__
+ static const UInt kNoReplace = -1U; // Must be an illegal index
+ UInt replace = kNoReplace;
+
+ IOLockLock(sBusStallLock);
+
+ UInt count = sBusStall->getLength() / sizeof(BusStallEntry);
+ BusStallEntry *entries = (BusStallEntry *) sBusStall->getBytesNoCopy();
+
+ if (ns) {
+ const BusStallEntry ne = {this, ns};
+
+ // Set Maximum bus delay.
+ for (UInt i = 0; i < count; i++) {
+ const IOService *thisService = entries[i].fService;
+ if (this == thisService)
+ replace = i;
+ else if (!thisService) {
+ if (kNoReplace == replace)
+ replace = i;
+ }
+ else {
+ const UInt32 thisMax = entries[i].fMaxDelay;
+ if (thisMax < ns)
+ ns = thisMax;
+ }
+ }
+
+ // Must be safe to call from locked context
+ ml_set_maxbusdelay(ns);
+
+ if (kNoReplace == replace)
+ sBusStall->appendBytes(&ne, sizeof(ne));
+ else
+ entries[replace] = ne;
+ }
+ else {
+ ns = -1U; // Set to max unsigned, i.e. no restriction
+
+ for (UInt i = 0; i < count; i++) {
+ // Clear a maximum bus delay.
+ const IOService *thisService = entries[i].fService;
+ UInt32 thisMax = entries[i].fMaxDelay;
+ if (this == thisService)
+ replace = i;
+ else if (thisService && thisMax < ns)
+ ns = thisMax;
+ }
+
+ // Check if entry found
+ if (kNoReplace != replace) {
+ entries[replace].fService = 0; // Null the entry
+ ml_set_maxbusdelay(ns);
+ }
+ }
+
+ IOLockUnlock(sBusStallLock);
+#endif /* __i386__ */
+}
+
/*
* Device interrupts
*/
OSMetaClassDefineReservedUnused(IOService, 45);
OSMetaClassDefineReservedUnused(IOService, 46);
OSMetaClassDefineReservedUnused(IOService, 47);
+
+#ifdef __ppc__
OSMetaClassDefineReservedUnused(IOService, 48);
OSMetaClassDefineReservedUnused(IOService, 49);
OSMetaClassDefineReservedUnused(IOService, 50);
OSMetaClassDefineReservedUnused(IOService, 61);
OSMetaClassDefineReservedUnused(IOService, 62);
OSMetaClassDefineReservedUnused(IOService, 63);
+#endif