X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/13fec9890cf095cc781fdf7b8917cb03bf32dd4c..c0fea4742e91338fffdcf79f86a7c1d5e2b97eb1:/iokit/Kernel/IOService.cpp diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 781fad86c..6fbc9e75e 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -191,6 +191,22 @@ bool IOService::isInactive( void ) const /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ +#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; @@ -330,6 +346,7 @@ void IOService::stop( IOService * provider ) void IOService::free( void ) { + requireMaxBusStall(0); if( getPropertyTable()) unregisterAllInterest(); PMfree(); @@ -484,6 +501,8 @@ void IOService::startMatching( IOOptionBits options ) || ((provider = getProvider()) && (provider->__state[1] & kIOServiceSynchronousState)); + if ( options & kIOServiceAsynchronous ) + sync = false; needConfig = (0 == (__state[1] & (kIOServiceNeedConfigState | kIOServiceConfigState))) && (0 == (__state[0] & kIOServiceInactiveState)); @@ -1278,18 +1297,18 @@ IOReturn IOService::messageClient( UInt32 type, OSObject * client, 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); @@ -1314,6 +1333,14 @@ void IOService::applyToInterested( const OSSymbol * typeOfInterest, } } +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; @@ -2881,21 +2908,15 @@ UInt32 IOService::_adjustBusy( SInt32 delta ) 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(); @@ -4010,6 +4031,9 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID, 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) { @@ -4027,6 +4051,7 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID, if (!userClientClass) return kIOReturnUnsupported; + // This reference is consumed by the IOServiceOpen call temp = OSMetaClass::allocClassWithName(userClientClass); if (!temp) return kIOReturnNoMemory; @@ -4061,7 +4086,7 @@ IOReturn IOService::newUserClient( task_t owningTask, void * securityID, 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 ) @@ -4296,6 +4321,92 @@ void IOService::setDeviceMemory( OSArray * array ) 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 */ @@ -4501,6 +4612,8 @@ OSMetaClassDefineReservedUnused(IOService, 44); OSMetaClassDefineReservedUnused(IOService, 45); OSMetaClassDefineReservedUnused(IOService, 46); OSMetaClassDefineReservedUnused(IOService, 47); + +#ifdef __ppc__ OSMetaClassDefineReservedUnused(IOService, 48); OSMetaClassDefineReservedUnused(IOService, 49); OSMetaClassDefineReservedUnused(IOService, 50); @@ -4517,3 +4630,4 @@ OSMetaClassDefineReservedUnused(IOService, 60); OSMetaClassDefineReservedUnused(IOService, 61); OSMetaClassDefineReservedUnused(IOService, 62); OSMetaClassDefineReservedUnused(IOService, 63); +#endif