bool IOWorkLoop::init() { // The super init and gateLock allocation MUST be done first. if ( !super::init() ) return false; // Allocate our ExpansionData if it hasn't been allocated already. if ( !reserved ) { reserved = IONew(ExpansionData,1); if ( !reserved ) return false; bzero(reserved,sizeof(ExpansionData)); } #if DEBUG OSBacktrace ( reserved->allocationBacktrace, sizeof ( reserved->allocationBacktrace ) / sizeof ( reserved->allocationBacktrace[0] ) ); #endif if ( gateLock == NULL ) { if ( !( gateLock = IORecursiveLockAlloc()) ) return false; } if ( workToDoLock == NULL ) { if ( !(workToDoLock = IOSimpleLockAlloc()) ) return false; IOSimpleLockInit(workToDoLock); workToDo = false; } if (!reserved) { reserved = IONew(ExpansionData, 1); reserved->options = 0; } IOStatisticsRegisterCounter(); if ( controlG == NULL ) { controlG = IOCommandGate::commandGate( this, OSMemberFunctionCast( IOCommandGate::Action, this, &IOWorkLoop::_maintRequest)); if ( !controlG ) return false; // Point the controlGate at the workLoop. Usually addEventSource // does this automatically. The problem is in this case addEventSource // uses the control gate and it has to be bootstrapped. controlG->setWorkLoop(this); if (addEventSource(controlG) != kIOReturnSuccess) return false; } if ( workThread == NULL ) { thread_continue_t cptr = OSMemberFunctionCast( thread_continue_t, this, &IOWorkLoop::threadMain); if (KERN_SUCCESS != kernel_thread_start(cptr, this, &workThread)) return false; } (void) thread_set_tag(workThread, THREAD_TAG_IOWORKLOOP); return true; }
IOReturn IOUSBCommandPool::gatedReturnCommand(IOCommand * command) { IOUSBCommand *usbCommand = OSDynamicCast(IOUSBCommand, command); // only one of these should be non-null IOUSBIsocCommand *isocCommand = OSDynamicCast(IOUSBIsocCommand, command); USBLog(7,"IOUSBCommandPool[%p]::gatedReturnCommand %p", this, command); if (!command) { #if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION panic("IOUSBCommandPool::gatedReturnCommand( NULL )"); #endif return kIOReturnBadArgument; } if (command->fCommandChain.next && (&command->fCommandChain != command->fCommandChain.next || &command->fCommandChain != command->fCommandChain.prev)) { #if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION kprintf("WARNING: gatedReturnCommand(%p) already on queue [next=%p prev=%p]\n", command, command->fCommandChain.next, command->fCommandChain.prev); panic("IOUSBCommandPool::gatedReturnCommand already on queue"); #endif char* bt[8]; OSBacktrace((void**)bt, 8); USBError(1,"IOUSBCommandPool::gatedReturnCommand command already in queue, not putting it back into the queue, bt: [%p][%p][%p][%p][%p][%p][%p][%p]", bt[0], bt[1], bt[2], bt[3], bt[4], bt[5], bt[6], bt[7]); return kIOReturnBadArgument; } if (usbCommand) { IODMACommand *dmaCommand = usbCommand->GetDMACommand(); if (dmaCommand) { if (dmaCommand->getMemoryDescriptor()) { USBError(1, "IOUSBCommandPool::gatedReturnCommand - command (%p) still has dmaCommand(%p) with an active memory descriptor(%p)", usbCommand, dmaCommand, dmaCommand->getMemoryDescriptor()); #if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION panic("IOUSBCommandPool::gatedReturnCommand -dmaCommand still has active IOMD"); #endif } } else { USBError(1,"IOUSBCommandPool::gatedReturnCommand - missing dmaCommand in IOUSBCommand"); } // Test to poison the IOUSBCommand when returning it #if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION { char* bt[kUSBCommandScratchBuffers]; OSBacktrace((void**)bt, kUSBCommandScratchBuffers); for ( int i=0; i < kUSBCommandScratchBuffers; i++) usbCommand->SetBT(i, bt[i]); } #endif // Clean up the command before returning it IOUSBCompletion nullCompletion; nullCompletion.target = (void *) POISONVALUE; nullCompletion.action = (IOUSBCompletionAction) NULL; nullCompletion.parameter = (void *) POISONVALUE; usbCommand->SetSelector(INVALID_SELECTOR); usbCommand->SetRequest((IOUSBDeviceRequestPtr) POISONVALUE); usbCommand->SetAddress(0xFF); usbCommand->SetEndpoint(0xFF); usbCommand->SetDirection(0xFF); usbCommand->SetType(0xFF); usbCommand->SetBufferRounding(false); usbCommand->SetBuffer((IOMemoryDescriptor *) POISONVALUE); usbCommand->SetUSLCompletion(nullCompletion); usbCommand->SetClientCompletion(nullCompletion); usbCommand->SetDataRemaining(POISONVALUE); usbCommand->SetStage(0xFF); usbCommand->SetStatus(POISONVALUE); usbCommand->SetOrigBuffer((IOMemoryDescriptor *) POISONVALUE); usbCommand->SetDisjointCompletion(nullCompletion); usbCommand->SetDblBufLength(POISONVALUE); usbCommand->SetNoDataTimeout(POISONVALUE); usbCommand->SetCompletionTimeout(POISONVALUE); usbCommand->SetReqCount(POISONVALUE); usbCommand->SetMultiTransferTransaction(true); usbCommand->SetFinalTransferInTransaction(true); usbCommand->SetUseTimeStamp(true); usbCommand->SetIsSyncTransfer(FALSE); for ( int i=0; i < kUSBCommandScratchBuffers; i++) usbCommand->SetUIMScratch(i, POISONVALUE); usbCommand->SetStreamID(POISONVALUE); if ( usbCommand->GetBufferUSBCommand() != NULL ) { USBError(1,"IOUSBCommandPool::gatedReturnCommand - GetBufferUSBCommand() is not NULL"); } if ( usbCommand->GetRequestMemoryDescriptor() != NULL ) { USBError(1,"IOUSBCommandPool::gatedReturnCommand - GetRequestMemoryDescriptor() is not NULL"); } if ( usbCommand->GetBufferMemoryDescriptor() != NULL ) { USBError(1,"IOUSBCommandPool::gatedReturnCommand - GetBufferMemoryDescriptor() is not NULL"); } // Do not see these to anything but NULL as a lot of the code depends on checking for NULLness usbCommand->SetBufferUSBCommand(NULL); usbCommand->SetRequestMemoryDescriptor(NULL); usbCommand->SetBufferMemoryDescriptor(NULL); } if (isocCommand) { IODMACommand *dmaCommand = isocCommand->GetDMACommand(); if (dmaCommand) { if (dmaCommand->getMemoryDescriptor()) { USBError(1, "IOUSBCommandPool::gatedReturnCommand - isocCommand (%p) still has dmaCommand(%p) with an active memory descriptor(%p)", isocCommand, dmaCommand, dmaCommand->getMemoryDescriptor()); #if DEBUG_LEVEL != DEBUG_LEVEL_PRODUCTION panic("IOUSBCommandPool::gatedReturnCommand - dmaCommand still has active IOMD (isoc)"); #endif } } else { USBError(1,"IOUSBCommandPool::gatedReturnCommand - missing dmaCommand in IOUSBIsocCommand"); } } return IOCommandPool::gatedReturnCommand(command); }