void XHCIAsyncEndpoint::Complete(IOReturn passthruReturnCode) { XHCIAsyncTD* pTd; IOUSBCommand* command; IOUSBCompletion comp; while (doneHead) { pTd = GetTD(&doneHead, &doneTail, &numTDsDone); if (!pTd) continue; command = pTd->command; if (pTd->absoluteShortfall) command->SetUIMScratch(9U, pTd->shortfall); else command->SetUIMScratch(9U, command->GetUIMScratch(9U) + pTd->shortfall); if (pTd->interruptThisTD && pTd->finalTDInTransaction) { comp = command->GetUSLCompletion(); if (comp.action) { /* * Note: Mavericks updates a couple * of diagnostic counters here. */ provider->_completer.AddItem(&comp, passthruReturnCode, command->GetUIMScratch(9U), true); pTd->shortfall = 0U; pTd->absoluteShortfall = false; } pTd->interruptThisTD = false; } PutTD(&freeHead, &freeTail, pTd, &numTDsFree); } }
void XHCIAsyncEndpoint::MoveAllTDsFromReadyQToDoneQ(void) { XHCIAsyncTD* pTd; while (queuedHead) { pTd = GetTD(&queuedHead, &queuedTail, &numTDsQueued); if (pTd) PutTDonDoneQueue(pTd); } }
void XHCIAsyncEndpoint::MoveTDsFromReadyQToDoneQ(IOUSBCommand* command) { XHCIAsyncTD* pTd; while (queuedHead) { if (command && command != queuedHead->command) break; pTd = GetTD(&queuedHead, &queuedTail, &numTDsQueued); if (pTd) PutTDonDoneQueue(pTd); } }
XHCIAsyncTD* XHCIAsyncEndpoint::GetTDFromFreeQueue(bool newOneOk) { XHCIAsyncTD* pTd; if (!freeHead) return newOneOk ? XHCIAsyncTD::ForEndpoint(this) : 0; pTd = GetTD(&freeHead, &freeTail, &numTDsFree); if (pTd) pTd->reinit(); return pTd; }
// return Track Time // buffer: // byte 0 - frame // byte 1 - second // byte 2 - minute long CDRgetTD(unsigned char track, unsigned char *buffer) { long ret; if (!IsCdHandleOpen()) { memset(buffer + 1, 0, 3); return 0; } if (ReadMode == THREADED) pthread_mutex_lock(&mut); ret = GetTD(track, buffer); if (ReadMode == THREADED) pthread_mutex_unlock(&mut); return ret; }
struct XHCIAsyncTD* XHCIAsyncEndpoint::GetTDFromActiveQueueWithIndex(uint16_t indexInQueue) { XHCIAsyncTD *pPrevTd, *pTd; uint32_t orphanCount = 0U; pTd = pPrevTd = scheduledHead; while (pTd) { if (pTd->lastTrbIndex == indexInQueue) break; if (pTd == scheduledTail) return 0; ++orphanCount; pPrevTd = pTd; pTd = pTd->next; } if (!pTd) return 0; #if 0 if (pTd == scheduledTail) { if (pTd == scheduledHead) { scheduledTail = 0; scheduledHead = 0; } else scheduledTail = pPrevTd; } else if (pTd == scheduledHead) scheduledHead = pTd->next; else pPrevTd->next = pTd->next; --numTDsScheduled; #else if (orphanCount) { /* * Flush all scheduled TDs prior to pTd */ if (doneHead) doneTail->next = scheduledHead; else doneHead = scheduledHead; doneTail = pPrevTd; numTDsDone += orphanCount; scheduledHead = pTd; numTDsScheduled -= orphanCount; Complete(kIOReturnSuccess); if (provider) provider->_diagCounters[DIAGCTR_ORPHANEDTDS] += orphanCount; } GetTD(&scheduledHead, &scheduledTail, &numTDsScheduled); #endif return pTd; }
void XHCIAsyncEndpoint::FlushTDs(IOUSBCommand* command, int32_t updateDequeueOption) { XHCIAsyncTD* pTd; uint32_t streamId; int32_t indexInQueue; pTd = scheduledHead; if (!command || !pTd) return; indexInQueue = -1; streamId = 0U; while (pTd && pTd->command == command) { GetTD(&scheduledHead, &scheduledTail, &numTDsScheduled); if (updateDequeueOption) { streamId = pTd->streamId; #if 1 indexInQueue = pTd->lastTrbIndex + 1; if (indexInQueue >= static_cast<int32_t>(pRing->numTRBs) - 1) indexInQueue = 0; #else indexInQueue = GenericUSBXHCI::NextTransferDQ(pRing, pTd->lastTrbIndex); #endif } PutTDonDoneQueue(pTd); pTd = scheduledHead; } switch (updateDequeueOption) { case 0: return; case 1: if (scheduledHead) return; break; } if (indexInQueue < 0) return; #if 0 /* * Note: Added Mavericks */ if (!provider->_controllerAvailable) { pRing->dequeueIndex = static_cast<uint16_t>(indexInQueue); pRing->needsSetTRDQPtr = true; return; } #endif provider->SetTRDQPtr(pRing->slot, pRing->endpoint, streamId, indexInQueue); }
void XHCIAsyncEndpoint::ScheduleTDs(void) { XHCIAsyncTD* pTd; IOReturn rc; if (!queuedHead) return; if (aborting) { if (pRing->returnInProgress) pRing->needsDoorbell = true; return; } do { if (!(provider->CanTDFragmentFit(pRing, maxTDBytes))) { if (gux_log_level >= 2 && provider) ++provider->_diagCounters[DIAGCTR_XFERKEEPAWAY]; break; } pTd = GetTD(&queuedHead, &queuedTail, &numTDsQueued); if (!pTd) continue; rc = provider->_createTransfer(pTd, false, pTd->bytesThisTD, pTd->mystery, pTd->bytesPreceedingThisTD, pTd->interruptThisTD, pTd->multiTDTransaction, &pTd->firstTrbIndex, &pTd->TrbCount, &pTd->lastTrbIndex); if (rc != kIOReturnSuccess) { if (provider) ++provider->_diagCounters[DIAGCTR_XFERLAYOUT]; PutTDAtHead(&queuedHead, &queuedTail, pTd, &numTDsQueued); break; } PutTD(&scheduledHead, &scheduledTail, pTd, &numTDsScheduled); if (pRing->returnInProgress) pRing->needsDoorbell = true; else provider->StartEndpoint(pRing->slot, pRing->endpoint, pTd->streamId); } while(queuedHead); }
void XHCIAsyncEndpoint::UpdateTimeouts(bool abortAll, uint32_t frameNumber, bool stopped) { uint64_t addr; int64_t trbIndex64; XHCIAsyncTD* pTd; IOUSBCommand* command; IOReturn passthruReturnCode; uint32_t shortfall, ndto, cto, bytesShortfell, firstSeen, TRTime; int32_t next; bool returnATransfer = false, absoluteShortfall = false, oldAS; pTd = scheduledHead; if (!pTd) return; addr = GenericUSBXHCI::GetTRBAddr64(&pRing->stopTrb); trbIndex64 = GenericUSBXHCI::DiffTRBIndex(addr, pRing->physAddr); if (trbIndex64 < 0 || trbIndex64 >= pRing->numTRBs - 1U) { trbIndex64 = pRing->dequeueIndex; shortfall = pTd->bytesThisTD; } else { if ((pRing->stopTrb.d & XHCI_TRB_3_ED_BIT) != 0U) { shortfall = pTd->bytesThisTD - XHCI_TRB_2_REM_GET(pRing->stopTrb.c); if (provider->_errataBits & kErrataAbsoluteEDTLA) { absoluteShortfall = true; shortfall += pTd->bytesPreceedingThisTD; } } else { if (XHCI_TRB_2_ERROR_GET(pRing->stopTrb.c) == XHCI_TRB_ERROR_LENGTH) /* * Note: If stopped on a link TRB, this field is zero */ shortfall = XHCI_TRB_2_BYTES_GET(pRing->ptr[trbIndex64].c); else shortfall = XHCI_TRB_2_REM_GET(pRing->stopTrb.c); GenericUSBXHCI::CountRingToED(pRing, static_cast<int32_t>(trbIndex64), &shortfall); } } if (!abortAll) { command = pTd->command; if (!command) return; ndto = command->GetNoDataTimeout(); cto = command->GetCompletionTimeout(); firstSeen = command->GetUIMScratch(5U); if (!firstSeen) { command->SetUIMScratch(5U, frameNumber); firstSeen = frameNumber; } if (cto && frameNumber && frameNumber - firstSeen > cto) { pTd->shortfall = shortfall; pTd->absoluteShortfall = absoluteShortfall; returnATransfer = true; } if (ndto) { bytesShortfell = command->GetUIMScratch(4U); oldAS = ((bytesShortfell & OLDAS_MASK) != 0U); bytesShortfell &= ~OLDAS_MASK; TRTime = command->GetUIMScratch(6U); if (!TRTime || command->GetUIMScratch(3U) != static_cast<uint32_t>(trbIndex64) || bytesShortfell != shortfall || oldAS != absoluteShortfall) { command->SetUIMScratch(3U, static_cast<uint32_t>(trbIndex64)); command->SetUIMScratch(4U, absoluteShortfall ? (shortfall | OLDAS_MASK) : shortfall); command->SetUIMScratch(6U, frameNumber); } else if (frameNumber && frameNumber - TRTime > ndto) { pTd->shortfall = bytesShortfell; pTd->absoluteShortfall = oldAS; returnATransfer = true; } } if (!returnATransfer) return; passthruReturnCode = kIOUSBTransactionTimeout; } else { pTd->shortfall = shortfall; pTd->absoluteShortfall = absoluteShortfall; passthruReturnCode = kIOReturnNotResponding; } GetTD(&scheduledHead, &scheduledTail, &numTDsScheduled); if (provider->GetNeedsReset(pRing->slot)) passthruReturnCode = kIOReturnNotResponding; /* * Note: Mavericks updates a couple * of diagnostic counters here. */ #if 1 next = pTd->lastTrbIndex + 1; if (next >= static_cast<int32_t>(pRing->numTRBs) - 1) next = 0; #else next = GenericUSBXHCI::NextTransferDQ(pRing, pTd->lastTrbIndex); #endif if (!stopped) provider->QuiesceEndpoint(pRing->slot, pRing->endpoint); provider->SetTRDQPtr(pRing->slot, pRing->endpoint, pTd->streamId, next); RetireTDs(pTd, passthruReturnCode, true, true); }