AppleUSBEHCIHubInfo.cpp [plain text]
#include <IOKit/IOTypes.h>
#include <IOKit/usb/IOUSBLog.h>
#include "AppleUSBEHCI.h"
#include "AppleUSBEHCIHubInfo.h"
#include "AppleEHCIListElement.h"
#include "USBTracepoints.h"
extern KernelDebugLevel gKernelDebugLevel;
#if EHCI_USE_KPRINTF
#undef USBLog
#undef USBError
void kprintf(const char *format, ...) __attribute__((format(printf, 1, 2)));
#define USBLog( LEVEL, FORMAT, ARGS... ) if ((LEVEL) <= EHCI_USE_KPRINTF) { kprintf( FORMAT "\n", ## ARGS ) ; }
#define USBError( LEVEL, FORMAT, ARGS... ) { kprintf( FORMAT "\n", ## ARGS ) ; }
#endif
OSDefineMetaClassAndStructors(AppleUSBEHCIHubInfo, OSObject)
AppleUSBEHCIHubInfo*
AppleUSBEHCIHubInfo::AddHubInfo (AppleUSBEHCIHubInfo **hubListPtr, USBDeviceAddress hubAddr, UInt32 flags)
{
AppleUSBEHCIHubInfo *hiList = *hubListPtr;
AppleUSBEHCIHubInfo *hiPtr = new AppleUSBEHCIHubInfo;
USBLog(5, "AppleUSBEHCIHubInfo::NewHubInfo - new hiPtr[%p] for hubAddr[%d]", hiPtr, hubAddr);
if (hiPtr)
{
if (flags & kUSBEHCIFlagsMuliTT)
hiPtr->multiTT = true;
else
hiPtr->multiTT = false;
hiPtr->hubAddr = hubAddr;
hiPtr->next = hiList;
hiPtr->ttList = NULL;
hiList = hiPtr;
*hubListPtr = hiList;
}
return hiPtr;
}
AppleUSBEHCIHubInfo*
AppleUSBEHCIHubInfo::FindHubInfo(AppleUSBEHCIHubInfo *hiPtr, USBDeviceAddress hubAddr)
{
while (hiPtr)
{
if (hiPtr->hubAddr == hubAddr)
break;
hiPtr = hiPtr->next;
}
USBLog(6, "AppleUSBEHCIHubInfo::FindHubInfo for hubAddr[%d], returning hiPtr[%p]", hubAddr, hiPtr);
return hiPtr;
}
IOReturn
AppleUSBEHCIHubInfo::DeleteHubInfo(AppleUSBEHCIHubInfo **hubListPtr, USBDeviceAddress hubAddress)
{
AppleUSBEHCIHubInfo *hiList = *hubListPtr;
AppleUSBEHCIHubInfo *hiPtr, *tempPtr;
AppleUSBEHCITTInfo *ttiPtr, *tempTTPtr;
if (!hiList)
return kIOReturnInternalError;
if (hiList->hubAddr == hubAddress)
{
ttiPtr = hiList->ttList;
while (ttiPtr)
{
tempTTPtr = ttiPtr->next;
USBLog(5, "AppleUSBEHCIHubInfo::DeleteHubInfo - hiList[%p] releasing ttiPtr[%p]", hiList, ttiPtr);
ttiPtr->release();
ttiPtr = tempTTPtr;
}
hiPtr = hiList;
hiList = hiList->next;
USBLog(5, "AppleUSBEHCIHubInfo::DeleteHubInfo- hiList[%p] releasing hiPtr[%p] from head of list", hiList, hiPtr);
hiPtr->release();
}
else
{
hiPtr = hiList;
while (hiPtr && (hiPtr->next))
{
if (hiPtr->next->hubAddr == hubAddress)
{
tempPtr = hiPtr->next;
hiPtr->next = tempPtr->next;
ttiPtr = tempPtr->ttList;
while (ttiPtr)
{
tempTTPtr = ttiPtr->next;
USBLog(5, "AppleUSBEHCIHubInfo::DeleteHubInfo - hiPtr[%p] releasing ttiPtr[%p]", tempPtr, ttiPtr);
ttiPtr->release();
ttiPtr = tempTTPtr;
}
USBLog(5, "AppleUSBEHCIHubInfo::DeleteHubInfo- hiPtr[%p] releasing hiPtr[%p] from middle of list", tempPtr, tempPtr);
tempPtr->release();
}
else
hiPtr = hiPtr->next;
}
}
*hubListPtr = hiList; return kIOReturnSuccess;
}
AppleUSBEHCITTInfo *
AppleUSBEHCIHubInfo::GetTTInfo(int portAddress)
{
AppleUSBEHCITTInfo *ttiPtr = ttList;
if (multiTT)
{
while (ttiPtr && (ttiPtr->hubPort != portAddress))
ttiPtr = ttiPtr->next;
}
if (!ttiPtr)
{
ttiPtr = AppleUSBEHCITTInfo::NewTTInfo(multiTT ? portAddress : 0);
if (ttiPtr)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCIHubInfo[%p]::GetTTInfo - Adding ttiPtr[%p] to ttList", this, ttiPtr);
ttiPtr->next = ttList;
ttList = ttiPtr;
}
}
return ttiPtr;
}
#pragma mark AppleUSBEHCITTInfo
OSDefineMetaClassAndStructors(AppleUSBEHCITTInfo, OSObject)
static SInt32
CompareSPEs(const AppleUSBEHCISplitPeriodicEndpoint *pSPE1, const AppleUSBEHCISplitPeriodicEndpoint *pSPE2, const AppleUSBEHCITTInfo *forTT)
{
USBLog(6, "AppleUSBEHCITTInfo[%p]::CompareSPEs - pSPE1[%p] pSPE2[%p]", forTT, pSPE1, pSPE2);
if (!pSPE1 || !pSPE2)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::CompareSPEs - one or more objects NULL - returning 0", forTT);
return 0;
}
((AppleUSBEHCISplitPeriodicEndpoint *)pSPE1)->print(EHCISPLITTRANSFERLOGGING);
((AppleUSBEHCISplitPeriodicEndpoint *)pSPE2)->print(EHCISPLITTRANSFERLOGGING);
if ((pSPE1->_epType == kUSBIsoc) && (pSPE2->_epType == kUSBInterrupt))
{
return 1;
}
if ((pSPE1->_epType == kUSBInterrupt) && (pSPE2->_epType == kUSBIsoc))
{
return -1;
}
if (pSPE2->_startTime > pSPE1->_startTime)
{
return 1;
}
if (pSPE1->_startTime > pSPE2->_startTime)
{
return -1;
}
USBLog(6, "AppleUSBEHCITTInfo[%p]::CompareSPEs - EQUAL", forTT);
return 0;
}
AppleUSBEHCITTInfo *
AppleUSBEHCITTInfo::NewTTInfo(int portAddress)
{
AppleUSBEHCITTInfo *ttiPtr = new AppleUSBEHCITTInfo;
AppleUSBEHCISplitPeriodicEndpoint *pSPE;
IOReturn err = kIOReturnSuccess;
int i;
if (ttiPtr)
{
ttiPtr->next = NULL;
ttiPtr->hubPort = portAddress;
ttiPtr->_thinkTime = kEHCISplitTTThinkTime;
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
ttiPtr->_interruptQueue[i] = ttiPtr->_isochQueue[i] = NULL;
}
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
pSPE = AppleUSBEHCISplitPeriodicEndpoint::NewSplitPeriodicEndpoint(ttiPtr, kUSBInterrupt, NULL, kEHCIFSSOFBytesUsed + kEHCIFSHubAdjustBytes, kEHCIMaxPollingInterval);
if (!pSPE)
{
USBLog(1, "AppleUSBEHCITTInfo::NewTTInfo - unable to get interrupt SPE for index(%d)", i);
err = kIOReturnInternalError;
break;
}
pSPE->SetStartFrameAndStartTime(i, 0);
ttiPtr->_interruptQueue[i] = pSPE;
pSPE = AppleUSBEHCISplitPeriodicEndpoint::NewSplitPeriodicEndpoint(ttiPtr, kUSBIsoc, NULL, kEHCIFSSOFBytesUsed + kEHCIFSHubAdjustBytes, kEHCIMaxPollingInterval);
if (!pSPE)
{
USBLog(1, "AppleUSBEHCITTInfo::NewTTInfo - unable to get isoch SPE for index(%d)", i);
err = kIOReturnInternalError;
break;
}
pSPE->SetStartFrameAndStartTime(i, 0);
ttiPtr->_isochQueue[i] = pSPE;
ttiPtr->_FStimeUsed[i] = kEHCIFSSOFBytesUsed + kEHCIFSHubAdjustBytes;
}
ttiPtr->_pSPEsToAdjust = OSOrderedSet::withCapacity(kAppleEHCITTInfoInitialOrderedSetSize, (OSOrderedSet::OSOrderFunction)CompareSPEs, ttiPtr);
}
if (err != kIOReturnSuccess)
{
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
pSPE = ttiPtr->_interruptQueue[i];
if (pSPE)
pSPE->release();
pSPE = ttiPtr->_isochQueue[i];
if (pSPE)
pSPE->release();
}
if (ttiPtr->_pSPEsToAdjust)
ttiPtr->_pSPEsToAdjust->release();
ttiPtr->release();
ttiPtr = NULL;
}
return ttiPtr;
}
IOReturn
AppleUSBEHCITTInfo::ReserveHSSplitINBytes(int frame, int uFrame, UInt16 bytesToReserve)
{
if (!bytesToReserve)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveHSSplitINBytes - 0 bytesToReserve - nothing to do", this);
return kIOReturnSuccess;
}
if (bytesToReserve > kEHCIFSBytesPeruFrame)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveHSSplitINBytes - ERROR: bytesToReserve(%d) too big", this, (int)bytesToReserve);
return kIOReturnBadArgument;
}
if ((frame < 0) || (frame > kEHCIMaxPollingInterval))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveHSSplitINBytes - ERROR: invalid frame(%d)", this, frame);
return kIOReturnBadArgument;
}
if ((uFrame < 0) || (uFrame > kEHCIuFramesPerFrame))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveHSSplitINBytes - ERROR: invalid uFrame(%d)", this, uFrame);
return kIOReturnBadArgument;
}
_HSSplitINBytesUsed[frame][uFrame] += bytesToReserve;
USBLog(7, "AppleUSBEHCITTInfo[%p]::ReserveHSSplitINBytes - frame[%d] uFrame[%d] reserved _HSSplitINBytesUsed(%d)", this, frame, uFrame, _HSSplitINBytesUsed[frame][uFrame]);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::ReleaseHSSplitINBytes(int frame, int uFrame, UInt16 bytesToRelease)
{
if (!bytesToRelease)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - 0 bytesToRelease - nothing to do", this);
return kIOReturnSuccess;
}
if (bytesToRelease > kEHCIFSBytesPeruFrame)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - ERROR: bytesToRelease(%d) too big", this, (int)bytesToRelease);
return kIOReturnBadArgument;
}
if ((frame < 0) || (frame > kEHCIMaxPollingInterval))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - ERROR: invalid frame(%d)", this, frame);
return kIOReturnBadArgument;
}
if ((uFrame < 0) || (uFrame > kEHCIuFramesPerFrame))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - ERROR: invalid uFrame(%d)", this, uFrame);
return kIOReturnBadArgument;
}
if (bytesToRelease > _HSSplitINBytesUsed[frame][uFrame])
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - frame(%d) uFrame(%d) - trying to release more bytes(%d) than reserved(%d)", this, frame, uFrame, bytesToRelease, _HSSplitINBytesUsed[frame][uFrame]);
_HSSplitINBytesUsed[frame][uFrame] = 0;
}
else
{
_HSSplitINBytesUsed[frame][uFrame] -= bytesToRelease;
}
USBLog(7, "AppleUSBEHCITTInfo[%p]::ReleaseHSSplitINBytes - frame[%d] uFrame[%d] reserved _HSSplitINBytesUsed(%d)", this, frame, uFrame, _HSSplitINBytesUsed[frame][uFrame]);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::ReserveFSBusBytes(int frame, UInt16 bytesToReserve)
{
if (!bytesToReserve)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveFSBusBytes - 0 bytesToReserve - nothing to do", this);
return kIOReturnSuccess;
}
if (bytesToReserve > kEHCIFSMaxFrameBytes)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveFSBusBytes - ERROR: bytesToReserve(%d) too big", this, (int)bytesToReserve);
return kIOReturnBadArgument;
}
if ((frame < 0) || (frame > kEHCIMaxPollingInterval))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReserveFSBusBytes - ERROR: invalid frame(%d)", this, frame);
return kIOReturnBadArgument;
}
_FStimeUsed[frame] += bytesToReserve;
if (_FStimeUsed[frame] > kEHCIFSMaxFrameBytes)
{
USBLog(5, "AppleUSBEHCITTInfo[%p]::ReserveFSBusBytes - frame[%d] reserved space(%d) over the limit - could be OK", this, frame, _FStimeUsed[frame]);
return kIOReturnNoBandwidth;
}
USBLog(7, "AppleUSBEHCITTInfo[%p]::ReserveFSBusBytes - frame[%d] reserved _FStimeUsed(%d)", this, frame, _FStimeUsed[frame]);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::ReleaseFSBusBytes(int frame, UInt16 bytesToRelease)
{
if (!bytesToRelease)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseFSBusBytes - 0 bytesToRelease - nothing to do", this);
return kIOReturnSuccess;
}
if (bytesToRelease > kEHCIFSMaxFrameBytes)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseFSBusBytes - ERROR: bytesToRelease(%d) too big", this, (int)bytesToRelease);
return kIOReturnBadArgument;
}
if ((frame < 0) || (frame > kEHCIMaxPollingInterval))
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseFSBusBytes - ERROR: invalid frame(%d)", this, frame);
return kIOReturnBadArgument;
}
if (bytesToRelease > _FStimeUsed[frame])
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::ReleaseFSBusBytes - frame(%d) - trying to release more bytes(%d) than reserved(%d)", this, frame, bytesToRelease, _FStimeUsed[frame]);
_FStimeUsed[frame] = 0;
}
else
{
_FStimeUsed[frame] -= bytesToRelease;
}
USBLog(7, "AppleUSBEHCITTInfo[%p]::ReleaseFSBusBytes - frame[%d] reserved _FStimeUsed(%d)", this, frame, _FStimeUsed[frame]);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::AllocatePeriodicBandwidth(AppleUSBEHCISplitPeriodicEndpoint *pSPE)
{
IOReturn err;
int frameIndex;
AppleUSBEHCISplitPeriodicEndpoint *curSPE;
AppleUSBEHCISplitPeriodicEndpoint *prevSPE;
AppleUSBEHCISplitPeriodicEndpoint *tempSPE;
USBLog(3, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth: pSPE[%p]", this, pSPE);
ShowPeriodicBandwidthUsed(EHCISPLITTRANSFERLOGGING, "+AllocatePeriodicBandwidth");
if (!pSPE)
return kIOReturnInternalError;
err = pSPE->FindStartFrameAndStartTime();
if (err)
{
USBLog(3, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth - pSPE->FindStartFrameAndStartTime returned err[%p]", this, (void*)err);
return err;
}
for (frameIndex=pSPE->_startFrame; frameIndex < kEHCIMaxPollingInterval; frameIndex += pSPE->_period)
{
if (pSPE->_epType == kUSBIsoc)
{
prevSPE = _isochQueue[frameIndex]; if (!prevSPE)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth - invalid isoch queue head at frame (%d)", this, (int)frameIndex);
return kIOReturnInternalError;
}
curSPE = prevSPE->_nextSPE;
tempSPE = curSPE;
while(curSPE)
{
if (pSPE->CheckPlacementBefore(curSPE) == kIOReturnSuccess)
break;
prevSPE = curSPE;
curSPE = curSPE->_nextSPE;
}
if (curSPE != pSPE)
{
if (pSPE->_FSBytesUsed > kEHCIFSLargeIsochPacket)
_largeIsoch[frameIndex] = pSPE;
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth - inserting pSPE(%p) into frame (%d) between (%p) and (%p)", this, pSPE, frameIndex, prevSPE, curSPE);
if (frameIndex == pSPE->_startFrame)
pSPE->_nextSPE = curSPE;
while (tempSPE)
{
if (tempSPE == pSPE)
break;
tempSPE = tempSPE->_nextSPE;
}
if (tempSPE != pSPE)
prevSPE->_nextSPE = pSPE;
}
}
}
else
{
prevSPE = _interruptQueue[frameIndex]; if (!prevSPE)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth - invalid interrupt queue head at frame (%d)", this, (int)frameIndex);
return kIOReturnInternalError;
}
curSPE = prevSPE->_nextSPE;
while(curSPE)
{
if (pSPE->CheckPlacementBefore(curSPE) == kIOReturnSuccess)
break;
prevSPE = curSPE;
curSPE = curSPE->_nextSPE;
}
if (curSPE != pSPE)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::AllocatePeriodicBandwidth - inserting pSPE(%p) into frame (%d) between (%p) and (%p)", this, pSPE, frameIndex, prevSPE, curSPE);
if (frameIndex == pSPE->_startFrame)
pSPE->_nextSPE = curSPE; prevSPE->_nextSPE = pSPE;
}
}
ReserveFSBusBytes(frameIndex, pSPE->_FSBytesUsed);
}
ShowPeriodicBandwidthUsed(EHCISPLITTRANSFERLOGGING, "-AllocatePeriodicBandwidth");
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::DeallocatePeriodicBandwidth(AppleUSBEHCISplitPeriodicEndpoint *pSPE)
{
IOReturn err;
int frameIndex;
AppleUSBEHCISplitPeriodicEndpoint *curSPE;
AppleUSBEHCISplitPeriodicEndpoint *prevSPE;
AppleUSBEHCISplitPeriodicEndpoint *tempSPE;
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::DeallocatePeriodicBandwidth: pSPE[%p]", this, pSPE);
if (!pSPE)
return kIOReturnInternalError;
for (frameIndex=pSPE->_startFrame; frameIndex < kEHCIMaxPollingInterval; frameIndex += pSPE->_period)
{
if (_largeIsoch[frameIndex] == pSPE)
{
USBLog(6, "AppleUSBEHCITTInfo[%p]::DeallocatePeriodicBandwidth - removing large Isoch xaction (%p) from frame (%d)", this, pSPE, (int)frameIndex);
_largeIsoch[frameIndex] = NULL;
}
else
{
if (pSPE->_epType == kUSBIsoc)
{
prevSPE = _isochQueue[frameIndex]; }
else
{
prevSPE = _interruptQueue[frameIndex]; }
if (!prevSPE)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::DeallocatePeriodicBandwidth - invalid isoch queue head at frame (%d)", this, (int)frameIndex);
return kIOReturnInternalError;
}
curSPE = prevSPE->_nextSPE;
tempSPE = curSPE;
while(curSPE && (curSPE != pSPE))
{
prevSPE = curSPE;
curSPE = curSPE->_nextSPE;
}
if (curSPE == pSPE)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::DeallocatePeriodicBandwidth - removing pSPE(%p) from frame (%d) between (%p) and (%p)", this, pSPE, frameIndex, prevSPE, curSPE->_nextSPE);
prevSPE->_nextSPE = curSPE->_nextSPE;
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::DeallocatePeriodicBandwidth - could not find pSPE(%p) in frame(%d) often this is fine", this, pSPE, frameIndex);
}
}
ReleaseFSBusBytes(frameIndex, pSPE->_FSBytesUsed);
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::CalculateSPEsToAdjustAfterChange(AppleUSBEHCISplitPeriodicEndpoint *pSPEChanged, bool added)
{
int index;
AppleUSBEHCISplitPeriodicEndpoint *pSPE;
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - pSPEChanged(%p) %s", this, pSPEChanged, added ? "ADDED" : "REMOVED");
if (_pSPEsToAdjust->getCount())
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - ordered set already exists. error", this);
return kIOReturnInternalError;
}
if (pSPEChanged->_FSBytesUsed >= kEHCIFSLargeIsochPacket)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - %s packet is a large one. everyone needs to move", this, added ? "new" : "old");
for (index = 0; index < kEHCIMaxPollingInterval; index++)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - looking at Isoch queue index(%d)[%p]", this, index, _isochQueue[index]);
pSPE = _isochQueue[index]->_nextSPE; while (pSPE)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) already in adjust set", this, index, pSPE);
}
pSPE = pSPE->_nextSPE;
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - looking at interrupt queue index(%d)[%p]", this, index, _interruptQueue[index]);
pSPE = _interruptQueue[index]->_nextSPE; while (pSPE)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) already in adjust set", this, index, pSPE);
}
pSPE = pSPE->_nextSPE;
}
}
}
else if (pSPEChanged->_epType == kUSBIsoc)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - %s packet is a ISOCH. some Isoch and all Int will move", this, added ? "new" : "old");
for (index = 0; index < kEHCIMaxPollingInterval; index++)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - looking at Isoch queue index(%d)[%p]", this, index, _isochQueue[index]);
pSPE = _isochQueue[index]->_nextSPE; if (!added)
{
while (pSPE)
{
if (pSPE != pSPEChanged)
{
if (pSPE->_startTime >= pSPEChanged->_startTime)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) not a candidate because of a lower start time", this, index, pSPE);
}
}
pSPE = pSPE->_nextSPE;
}
}
else
{
while (pSPE && (pSPEChanged->CheckPlacementBefore(pSPE) == kIOReturnSuccess))
{
pSPE = pSPE->_nextSPE;
}
while (pSPE)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
pSPE = pSPE->_nextSPE;
}
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - looking at interrupt queue index(%d)[%p]", this, index, _interruptQueue[index]);
pSPE = _interruptQueue[index]->_nextSPE; while (pSPE)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - looking at interrupt queue _nextSPE[%p]", this, pSPE->_nextSPE);
pSPE = pSPE->_nextSPE;
}
}
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - %s packet is INTERRUPT - some Int will move", this, added ? "new" : "old");
for (index = 0; index < kEHCIMaxPollingInterval; index++)
{
pSPE = _interruptQueue[index]->_nextSPE; if (!added)
{
while (pSPE)
{
if (pSPE != pSPEChanged)
{
if (pSPE->_startTime >= pSPEChanged->_startTime)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
}
else
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) not a candidate because of a lower start time", this, index, pSPE);
}
}
pSPE = pSPE->_nextSPE;
}
}
else
{
while (pSPE && (pSPEChanged->CheckPlacementBefore(pSPE) != kIOReturnSuccess))
{
pSPE = pSPE->_nextSPE;
}
while (pSPE)
{
if (pSPE != pSPEChanged)
{
if (!_pSPEsToAdjust->containsObject(pSPE))
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - index[%d] pSPE(%p) being added to adjustment set", this, index, pSPE);
_pSPEsToAdjust->setObject(pSPE);
}
}
pSPE = pSPE->_nextSPE;
}
}
}
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCITTInfo[%p]::CalculateSPEsToAdjustAfterChange - %d candidates to consider", this, _pSPEsToAdjust->getCount());
return kIOReturnSuccess;
}
void
AppleUSBEHCITTInfo::release() const
{
int i;
int oldCount = getRetainCount();
OSObject::release();
if ((oldCount-1) == (2 * kEHCIMaxPollingInterval))
{
USBLog(6, "AppleUSBEHCITTInfo[%p]::release - retainCount is now %d", this, getRetainCount());
if (_pSPEsToAdjust->getCount() > 0)
{
USBLog(1, "AppleUSBEHCITTInfo[%p]::release - _pSPEsToAdjust has a count of %d", this, _pSPEsToAdjust->getCount());
}
_pSPEsToAdjust->release();
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
if (_interruptQueue[i])
_interruptQueue[i]->release();
if (_isochQueue[i])
_isochQueue[i]->release();
}
}
}
#pragma mark Debugging methods
IOReturn
AppleUSBEHCITTInfo::ShowPeriodicBandwidthUsed(int level, const char *fromStr)
{
int frame;
USBLog(level, "AppleUSBEHCITTInfo[%p]::ShowPeriodicBandwidthUsed called from %s", this, fromStr);
for (frame = 0; frame < kEHCIMaxPollingInterval; frame++)
USBLog(level, "AppleUSBEHCITTInfo[%p]::ShowPeriodicBandwidthUsed - Frame %2.2d: [%3.3d]", this, frame, _FStimeUsed[frame]);
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCITTInfo::ShowHSSplitTimeUsed(int level, const char *fromStr)
{
int frame;
USBLog(level, "AppleUSBEHCITTInfo[%p]::ShowHSSplitTimeUsed called from %s", this, fromStr);
for (frame = 0; frame < kEHCIMaxPollingInterval; frame++)
USBLog(level, "AppleUSBEHCITTInfo[%p]::ShowHSSplitTimeUsed - Frame %2.2d: [%3.3d] [%3.3d] [%3.3d] [%3.3d] [%3.3d] [%3.3d] [%3.3d] [%3.3d]",
this, frame,
_HSSplitINBytesUsed[frame][0],
_HSSplitINBytesUsed[frame][1],
_HSSplitINBytesUsed[frame][2],
_HSSplitINBytesUsed[frame][3],
_HSSplitINBytesUsed[frame][4],
_HSSplitINBytesUsed[frame][5],
_HSSplitINBytesUsed[frame][6],
_HSSplitINBytesUsed[frame][7]);
return kIOReturnSuccess;
}
void
AppleUSBEHCITTInfo::print(int level, const char *fromStr)
{
int i;
USBLog(level, "AppleUSBEHCITTInfo[%p]::print called from %s", this, fromStr);
USBLog(level, "AppleUSBEHCITTInfo[%p]::print - next(%p)", this, next);
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
if (_largeIsoch[i])
{
USBLog(level, "AppleUSBEHCITTInfo[%p]::print - _largeIsoch[%d](%p)", this, i, _largeIsoch[i]);
_largeIsoch[i]->print(level);
}
}
USBLog(level, "---------------------------------------------------------");
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
AppleUSBEHCISplitPeriodicEndpoint *curSPE = _isochQueue[i];
if (curSPE && (curSPE->_nextSPE))
{
USBLog(level, "AppleUSBEHCITTInfo[%p]::print - _isochQueue[%d](%p)", this, i, curSPE);
while (curSPE)
{
curSPE->print(level);
curSPE=curSPE->_nextSPE;
}
}
}
USBLog(level, "---------------------------------------------------------");
for (i=0; i < kEHCIMaxPollingInterval; i++)
{
AppleUSBEHCISplitPeriodicEndpoint *curSPE = _interruptQueue[i];
if (curSPE && (curSPE->_nextSPE))
{
USBLog(level, "AppleUSBEHCITTInfo[%p]::print - _interruptQueue[%d](%p)", this, i, curSPE);
while (curSPE)
{
curSPE->print(level);
curSPE=curSPE->_nextSPE;
}
}
}
}
#pragma mark AppleUSBEHCISplitPeriodicEndpoint
OSDefineMetaClassAndStructors(AppleUSBEHCISplitPeriodicEndpoint, OSObject)
AppleUSBEHCISplitPeriodicEndpoint*
AppleUSBEHCISplitPeriodicEndpoint::NewSplitPeriodicEndpoint( AppleUSBEHCITTInfo *whichTT,
UInt16 epType, OSObject *pEP,
UInt16 FSBytesUsed, UInt8 period)
{
AppleUSBEHCISplitPeriodicEndpoint *pSPE = new AppleUSBEHCISplitPeriodicEndpoint;
if (pSPE)
{
USBLog(7, "AppleUSBEHCISplitPeriodicEndpoint[%p]::NewSplitPeriodicEndpoint - retaining TT (%p)", pSPE, whichTT);
whichTT->retain(); pSPE->_myTT = whichTT;
pSPE->_epType = epType;
pSPE->_FSBytesUsed = FSBytesUsed;
pSPE->_period = period;
if (epType == kUSBInterrupt)
{
pSPE->_intEP = OSDynamicCast(AppleEHCIQueueHead, pEP);
if (pSPE->_intEP)
pSPE->_direction = pSPE->_intEP->_direction;
pSPE->_isochEP = NULL;
}
else if (epType == kUSBIsoc)
{
pSPE->_isochEP = OSDynamicCast(AppleEHCIIsochEndpoint, pEP);
if (pSPE->_isochEP)
pSPE->_direction = pSPE->_isochEP->direction;
pSPE->_intEP = NULL;
}
else
{
USBLog(1, "AppleUSBEHCISplitPeriodicEndpoint::NewSplitPeriodicEndpoint - invalid epType(%d)", (int)epType);
whichTT->release();
pSPE->release();
return NULL;
}
pSPE->_nextSPE = NULL;
pSPE->_startFrame = 0;
pSPE->_startTime = 0;
pSPE->_numSS = 0;
pSPE->_numCS = 0;
pSPE->_SSflags = 0;
pSPE->_CSflags = 0;
pSPE->_wraparound = false;
}
return pSPE;
}
void
AppleUSBEHCISplitPeriodicEndpoint::release() const
{
if (getRetainCount() == 1)
{
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::release - down to the last one. releasing TT[%p]", this, _myTT);
_myTT->release();
}
OSObject::release();
}
void
AppleUSBEHCISplitPeriodicEndpoint::print(int level)
{
if (gKernelDebugLevel >= (KernelDebugLevel)level)
{
if (_intEP || _isochEP || _startTime)
{
int functionNum = 0;
int endpointNum = 0;
void *pEP = NULL;
if (_epType == kUSBInterrupt)
{
pEP = _intEP;
if (_intEP)
{
functionNum = _intEP->_functionNumber;
endpointNum = _intEP->_endpointNumber;
}
}
else if (_epType == kUSBIsoc)
{
pEP = _isochEP;
if (_isochEP)
{
functionNum = _isochEP->functionAddress;
endpointNum = _isochEP->endpointNumber;
}
}
#if __LP64__
USBLog(level, "EHCISPE[%p]::print - _nextSPE[0x%8.8qx] EP(%d:%d)[%p] _myTT[%p] _epType[%d](%s) _startTime[%3.3d] _FSBytesUsed[%3.3d] _period[%2.2d] _startFrame[%d] _numSS[%d] _numCS[%d] _SSflags[%p] _CSflags[%p] _wraparound[%s]", this, (uint64_t)_nextSPE, functionNum, endpointNum, pEP, _myTT, (int)_epType, _epType == kUSBIsoc ? "Isoc" : "Interrupt", (int)_startTime, (int)_FSBytesUsed, (int)_period, (int)_startFrame, (int)_numSS, (int)_numCS, (void*)_SSflags, (void*)_CSflags, _wraparound ? "true" : "false");
#else
USBLog(level, "EHCISPE[%p]::print - _nextSPE[0x%8.8x] EP(%d:%d)[%p] _myTT[%p] _epType[%d](%s) _startTime[%3.3d] _FSBytesUsed[%3.3d] _period[%2.2d] _startFrame[%d] _numSS[%d] _numCS[%d] _SSflags[%p] _CSflags[%p] _wraparound[%s]", this, (uint32_t)_nextSPE, functionNum, endpointNum, pEP, _myTT, (int)_epType, _epType == kUSBIsoc ? "Isoc" : "Interrupt", (int)_startTime, (int)_FSBytesUsed, (int)_period, (int)_startFrame, (int)_numSS, (int)_numCS, (void*)_SSflags, (void*)_CSflags, _wraparound ? "true" : "false");
#endif
IOSleep(1);
}
}
}
IOReturn
AppleUSBEHCISplitPeriodicEndpoint::SetStartFrameAndStartTime(UInt8 startFrame, UInt16 startTime)
{
_startFrame = startFrame;
_startTime = startTime;
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCISplitPeriodicEndpoint::FindStartFrameAndStartTime(void)
{
UInt16 tempStartTimes[kEHCIMaxPollingInterval];
int frameIndex, bestFrame;
UInt16 bestStartTimeFound = kEHCIFSMinStartTime;
UInt16 bestTimeUsedFound = kEHCIFSMinStartTime;
UInt16 bestStartTimeFrame = kEHCIMaxPollingInterval;
UInt16 bestTimeUsedFrame = kEHCIMaxPollingInterval;
UInt32 timeUsedForBestStartTimeFrame = 0;
UInt32 timeUsedForBestTimeUsedFrame = 0;
bool foundStartTimeCandidate = false;
bool foundTimeUsedCandidate = false;
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - _FSBytesUsed (%d)", this, _FSBytesUsed);
CalculateAllFrameStartTimes(tempStartTimes);
for (frameIndex=0; frameIndex < _period; frameIndex++)
{
UInt16 totalTimeUsedThisHarmonic = 0; UInt16 startTimeThisFrame = kEHCIFSMinStartTime;
int frameIndex2;
bool epWillFit = true;
for (frameIndex2 = frameIndex; frameIndex2 < kEHCIMaxPollingInterval; frameIndex2 += _period)
{
UInt16 startTimeThisHarmonic;
UInt16 tempTimeUsed = _myTT->_FStimeUsed[frameIndex2] + _FSBytesUsed;
if ((_FSBytesUsed > kEHCIFSLargeIsochPacket) && (_myTT->_largeIsoch[frameIndex]))
{
USBLog(1, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - second large isoc not allowed in frame %d", this, frameIndex2);
epWillFit = false;
break; }
if (tempTimeUsed > kEHCIFSMaxFrameBytes)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - no room in frame(%d) based on time used", this, frameIndex2);
epWillFit = false;
break; }
startTimeThisHarmonic = tempStartTimes[frameIndex2];
if ((startTimeThisHarmonic + _FSBytesUsed) > kEHCIFSMaxFrameBytes)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - no room in frame(%d) based on start time", this, frameIndex2);
epWillFit = false;
break;
}
totalTimeUsedThisHarmonic += tempTimeUsed;
if (startTimeThisHarmonic > startTimeThisFrame)
startTimeThisFrame = startTimeThisHarmonic;
}
if (epWillFit)
{
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - looks like we fit at frame (%d)", this, (int)frameIndex);
if (!foundStartTimeCandidate)
{
foundStartTimeCandidate = true;
bestStartTimeFound = startTimeThisFrame+1;
}
if (!foundTimeUsedCandidate)
{
foundTimeUsedCandidate = true;
bestTimeUsedFound = totalTimeUsedThisHarmonic+1;
}
if (startTimeThisFrame < bestStartTimeFound)
{
bestStartTimeFound = startTimeThisFrame;
bestStartTimeFrame = frameIndex;
timeUsedForBestStartTimeFrame = totalTimeUsedThisHarmonic;
}
if (totalTimeUsedThisHarmonic < bestTimeUsedFound)
{
bestTimeUsedFound = totalTimeUsedThisHarmonic;
bestTimeUsedFrame = frameIndex;
}
}
}
if (!foundStartTimeCandidate)
{
USBLog(3, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - using Start Time entry found - _startFrame(%d) _startTime(%d)", this, (int)_startFrame, _startTime);
_startTime = 0;
_startFrame = kEHCIMaxPollingInterval; return kIOReturnNoBandwidth;
}
else
{
if (bestStartTimeFound <= bestTimeUsedFound)
{
_startTime = bestStartTimeFound;
_startFrame = bestStartTimeFrame;
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - using Start Time entry found - _startFrame(%d) _startTime(%d)", this, (int)_startFrame, _startTime);
}
else
{
_startTime = bestTimeUsedFound;
_startFrame = bestTimeUsedFrame;
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::FindStartFrameAndStartTime - using Start Frame entry found - _startFrame(%d) _startTime(%d)", this, (int)_startFrame, _startTime);
}
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCISplitPeriodicEndpoint::CalculateAllFrameStartTimes(UInt16 *startTimes)
{
AppleUSBEHCISplitPeriodicEndpoint *curSPE;
AppleUSBEHCISplitPeriodicEndpoint *prevSPE;
int frameIndex;
for (frameIndex=0; frameIndex < kEHCIMaxPollingInterval; frameIndex++)
{
if (_epType == kUSBInterrupt)
prevSPE = _myTT->_interruptQueue[frameIndex];
else
prevSPE = _myTT->_isochQueue[frameIndex];
if (!prevSPE)
{
USBLog(1, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateAllFrameStartTimes - no queue head for frameIndex(%d)", this, (int)frameIndex);
return kIOReturnInternalError;
}
curSPE = prevSPE->_nextSPE;
while (curSPE)
{
if (CheckPlacementBefore(curSPE) == kIOReturnSuccess)
break;
prevSPE = curSPE;
curSPE = curSPE->_nextSPE;
}
startTimes[frameIndex] = CalculateStartTime(frameIndex, prevSPE, curSPE);
}
return kIOReturnSuccess;
}
IOReturn
AppleUSBEHCISplitPeriodicEndpoint::CheckPlacementBefore(AppleUSBEHCISplitPeriodicEndpoint *afterEP)
{
IOReturn result = kIOReturnInvalid;
if (_FSBytesUsed < kEHCIFSLargeIsochPacket)
{
if (afterEP)
{
if (afterEP == this)
{
result = kIOReturnSuccess;
}
else
{
if ((_epType == kUSBInterrupt) && (afterEP->_period < _period))
result = kIOReturnSuccess;
else if ((_epType == kUSBIsoc) && (afterEP->_period <= _period))
result = kIOReturnSuccess;
}
}
else
{
result = kIOReturnSuccess;
}
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CheckPlacementBefore - afterEP[%p] - returning[%p]", this, afterEP, (void*)result);
return result;
}
UInt16
AppleUSBEHCISplitPeriodicEndpoint::CalculateStartTime(UInt16 frameIndex, AppleUSBEHCISplitPeriodicEndpoint *prevSPE, AppleUSBEHCISplitPeriodicEndpoint *postSPE)
{
UInt16 startTime = 0;
AppleUSBEHCISplitPeriodicEndpoint *tempSPE = NULL;
if (!prevSPE)
{
USBLog(1, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateStartTime - prevSPE is NULL. no good!", this);
return 0;
}
if (postSPE)
{
if (_epType == kUSBIsoc)
{
startTime = postSPE->_startTime + postSPE->_FSBytesUsed;
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateStartTime - found ISOCH frameIndex(%d) prevSPE(%p)", this, frameIndex, prevSPE);
prevSPE->print(EHCISPLITTRANSFERLOGGING);
}
else
{
if (prevSPE == _myTT->_interruptQueue[frameIndex])
{
tempSPE = _myTT->_isochQueue[frameIndex]; if (tempSPE->_nextSPE)
{
tempSPE = tempSPE->_nextSPE;
}
else if (_myTT->_largeIsoch[frameIndex])
{
tempSPE = _myTT->_largeIsoch[frameIndex];
}
startTime = tempSPE->_startTime + tempSPE->_FSBytesUsed;
}
else
{
startTime = prevSPE->_startTime + prevSPE->_FSBytesUsed;
}
}
}
else {
if (_epType == kUSBIsoc)
{
tempSPE = _myTT->_largeIsoch[frameIndex];
if (tempSPE)
startTime = tempSPE->_startTime + tempSPE->_FSBytesUsed;
else
{
tempSPE = _myTT->_isochQueue[frameIndex];
startTime = tempSPE->_startTime + tempSPE->_FSBytesUsed;
}
}
else {
if (prevSPE != _myTT->_interruptQueue[frameIndex])
{
startTime = prevSPE->_startTime + prevSPE->_FSBytesUsed;
}
else
{
tempSPE = _myTT->_isochQueue[frameIndex];
if (tempSPE->_nextSPE)
{
tempSPE = tempSPE->_nextSPE;
}
else if (_myTT->_largeIsoch[frameIndex])
{
tempSPE = _myTT->_largeIsoch[frameIndex];
}
startTime = tempSPE->_startTime + tempSPE->_FSBytesUsed;
}
}
}
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateStartTime - index (%d) returning startTime(%d)", this, (int)frameIndex, (int)startTime);
return startTime;
}
UInt16
AppleUSBEHCISplitPeriodicEndpoint::CalculateNewStartTimeFromChange(AppleUSBEHCISplitPeriodicEndpoint *changeSPE)
{
UInt16 startTime = 0;
UInt16 worstStartTimeFound = kEHCIFSSOFBytesUsed + kEHCIFSHubAdjustBytes;
AppleUSBEHCISplitPeriodicEndpoint *prevSPE;
int index;
USBLog(EHCISPLITTRANSFERLOGGING, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateNewStartTimeFromChange - changeSPE[%p]", this, changeSPE);
print(EHCISPLITTRANSFERLOGGING);
if (changeSPE)
changeSPE->print(EHCISPLITTRANSFERLOGGING);
for (index = _startFrame; index < kEHCIMaxPollingInterval; index += _period)
{
if (_epType == kUSBIsoc)
prevSPE = _myTT->_isochQueue[index];
else
prevSPE = _myTT->_interruptQueue[index];
while (prevSPE->_nextSPE != this)
prevSPE = prevSPE->_nextSPE;
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateNewStartTimeFromChange - calling CalculateStartTime with index(%d) prevSPE(%p) _nextSPE(%p)", this, index, prevSPE, _nextSPE);
startTime = CalculateStartTime(index, prevSPE, _nextSPE);
if (startTime > worstStartTimeFound)
{
USBLog(5, "AppleUSBEHCISplitPeriodicEndpoint[%p]::CalculateNewStartTimeFromChange - changeSPE(%p) new startTime(%d)", this, changeSPE, (int)startTime);
worstStartTimeFound = startTime;
}
}
return worstStartTimeFound;
}