X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/8ad349bb6ed4a0be06e34c92be0d98b92e078db4..5d5c5d0d5b79ade9a973d55186ffda2638ba2b6e:/iokit/Kernel/IOService.cpp?ds=sidebyside diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 2ac657d25..bb64f9a1c 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -199,6 +199,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; @@ -338,6 +354,7 @@ void IOService::stop( IOService * provider ) void IOService::free( void ) { + requireMaxBusStall(0); if( getPropertyTable()) unregisterAllInterest(); PMfree(); @@ -492,6 +509,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)); @@ -4020,6 +4039,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) { @@ -4037,6 +4059,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; @@ -4071,7 +4094,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 ) @@ -4306,6 +4329,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 */ @@ -4511,6 +4620,8 @@ OSMetaClassDefineReservedUnused(IOService, 44); OSMetaClassDefineReservedUnused(IOService, 45); OSMetaClassDefineReservedUnused(IOService, 46); OSMetaClassDefineReservedUnused(IOService, 47); + +#ifdef __ppc__ OSMetaClassDefineReservedUnused(IOService, 48); OSMetaClassDefineReservedUnused(IOService, 49); OSMetaClassDefineReservedUnused(IOService, 50); @@ -4527,3 +4638,4 @@ OSMetaClassDefineReservedUnused(IOService, 60); OSMetaClassDefineReservedUnused(IOService, 61); OSMetaClassDefineReservedUnused(IOService, 62); OSMetaClassDefineReservedUnused(IOService, 63); +#endif