📄 appleusbohci.cpp
字号:
UInt64 AppleUSBOHCI::GetFrameNumber(){ UInt64 bigFrameNumber; UInt16 framenumber16; framenumber16 = USBToHostWord(*(UInt16*)(_pHCCA + 0x80)); bigFrameNumber = _frameNumber + framenumber16; if (framenumber16 < 200) if (_pOHCIRegisters->hcInterruptStatus & HostToUSBLong(kOHCIHcInterrupt_FNO)) bigFrameNumber += kOHCIFrameOverflowBit; return bigFrameNumber;}UInt32 AppleUSBOHCI::GetFrameNumber32(){ UInt16 framenumber16; UInt32 largishFrameNumber; framenumber16 = USBToHostWord(*(UInt16*)(_pHCCA + 0x80)); largishFrameNumber = ((UInt32)_frameNumber) + framenumber16; if (framenumber16 < 200) if (_pOHCIRegisters->hcInterruptStatus & HostToUSBLong(kOHCIHcInterrupt_FNO)) largishFrameNumber += kOHCIFrameOverflowBit; return largishFrameNumber;}// #ifdef DEBUGvoid AppleUSBOHCI::dumpRegs(void){ UInt32 lvalue; lvalue = _device->configRead32(cwVendorID); USBLog(5,"OHCI: cwVendorID=%lx", lvalue); lvalue = _device->configRead32(clClassCodeAndRevID); USBLog(5,"OHCI: clClassCodeAndRevID=%lx", lvalue); lvalue = _device->configRead32(clHeaderAndLatency); USBLog(5,"OHCI: clHeaderAndLatency=%lx", lvalue); lvalue = _device->configRead32(clBaseAddressZero); USBLog(5,"OHCI: clBaseAddressZero=%lx", lvalue); lvalue = _device->configRead32(clBaseAddressOne); USBLog(5,"OHCI: clBaseAddressOne=%lx", lvalue); lvalue = _device->configRead32(clExpansionRomAddr); USBLog(5,"OHCI: clExpansionRomAddr=%lx", lvalue); lvalue = _device->configRead32(clLatGntIntPinLine); USBLog(5,"OHCI: clLatGntIntPinLine=%lx", lvalue); lvalue = _device->configRead32(clLatGntIntPinLine+4); USBLog(5,"OHCI: clLatGntIntPinLine+4=%lx", lvalue); lvalue = _device->configRead32(cwCommand); USBLog(5,"OHCI: cwCommand=%lx", lvalue & 0x0000ffff); USBLog(5,"OHCI: cwStatus=%lx", lvalue & 0xffff0000); lvalue = _device->configRead32(cwCommand); _device->configWrite32(cwCommand, lvalue); _device->configWrite32(cwCommand, (lvalue & 0xffff0000) | (cwCommandEnableBusMaster | cwCommandEnableMemorySpace)); lvalue = _device->configRead32(cwCommand); USBLog(5,"OHCI: cwCommand=%lx", lvalue & 0x0000ffff); USBLog(5,"OHCI: cwStatus=%lx", lvalue & 0xffff0000); USBLog(5,"OHCI: HcRevision=%lx", USBToHostLong((_pOHCIRegisters)->hcRevision)); USBLog(5," HcControl=%lx", USBToHostLong((_pOHCIRegisters)->hcControl)); USBLog(5," HcFmInterval=%lx", USBToHostLong((_pOHCIRegisters)->hcFmInterval)); USBLog(5," hcRhDescriptorA=%lx", USBToHostLong((_pOHCIRegisters)->hcRhDescriptorA)); USBLog(5," hcRhDescriptorB=%lx", USBToHostLong((_pOHCIRegisters)->hcRhDescriptorB));}// #endif /* DEBUG */IOReturn AppleUSBOHCI::TranslateStatusToUSBError(UInt32 status){ static const UInt32 statusToErrorMap[] = { /* OHCI Error */ /* USB Error */ /* 0 */ kIOReturnSuccess, /* 1 */ kIOUSBCRCErr, /* 2 */ kIOUSBBitstufErr, /* 3 */ kIOUSBDataToggleErr, /* 4 */ kIOUSBPipeStalled, /* 5 */ kIOReturnNotResponding, /* 6 */ kIOUSBPIDCheckErr, /* 7 */ kIOUSBWrongPIDErr, /* 8 */ kIOReturnOverrun, /* 9 */ kIOReturnUnderrun, /* 10 */ kIOUSBReserved1Err, /* 11 */ kIOUSBReserved2Err, /* 12 */ kIOUSBBufferOverrunErr, /* 13 */ kIOUSBBufferUnderrunErr, /* 14 */ kIOUSBNotSent1Err, /* 15 */ kIOUSBNotSent2Err }; if (status > 15) return(kIOReturnInternalError); return(statusToErrorMap[status]);}void AppleUSBOHCI::ReturnTransactions( AppleOHCIGeneralTransferDescriptorPtr transaction, UInt32 tail){ UInt32 physicalAddress; AppleOHCIGeneralTransferDescriptorPtr nextTransaction; AppleOHCIIsochTransferDescriptorPtr isochTransaction = ( AppleOHCIIsochTransferDescriptorPtr) transaction; AppleOHCIIsochTransferDescriptorPtr nextIsochTransaction = NULL; USBLog(6, "%s[%p]::ReturnTransactions: (0x%x, 0x%x)", getName(), this, (UInt32) transaction->pPhysical, tail); if ( (transaction->pType == kOHCIIsochronousInType) || (transaction->pType == kOHCIIsochronousOutType) || (transaction->pType == kOHCIIsochronousInLowLatencyType) || (transaction->pType == kOHCIIsochronousOutLowLatencyType)) { // We have an isoc transaction // while(isochTransaction->pPhysical != tail) { if (isochTransaction->completion.action != NULL) { ProcessCompletedITD(isochTransaction, kIOUSBTransactionReturned); } /* walk the physically-addressed list */ physicalAddress = USBToHostLong(isochTransaction->pShared->nextTD) & kOHCIHeadPMask; nextIsochTransaction = AppleUSBOHCIitdMemoryBlock::GetITDFromPhysical (physicalAddress); DeallocateITD(isochTransaction); isochTransaction = nextIsochTransaction; if(isochTransaction == NULL) { USBLog(1, "%s[%p]::ReturnTransactions: Isoc Return queue broken", getName(), this); break; } } } else { // Deal with non-isoc transactions // while(transaction->pPhysical != tail) { // if (transaction->completion.action != NULL) if (transaction->uimFlags & kUIMFlagsCallbackTD) { IOUSBCompletion completion = transaction->command->GetUSLCompletion(); transaction->uimFlags &= ~kUIMFlagsCallbackTD; Complete(completion, kIOUSBTransactionReturned, 0); } /* walk the physically-addressed list */ physicalAddress = USBToHostLong(transaction->pShared->nextTD) & kOHCIHeadPMask; nextTransaction = AppleUSBOHCIgtdMemoryBlock::GetGTDFromPhysical(physicalAddress); DeallocateTD(transaction); transaction = nextTransaction; if(transaction == NULL) { USBLog(1, "%s[%p]::ReturnTransactions: Return queue broken", getName(), this); break; } } }}void AppleUSBOHCI::ReturnOneTransaction( AppleOHCIGeneralTransferDescriptorPtr transaction, AppleOHCIEndpointDescriptorPtr pED, IOReturn err){ UInt32 physicalAddress; AppleOHCIGeneralTransferDescriptorPtr nextTransaction; UInt32 something; UInt32 tail; UInt32 bufferSizeRemaining = 0; USBError(1, "+%s[%p]::ReturnOneTransaction(%p, %p, %x)", getName(), this, transaction, pED, err); // first mark the pED as skipped so we don't conflict pED->pShared->flags |= HostToUSBLong (kOHCIEDControl_K); // We used to wait for a SOF interrupt here. Now just sleep for 1 ms. // IOSleep(1); // make sure we are still on the same transaction if (transaction->pPhysical == (USBToHostLong(pED->pShared->tdQueueHeadPtr) & kOHCIHeadPMask)) { tail = USBToHostLong(pED->pShared->tdQueueTailPtr); while(transaction->pPhysical != tail) { // walk the physically-addressed list physicalAddress = HostToUSBLong(transaction->pShared->nextTD) & kOHCIHeadPMask; nextTransaction = AppleUSBOHCIgtdMemoryBlock::GetGTDFromPhysical(physicalAddress); // take out TD from list pED->pShared->tdQueueHeadPtr = transaction->pShared->nextTD; pED->pLogicalHeadP = nextTransaction; bufferSizeRemaining += findBufferRemaining(transaction); if (transaction->uimFlags & kUIMFlagsCallbackTD) { IOUSBCompletion completion = transaction->command->GetUSLCompletion(); transaction->uimFlags &= ~kUIMFlagsCallbackTD; if (!(transaction->uimFlags & kUIMFlagsMultiTDTransaction)) { USBLog(2, "%s(%p)::ReturnOneTransaction - found the end of a non-multi transaction(%p)!", getName(), this, transaction); DeallocateTD(transaction); Complete(completion, err, bufferSizeRemaining); break; } // this is a multi-TD transaction (control) - check to see if we are at the end of it else if (transaction->uimFlags & kUIMFlagsFinalTDinTransaction) { USBLog(2, "%s(%p)::ReturnOneTransaction - found the end of a MULTI transaction(%p)!", getName(), this, transaction); DeallocateTD(transaction); Complete(completion, err, bufferSizeRemaining); break; } else { USBLog(2, "%s(%p)::ReturnOneTransaction - returning the non-end of a MULTI transaction(%p)!", getName(), this, transaction); DeallocateTD(transaction); Complete(completion, err, bufferSizeRemaining); // keep going around the loop } } else DeallocateTD(transaction); transaction = nextTransaction; if(transaction == NULL) { USBError(1, "ReturnOneTransaction: Return queue broken"); break; } } } else { USBLog(2, "%s[%p]::ReturnOneTransaction - transaction not at beginning!(%p, %p)", getName(), this, transaction->pPhysical, pED->pShared->tdQueueHeadPtr); } USBLog(2, "-%s[%p]::ReturnOneTransaction - done, new queue head (L%p, P%p) V%p", getName(), this, pED->pLogicalHeadP, pED->pShared->tdQueueHeadPtr, ((AppleOHCIGeneralTransferDescriptorPtr)pED->pLogicalHeadP)->pPhysical); pED->pShared->flags &= ~HostToUSBLong(kOHCIEDControl_K); // activate ED again}IOReturn AppleUSBOHCI::message( UInt32 type, IOService * provider, void * argument ){ cs_event_t pccardevent; // Let our superclass decide handle this method // messages // if ( type == kIOPCCardCSEventMessage) { pccardevent = (UInt32) argument; if ( pccardevent == CS_EVENT_CARD_REMOVAL ) { USBLog(5,"%s[%p]: Received kIOPCCardCSEventMessage Need to return all transactions",getName(),this); _pcCardEjected = true; IOSleep(5); ReturnAllTransactionsInEndpoint(_pControlHead, _pControlTail); ReturnAllTransactionsInEndpoint(_pBulkHead, _pBulkTail); IOSleep(5); } } USBLog(6, "%s[%p]::message type: 0x%x, isInactive = %d", getName(), this, type, isInactive()); return super::message( type, provider, argument ); }void AppleUSBOHCI::stop(IOService * provider){ USBLog(5, "%s[%p]::stop isInactive = %d", getName(), this, isInactive()); return super::stop(provider);}bool AppleUSBOHCI::finalize(IOOptionBits options){ USBLog(5, "%s[%p]::finalize isInactive = %d", getName(), this, isInactive()); return super::finalize(options);}//=============================================================================================//// UIMInitializeForPowerUp//// This routine is called for a controller that cannot survive sleep (mostly because it loses// power across sleep. It will re-intialize the OHCI registers and do everything needed to get// the card up. The one thing that it does not do is do any memory allocations, as those have// already been done and we don't need to do it again. This routine is essentially the same as// UIMInitialize w/out the memory allocations.//// To Do: Verify that we do need to call the ControlInintialize(), BulkInitialize(), etc. I'm// not sure that we do.////=============================================================================================//IOReturn AppleUSBOHCI::UIMInitializeForPowerUp(void){ UInt32 commandRegister; IOPhysicalAddress hcDoneHead; USBLog(5, "%s[%p]: initializing UIM for PowerUp @ %lx (%lx)", getName(), this, (long)_deviceBase->getVirtualAddress(), _deviceBase->getPhysicalAddress());#if (DEBUGGING_LEVEL > 2) dumpRegs();#endif // Enable the controller // commandRegister = _device->configRead32(cwCommand); _device->configWrite32(cwCommand, (commandRegister & 0xffff0000) | (cwCommandEnableBusMaster | cwCommandEnableMemorySpace)); // Check to see if the hcDoneHead is not NULL. If so, then we need to reset the controller // hcDoneHead = USBToHostLong(_pOHCIRegisters->hcDoneHead); if ( hcDoneHead != NULL ) { USBError(1,"%s[%p]::UIMInitialize Non-NULL hcDoneHead: %p", getName(), this, hcDoneHead ); // Reset it now // _pOHCIRegisters->hcCommandStatus = USBToHostLong(kOHCIHcCommandStatus_HCR); // Reset OHCI IOSleep(3); } // Restore the Control and Bulk head pointers // _pOHCIRegisters->hcControlCurrentED = 0; _pOHCIRegisters->hcControlHeadED = HostToUSBLong ((UInt32) _pControlHead->pPhysical); _pOHCIRegisters->hcBulkHeadED = HostToUSBLong ((UInt32) _pBulkHead->pPhysical); IOSync(); // Write the HCCA // OSWriteLittleInt32(&_pOHCIRegisters->hcHCCA, 0, _hccaPhysAddr); IOSync(); // Set the HC to write the donehead to the HCCA, and enable interrupts _pOHCIRegisters->hcInterruptStatus = USBToHostLong(kOHCIHcInterrupt_WDH); IOSync(); // Enable the interrupt delivery. _workLoop->enableAllInterrupts(); // Set up hcFmInterval. UInt32 hcFSMPS; // in register hcFmInterval UInt32 hcFI; // in register hcFmInterval UInt32 hcPS; // in register hcPeriodicStart hcFI = USBToHostLong(_pOHCIRegisters->hcFmInterval) & kOHCIHcFmInterval_FI; // this formula is from the OHCI spec, section 5.4 hcFSMPS = ((((hcFI-kOHCIMax_OverHead) * 6)/7) << kOHCIHcFmInterval_FSMPSPhase); hcPS = (hcFI * 9) / 10; // per spec- 90% _pOHCIRegisters->hcFmInterval = HostToUSBLong(hcFI | hcFSMPS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -