AppleUSBUHCI_UIM.cpp [plain text]
#include <kern/clock.h>
#include <machine/limits.h>
#include <IOKit/usb/IOUSBRootHubDevice.h>
#include <IOKit/usb/IOUSBLog.h>
#include "AppleUSBUHCI.h"
#include "AppleUHCIListElement.h"
static char *
USBErrorToString(IOReturn status)
{
switch (status) {
case kIOReturnSuccess:
return "kIOReturnSuccess";
case kIOReturnError:
return "kIOReturnError";
case kIOReturnNotResponding:
return "kIOReturnNotResponding";
case kIOUSBPipeStalled:
return "kIOUSBPipeStalled";
case kIOReturnOverrun:
return "kIOReturnOverrun";
case kIOReturnUnderrun:
return "kIOReturnUnderrun";
case kIOUSBLinkErr:
return "kIOUSBLinkErr";
case kIOUSBCRCErr:
return "kIOUSBCRCErr";
case kIOUSBBitstufErr:
return "kIOUSBBitstufErr";
case kIOUSBTransactionReturned:
return "kIOUSBTransactionReturned";
case kIOReturnAborted:
return "kIOReturnAborted";
case kIOReturnIsoTooNew:
return "kIOReturnIsoTooNew";
case kIOReturnIsoTooOld:
return "kIOReturnIsoTooOld";
case kIOReturnNoDevice:
return "kIOReturnNoDevice";
case kIOReturnBadArgument:
return "kIOReturnBadArgument";
case kIOReturnInternalError:
return "kIOReturnInternalError";
case kIOReturnNoMemory:
return "kIOReturnNoMemory";
case kIOReturnUnsupported:
return "kIOReturnUnsupported";
case kIOReturnNoResources:
return "kIOReturnNoResources";
case kIOReturnNoBandwidth:
return "kIOReturnNoBandwidth";
case kIOReturnIPCError:
return "kIOReturnIPCError";
case kIOReturnTimeout:
return "kIOReturnTimeout";
case kIOReturnBusy:
return "kIOReturnBusy";
case kIOUSBTransactionTimeout:
return "kIOUSBTransactionTimeout";
case kIOUSBNotSent1Err:
return "kIOUSBNotSent1Err";
case kIOUSBNotSent2Err:
return "kIOUSBNotSent2Err";
}
return "Unknown";
}
#pragma mark Control
IOReturn
AppleUSBUHCI::UIMCreateControlEndpoint(
UInt8 functionNumber,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed,
USBDeviceAddress highSpeedHub,
int highSpeedPort)
{
return UIMCreateControlEndpoint(functionNumber, endpointNumber, maxPacketSize, speed);
}
IOReturn
AppleUSBUHCI::UIMCreateControlEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt16 maxPacketSize,
UInt8 speed)
{
AppleUHCIQueueHead *pQH;
AppleUHCIQueueHead *prevQH;
AppleUHCITransferDescriptor *pTD;
if (functionNumber == _rootFunctionNumber)
{
return kIOReturnSuccess;
}
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateControlEndpoint (f %d ep %d) max %d spd %d", this, functionNumber, endpointNumber, maxPacketSize, speed);
if (maxPacketSize == 0)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateControlEndpoint - maxPacketSize 0 is illegal (kIOReturnBadArgument)", this);
return kIOReturnBadArgument;
}
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateControlEndpoint allocating endpoint", this);
pQH = AllocateQH(functionNumber, endpointNumber, kUSBNone, speed, maxPacketSize, kUSBControl);
if (pQH == NULL)
return kIOReturnNoMemory;
pTD = AllocateTD(pQH);
if (!pTD)
{
DeallocateQH(pQH);
return kIOReturnNoMemory;
}
pTD->GetSharedLogical()->ctrlStatus = 0; pQH->firstTD = pTD;
pQH->lastTD = pTD;
pQH->GetSharedLogical()->elink = HostToUSBLong(pTD->GetPhysicalAddrWithType());
if (speed == kUSBDeviceSpeedLow)
{
prevQH = _lsControlQHEnd;
} else
{
prevQH = _fsControlQHEnd;
}
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateControlEndpoint linking qh %p into schedule after %p", this, pQH, prevQH);
pQH->_logicalNext = prevQH->_logicalNext;
pQH->SetPhysicalLink(prevQH->GetPhysicalLink());
IOSync();
prevQH->_logicalNext = pQH;
prevQH->SetPhysicalLink(pQH->GetPhysicalAddrWithType());
IOSync();
if (speed == kUSBDeviceSpeedLow)
{
_lsControlQHEnd = pQH;
} else
{
_fsControlQHEnd = pQH;
}
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateControlEndpoint done pQH %p FN %d EP %d MPS %d", this, pQH, pQH->functionNumber, pQH->endpointNumber, pQH->maxPacketSize);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::UIMCreateControlTransfer(short functionNumber,
short endpointNumber,
IOUSBCommand* command,
IOMemoryDescriptor *CBP,
bool bufferRounding, UInt32 bufferSize,
short direction)
{
AppleUHCIQueueHead *pQH;
AppleUHCITransferDescriptor *td, *last_td;
IOReturn status;
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateControlTransfer (f %d ep %d dir %d) size %d", this, functionNumber, endpointNumber, direction, (int)bufferSize);
pQH = FindQueueHead(functionNumber, endpointNumber, kUSBAnyDirn, kUSBControl);
if (pQH == NULL)
{
USBLog(2, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - queue head not found", this);
return kIOUSBEndpointNotFound;
}
if (pQH->stalled)
{
if (endpointNumber == 0)
{
USBError(1, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - address %d endpoint 0 is incorrectly marked as stalled!", this, functionNumber);
}
else
{
USBLog(2, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - Control pipe for ep %d stalled", this, endpointNumber);
return kIOUSBPipeStalled;
}
}
if ( _idleSuspend )
{
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - in _idleSuspend - restarting bus", this);
setPowerState(kUHCIPowerLevelRunning, this);
}
USBLog(6, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - allocating TD chain with CBP %p", this, CBP);
status = AllocTDChain(pQH, command, CBP, bufferSize, direction, true);
if (status != kIOReturnSuccess)
{
USBLog(2, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - returning status %p", this, (void*)status);
}
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateControlTransfer - pQH[%p] firstTD[%p] lastTD[%p] status[%p]", this, pQH, pQH->firstTD, pQH->lastTD, (void*)status);
return status;
}
#pragma mark Bulk
IOReturn
AppleUSBUHCI::UIMCreateBulkEndpoint(UInt8 functionNumber,
UInt8 endpointNumber,
UInt8 direction,
UInt8 speed,
UInt16 maxPacketSize,
USBDeviceAddress highSpeedHub,
int highSpeedPort)
{
return UIMCreateBulkEndpoint(functionNumber, endpointNumber, direction, speed, maxPacketSize);
}
IOReturn
AppleUSBUHCI::UIMCreateBulkEndpoint(UInt8 functionNumber, UInt8 endpointNumber, UInt8 direction, UInt8 speed, UInt8 maxPacketSize)
{
AppleUHCITransferDescriptor *pTD;
AppleUHCIQueueHead *pQH;
AppleUHCIQueueHead *prevQH;
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateBulkEndpoint (fn %d ep %d dir %d) speed %d mp %d", this, functionNumber, endpointNumber, direction, speed, maxPacketSize);
if (maxPacketSize == 0)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateBulkEndpoint - maxPacketSize 0 is illegal (kIOReturnBadArgument)", this);
return kIOReturnBadArgument;
}
pQH = AllocateQH(functionNumber, endpointNumber, direction, speed, maxPacketSize, kUSBBulk);
if (pQH == NULL)
{
return kIOReturnNoMemory;
}
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateBulkEndpoint allocating dummy TD", this);
pTD = AllocateTD(pQH);
if (!pTD)
{
DeallocateQH(pQH);
return kIOReturnNoMemory;
}
pTD->GetSharedLogical()->ctrlStatus = 0; pQH->firstTD = pTD;
pQH->lastTD = pTD;
pQH->GetSharedLogical()->elink = HostToUSBLong(pTD->GetPhysicalAddrWithType());
prevQH = _bulkQHEnd;
pQH->_logicalNext = prevQH->_logicalNext;
pQH->SetPhysicalLink(prevQH->GetPhysicalLink());
IOSync();
prevQH->_logicalNext = pQH;
prevQH->SetPhysicalLink(pQH->GetPhysicalAddrWithType());
IOSync();
_bulkQHEnd = pQH;
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::UIMCreateBulkTransfer(IOUSBCommand* command)
{
AppleUHCIQueueHead *pQH = NULL;
IOMemoryDescriptor *mp = NULL;
IOReturn status = 0xDEADBEEF;
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateBulkTransfer (%d, %d, %d) size %d", this, command->GetAddress(), command->GetEndpoint(), command->GetDirection(), (int)command->GetReqCount());
pQH = FindQueueHead(command->GetAddress(), command->GetEndpoint(), command->GetDirection(), kUSBBulk);
if (pQH == NULL)
{
USBLog(2, "AppleUSBUHCI[%p]::UIMCreateBulkTransfer - endpoint (fn %d, ep %d, dir %d) not found", this, command->GetAddress(), command->GetEndpoint(), command->GetDirection() );
return kIOUSBEndpointNotFound;
}
if (pQH->stalled)
{
USBLog(4, "AppleUSBUHCI[%p]::UIMCreateBulkTransfer - Bulk pipe stalled", this);
return kIOUSBPipeStalled;
}
mp = command->GetBuffer();
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateBulkTransfer - allocating TD chain with mp %p", this, mp);
status = AllocTDChain(pQH, command, mp, command->GetReqCount(), command->GetDirection(), false);
if (status != kIOReturnSuccess)
{
USBLog(4, "AppleUSBUHCI[%p]::UIMCreateBulkTransfer - AllocTDChain returns %d", this, status);
return status;
}
return kIOReturnSuccess;
}
#pragma mark Interrupt
IOReturn
AppleUSBUHCI::UIMCreateInterruptEndpoint(
short functionNumber,
short endpointNumber,
UInt8 direction,
short speed,
UInt16 maxPacketSize,
short pollingRate,
USBDeviceAddress highSpeedHub,
int highSpeedPort)
{
return UIMCreateInterruptEndpoint(functionNumber, endpointNumber, direction, speed, maxPacketSize, pollingRate);
}
IOReturn
AppleUSBUHCI::UIMCreateInterruptEndpoint(short functionNumber,
short endpointNumber,
UInt8 direction,
short speed,
UInt16 maxPacketSize,
short pollingRate)
{
AppleUHCIQueueHead *pQH, *prevQH;
AppleUHCITransferDescriptor *pTD;
int i;
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint (fn %d, ep %d, dir %d) spd %d pkt %d rate %d", this, functionNumber, endpointNumber, direction, speed, maxPacketSize, pollingRate );
if (functionNumber == _rootFunctionNumber)
{
if (endpointNumber != 0 && endpointNumber != 1)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint - maxPacketSize 0 is illegal (kIOReturnBadArgument)", this);
return kIOReturnBadArgument;
}
return RHCreateInterruptEndpoint(endpointNumber, direction, speed, maxPacketSize, pollingRate);
}
pQH = FindQueueHead(functionNumber, endpointNumber, direction, kUSBInterrupt);
if ( pQH != NULL )
{
IOReturn ret;
USBLog(2, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint endpoint already existed -- deleting it", this);
ret = UIMDeleteEndpoint(functionNumber, endpointNumber, direction);
if ( ret != kIOReturnSuccess)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint deleting endpoint returned %p", this, (void*)ret);
return ret;
}
}
for (i=kUHCI_NINTR_QHS-1; i>=0; i--)
{
if ((1 << i) <= pollingRate)
{
break;
}
}
if (i<0)
{
i = 0;
}
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint - we will use interrupt queue %d, which corresponds to a rate of %d", this, i, (1 << i));
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint allocating endpoint", this);
pQH = AllocateQH(functionNumber, endpointNumber, direction, speed, maxPacketSize, kUSBInterrupt);
if (pQH == NULL)
return kIOReturnNoMemory;
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint allocating dummy TD", this);
pTD = AllocateTD(pQH);
if (!pTD)
{
DeallocateQH(pQH);
return kIOReturnNoMemory;
}
pTD->GetSharedLogical()->ctrlStatus = 0; pQH->firstTD = pTD;
pQH->lastTD = pTD;
pQH->GetSharedLogical()->elink = HostToUSBLong(pTD->GetPhysicalAddrWithType());
prevQH = _intrQH[i];
pQH->_logicalNext = prevQH->_logicalNext;
pQH->SetPhysicalLink(prevQH->GetPhysicalLink());
IOSync();
prevQH->_logicalNext = pQH;
prevQH->SetPhysicalLink(pQH->GetPhysicalAddrWithType());
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateInterruptEndpoint done pQH[%p]", this, pQH);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::UIMCreateInterruptTransfer(IOUSBCommand* command)
{
AppleUHCIQueueHead *pQH;
IOReturn status;
IOMemoryDescriptor *mp;
IOByteCount len;
if (command->GetAddress() == _rootFunctionNumber)
{
IODMACommand *dmaCommand = command->GetDMACommand();
IOMemoryDescriptor *memDesc = dmaCommand ? (IOMemoryDescriptor*)dmaCommand->getMemoryDescriptor() : NULL;
if (memDesc)
{
USBLog(3, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - root hub interrupt transfer - clearing memDesc (%p) from dmaCommand (%p)", this, memDesc, dmaCommand);
dmaCommand->clearMemoryDescriptor();
}
return RHCreateInterruptTransfer(command);
}
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - adr=(%d,%d) len %d rounding %d", this, command->GetAddress(), command->GetEndpoint(), (int)command->GetReqCount(), command->GetBufferRounding());
pQH = FindQueueHead(command->GetAddress(), command->GetEndpoint(), command->GetDirection(), kUSBInterrupt);
if (pQH == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - QH not found", this);
return kIOUSBEndpointNotFound;
}
if (pQH->stalled)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - Interrupt pipe stalled", this);
return kIOUSBPipeStalled;
}
mp = command->GetBuffer();
len = command->GetReqCount();
#define INTERRUPT_TRANSFERS_ONE_PACKET 0
#if INTERRUPT_TRANSFERS_ONE_PACKET
if ((int)len > ep->maxPacketSize)
{
len = ep->maxPacketSize;
}
#endif
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - allocating TD chain with mp %p", this, mp);
status = AllocTDChain(pQH, command, mp, len, command->GetDirection(), false);
if (status != kIOReturnSuccess)
{
return status;
}
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateInterruptTransfer - done", this);
return kIOReturnSuccess;
}
#pragma mark Isochronous
IOReturn
AppleUSBUHCI::UIMCreateIsochEndpoint(short functionNumber,
short endpointNumber,
UInt32 maxPacketSize,
UInt8 direction,
USBDeviceAddress highSpeedHub,
int highSpeedPort)
{
return UIMCreateIsochEndpoint(functionNumber, endpointNumber, maxPacketSize, direction);
}
IOReturn
AppleUSBUHCI::UIMCreateIsochEndpoint(short functionAddress,
short endpointNumber,
UInt32 maxPacketSize,
UInt8 direction)
{
IOUSBControllerIsochEndpoint* pEP;
UInt32 curMaxPacketSize;
UInt32 xtraRequest;
IOReturn res;
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateIsochEndpoint(%d, %d, %ld, %d)", this, functionAddress, endpointNumber, maxPacketSize, direction);
pEP = FindIsochronousEndpoint(functionAddress, endpointNumber, direction, NULL);
if (pEP)
{
USBLog(6,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint endpoint already exists, attempting to change maxPacketSize to %ld", this, maxPacketSize);
curMaxPacketSize = pEP->maxPacketSize;
if (maxPacketSize == curMaxPacketSize)
{
USBLog(4, "AppleUSBUHCI[%p]::UIMCreateIsochEndpoint maxPacketSize (%ld) the same, no change", this, maxPacketSize);
return kIOReturnSuccess;
}
if (maxPacketSize > curMaxPacketSize)
{
xtraRequest = maxPacketSize - curMaxPacketSize;
if (xtraRequest > _isocBandwidth)
{
USBLog(1,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint out of bandwidth, request (extra) = %ld, available: %ld", this, xtraRequest, _isocBandwidth);
return kIOReturnNoBandwidth;
}
_isocBandwidth -= xtraRequest;
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateIsochEndpoint grabbing additional bandwidth: %ld, new available: %ld", this, xtraRequest, _isocBandwidth);
} else
{
xtraRequest = curMaxPacketSize - maxPacketSize;
_isocBandwidth += xtraRequest;
USBLog(5, "AppleUSBUHCI[%p]::UIMCreateIsochEndpoint returning some bandwidth: %ld, new available: %ld", this, xtraRequest, _isocBandwidth);
}
pEP->maxPacketSize = maxPacketSize;
USBLog(6,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint new size %ld", this, maxPacketSize);
return kIOReturnSuccess;
}
else
USBLog(7,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint no endpoint", this);
if (maxPacketSize > _isocBandwidth)
{
USBLog(1,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint out of bandwidth, request (extra) = %ld, available: %ld", this, maxPacketSize, _isocBandwidth);
return kIOReturnNoBandwidth;
}
pEP = CreateIsochronousEndpoint(functionAddress, endpointNumber, direction);
if (pEP == NULL)
return kIOReturnNoMemory;
pEP->maxPacketSize = maxPacketSize;
USBLog(5,"AppleUSBUHCI[%p]::UIMCreateIsochEndpoint 2 size %ld", this, maxPacketSize);
pEP->inSlot = kUHCI_NVFRAMES+1;
_isocBandwidth -= maxPacketSize;
USBLog(6, "AppleUSBUHCI[%p]::UIMCreateIsochEndpoint success. bandwidth used = %ld, new available: %ld", this, maxPacketSize, _isocBandwidth);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::DeleteIsochEP(IOUSBControllerIsochEndpoint* pEP)
{
IOUSBControllerIsochEndpoint *curEP, *prevEP;
UInt32 currentMaxPacketSize;
USBLog(7, "AppleUSBUHCI[%p]::DeleteIsochEP (%p)", this, pEP);
if (pEP->activeTDs)
{
USBLog(6, "AppleUSBUHCI[%p]::DeleteIsochEP- there are still %ld active TDs - aborting", this, pEP->activeTDs);
AbortIsochEP(pEP);
if (pEP->activeTDs)
{
USBError(1, "AppleUSBUHCI[%p]::DeleteIsochEP- after abort there are STILL %ld active TDs", this, pEP->activeTDs);
}
}
prevEP = NULL;
curEP = _isochEPList;
while (curEP)
{
if (curEP == pEP)
{
if (prevEP)
prevEP->nextEP = curEP->nextEP;
else
_isochEPList = curEP->nextEP;
break;
}
prevEP = curEP;
curEP = curEP->nextEP;
}
currentMaxPacketSize = pEP->maxPacketSize;
_isocBandwidth += currentMaxPacketSize;
USBLog(4, "AppleUSBUHCI[%p]::DeleteIsochEP returned bandwidth %ld, new available: %ld", this, currentMaxPacketSize, _isocBandwidth);
DeallocateIsochEP(pEP);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::CreateIsochTransfer(IOUSBControllerIsochEndpoint* pEP, IOUSBIsocCommand *command)
{
AppleUHCIIsochTransferDescriptor *pNewITD=NULL;
UInt64 maxOffset;
UInt64 curFrameNumber = GetFrameNumber();
UInt64 frameDiff;
UInt32 diff32;
IOByteCount transferOffset;
UInt32 bufferSize;
UInt32 ioc = 0;
UInt32 i;
UInt32 pageOffset;
IOPhysicalAddress dmaStartAddr;
IOByteCount segLen;
UInt32 myStatFlags;
UInt32 myDirection;
bool lowLatency = command->GetLowLatency();
UInt32 updateFrequency = command->GetUpdateFrequency();
IOUSBIsocFrame * pFrames = command->GetFrameList();
IOUSBLowLatencyIsocFrame * pLLFrames = (IOUSBLowLatencyIsocFrame *)pFrames;
UInt32 frameCount = command->GetNumFrames();
UInt64 frameNumberStart = command->GetStartFrame();
IODMACommand * dmaCommand = command->GetDMACommand();
IOMemoryDescriptor * pBuffer = command->GetBuffer(); UInt64 offset;
IODMACommand::Segment64 segments64;
UInt32 numSegments;
IOReturn status;
USBLog(7, "AppleUSBUHCI[%p]::CreateIsochTransfer - frameCount %ld - frameNumberStart %Ld - curFrameNumber %Ld", this, frameCount, frameNumberStart, curFrameNumber);
USBLog(7, "AppleUSBUHCI[%p]::CreateIsochTransfer - updateFrequency %ld - lowLatency %d", this, updateFrequency, lowLatency);
if (!pEP)
{
USBError(1, "AppleUSBUHCI[%p]::CreateIsochTransfer - no endpoint", this);
return kIOReturnBadArgument;
}
maxOffset = kUHCI_NVFRAMES;
if (frameNumberStart < pEP->firstAvailableFrame)
{
USBLog(3,"AppleUSBUHCI[%p]::CreateIsochTransfer: no overlapping frames - EP (%p) frameNumberStart: %Ld, pEP->firstAvailableFrame: %Ld. Returning 0x%x", this, pEP, frameNumberStart, pEP->firstAvailableFrame, kIOReturnIsoTooOld);
return kIOReturnIsoTooOld;
}
pEP->firstAvailableFrame = frameNumberStart;
switch (pEP->direction)
{
case kUSBIn:
myDirection = kUHCI_TD_PID_IN;
break;
case kUSBOut:
myDirection = kUHCI_TD_PID_OUT;
break;
default:
USBLog(3,"AppleUSBUHCI[%p]::CreateIsochTransfer: bad direction(%d) in pEP[%p]", this, pEP->direction, pEP);
return kIOReturnBadArgument;
}
if (frameNumberStart <= curFrameNumber)
{
if (frameNumberStart < (curFrameNumber - maxOffset))
{
USBLog(3,"AppleUSBUHCI[%p]::CreateIsochTransfer request frame WAY too old. frameNumberStart: %Ld, curFrameNumber: %Ld. Returning 0x%x", this, frameNumberStart, curFrameNumber, kIOReturnIsoTooOld);
return kIOReturnIsoTooOld;
}
USBLog(5,"AppleUSBUHCI[%p]::CreateIsochTransfer WARNING! curframe later than requested, expect some notSent errors! frameNumberStart: %Ld, curFrameNumber: %Ld. USBIsocFrame Ptr: %p, First ITD: %p", this, frameNumberStart, curFrameNumber, pFrames, pEP->toDoEnd);
} else
{ if (frameNumberStart > (curFrameNumber + maxOffset))
{
USBLog(3,"AppleUSBUHCI[%p]::CreateIsochTransfer request frame too far ahead! frameNumberStart: %Ld, curFrameNumber: %Ld", this, frameNumberStart, curFrameNumber);
return kIOReturnIsoTooNew;
}
frameDiff = frameNumberStart - curFrameNumber;
diff32 = (UInt32)frameDiff;
if (diff32 < 2)
{
USBLog(5,"AppleUSBUHCI[%p]::CreateIsochTransfer WARNING! - frameNumberStart less than 2 ms (is %ld)! frameNumberStart: %Ld, curFrameNumber: %Ld", this, diff32, frameNumberStart, curFrameNumber);
}
}
pLLFrames = (IOUSBLowLatencyIsocFrame *)pFrames;
bufferSize = 0;
for ( i = 0; i < frameCount; i++)
{
if (!lowLatency)
{
if (pFrames[i].frReqCount > pEP->maxPacketSize)
{
USBLog(1,"AppleUSBUHCI[%p]::CreateIsochTransfer - Isoch frame (%ld) too big (%d) MPS (%ld)", this, i + 1, pFrames[i].frReqCount, pEP->maxPacketSize);
return kIOReturnBadArgument;
}
bufferSize += pFrames[i].frReqCount;
} else
{
if (pLLFrames[i].frReqCount > pEP->maxPacketSize)
{
USBLog(1,"AppleUSBUHCI[%p]::CreateIsochTransfer(LL) - Isoch frame (%ld) too big (%d) MPS (%ld)", this, i + 1, pLLFrames[i].frReqCount, pEP->maxPacketSize);
return kIOReturnBadArgument;
}
bufferSize += pLLFrames[i].frReqCount;
pLLFrames[i].frStatus = command->GetIsRosettaClient() ? (IOReturn) OSSwapInt32(kUSBLowLatencyIsochTransferKey) : (IOReturn) kUSBLowLatencyIsochTransferKey;
}
}
transferOffset = 0;
for ( i = 0; i < frameCount; i++)
{
UInt16 reqCount;
UInt32 token, ctrlStatus;
pNewITD = AllocateITD();
if (lowLatency)
reqCount = pLLFrames[i].frReqCount;
else
reqCount = pFrames[i].frReqCount;
USBLog(7, "AppleUSBUHCI[%p]::CreateIsochTransfer - new iTD %p size (%d)", this, pNewITD, reqCount);
if (!pNewITD)
{
USBLog(1,"AppleUSBUHCI[%p]::CreateIsochTransfer Could not allocate a new iTD", this);
return kIOReturnNoMemory;
}
pEP->firstAvailableFrame++;
pNewITD->_lowLatency = lowLatency;
offset = transferOffset;
numSegments = 1;
status = dmaCommand->gen64IOVMSegments(&offset, &segments64, &numSegments);
if (status || (numSegments != 1) || ((UInt32)(segments64.fIOVMAddr >> 32) > 0) || ((UInt32)(segments64.fLength >> 32) > 0))
{
USBError(1, "AppleUSBUHCI[%p]::CreateIsochTransfer - could not generate segments err (%p) numSegments (%d) fIOVMAddr (0x%Lx) fLength (0x%Lx)", this, (void*)status, (int)numSegments, segments64.fIOVMAddr, segments64.fLength);
status = status ? status : kIOReturnInternalError;
dmaStartAddr = 0;
segLen = 0;
}
else
{
dmaStartAddr = (IOPhysicalAddress)segments64.fIOVMAddr;
segLen = (UInt32)segments64.fLength;
}
if (segLen > reqCount)
{
segLen = reqCount;
}
if (segLen < reqCount)
{
UHCIAlignmentBuffer *bp = GetIsochAlignmentBuffer();
if (!bp)
{
USBLog(1, "AppleUSBUHCI[%p]:CreateIsochTransfer - could not get the alignment buffer I needed", this);
USBError(1,"The USB UHCI driver could not get the resources it needed. Transfers will be affected (%d:%d)", command->GetAddress(), command->GetEndpoint());
reqCount = segLen;
break;
}
USBLog(6, "AppleUSBUHCI[%p]:CreateIsochTransfer - using alignment buffer %p at pPhysical %p instead of %p direction %s EP %d", this, (void*)bp->vaddr, (void*)bp->paddr, (void*)dmaStartAddr, (pEP->direction == kUSBOut) ? "OUT" : "IN", pEP->endpointNumber);
pNewITD->alignBuffer = bp;
dmaStartAddr = bp->paddr;
if (pEP->direction == kUSBOut)
{
pBuffer->readBytes(transferOffset, (void *)bp->vaddr, reqCount);
}
bp->userBuffer = pBuffer;
bp->userOffset = transferOffset;
bp->dmaCommand = OSDynamicCast(AppleUSBUHCIDMACommand, dmaCommand);
bp->actCount = 0;
}
transferOffset += reqCount;
bufferSize -= reqCount;
pNewITD->_pFrames = pFrames;
pNewITD->_frameNumber = frameNumberStart + i;
pNewITD->_frameIndex = i;
if (i == (frameCount-1))
{
ioc = kUHCI_TD_IOC;
pNewITD->_completion = command->GetUSLCompletion();
}
else if (lowLatency)
{
if (!updateFrequency)
ioc = (((i+1) % 8) == 0) ? (UInt32)kUHCI_TD_IOC : 0;
else
ioc = (((i+1) % updateFrequency) == 0) ? (UInt32)kUHCI_TD_IOC : 0;
}
else
ioc = 0;
pNewITD->GetSharedLogical()->buffer = HostToUSBLong(dmaStartAddr);
pNewITD->SetPhysicalLink(kUHCI_QH_T);
pNewITD->_lowLatency = lowLatency;
token = myDirection | UHCI_TD_SET_MAXLEN(reqCount) | UHCI_TD_SET_ENDPT(pEP->endpointNumber) | UHCI_TD_SET_ADDR(pEP->functionAddress);
pNewITD->GetSharedLogical()->token = HostToUSBLong(token);
ctrlStatus = kUHCI_TD_ACTIVE | kUHCI_TD_ISO | UHCI_TD_SET_ACTLEN(0) | ioc;
pNewITD->GetSharedLogical()->ctrlStatus = HostToUSBLong(ctrlStatus);
pNewITD->_pEndpoint = pEP;
pNewITD->_requestFromRosettaClient = command->GetIsRosettaClient();
PutTDonToDoList(pEP, pNewITD);
}
USBLog(7, "AppleUSBUHCI[%p]::CreateIsochTransfer - calling AddIsochFramesToSchedule", this);
AddIsochFramesToSchedule(pEP);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::UIMCreateIsochTransfer(short functionNumber,
short endpointNumber,
IOUSBIsocCompletion completion,
UInt8 direction,
UInt64 frameStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBIsocFrame *pFrames)
{
USBError(1, "AppleUSBUHCI::UIMCreateIsochTransfer(LL) - old method");
return kIOReturnIPCError;
}
IOReturn
AppleUSBUHCI::UIMCreateIsochTransfer(short functionNumber,
short endpointNumber,
IOUSBIsocCompletion completion,
UInt8 direction,
UInt64 frameStart,
IOMemoryDescriptor *pBuffer,
UInt32 frameCount,
IOUSBLowLatencyIsocFrame *pFrames,
UInt32 updateFrequency)
{
USBError(1, "AppleUSBUHCI::UIMCreateIsochTransfer(LL) - old method");
return kIOReturnIPCError;
}
IOReturn
AppleUSBUHCI::UIMCreateIsochTransfer(IOUSBIsocCommand * command)
{
IOReturn err;
IOUSBControllerIsochEndpoint * pEP;
UInt64 maxOffset;
UInt64 curFrameNumber = GetFrameNumber();
UInt64 frameDiff;
UInt32 diff32;
USBLog(7, "AppleUSBUHCI[%p]::UIMCreateIsochTransfer - adr=%d:%d IOMD=%p, frameStart: %qd, count: %ld, pFrames: %p", this,
command->GetAddress(), command->GetEndpoint(),
command->GetBuffer(),
command->GetStartFrame(), command->GetNumFrames(), command->GetFrameList());
if ( (command->GetNumFrames() == 0) || (command->GetNumFrames() > 1000) )
{
USBLog(3,"AppleUSBUHCI[%p]::UIMCreateIsochTransfer bad frameCount: %ld", this, command->GetNumFrames());
return kIOReturnBadArgument;
}
pEP = FindIsochronousEndpoint(command->GetAddress(), command->GetEndpoint(), command->GetDirection(), NULL);
if(pEP == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCreateIsochTransfer - Endpoint not found", this);
return kIOUSBEndpointNotFound;
}
return CreateIsochTransfer(pEP, command);
}
#pragma mark Endpoints
IOReturn
AppleUSBUHCI::HandleEndpointAbort(short functionAddress, short endpointNumber, short direction, bool clearToggle)
{
AppleUHCIQueueHead *pQH, *pQHPrev;
UInt32 link;
IOUSBControllerIsochEndpoint *pIsochEP;
AppleUHCITransferDescriptor *savedFirstTD = NULL;
AppleUHCITransferDescriptor *savedLastTD = NULL;
USBLog(4, "AppleUSBUHCI[%p]::HandleEndpointAbort: Addr: %d, Endpoint: %d,%d", this, functionAddress, endpointNumber, direction);
if (functionAddress == _rootFunctionNumber)
{
if ( (endpointNumber != 1) && (endpointNumber != 0) )
{
USBLog(1, "AppleUSBUHCI[%p]::HandleEndpointAbort: bad params - endpNumber: %d", this, endpointNumber );
return kIOReturnBadArgument;
}
USBLog(5, "AppleUSBUHCI[%p]::HandleEndpointAbort: Attempting operation on root hub", this);
return RHAbortEndpoint(endpointNumber, direction);
}
pIsochEP = FindIsochronousEndpoint(functionAddress, endpointNumber, direction, NULL);
if (pIsochEP)
{
return AbortIsochEP(pIsochEP);
}
if (pQH = FindQueueHead(functionAddress, endpointNumber, direction, kUSBControl, &pQHPrev), pQH)
{
USBLog(5, "AppleUSBUHCI[%p]::HandleEndpointAbort - Found control queue head %p prev %p", this, pQH, pQHPrev);
}
else if (pQH = FindQueueHead(functionAddress, endpointNumber, direction, kUSBInterrupt, &pQHPrev), pQH)
{
USBLog(5, "AppleUSBUHCI[%p]::HandleEndpointAbort - Found interrupt queue head %p prev %p", this, pQH, pQHPrev);
}
else if (pQH = FindQueueHead(functionAddress, endpointNumber, direction, kUSBBulk, &pQHPrev), pQH)
{
USBLog(5, "AppleUSBUHCI[%p]::HandleEndpointAbort - Found bulk queue head %p prev %p", this, pQH, pQHPrev);
}
if (pQH == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::HandleEndpointAbort - endpoint not found", this);
return kIOUSBEndpointNotFound;
}
if(pQH->firstTD != pQH->lastTD) {
link = pQHPrev->GetPhysicalLink(); pQHPrev->SetPhysicalLink(pQH->GetPhysicalLink()); IOSleep(1); USBLog(4, "AppleUSBUHCI[%p]::HandleEndpointAbort: removing TDs", this);
savedFirstTD = pQH->firstTD;
savedLastTD = pQH->lastTD;
pQH->firstTD = pQH->lastTD;
if (clearToggle)
pQH->firstTD->GetSharedLogical()->token = 0; pQH->GetSharedLogical()->elink = HostToUSBLong(pQH->firstTD->GetPhysicalAddrWithType());
IOSync();
pQHPrev->SetPhysicalLink(link); }
else
{
if (clearToggle)
pQH->firstTD->GetSharedLogical()->token = 0;
pQH->GetSharedLogical()->elink = HostToUSBLong(pQH->firstTD->GetPhysicalAddrWithType());
IOSync();
}
pQH->stalled = false;
USBLog(4, "AppleUSBUHCI[%p]::HandleEndpointAbort: Addr: %d, Endpoint: %d,%d - calling DoDoneQueue", this, functionAddress, endpointNumber, direction);
UHCIUIMDoDoneQueueProcessing(savedFirstTD, kIOUSBTransactionReturned, savedLastTD);
return kIOReturnSuccess;
}
IOReturn
AppleUSBUHCI::UIMAbortEndpoint(short functionAddress, short endpointNumber, short direction)
{
USBLog(3, "AppleUSBUHCI[%p]::UIMAbortEndpoint - endpoint %d:%d,%d", this, functionAddress, endpointNumber, direction);
return HandleEndpointAbort(functionAddress, endpointNumber, direction, false);
}
IOReturn
AppleUSBUHCI::UIMClearEndpointStall(short functionAddress, short endpointNumber, short direction)
{
USBLog(5, "AppleUSBUHCI[%p]::UIMClearEndpointStall - endpoint %d:%d,%d", this, functionAddress, endpointNumber, direction);
return HandleEndpointAbort(functionAddress, endpointNumber, direction, true);
}
IOReturn
AppleUSBUHCI::UIMDeleteEndpoint(short functionNumber, short endpointNumber, short direction)
{
AppleUHCIQueueHead *pQH;
IOUSBControllerIsochEndpoint* pIsochEP;
int i;
AppleUHCIQueueHead *pQHPrev = NULL;
IOReturn err;
USBLog(3, "AppleUSBUHCI[%p]::UIMDeleteEndpoint %d %d %d", this, functionNumber, endpointNumber, direction);
if (functionNumber == _rootFunctionNumber)
{
if (endpointNumber != 0 && endpointNumber != 1)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - not ep 0 or ep 1 [%d](kIOReturnBadArgument)", this, endpointNumber);
return kIOReturnBadArgument;
}
return RHDeleteEndpoint(endpointNumber, direction);
}
pIsochEP = FindIsochronousEndpoint(functionNumber, endpointNumber, direction, NULL);
if (pIsochEP)
return DeleteIsochEP(pIsochEP);
if (pQH = FindQueueHead(functionNumber, endpointNumber, direction, kUSBControl, &pQHPrev), pQH)
{
USBLog(7, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - Found control queue head %p prev %p", this, pQH, pQHPrev);
}
else if (pQH = FindQueueHead(functionNumber, endpointNumber, direction, kUSBInterrupt, &pQHPrev), pQH)
{
USBLog(7, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - Found interrupt queue head %p prev %p", this, pQH, pQHPrev);
}
else if (pQH = FindQueueHead(functionNumber, endpointNumber, direction, kUSBBulk, &pQHPrev), pQH)
{
USBLog(7, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - Found bulk queue head %p prev %p", this, pQH, pQHPrev);
}
if (pQH == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - endpoint not found", this);
return kIOUSBEndpointNotFound;
}
err = UnlinkQueueHead(pQH, pQHPrev);
if (err)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - err %p unlinking endpoint", this, (void*)err);
}
if(pQH->firstTD != pQH->lastTD) {
USBLog(5, "AppleUSBUHCI[%p]::UIMDeleteEndpoint: removing TDs", this);
UHCIUIMDoDoneQueueProcessing(pQH->firstTD, kIOUSBTransactionReturned, pQH->lastTD);
pQH->firstTD = pQH->lastTD;
}
if ( pQH->firstTD != NULL )
{
USBLog(7, "AppleUSBUHCI[%p]::UIMDeleteEndpoint - deallocating the dummy TD", this);
DeallocateTD(pQH->firstTD);
pQH->firstTD = NULL;
}
USBLog(7, "AppleUSBUHCI[%p]::UIMDeleteEndpoint: Deallocating %p", this, pQH);
DeallocateQH(pQH);
return kIOReturnSuccess;
}
AppleUHCIQueueHead *
AppleUSBUHCI::FindQueueHead(short functionNumber, short endpointNumber, UInt8 direction, UInt8 type, AppleUHCIQueueHead **ppQHPrev)
{
AppleUHCIQueueHead *pQH, *firstQH, *lastQH, *prevQH = NULL;
USBLog(7, "AppleUSBUHCI[%p]::FindQueueHead(%d, %d, %d, %d)", this, functionNumber, endpointNumber, direction, type);
switch (type)
{
case kUSBInterrupt:
firstQH = _intrQH[kUHCI_NINTR_QHS-1];
lastQH = _lsControlQHStart;
break;
case kUSBControl:
firstQH = _lsControlQHStart;
lastQH = _bulkQHStart;
break;
case kUSBBulk:
firstQH = _bulkQHStart;
lastQH = _lastQH;
break;
default:
firstQH = lastQH = NULL;
}
pQH = firstQH;
while (pQH && (pQH != lastQH))
{
USBLog(7, "AppleUSBUHCI[%p]::FindQueueHead - looking at queue head %p (%d, %d, %d, %d)", this, pQH, pQH->functionNumber, pQH->endpointNumber, pQH->direction, pQH->type);
if ((pQH->functionNumber == functionNumber) && (pQH->endpointNumber == endpointNumber) && ((direction == kUSBAnyDirn) || (pQH->direction == direction)) && (pQH->type == type))
{
USBLog(7, "AppleUSBUHCI[%p]::FindQueueHead - found Queue Head %p", this, pQH);
if (ppQHPrev)
*ppQHPrev = prevQH;
return pQH;
}
prevQH = pQH;
pQH = OSDynamicCast(AppleUHCIQueueHead, pQH->_logicalNext);
}
USBLog(7, "AppleUSBUHCI[%p]::FindQueueHead - endpoint not found", this);
return NULL;
}
IOReturn
AppleUSBUHCI::UnlinkQueueHead(AppleUHCIQueueHead *pQH, AppleUHCIQueueHead *pQHBack)
{
if (!pQH || !pQHBack)
{
USBLog(1, "AppleUSBUHCI[%p]::UnlinkQueueHead - invalid params (%p, %p)", this, pQH, pQHBack);
return kIOReturnBadArgument;
}
USBLog(7, "AppleUSBUHCI[%p]::UnlinkQueueHead(%p, %p)", this, pQH, pQHBack);
if (pQH == _lsControlQHEnd)
_lsControlQHEnd = pQHBack;
else if (pQH == _fsControlQHEnd)
_fsControlQHEnd = pQHBack;
else if (pQH == _bulkQHEnd)
_bulkQHEnd = pQHBack;
pQHBack->SetPhysicalLink(pQH->GetPhysicalLink());
pQHBack->_logicalNext = pQH->_logicalNext;
IOSleep(1);
return kIOReturnSuccess;
}
#pragma mark Transaction starting and completing
#define kUHCIUIMScratchFirstActiveFrame 0
void
AppleUSBUHCI::UIMCheckForTimeouts(void)
{
AbsoluteTime currentTime, t;
UInt64 elapsedTime;
UInt64 frameNumber;
UInt16 status;
AppleUHCIQueueHead *pQH = NULL, *pQHBack = NULL, *pQHBack1 = NULL;
AppleUHCITransferDescriptor *pTD = NULL;
IOPhysicalAddress pTDPhys;
UInt32 noDataTimeout;
UInt32 completionTimeout;
UInt32 curFrame = GetFrameNumber32();
UInt32 rem;
bool logging = false;
int loopCount = 0;
if (_needToCreateRootHub)
{
USBLog(1,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - Need to recreate root hub on bus %ld INTR[%p] _uhciBusState[%d] _uhciAvailable[%s], sleeping for 5 seconds", this, _busNumber, (void*)ioRead16(kUHCI_INTR), _uhciBusState, _uhciAvailable ? "true" : "false");
_needToCreateRootHub = false;
IOSleep(5000);
USBLog(2,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - Need to recreate root hub on bus %ld, powering up hardware", this, _busNumber);
UIMInitializeForPowerUp();
_uhciAvailable = true; Run(true);
_uhciBusState = kUHCIBusStateRunning;
_wakingFromHibernation = false;
if ( _rootHubDevice == NULL )
{
IOReturn err;
err = CreateRootHubDevice( _device, &_rootHubDevice );
if ( err != kIOReturnSuccess )
{
USBError(1,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - Could not create root hub device upon wakeup (%x)!", this, err);
}
else
{
USBLog(2,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - calling registerService on new root hub", this);
_rootHubDevice->registerService(kIOServiceRequired | kIOServiceSynchronous);
}
}
USBLog(1,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - done creating root hub on bus %ld INTR[%p] _uhciBusState[%d] _uhciAvailable[%s]", this, _busNumber, (void*)ioRead16(kUHCI_INTR), _uhciBusState, _uhciAvailable ? "true" : "false");
return; }
if (isInactive() || (_uhciBusState != kUHCIBusStateRunning) || _wakingFromHibernation)
{
return;
}
USBLog(7, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - calling ProcessCompletedTransactions", this);
ProcessCompletedTransactions();
clock_get_uptime(¤tTime);
status = ioRead16(kUHCI_STS);
if (status & kUHCI_STS_HCH)
{
ioWrite16(kUHCI_STS, kUHCI_STS_HCH);
USBError(1, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - Host controller halted, resetting", this);
Reset(true);
Run(true);
}
frameNumber = GetFrameNumber();
_lastTimeoutFrameNumber = frameNumber;
_lastFrameNumberTime = currentTime;
for (pQH = _lsControlQHStart; pQH && (loopCount++ < 100); pQH = OSDynamicCast(AppleUHCIQueueHead, pQH->_logicalNext))
{
if (pQH == pQH->_logicalNext)
{
USBError(1,"AppleUSBUHCI[%p]::UIMCheckForTimeouts pQH (%p) linked to itself", this, pQH);
}
pQHBack = pQHBack1;
pQHBack1 = pQH;
if (pQH->type == kQHTypeDummy)
continue;
logging = true;
USBLog(7, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - checking QH [%p]", this, pQH);
pQH->print(7);
pTDPhys = USBToHostLong(pQH->GetSharedLogical()->elink);
pTD = pQH->firstTD;
if (!pTD)
{
USBLog(3, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - no TD", this);
continue;
}
if (!pTD->command)
{
USBLog(7, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - found a TD without a command - moving on", this);
continue;
}
if (pTD == pQH->lastTD)
{
USBLog(1, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - ED (%p) - TD is TAIL but there is a command - pTD (%p)", this, pQH, pTD);
pQH->print(1);
}
if(pTDPhys != pTD->GetPhysicalAddrWithType())
{
USBLog(6, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - pED (%p) - mismatched logical and physical - TD (%p) will be scavenged later", this, pQH, pTD);
pQH->print(7);
pTD->print(7);
continue;
}
noDataTimeout = pTD->command->GetNoDataTimeout();
completionTimeout = pTD->command->GetCompletionTimeout();
if (completionTimeout)
{
UInt32 firstActiveFrame = pTD->command->GetUIMScratch(kUHCIUIMScratchFirstActiveFrame);
if (!firstActiveFrame)
{
pTD->command->SetUIMScratch(kUHCIUIMScratchFirstActiveFrame, curFrame);
continue;
}
if ((curFrame - firstActiveFrame) >= completionTimeout)
{
USBLog(2, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - Found a TD [%p] on QH [%p] past the completion deadline, timing out! (0x%lx - 0x%lx)", this, pTD, pQH, curFrame, firstActiveFrame);
USBError(1, "AppleUSBUHCI[%p]::Found a transaction past the completion deadline on bus %ld, timing out!", this, _busNumber);
pQH->print(2);
ReturnOneTransaction(pTD, pQH, pQHBack, kIOUSBTransactionTimeout);
continue;
}
}
if (!noDataTimeout)
continue;
if (!pTD->lastFrame || (pTD->lastFrame > curFrame))
{
pTD->lastFrame = curFrame;
pTD->lastRemaining = findBufferRemaining(pQH);
continue;
}
rem = findBufferRemaining(pQH);
if (pTD->lastRemaining != rem)
{
pTD->lastRemaining = rem;
continue;
}
if ((curFrame - pTD->lastFrame) >= noDataTimeout)
{
USBLog(2, "AppleUSBUHCI[%p]UIMCheckForTimeouts: Found a transaction (%p) which hasn't moved in 5 seconds, timing out! (0x%lx - 0x%lx)(CMD:%p STS:%p INTR:%p PORTSC1:%p PORTSC2:%p FRBASEADDR:%p ConfigCMD:%p)", this, pTD, curFrame, pTD->lastFrame, (void*)ioRead16(kUHCI_CMD), (void*)ioRead16(kUHCI_STS), (void*)ioRead16(kUHCI_INTR), (void*)ioRead16(kUHCI_PORTSC1), (void*)ioRead16(kUHCI_PORTSC2), (void*)ioRead32(kUHCI_FRBASEADDR), (void*)_device->configRead16(kIOPCIConfigCommand));
USBError(1, "AppleUSBUHCI[%p]::Found a transaction which hasn't moved in 5 seconds on bus %ld, timing out!", this, _busNumber);
pQH->print(2);
pTD->print(2);
ReturnOneTransaction(pTD, pQH, pQHBack, kIOUSBTransactionTimeout);
continue;
}
}
t = currentTime;
SUB_ABSOLUTETIME(&t, &_lastTime);
absolutetime_to_nanoseconds(t, &elapsedTime);
elapsedTime /= 1000000000;
if (elapsedTime > kUHCICheckForRootHubConnectionsPeriod)
{
_lastTime = currentTime;
if (_uhciBusState != kUHCIBusStateSuspended)
{
USBLog(7, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - checking root hub for connections", this);
if (RHAreAllPortsDisconnectedOrSuspended())
{
t = currentTime;
SUB_ABSOLUTETIME(&t, &_rhChangeTime);
absolutetime_to_nanoseconds(t, &elapsedTime);
elapsedTime /= 1000000000;
if (elapsedTime >= kUHCICheckForRootHubInactivityPeriod)
{
USBLog(2,"AppleUSBUHCI[%p]::UIMCheckForTimeouts - Suspending idle root hub", this);
setPowerState( kUHCIPowerLevelIdleSuspend, this);
}
}
}
}
if (loopCount > 99)
{
USBError(1,"AppleUSBUHCI[%p]::UIMCheckForTimeouts Too many loops around", this);
}
if (logging)
USBLog(7, "AppleUSBUHCI[%p]::UIMCheckForTimeouts - done", this);
}
void
AppleUSBUHCI::ReturnOneTransaction(AppleUHCITransferDescriptor *pTD,
AppleUHCIQueueHead *pQH,
AppleUHCIQueueHead *pQHBack,
IOReturn err)
{
AppleUHCITransferDescriptor *pTDFirst = pTD;
pQHBack->SetPhysicalLink(pQH->GetPhysicalLink());
IOSleep(1);
while(pTD != NULL)
{
if (pTD->lastTDofTransaction)
break;
pTD = OSDynamicCast(AppleUHCITransferDescriptor, pTD->_logicalNext);
}
if(pTD == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::ReturnOneTransaction - got to the end with no callback", this);
}
else
{
pTD = OSDynamicCast(AppleUHCITransferDescriptor, pTD->_logicalNext);
pQH->GetSharedLogical()->elink = HostToUSBLong(pTD->GetPhysicalAddrWithType());
IOSync();
pQH->firstTD = pTD;
pQHBack->SetPhysicalLink(pQH->GetPhysicalAddrWithType()); }
USBLog(5, "AppleUSBUHCI[%p]::ReturnOneTransaction - returning transactions", this);
UHCIUIMDoDoneQueueProcessing(pTDFirst, err, pTD);
}
UInt32
AppleUSBUHCI::findBufferRemaining(AppleUHCIQueueHead *pQH)
{
UInt32 ctrlStatus, token, bufferSizeRemaining = 0;
AppleUHCITransferDescriptor *pTD = pQH->firstTD;
while (pTD && (pTD != pQH->lastTD))
{
ctrlStatus = USBToHostLong(pTD->GetSharedLogical()->ctrlStatus);
token = USBToHostLong(pTD->GetSharedLogical()->token);
bufferSizeRemaining += (UHCI_TD_GET_MAXLEN(token) - UHCI_TD_GET_ACTLEN(ctrlStatus));
if (pTD->lastTDofTransaction)
break;
pTD = OSDynamicCast(AppleUHCITransferDescriptor, pTD->_logicalNext);
}
return bufferSizeRemaining;
}
IOReturn
AppleUSBUHCI::TDToUSBError(UInt32 status)
{
IOReturn result;
status &= kUHCI_TD_ERROR_MASK;
if (status == 0)
{
result = kIOReturnSuccess;
} else if (status & kUHCI_TD_CRCTO)
{
result = kIOReturnNotResponding;
} else if (status & kUHCI_TD_BABBLE)
{
result = kIOReturnOverrun;
} else if (status & kUHCI_TD_STALLED)
{
result = kIOUSBPipeStalled;
} else if (status & kUHCI_TD_DBUF)
{
result = kIOReturnOverrun;
} else if (status & kUHCI_TD_CRCTO)
{
result = kIOUSBCRCErr;
} else if (status & kUHCI_TD_BITSTUFF)
{
result = kIOUSBBitstufErr;
} else
{
result = kIOUSBTransactionReturned;
}
return result;
}
#pragma mark Transaction descriptors
IOReturn
AppleUSBUHCI::AllocTDChain(AppleUHCIQueueHead* pQH, IOUSBCommand *command, IOMemoryDescriptor* CBP, UInt32 bufferSize, UInt16 direction, Boolean controlTransaction)
{
AppleUHCITransferDescriptor *pTD1, *pTD, *pTDnew, *pTDLast;
UInt32 myToggle = 0;
UInt32 myDirection = 0;
IOByteCount transferOffset;
UInt32 token;
UInt32 ctrlStatus;
IOReturn status = kIOReturnSuccess;
UInt32 maxPacket;
UInt32 totalPhysLength;
IOPhysicalAddress dmaStartAddr;
UInt32 bytesToSchedule;
IODMACommand *dmaCommand = NULL;
UInt64 offset;
IODMACommand::Segment64 segments64;
UInt32 numSegments;
if(controlTransaction)
{
if(direction != kUSBNone)
{ myToggle = kUHCI_TD_D; }
}
else
{
myToggle = USBToHostLong(pQH->lastTD->GetSharedLogical()->token) & kUHCI_TD_D;
}
switch (direction)
{
case kUSBIn:
myDirection = kUHCI_TD_PID_IN;
break;
case kUSBOut:
myDirection = kUHCI_TD_PID_OUT;
break;
default:
myDirection = kUHCI_TD_PID_SETUP;
}
maxPacket = pQH->maxPacketSize;
if ((bufferSize > 0) && (maxPacket == 0))
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - buffserSize %d with maxPacket %d", this, (int)bufferSize, (int)maxPacket);
return kIOReturnNoResources;
}
pTD1 = AllocateTD(pQH);
if (pTD1 == NULL)
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - can't allocate 1st new TD", this);
return kIOReturnNoMemory;
}
pTD = pTD1;
ctrlStatus = kUHCI_TD_ACTIVE | UHCI_TD_SET_ERRCNT(3) | UHCI_TD_SET_ACTLEN(0);
if (direction == kUSBIn)
ctrlStatus |= kUHCI_TD_SPD;
if (pQH->speed == kUSBDeviceSpeedLow)
ctrlStatus |= kUHCI_TD_LS;
if (CBP && bufferSize)
{
dmaCommand = command->GetDMACommand();
if (!dmaCommand)
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - no dmaCommand", this);
DeallocateTD(pTD1);
return kIOReturnInternalError;
}
if (dmaCommand->getMemoryDescriptor() != CBP)
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - mismatched CBP (%p) and dmaCommand memory descriptor (%p)", this, CBP, dmaCommand->getMemoryDescriptor());
DeallocateTD(pTD);
return kIOReturnInternalError;
}
}
if (bufferSize != 0)
{
transferOffset = 0;
while (transferOffset < bufferSize)
{
offset = transferOffset;
numSegments = 1;
status = dmaCommand->gen64IOVMSegments(&offset, &segments64, &numSegments);
if (status || (numSegments != 1))
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - could not generate segments err (%p) offset (%d) transferOffset (%d) bufferSize (%d) getMemoryDescriptor (%p)", this, (void*)status, (int)offset, (int)transferOffset, (int)bufferSize, dmaCommand->getMemoryDescriptor());
status = status ? status : kIOReturnInternalError;
return status;
}
if (((UInt32)(segments64.fIOVMAddr >> 32) > 0) || ((UInt32)(segments64.fLength >> 32) > 0))
{
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain - generated segment not 32 bit - offset (0x%Lx) length (0x%Lx) ", this, segments64.fIOVMAddr, segments64.fLength);
return kIOReturnInternalError;
}
dmaStartAddr = (IOPhysicalAddress)segments64.fIOVMAddr;
totalPhysLength = (UInt32)segments64.fLength;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - gen64IOVMSegments returned length of %ld (out of %ld) and start of 0x%lx", this, totalPhysLength, bufferSize, dmaStartAddr);
bytesToSchedule = 0;
if ((bufferSize-transferOffset) > maxPacket)
{
bytesToSchedule = maxPacket;
}
else
{
bytesToSchedule = (bufferSize-transferOffset);
}
if (totalPhysLength < bytesToSchedule)
{
UHCIAlignmentBuffer *bp;
bp = GetCBIAlignmentBuffer();
if (!bp)
{
USBError(1, "AppleUSBUHCI[%p]:AllocTDChain - could not get the alignment buffer I needed", this);
return kIOReturnNoResources;
}
USBLog(1, "AppleUSBUHCI[%p]:AllocTDChain - pTD (%p) using UHCIAlignmentBuffer (%p) paddr (%p) instead of CBP (%p) dmaStartAddr (%p) totalPhysLength (%d) bytesToSchedule (%d)", this, pTD, bp, (void*)bp->paddr, CBP, (void*)dmaStartAddr, (int)totalPhysLength, (int)bytesToSchedule);
pTD->alignBuffer = bp;
dmaStartAddr = bp->paddr;
if (direction != kUSBIn)
{
CBP->readBytes(transferOffset, (void *)bp->vaddr, bytesToSchedule);
}
bp->userBuffer = CBP;
bp->userOffset = transferOffset;
bp->actCount = 0;
}
transferOffset += bytesToSchedule;
pTD->direction = direction;
pTD->GetSharedLogical()->buffer = HostToUSBLong(dmaStartAddr);
token = myDirection | myToggle | UHCI_TD_SET_MAXLEN(bytesToSchedule) | UHCI_TD_SET_ENDPT(pQH->endpointNumber) | UHCI_TD_SET_ADDR(pQH->functionNumber);
pTD->GetSharedLogical()->token = HostToUSBLong(token);
myToggle = myToggle ? 0 : (int)kUHCI_TD_D;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - putting command into TD (%p) on QH (%p)", this, pTD, pQH);
pTD->command = command; if (transferOffset >= bufferSize)
{
ctrlStatus |= kUHCI_TD_IOC;
pTD->lastTDofTransaction = true;
pTD->logicalBuffer = CBP;
pTD->GetSharedLogical()->ctrlStatus = HostToUSBLong(ctrlStatus & ~kUHCI_TD_SPD); }
else
{
pTD->lastTDofTransaction = false;
pTDnew = AllocateTD(pQH);
if (pTDnew == NULL)
{
status = kIOReturnNoMemory;
USBError(1, "AppleUSBUHCI[%p]::AllocTDChain can't allocate new TD", this);
}
else
{
pTD->SetPhysicalLink(pTDnew->GetPhysicalAddrWithType());
pTD->_logicalNext = pTDnew; pTD->GetSharedLogical()->ctrlStatus = HostToUSBLong(ctrlStatus);
pTD = pTDnew;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - got another TD - going to fill it up too (%ld, %ld)", this, transferOffset, bufferSize);
}
}
}
}
else
{
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - (no buffer)- putting command into TD (%p) on QH (%p)", this, pTD, pQH);
pTD->command = command; ctrlStatus |= kUHCI_TD_IOC;
pTD->lastTDofTransaction = true;
pTD->logicalBuffer = CBP;
token = myDirection | myToggle | UHCI_TD_SET_MAXLEN(0) | UHCI_TD_SET_ENDPT(pQH->endpointNumber) | UHCI_TD_SET_ADDR(pQH->functionNumber);
pTD->GetSharedLogical()->token = HostToUSBLong(token);
pTD->GetSharedLogical()->ctrlStatus = HostToUSBLong(ctrlStatus);
myToggle = myToggle ? 0 : (int)kUHCI_TD_D;
}
pTDLast = pQH->lastTD;
pTD->SetPhysicalLink(pTD1->GetPhysicalAddrWithType());
pTD->_logicalNext = pTD1;
ctrlStatus = pTD1->GetSharedLogical()->ctrlStatus;
pTD1->GetSharedLogical()->ctrlStatus = 0;
pTDLast->SetPhysicalLink(pTD1->GetPhysicalLink());
pTDLast->GetSharedLogical()->ctrlStatus = pTD1->GetSharedLogical()->ctrlStatus;
pTDLast->GetSharedLogical()->token = pTD1->GetSharedLogical()->token;
pTDLast->GetSharedLogical()->buffer = pTD1->GetSharedLogical()->buffer;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - transfering command from TD (%p) to TD (%p)", this, pTD1, pTDLast);
pTDLast->command = pTD1->command;
pTDLast->lastTDofTransaction = pTD1->lastTDofTransaction;
pTDLast->_logicalNext = pTD1->_logicalNext;
pTDLast->logicalBuffer = pTD1->logicalBuffer;
if (pTD1->alignBuffer)
{
USBLog(1, "AppleUSBUHCI[%p]::AllocTDChain - moving alignBuffer from TD (%p) to TD (%p)", this, pTD1, pTDLast);
}
pTDLast->alignBuffer = pTD1->alignBuffer;
pTD->SetPhysicalLink(pTD1->GetPhysicalAddrWithType());
pTD->_logicalNext = pTD1;
pTD1->SetPhysicalLink(kUHCI_TD_T);
pTD1->GetSharedLogical()->token = HostToUSBLong(myToggle); pTD1->GetSharedLogical()->buffer = 0; pTD1->_logicalNext = NULL;
pTD1->alignBuffer = NULL;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - zeroing out command in TD (%p)", this, pTD1);
pTD1->command = NULL;
pQH->lastTD = pTD1;
pTDLast->GetSharedLogical()->ctrlStatus = ctrlStatus;
USBLog(7, "AllocTDChain - TD list for QH %p firstTD %p lastTD %p ================================================", pQH, pQH->firstTD, pQH->lastTD);
pTD = pQH->firstTD;
while (pTD)
{
pTD->print(7);
pTD = (AppleUHCITransferDescriptor*)pTD->_logicalNext;
}
USBLog(7, "AllocTDChain - end of chain =========================================================");
if (status)
{
USBLog(2, "AppleUSBUHCI[%p]::AllocTDChain: returning status 0x%x", this, status);
}
if ((pQH->type == kUSBControl) || (pQH->type == kUSBBulk))
{
if (!_controlBulkTransactionsOut)
{
UInt32 link;
link = _lastQH->GetPhysicalLink();
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - first transaction - unblocking list (%p to %p)", this, (void*)link, (void*)(link & ~kUHCI_QH_T));
_lastQH->SetPhysicalLink(link & ~kUHCI_QH_T);
}
_controlBulkTransactionsOut++;
USBLog(7, "AppleUSBUHCI[%p]::AllocTDChain - _controlBulkTransactionsOut(%p)", this, (void*)_controlBulkTransactionsOut);
}
return status;
}
void
AppleUSBUHCI::AddIsochFramesToSchedule(IOUSBControllerIsochEndpoint* pEP)
{
UInt64 currFrame, startFrame, finFrame;
IOUSBControllerIsochListElement *pTD = NULL;
UInt16 nextSlot, firstOutSlot;
AbsoluteTime timeStamp;
if(pEP->toDoList == NULL)
{
USBLog(7, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - no frames to add fn:%d EP:%d", this, pEP->functionAddress, pEP->endpointNumber);
return;
}
if(pEP->aborting)
{
USBLog(1, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - EP (%p) is aborting - not adding", this, pEP);
return;
}
if (!IOSimpleLockTryLock(_isochScheduleLock))
{
USBError(1, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - could not obtain scheduling lock", this);
return;
}
currFrame = GetFrameNumber();
startFrame = currFrame;
clock_get_uptime(&timeStamp);
while(pEP->toDoList->_frameNumber <= (currFrame+1)) {
IOReturn ret;
UInt64 newCurrFrame;
pTD = GetTDfromToDoList(pEP);
ret = pTD->UpdateFrameList(timeStamp); if (pEP->scheduledTDs)
PutTDonDeferredQueue(pEP, pTD);
else
{
PutTDonDoneQueue(pEP, pTD, true);
}
if(pEP->toDoList == NULL)
{
IOSimpleLockUnlock(_isochScheduleLock);
USBLog(7, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - calling the ReturnIsocDoneQueue on a separate thread", this);
thread_call_enter1(_returnIsochDoneQueueThread, (thread_call_param_t) pEP);
return;
}
newCurrFrame = GetFrameNumber();
if (newCurrFrame > currFrame)
{
currFrame = newCurrFrame;
}
}
firstOutSlot = (currFrame+1) & kUHCI_NVFRAMES_MASK;
currFrame = pEP->toDoList->_frameNumber;
pEP->inSlot = currFrame & kUHCI_NVFRAMES_MASK;
do
{
nextSlot = (pEP->inSlot + 1) & kUHCI_NVFRAMES_MASK;
if (pEP->inSlot == _outSlot)
{
break;
}
if( nextSlot == _outSlot) {
break;
}
pTD = GetTDfromToDoList(pEP);
if(currFrame == pTD->_frameNumber)
{
if(_outSlot > kUHCI_NVFRAMES)
{
_outSlot = firstOutSlot;
}
USBLog(7, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - linking TD (%p) with frame (0x%Ld) into slot (0x%x) - curr next log (%p) phys (%p)", this, pTD, pTD->_frameNumber, pEP->inSlot, _logicalFrameList[pEP->inSlot], (void*)USBToHostLong(_frameList[pEP->inSlot]));
pTD->print(7);
pTD->SetPhysicalLink(USBToHostLong(_frameList[pEP->inSlot]));
pTD->_logicalNext = _logicalFrameList[pEP->inSlot];
_logicalFrameList[pEP->inSlot] = pTD;
_frameList[pEP->inSlot] = HostToUSBLong(pTD->GetPhysicalAddrWithType());
pEP->scheduledTDs++;
}
else
{
USBError(1, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - expected frame (%qd) and see frame (%qd) - should do something here!!", this, currFrame, pTD->_frameNumber);
}
currFrame++;
pEP->inSlot = nextSlot;
} while(pEP->toDoList != NULL);
finFrame = GetFrameNumber();
IOSimpleLockUnlock(_isochScheduleLock);
if ((finFrame - startFrame) > 1)
USBError(1, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - end - startFrame(0x%Ld) finFrame(0x%Ld)", this, startFrame, finFrame);
USBLog(7, "AppleUSBUHCI[%p]::AddIsochFramesToSchedule - finished, currFrame: %Ld", this, GetFrameNumber() );
}
IOReturn
AppleUSBUHCI::AbortIsochEP(IOUSBControllerIsochEndpoint* pEP)
{
UInt32 slot;
IOReturn err;
IOUSBControllerIsochListElement *pTD;
AbsoluteTime timeStamp;
if (pEP->deferredQueue || pEP->toDoList || pEP->doneQueue || pEP->activeTDs || pEP->onToDoList || pEP->scheduledTDs || pEP->deferredTDs || pEP->onReversedList || pEP->onDoneQueue)
USBLog(6, "+AppleUSBUHCI[%p]::AbortIsochEP[%p] - start - _outSlot (0x%x) pEP->inSlot (0x%x) activeTDs (%ld) onToDoList (%ld) todo (%p) deferredTDs (%ld) deferred(%p) scheduledTDs (%ld) onProducerQ (%ld) consumer (%ld) producer (%ld) onReversedList (%ld) onDoneQueue (%ld) doneQueue (%p)", this, pEP, _outSlot, pEP->inSlot, pEP->activeTDs, pEP->onToDoList, pEP->toDoList, pEP->deferredTDs, pEP->deferredQueue, pEP->scheduledTDs, pEP->onProducerQ, _consumerCount, _producerCount, pEP->onReversedList, pEP->onDoneQueue, pEP->doneQueue);
USBLog(7, "+AppleUSBUHCI[%p]::AbortIsochEP (%p)", this, pEP);
_inAbortIsochEP = true;
pEP->aborting = true;
clock_get_uptime(&timeStamp);
while (_filterInterruptActive)
;
err = scavengeIsochTransactions();
if (err)
{
USBLog(1, "AppleUSBUHCI[%p]::AbortIsochEP - err (0x%x) from scavengeIsochTransactions", this, err);
}
if (pEP->deferredQueue || pEP->toDoList || pEP->doneQueue || pEP->activeTDs || pEP->onToDoList || pEP->scheduledTDs || pEP->deferredTDs || pEP->onReversedList || pEP->onDoneQueue)
USBLog(6, "+AppleUSBUHCI[%p]::AbortIsochEP[%p] - after scavenge - _outSlot (0x%x) pEP->inSlot (0x%x) activeTDs (%ld) onToDoList (%ld) todo (%p) deferredTDs (%ld) deferred(%p) scheduledTDs (%ld) onProducerQ (%ld) consumer (%ld) producer (%ld) onReversedList (%ld) onDoneQueue (%ld) doneQueue (%p)", this, pEP, _outSlot, pEP->inSlot, pEP->activeTDs, pEP->onToDoList, pEP->toDoList, pEP->deferredTDs, pEP->deferredQueue, pEP->scheduledTDs, pEP->onProducerQ, _consumerCount, _producerCount, pEP->onReversedList, pEP->onDoneQueue, pEP->doneQueue);
if ((_outSlot < kUHCI_NVFRAMES) && (pEP->inSlot < kUHCI_NVFRAMES))
{
bool stopAdvancing = false;
IOUSBControllerIsochListElement *activeTD = NULL;
slot = _outSlot;
while (slot != pEP->inSlot)
{
IOUSBControllerListElement *thing;
IOUSBControllerListElement *nextThing;
IOUSBControllerListElement *prevThing;
UInt32 nextSlot;
nextSlot = (slot+1) & kUHCI_NVFRAMES_MASK;
thing = _logicalFrameList[slot];
prevThing = NULL;
if (thing == NULL && (nextSlot != pEP->inSlot))
_outSlot = nextSlot;
while (thing != NULL)
{
nextThing = thing->_logicalNext;
pTD = OSDynamicCast(IOUSBControllerIsochListElement, thing);
if(pTD)
{
if (pTD->_pEndpoint == pEP)
{
UInt16 frSlot = (ReadFrameNumber() & kUHCI_NVFRAMES_MASK);
if (prevThing)
{
prevThing->_logicalNext = thing->_logicalNext;
prevThing->SetPhysicalLink(thing->GetPhysicalLink());
thing = prevThing; }
else
{
_logicalFrameList[slot] = nextThing;
_frameList[slot] = HostToUSBLong(thing->GetPhysicalLink());
thing = NULL; if (nextThing == NULL)
{
if (!stopAdvancing)
{
USBLog(5, "AppleUSBUHCI[%p]::AbortIsochEP(%p) - advancing _outslot from 0x%x to 0x%lx", this, pEP, _outSlot, nextSlot);
_outSlot = nextSlot;
}
else
{
USBLog(5, "AppleUSBUHCI[%p]::AbortIsochEP(%p) - would have advanced _outslot from 0x%x to 0x%lx", this, pEP, _outSlot, nextSlot);
}
}
}
if (frSlot == slot)
{
if (activeTD)
{
activeTD->UpdateFrameList(timeStamp);
}
activeTD = pTD;
}
else
{
err = pTD->UpdateFrameList(timeStamp);
}
pEP->scheduledTDs--;
PutTDonDoneQueue(pEP, pTD, true );
}
else if (pTD->_pEndpoint == NULL)
{
USBLog(1, "AppleUSBUHCI[%p]::AbortIsochEP (%p) - NULL endpoint in pTD %p", this, pEP, pTD);
}
else
{
stopAdvancing = true;
USBLog(7, "AppleUSBUHCI[%p]::AbortIsochEP (%p) - a different EP in play (%p) - stop advancing", this, pEP, pTD->_pEndpoint);
}
}
else
{
break;
}
prevThing = thing;
thing = nextThing;
}
slot = nextSlot;
}
if (activeTD)
{
IODelay(1000);
activeTD->UpdateFrameList(timeStamp);
}
}
pTD = GetTDfromToDoList(pEP);
while (pTD)
{
err = pTD->UpdateFrameList(timeStamp);
PutTDonDoneQueue(pEP, pTD, true);
pTD = GetTDfromToDoList(pEP);
}
if (!pEP->scheduledTDs)
{
pEP->firstAvailableFrame = 0;
pEP->inSlot = kUHCI_NVFRAMES + 1;
}
_inAbortIsochEP = false;
pEP->accumulatedStatus = kIOReturnAborted;
ReturnIsochDoneQueue(pEP);
pEP->accumulatedStatus = kIOReturnSuccess;
if (pEP->deferredQueue || pEP->toDoList || pEP->doneQueue || pEP->activeTDs || pEP->onToDoList || pEP->scheduledTDs || pEP->deferredTDs || pEP->onReversedList || pEP->onDoneQueue)
{
USBLog(1, "+AppleUSBUHCI[%p]::AbortIsochEP[%p] - done - _outSlot (0x%x) pEP->inSlot (0x%x) activeTDs (%ld) onToDoList (%ld) todo (%p) deferredTDs (%ld) deferred(%p) scheduledTDs (%ld) onProducerQ (%ld) consumer (%ld) producer (%ld) onReversedList (%ld) onDoneQueue (%ld) doneQueue (%p)", this, pEP, _outSlot, pEP->inSlot, pEP->activeTDs, pEP->onToDoList, pEP->toDoList, pEP->deferredTDs, pEP->deferredQueue, pEP->scheduledTDs, pEP->onProducerQ, _consumerCount, _producerCount, pEP->onReversedList, pEP->onDoneQueue, pEP->doneQueue);
}
else
{
USBLog(6, "-AppleUSBUHCI[%p]::AbortIsochEP[%p] - done - all clean - _outSlot (0x%x), pEP->inSlot (0x%x)", this, pEP, _outSlot, pEP->inSlot);
}
pEP->aborting = false;
USBLog(7, "-AppleUSBUHCI[%p]::AbortIsochEP (%p)", this, pEP);
return kIOReturnSuccess;
}