AppleUSBXHCI_Bandwidth.cpp [plain text]
#include "AppleUSBXHCI_Bandwidth.h"
#if (DEBUG_REGISTER_READS == 1)
#define Read32Reg(registerPtr, ...) Read32RegWithFileInfo(registerPtr, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define Read32RegWithFileInfo(registerPtr, function, file, line, ...) ( \
fTempReg = Read32Reg(registerPtr, ##__VA_ARGS__), \
fTempReg = (fTempReg == (typeof (*(registerPtr))) -1) ? \
(kprintf("AppleUSBXHCI[%p]::%s Invalid register at %s:%d %s\n", this,function,file, line,#registerPtr), -1) : fTempReg, \
(typeof(*(registerPtr)))fTempReg)
#define Read64Reg(registerPtr, ...) Read64RegWithFileInfo(registerPtr, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__)
#define Read64RegWithFileInfo(registerPtr, function, file, line, ...) ( \
fTempReg = Read64Reg(registerPtr, ##__VA_ARGS__), \
fTempReg = (fTempReg == (typeof (*(registerPtr))) -1) ? \
(kprintf("AppleUSBXHCI[%p]::%s Invalid register at %s:%d %s\n", this,function,file, line,#registerPtr), -1) : fTempReg, \
(typeof(*(registerPtr)))fTempReg)
#endif
#pragma mark ----------- TT Bandwidth Table ---------------------
OSDefineMetaClassAndStructors(TTBandwidthTable, OSObject);
TTBandwidthTable *
TTBandwidthTable::WithHubAndPort(UInt8 hubSlot, UInt8 hubPort, bool mtt)
{
TTBandwidthTable *me = OSTypeAlloc(TTBandwidthTable);
if (me)
{
int i;
me->init();
me->hubSlotID = hubSlot;
me->mtt = mtt;
if (mtt)
me->hubPortNum = hubPort;
for (i=0; i < kMaxIntervalTableSize; i++)
{
me->interval[i].worstCaseMPS = 0;
me->interval[i].totalPackets = 0;
me->interval[i].packetOverhead = 0;
}
}
return me;
}
void
TTBandwidthTable::AddToTable(UInt8 epSpeed, UInt8 epInterval, UInt16 mps)
{
UInt16 mpsInBlocks= 0;
bool forceLS = false;
UInt8 normalizedInterval = epInterval - 3;
USBLog(5, "TTBandwidthTable[%p]::AddToTable: epSpeed(%d) epInterval(%d) mps(%d)", this, epSpeed, epInterval, mps);
if ((epInterval < 3) || (epInterval >= kMaxFSIsochInterval))
{
USBLog(1, "TTBandwidthTable[%p]::AddToTable - invalid FS/LS interval of %d", this, epInterval);
return;
}
if (epSpeed == kUSBDeviceSpeedLow)
forceLS = true;
if (forceLS)
{
mps = mps * 8;
USBLog(5, "TTBandwidthTable[%p]::AddToTable - LS device new mps %d", this, mps);
}
mpsInBlocks = (mps + kFSBytesPerBlock-1) / kFSBytesPerBlock;
if (normalizedInterval == 0)
{
interval[0].worstCaseMPS += (mpsInBlocks + (forceLS ? kLSPacketOverheadInBlocks : kFSPacketOverheadInBlocks));
}
else
{
interval[normalizedInterval].totalPackets++;
if (mpsInBlocks > interval[normalizedInterval].worstCaseMPS)
interval[normalizedInterval].worstCaseMPS = mpsInBlocks;
if (forceLS)
interval[normalizedInterval].packetOverhead = kLSPacketOverheadInBlocks;
else if (interval[normalizedInterval].packetOverhead == 0)
interval[normalizedInterval].packetOverhead = kFSPacketOverheadInBlocks;
}
USBLog(5, "TTBandwidthTable[%p]::AddToTable: interval[%d].worstCaseMPS(%d)", this, normalizedInterval, interval[normalizedInterval].worstCaseMPS);
}
SInt16
TTBandwidthTable::BandwidthAvailable()
{
UInt16 bandwidthUsedinBlocks = interval[0].worstCaseMPS; UInt32 numPacketRemainder = 0; UInt32 maxPacketSizeRemainder = 0; UInt32 numPacketsThisInterval = 0;
UInt32 packetOverhead = 0;
UInt32 maxBandwidthInBlocks;
USBLog(6, "TTBandwidthTable[%p]::BandwidthAvailable - start with bandwidth used: %d", this, bandwidthUsedinBlocks);
for (int i=1; i < kMaxIntervalTableSize; i++)
{
USBLog(6, "TTBandwidthTable[%p]::BandwidthAvailable - interval:%d pkts:%d mps:%d overhead:%d numPktRmndr:%d mpsRmndr:%d ", this, i, (int)interval[i].totalPackets, (int)interval[i].worstCaseMPS, (int)interval[i].packetOverhead, (int)numPacketRemainder, (int)maxPacketSizeRemainder);
numPacketRemainder = 2 * numPacketRemainder + interval[i].totalPackets;
if (interval[i].worstCaseMPS > maxPacketSizeRemainder)
maxPacketSizeRemainder = interval[i].worstCaseMPS;
numPacketsThisInterval = numPacketRemainder >> i;
if (interval[i].packetOverhead > packetOverhead)
{
packetOverhead = interval[i].packetOverhead;
}
USBLog(6, "TTBandwidthTable[%p]::BandwidthAvailable - bandwidthUsed[%d] adding %d packets at %d blocks", this, (int)bandwidthUsedinBlocks, (int)numPacketsThisInterval, (int)(packetOverhead + maxPacketSizeRemainder));
bandwidthUsedinBlocks += numPacketsThisInterval * (maxPacketSizeRemainder + packetOverhead);
numPacketRemainder = numPacketRemainder % (1 << i);
if (numPacketRemainder == 0)
{
maxPacketSizeRemainder = 0;
packetOverhead = 0;
}
else if (numPacketsThisInterval > 0)
{
maxPacketSizeRemainder = interval[i].worstCaseMPS;
}
}
if (numPacketRemainder)
{
USBLog(6, "TTBandwidthTable[%p]::BandwidthAvailable - finished with pkts:%d mps:%d overhead:%d", this, (int)numPacketRemainder, (int)maxPacketSizeRemainder, (int)packetOverhead);
bandwidthUsedinBlocks += (packetOverhead + maxPacketSizeRemainder);
}
USBLog(4, "TTBandwidthTable[%p]::BandwidthAvailable - returning bandwidth available of %d (out of %d)", this, kLSFSBandwidthLimitInBlocks-bandwidthUsedinBlocks, kLSFSBandwidthLimitInBlocks);
return kLSFSBandwidthLimitInBlocks-bandwidthUsedinBlocks;
}
TTBandwidthTable *
GetTTBandwidthTable(OSArray *ttArray, UInt32 hubSlot, UInt32 hubPort, bool multiTT)
{
TTBandwidthTable * ret = NULL;
int numTables = ttArray->getCount();
int i;
USBLog(5, "GetTTBandwidthTable - slot(%d) port (%d) multiTT(%d)", (int)hubSlot, (int)hubPort, (int)multiTT);
for (i=0; i < numTables; i++)
{
ret = (TTBandwidthTable*)ttArray->getObject(i);
if (multiTT)
{
if ( (ret->hubSlotID == hubSlot) && (ret->hubPortNum == hubPort))
{
break;
}
}
else
{
if (ret->hubSlotID == hubSlot)
{
break;
}
else
{
USBLog(6, "GetTTBandwidthTable - table %p slot %d != hubSlot %d", ret, (int)ret->hubSlotID, (int)hubSlot);
ret = NULL;
}
}
}
if (!ret)
{
ret = TTBandwidthTable::WithHubAndPort(hubSlot, hubPort, multiTT);
if (ret)
{
USBLog(5, "GetTTBandwidthTable - new table %p", ret);
ttArray->setObject(ret);
ret->release(); }
}
return ret;
}
#pragma mark ----------- Root Hub Port Table ---------------------
OSDefineMetaClassAndStructors(RootHubPortTable, OSObject);
RootHubPortTable *
RootHubPortTable::WithRHPortAndSpeed(UInt8 rhPort, UInt8 rhPortSpeed)
{
RootHubPortTable *me = OSTypeAlloc(RootHubPortTable);
if (me)
{
int i;
me->init();
USBLog(5, "RootHubPortTable[%p]::WithRHPortAndSpeed - rhPort(%d) rhSpeed(%d)", me, rhPort, rhPortSpeed);
me->rhPort = rhPort;
me->rhPortSpeed = rhPortSpeed;
for (i=0; i < kMaxIntervalTableSize; i++)
{
me->interval[i].worstCaseMPS = 0;
me->interval[i].totalPackets = 0;
me->interval[i].packetOverhead = 0;
}
}
return me;
}
void
RootHubPortTable::AddToTable(UInt8 epInterval, UInt16 mps, UInt8 maxBurst, UInt8 mult, UInt8 epSpeed, UInt8 hubSlot, UInt8 hubPort, bool mtt)
{
UInt16 mpsInBlocks = mps;
UInt16 packetoverhead;
interval[epInterval].totalPackets += (maxBurst +1);
if ((rhPortSpeed == kUSBDeviceSpeedLow) || ((rhPortSpeed == kUSBDeviceSpeedFull) && (epSpeed == kUSBDeviceSpeedLow)))
{
mpsInBlocks *= 8; mpsInBlocks += (kFSBytesPerBlock-1); mpsInBlocks /= kFSBytesPerBlock;
packetoverhead = kLSPacketOverheadInBlocks;
}
else if (rhPortSpeed == kUSBDeviceSpeedFull)
{
mpsInBlocks += (kFSBytesPerBlock-1); mpsInBlocks /= kFSBytesPerBlock;
packetoverhead = kFSPacketOverheadInBlocks;
}
else if (rhPortSpeed == kUSBDeviceSpeedHigh)
{
mps *= (mult+1); mpsInBlocks += (kHSBytesPerBlock-1); mpsInBlocks /= kHSBytesPerBlock; packetoverhead = kHSPacketOverheadInBlocks;
}
else
{
mps *= (maxBurst * 1); mps *= (mult + 1); mpsInBlocks += (kSSBytesPerBlock-1); mpsInBlocks /= kSSBytesPerBlock; packetoverhead = kSSBurstOverheadInBlocks;
}
USBLog(6, "RootHubPortTable[%p]::AddToTable - adjusted numbers: interval:%d mpsInBlocks:%d overhead:%d",this, epInterval, mpsInBlocks, packetoverhead);
if (epInterval == 0)
{
interval[0].worstCaseMPS += ((maxBurst+1) * (mpsInBlocks + packetoverhead));
}
else
{
if (mpsInBlocks > interval[epInterval].worstCaseMPS)
interval[epInterval].worstCaseMPS = mpsInBlocks;
if (packetoverhead > interval[epInterval].packetOverhead)
interval[epInterval].packetOverhead = packetoverhead;
}
if (hubSlot)
{
if (!ttArray)
{
ttArray = OSArray::withCapacity(10);
}
if (ttArray)
{
TTBandwidthTable* tt = GetTTBandwidthTable(ttArray, hubSlot, hubPort, mtt);
if (tt)
{
tt->AddToTable(epSpeed, epInterval, mps);
}
}
}
}
void
RootHubPortTable::PrintTableInfo()
{
USBLog(6, "RootHubPortTable[%p]::PrintTableInfo - checking rhPort(%d) speed (%d) downstream tts (%d)", this, rhPort, rhPortSpeed, ttArray ? ttArray->getCount() : 0);
for (int j=0; j < kMaxIntervalTableSize; j++)
{
if (interval[j].totalPackets)
{
USBLog(6, "RootHubPortTable[%p]::PrintTableInfo - rhPort[%d] interval:%d packets:%d MPS:%d overhead:%d", this, rhPort, j, interval[j].totalPackets, interval[j].worstCaseMPS, interval[j].packetOverhead);
}
}
if (ttArray)
{
int numTTTables = ttArray->getCount();
for (int i = 0; i < numTTTables; i++)
{
TTBandwidthTable *ttTable = (TTBandwidthTable*)ttArray->getObject(i);
for (int j=0; j < kMaxIntervalTableSize; j++)
{
if (ttTable->interval[j].totalPackets || ttTable->interval[j].worstCaseMPS)
{
USBLog(6, "RootHubPortTable[%p]::PrintTableInfo - ttTable[%p] interval[%d] packets[%d] MPS[%d] overhead[%d]", this, ttTable, j, ttTable->interval[j].totalPackets, ttTable->interval[j].worstCaseMPS, ttTable->interval[i].packetOverhead);
}
}
}
}
}
SInt16
RootHubPortTable::BandwidthAvailable(void)
{
UInt16 bandwidthUsedinBlocks = interval[0].worstCaseMPS;
UInt32 numPacketRemainder = 0; UInt32 maxPacketSizeRemainder = 0; UInt32 numPacketsThisInterval = 0;
UInt32 packetOverhead = 0;
UInt32 maxBandwidthInBlocks = 0;
SInt16 bandwidthAvailable = 0;
switch (rhPortSpeed)
{
case kUSBDeviceSpeedLow:
maxBandwidthInBlocks = kLSFSBandwidthLimitInBlocks;
break;
case kUSBDeviceSpeedFull:
maxBandwidthInBlocks = kLSFSBandwidthLimitInBlocks;
break;
case kUSBDeviceSpeedHigh:
maxBandwidthInBlocks = kHSBandwidthLimitInBlocks;
break;
case kUSBDeviceSpeedSuper:
maxBandwidthInBlocks = kSSBandwidthLimitInBlocks;
break;
default:
break;
}
USBLog(6, "RootHubPortTable[%p]::BandwidthAvailable - checking rhPort(%d) speed (%d) downstream tts (%d) BW0[%d]", this, rhPort, rhPortSpeed, ttArray ? ttArray->getCount() : 0, interval[0].worstCaseMPS);
if (ttArray)
{
int numTTS = ttArray->getCount();
for (int i=0; i < numTTS; i++)
{
TTBandwidthTable *tt = (TTBandwidthTable*)ttArray->getObject(i);
bandwidthAvailable = tt->BandwidthAvailable();
if (bandwidthAvailable < 0)
{
USBLog(1, "RootHubPortTable[%p]::BandwidthAvailable: TT did not have enough secondary bandwidth: %d", this, bandwidthAvailable);
break;
}
}
}
if (bandwidthAvailable >= 0)
{
USBLog(6, "RootHubPortTable[%p]::BandwidthAvailable - start interval:0 bandwidth used:%d", this, bandwidthUsedinBlocks);
for (int i=1; i < kMaxIntervalTableSize; i++)
{
USBLog(6, "RootHubPortTable[%p]::BandwidthAvailable - interval:%d pkts:%d mps:%d overhead:%d numPktRmndr:%d mpsRmndr:%d ", this, i, (int)interval[i].totalPackets, (int)interval[i].worstCaseMPS, (int)interval[i].packetOverhead, (int)numPacketRemainder, (int)maxPacketSizeRemainder);
numPacketRemainder = 2 * numPacketRemainder + interval[i].totalPackets;
if (interval[i].worstCaseMPS > maxPacketSizeRemainder)
maxPacketSizeRemainder = interval[i].worstCaseMPS;
if (interval[i].packetOverhead > packetOverhead)
packetOverhead = interval[i].packetOverhead;
numPacketsThisInterval = numPacketRemainder >> i;
if (numPacketsThisInterval)
{
USBLog(6, "RootHubPortTable[%p]::BandwidthAvailable - bandwidthUsed[%d] adding %d packets at %d blocks", this, (int)bandwidthUsedinBlocks, (int)numPacketsThisInterval, (int)(packetOverhead + maxPacketSizeRemainder));
}
bandwidthUsedinBlocks += numPacketsThisInterval * (packetOverhead + maxPacketSizeRemainder);
numPacketRemainder = numPacketRemainder % (1 << i);
if (numPacketRemainder == 0)
{
maxPacketSizeRemainder = 0;
packetOverhead = 0; }
else if (numPacketsThisInterval > 0)
{
maxPacketSizeRemainder = interval[i].worstCaseMPS;
}
}
if (numPacketRemainder)
{
USBLog(6, "RootHubPortTable[%p]::BandwidthAvailable - finished with pkts:%d mps:%d overhead:%d", this, (int)numPacketRemainder, (int)maxPacketSizeRemainder, (int)packetOverhead);
bandwidthUsedinBlocks += (packetOverhead + maxPacketSizeRemainder);
}
bandwidthAvailable = maxBandwidthInBlocks - bandwidthUsedinBlocks;
}
USBLog(4, "RootHubPortTable[%p]::BandwidthAvailable - returning bandwidth available of %d (out of %d)", this, bandwidthAvailable, (int)maxBandwidthInBlocks);
return bandwidthAvailable;
}
void
RootHubPortTable::free()
{
if (ttArray)
ttArray->release();
OSObject::free();
}
RootHubPortTable *
GetRootHubPortTable(OSArray *rhPortArray, UInt8 rhPort)
{
RootHubPortTable * ret = NULL;
int numTables = rhPortArray->getCount();
int i;
USBLog(6, "GetRootHubPortTable - numTables %d rhPort %d", numTables, rhPort);
for (i=0; i < numTables; i++)
{
ret = (RootHubPortTable*)rhPortArray->getObject(i);
if (ret && ret->rhPort == rhPort)
{
break;
}
}
if (ret && ret->rhPort != rhPort)
{
USBLog(1, "GetRootHubPortTable - could not find table for port %d", rhPort);
ret = NULL;
}
return ret;
}
IOReturn
AppleUSBXHCI::BuildRHPortBandwidthArray(OSArray *rhPortArray)
{
for(int slot = 0; slot < _numDeviceSlots; slot++)
{
if(_slots[slot].buffer != NULL)
{
Context * slotContext = GetSlotContext(slot);
UInt8 slotSpeed = GetSlCtxSpeed(slotContext);
UInt8 rhPort = GetSlCtxRootHubPort(slotContext);
UInt32 slotRouteString = GetSlCtxRouteString(slotContext);
if (slotRouteString == 0)
{
RootHubPortTable * rhTable = RootHubPortTable::WithRHPortAndSpeed(rhPort, slotSpeed);
if (rhTable)
{
rhPortArray->setObject(rhTable);
rhTable->release(); }
}
}
}
for(int slot = 0; slot < _numDeviceSlots; slot++)
{
if(_slots[slot].buffer != NULL)
{
Context * slotContext = GetSlotContext(slot);
UInt8 slotSpeed = GetSlCtxSpeed(slotContext);
UInt8 slotTTHubSlot = GetSlCtxTTSlot(slotContext);
UInt8 slotTTHubPort = GetSlCtxTTPort(slotContext);
bool slotOnMTTHub = GetSlCtxMTT(slotContext);
UInt8 rhPort = GetSlCtxRootHubPort(slotContext);
RootHubPortTable * rhTable = GetRootHubPortTable(rhPortArray, rhPort);
if (!rhTable)
{
USBLog(1, "AppleUSBXHCI[%p]::BuildRHPortBandwidthArray - could not find a rh table for rhPort %d", this, rhPort);
continue;
}
UInt8 numEpContexts = GetSlCtxEntries(slotContext);
if (numEpContexts)
{
USBLog(6, "AppleUSBXHCI[%p]::BuildRHPortBandwidthArray - slot %d has %d endpoints", this, slot, numEpContexts);
for (int endp = 2; endp <= numEpContexts; endp++)
{
Context *epContext = GetEndpointContext(slot, endp);
if (GetEpCtxEpState(epContext) != kXHCIEpCtx_State_Disabled)
{
UInt8 thisEpType = GetEpCtxEpType(epContext);
UInt8 thisEpInterval = GetEPCtxInterval(epContext);
UInt16 thisEpMPS = GetEpCtxMPS(epContext);
UInt8 thisEPMaxBurst = GetEPCtxMaxBurst(epContext);
UInt8 thisEPMult = GetEPCtxMult(epContext);
if ((thisEpType == kXHCIEpCtx_EPType_BulkIN) || (thisEpType == kXHCIEpCtx_EPType_BulkOut) || (thisEpType == kXHCIEpCtx_EPType_Control))
{
USBLog(7, "AppleUSBXHCI[%p]::BuildRHPortBandwidthArray - don't need to look at Control/Bulk EPs", this);
continue;
}
rhTable->AddToTable(thisEpInterval, thisEpMPS, thisEPMaxBurst, thisEPMult, slotSpeed, slotTTHubSlot, slotTTHubPort, slotOnMTTHub);
}
}
}
}
} return kIOReturnSuccess;
}
#pragma mark ----------- Main Method ---------------------
IOReturn
AppleUSBXHCI::CheckPeriodicBandwidth(int slotID, int endpointIdx, UInt16 maxPacketSize, short interval, int epType, UInt8 maxStream, UInt8 maxBurst, UInt8 mult)
{
IOReturn err = kIOReturnSuccess;
Context * newEpSlotContext;
UInt32 newEpRootHubPort;
UInt8 newEpSpeed;
UInt8 newEpTTHubSlot;
UInt8 newEpTTHubPort;
bool newEpOnMTTHub;
UInt16 bandwidthUsed[_v3ExpansionData->_rootHubNumPortsHS + _v3ExpansionData->_rootHubNumPortsSS];
OSArray * rhPortArray = OSArray::withCapacity(10);
RootHubPortTable * rhTableForNewEP = NULL;
SInt16 bandwidthAvailable;
USBLog(5, "AppleUSBXHCI[%p]::CheckPeriodicBandwidth - Sl:%d, ep:%d, mps:%d, poll:%d, typ:%d, maxStream:%d, maxBurst:%d, mult: %d", this, slotID, endpointIdx, maxPacketSize, interval, epType, (int)maxStream, (int)maxBurst, (int)mult);
newEpSlotContext = GetSlotContext(slotID);
newEpRootHubPort = GetSlCtxRootHubPort(newEpSlotContext);
newEpTTHubSlot = GetSlCtxTTSlot(newEpSlotContext);
newEpTTHubPort = GetSlCtxTTPort(newEpSlotContext);
newEpOnMTTHub = GetSlCtxMTT(newEpSlotContext);
newEpSpeed = GetSlCtxSpeed(newEpSlotContext);
USBLog(5, "AppleUSBXHCI[%p]::CheckPeriodicBandwidth - new EP speed (%d) RH port(%d) TTHub(%d) TTPort(%d) MTT(%d)", this, newEpSpeed, (int)newEpRootHubPort, newEpTTHubSlot, newEpTTHubPort, newEpOnMTTHub);
err = BuildRHPortBandwidthArray(rhPortArray);
rhTableForNewEP = GetRootHubPortTable(rhPortArray, newEpRootHubPort);
USBLog(6, "AppleUSBXHCI[%p]::CheckPeriodicBandwidth - new endpoint rhTable %p", this, rhTableForNewEP);
if (rhTableForNewEP)
{
rhTableForNewEP->AddToTable(interval, maxPacketSize, maxBurst, mult, newEpSpeed, newEpTTHubSlot, newEpTTHubPort, newEpOnMTTHub);
bandwidthAvailable = rhTableForNewEP->BandwidthAvailable();
if (bandwidthAvailable < 0)
err = kIOReturnNoBandwidth;
}
int numRHPortTables = rhPortArray->getCount();
for (int i = 0; i < numRHPortTables; i++)
{
RootHubPortTable *rhTable = (RootHubPortTable*)rhPortArray->getObject(i);
rhTable->PrintTableInfo();
}
if (rhPortArray)
rhPortArray->release();
return err;
}
UInt32
AppleUSBXHCI::GetBandwidthAvailable( void )
{
return 0;
}
IOReturn
AppleUSBXHCI::GetBandwidthAvailableForDevice(IOUSBDevice *forDevice, UInt32 *pBandwidthAvailable)
{
IOReturn ret = kIOReturnSuccess;
OSArray * rhPortArray = OSArray::withCapacity(10);
RootHubPortTable * rhTableForPort = NULL;
SInt16 bandwidthAvailableInBlocks = 0; UInt32 bandwidthAvailable = 0;
UInt8 rhPortSpeed = 0;
int slotID = GetSlotID(forDevice->GetAddress());
Context * slotContext;
UInt32 rootHubPort = 0;
UInt8 deviceSpeed = 0;
UInt8 controllingPortSpeed;
if (rhPortArray && slotID)
{
slotContext = GetSlotContext(slotID);
rootHubPort = GetSlCtxRootHubPort(slotContext);
deviceSpeed = GetSlCtxSpeed(slotContext);
ret = BuildRHPortBandwidthArray(rhPortArray);
rhTableForPort = GetRootHubPortTable(rhPortArray, rootHubPort);
if (rhTableForPort)
{
rhPortSpeed = rhTableForPort->rhPortSpeed;
controllingPortSpeed = rhPortSpeed;
bandwidthAvailableInBlocks = rhTableForPort->BandwidthAvailable();
if ((rhPortSpeed == kUSBDeviceSpeedHigh) && (deviceSpeed != kUSBDeviceSpeedHigh))
{
if (rhTableForPort->ttArray)
{
UInt8 slotTTHubSlot = GetSlCtxTTSlot(slotContext);
UInt8 slotTTHubPort = GetSlCtxTTPort(slotContext);
bool slotOnMTTHub = GetSlCtxMTT(slotContext);
TTBandwidthTable * ttTable = GetTTBandwidthTable(rhTableForPort->ttArray, slotTTHubSlot, slotTTHubPort, slotOnMTTHub);
if (ttTable)
{
USBLog(2, "AppleUSBXHCI::GetBandwidthAvailableForDevice - using ttTable for hubSlot(%d) hubPort(%d) onMTT(%d)", (int)slotTTHubSlot, (int)slotTTHubPort, (int)slotOnMTTHub);
bandwidthAvailableInBlocks = ttTable->BandwidthAvailable();
controllingPortSpeed = deviceSpeed; }
else
{
USBLog(2, "AppleUSBXHCI::GetBandwidthAvailableForDevice - no ttTable for hubSlot(%d) hubPort(%d) onMTT(%d)", (int)slotTTHubSlot, (int)slotTTHubPort, (int)slotOnMTTHub);
}
}
else
{
USBLog(2, "AppleUSBXHCI::GetBandwidthAvailableForDevice - no ttArray for rootHubPort (%d)", (int)rootHubPort);
}
}
if ((rhPortSpeed == kUSBDeviceSpeedFull) && (deviceSpeed != kUSBDeviceSpeedFull))
{
controllingPortSpeed = deviceSpeed;
}
}
}
if (bandwidthAvailableInBlocks > 0)
{
switch (controllingPortSpeed)
{
case kUSBDeviceSpeedLow:
bandwidthAvailable = (bandwidthAvailableInBlocks * kFSBytesPerBlock) / 8;
break;
case kUSBDeviceSpeedFull:
bandwidthAvailable = bandwidthAvailableInBlocks * kFSBytesPerBlock;
break;
case kUSBDeviceSpeedHigh:
bandwidthAvailable = bandwidthAvailableInBlocks * kHSBytesPerBlock;
break;
case kUSBDeviceSpeedSuper:
bandwidthAvailable = bandwidthAvailableInBlocks * kSSBytesPerBlock;
break;
default:
bandwidthAvailable = 0;
}
}
else
{
bandwidthAvailable = 0;
}
USBLog(2, "AppleUSBXHCI::GetBandwidthAvailableForRootHubPort - port(%d) portSpeed (%d) deviceSpeed(%d) - bandwidthAvailableInBlocks (%d) - returning (%d)", (int)rootHubPort, rhPortSpeed, deviceSpeed, bandwidthAvailableInBlocks, (int)bandwidthAvailable);
if (rhPortArray)
rhPortArray->release();
if (ret == kIOReturnSuccess)
*pBandwidthAvailable = bandwidthAvailable;
return ret;
}