?? isp1161hc.cpp
字號:
m_ITLTransferLen = 0;
for (UINT index =0; index < m_TdsPutToITLIndex; index++)
{
paCurITd = m_TdsPutToITL[index];
pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);
SDevice *pDev;
SEndpoint *pEndpt;
SEndpointDescriptor *pEndptDesc;
EnterCriticalSection(&m_csDeviceListLock);
pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
LeaveCriticalSection(&m_csDeviceListLock);
ASSERT(pDev);
EnterCriticalSection(&pDev->csAccessingEndpointArray);
pEndpt = pDev->ppEndpts[
(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
LeaveCriticalSection(&pDev->csAccessingEndpointArray);
ASSERT(pEndpt);
pEndptDesc = pEndpt->pEd;
LONG iRelativeNumber = (LONG)uFrameNumber - (LONG)pCurITd->bfStartFrame;
if((iRelativeNumber < 0))
{
break; //break out from this loop
}
else if (iRelativeNumber > (LONG)pCurITd->bfFrameCount)
{
break; //should break out this endpoint only
}
//Calcalate the length according to spec page 25
LONG dwBufferLen;
ULONG uspaEndingBuffer = 0;
ULONG uspaStartingBuffer = 0;
if (pCurITd->offsetPsw[iRelativeNumber] == pCurITd->offsetPsw[iRelativeNumber+1] )
{
dwBufferLen = 0;
}
else
{
//Staring address
if (pCurITd->offsetPsw[iRelativeNumber] & 0x1000)
uspaStartingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
else
uspaStartingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
uspaStartingBuffer |= pCurITd->offsetPsw[iRelativeNumber] & 0xFFF;
//Ending address
if (iRelativeNumber < (LONG)pCurITd->bfFrameCount) //not the last one
{
ULONG temp = pCurITd->offsetPsw[iRelativeNumber + 1] -1;
if(temp & 0x1000)
uspaEndingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
else
uspaEndingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
uspaEndingBuffer |= temp & 0xFFF;
}
else
{
uspaEndingBuffer = pCurITd->paBufferEnd;
}
dwBufferLen = (LONG)(uspaEndingBuffer & 0xFFF) - (LONG)(uspaStartingBuffer & 0xFFF);
if ( (uspaStartingBuffer & 0xFFFFF000) != (uspaEndingBuffer & 0xFFFFF000))
dwBufferLen += 4096;
dwBufferLen += 1;
if (dwBufferLen == 0x1040)
{
WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x8888);
WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x9999);
}
/*===================================================================/
Alignment of 4 bytes, If there are more than 1 PTD in ATL buffer,
the next should be alignment in 4 bytes
====================================================================*/
if (index < m_TdsPutToITLIndex -1)
{
if (dwBufferLen %4)
{
USHORT dwPayLoad = 4 - dwBufferLen % 4;
m_ITLTransferLen += dwPayLoad;
}
}
}
m_ITLTransferLen += dwBufferLen + sizeof(SPhilipsTransferDescriptor);
//As it turned out, this stack doesn't calculate correctly
//when crossing 4k boundary. I have to apply page 27 of
//OHCI to check offsetPsw[R] and offsetPsw[R+1] to skip
//this offset if smaller
if (iRelativeNumber < (LONG)pCurITd->bfFrameCount)
{
if (pCurITd->offsetPsw[iRelativeNumber + 1] < pCurITd->offsetPsw[iRelativeNumber])
m_ITLTransferLen = 0;
}
else
{
if (pCurITd->offsetPsw[pCurITd->bfFrameCount] <pCurITd->offsetPsw[ pCurITd->bfFrameCount])
m_ITLTransferLen = 0;
}
}
/*=====================================================================/
Break out from this loop if nothing to dump, No need, since
all the above cases that can cause m_ITLLengh is 0 has been break
already.
/=====================================================================*/
if (m_ITLTransferLen == 0)
{
return;
}
/*=====================================================================/
Prepare Transfer counter
/=====================================================================*/
WRITE_REGISTER_USHORT(HcWRTransCounter(m_regBase), (USHORT)m_ITLTransferLen);
/*=====================================================================/
Go through the array and push them one by one to ITL
/=====================================================================*/
WRITE_PORT_USHORT((PUSHORT)(m_regBase+2), 0xc0);
for (index =0; index < m_TdsPutToITLIndex; index++)
{
paCurITd = m_TdsPutToITL[index];
pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);
SDevice *pDev;
SEndpoint *pEndpt;
SEndpointDescriptor *pEndptDesc;
EnterCriticalSection(&m_csDeviceListLock);
pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
LeaveCriticalSection(&m_csDeviceListLock);
ASSERT(pDev);
EnterCriticalSection(&pDev->csAccessingEndpointArray);
pEndpt = pDev->ppEndpts[
(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
LeaveCriticalSection(&pDev->csAccessingEndpointArray);
ASSERT(pEndpt);
pEndptDesc = pEndpt->pEd;
//Depending on OHCD spec page 101 to calcuate length, m_ITLTransferLen
LONG iRelativeNumber = (LONG)uFrameNumber - (LONG)pCurITd->bfStartFrame;
LONG dwBufferLen = 0;
ULONG uspaEndingBuffer;
ULONG uspaStartingBuffer;
if (pCurITd->offsetPsw[iRelativeNumber] == pCurITd->offsetPsw[iRelativeNumber+1] )
{
dwBufferLen = 0;
}
else
{
//Staring address
if (pCurITd->offsetPsw[iRelativeNumber] & 0x1000)
uspaStartingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
else
uspaStartingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
uspaStartingBuffer |= pCurITd->offsetPsw[iRelativeNumber] & 0xFFF;
//Ending address
if (iRelativeNumber < (LONG)pCurITd->bfFrameCount) //not the last one
{
ULONG temp = pCurITd->offsetPsw[iRelativeNumber + 1] -1;
if(temp & 0x1000)
uspaEndingBuffer = pCurITd->paBufferEnd & 0xFFFFF000;
else
uspaEndingBuffer = pCurITd->paBufferPage0 & 0xFFFFF000;
uspaEndingBuffer |= temp & 0xFFF;
}
else
{
uspaEndingBuffer = pCurITd->paBufferEnd;
}
dwBufferLen = (LONG)(uspaEndingBuffer & 0xFFF) - (LONG)(uspaStartingBuffer & 0xFFF);
if ( (uspaStartingBuffer & 0xFFFFF000) != (uspaEndingBuffer & 0xFFFFF000))
dwBufferLen += 4096;
dwBufferLen += 1;
}
//ExecuteUSBTransanction
UCHAR dwEndpointType = pEndpt->endptType;
SPhilipsTransferDescriptor sPTD;
sPTD.bActualBytes = 0;
sPTD.bfToggle = pEndpt->fPhcdToggleBit;
sPTD.bfActive = 1; //Start the transfer
sPTD.bCompletionCode = 0;
sPTD.bMaxPacketSize = pEndptDesc->bfMaxPacketSize; //Lost the MSB
// sPTD.bMaxPacketSize = 64; //Lost the MSB
sPTD.bfSpeed = pEndptDesc->bfIsLowSpeed;
// sPTD.bfLastTd = pCurGTd->bfLastTd;
if (index == m_TdsPutToITLIndex -1)
sPTD.bfLastTd = 1;
else
sPTD.bfLastTd = 0;
sPTD.bEndpointNumber = pEndptDesc->bfEndpointNumber;
sPTD.bTotalBytes = dwBufferLen;
sPTD.bfPID = pEndptDesc->bfDirection;
sPTD.bTokenOnce = 0; //Not applicable
sPTD.bfAddr = pCurITd->paBufferPage0 & gcITdAddrMask;
sPTD.bFormat = pEndptDesc->bfIsIsochronous;
sPTD.bUnused1 = 0;
sPTD.bUnused2 = 0;
sPTD.bUnused3 = 0;
/*=====================================================================/
Send the PTD and the data inside TD to ATL
/======================================================================*/
UINT i;
PUSHORT pData;
PUSHORT psPTDData;
//PTD structure
psPTDData = (PUSHORT)(&sPTD);
for (i = 0; i< sizeof(SPhilipsTransferDescriptor)/sizeof(USHORT); i++)
WRITE_PORT_USHORT((PUSHORT)m_regBase, *(psPTDData+i));
//Data in the TD
if ( dwBufferLen > 0)
{
pData = (PUSHORT)m_pobMem->PaToVa(uspaStartingBuffer);
// dwBufferLen += 1, In odd case, we add one more byte.
for (i=0; i< (dwBufferLen + 1)/sizeof(USHORT); i++)
{
WRITE_PORT_USHORT((PUSHORT)m_regBase, *(pData + i));
}
/*=====================================================================/
Send Alignment (4 bytes) data to ATL buffer
/======================================================================*/
if (index < m_TdsPutToITLIndex -1)
{
if (dwBufferLen %4)
{
DWORD dwPayLoad = 4 - dwBufferLen % 4;
for (i=0; i< dwPayLoad/sizeof(USHORT); i++)
{
WRITE_PORT_USHORT((PUSHORT)m_regBase, 0);
}
}
}
}
/*
WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x8888);
WRITE_PORT_USHORT((PUSHORT)m_regBase, 0x9999);
*/
RETAILMSG(0,
(TEXT("PHCD::PTD(s) %d, ITL TD[%d] 0x%08X -> [%d], m_ITLTransferLen %04X\r\n"),
m_TdsPutToITLIndex, iRelativeNumber, paCurITd, index, m_ITLTransferLen));
}//End of For loop
}
VOID CPhcd::CheckITLList(PULONG p_TdsPutToITLIndex, ULONG m_TdsPutToITL[], PULONG pInterrupts)
{
//Quit1 if we don't want have to process it.
if( *p_TdsPutToITLIndex == 0)
return;
SIsochTransferDescriptor* pCurITd;
ULONG paCurITd;
uFrameNumber = *HccaFrameNumber(m_pHcca);
RETAILMSG(ISP1161DBG,
(TEXT("PHCD: CheckITLList, uFramNumber,0x%08X \r\n"), uFrameNumber));
for ( UINT index =0; index<*p_TdsPutToITLIndex; index++)
{
paCurITd = m_TdsPutToITL[index];
pCurITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paCurITd);
SDevice *pDev;
SEndpoint *pEndpt;
SEndpointDescriptor* pEndptDesc;
EnterCriticalSection(&m_csDeviceListLock);
pDev = m_ppDevices[pCurITd->paBufferPage0 & gcITdAddrMask];
LeaveCriticalSection(&m_csDeviceListLock);
ASSERT(pDev);
EnterCriticalSection(&pDev->csAccessingEndpointArray);
pEndpt = pDev->ppEndpts[
(pCurITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
LeaveCriticalSection(&pDev->csAccessingEndpointArray);
pEndptDesc = pEndpt->pEd;
//Quit2: if we haven't reached to the end of bfFrameCount
/*==============================================================
In the FrameNumber turn around time, We need do some trick.
Well, as it turned out, this has become a big headache. Cause
as uFrameNumber turn around 0xFFFF, I don't know whether this
Frame is just bigger than bfStartFrame, or the transfer haven't
started, just user choose a big startFrame. I wonder how the
OHCI does this job.
Another issue is OS thread schedule delay, by the time this
CheckITLList is called, we may miss a lot of frames already.
So, I add a value 1000. That means even this CheckITLList is
called 1000 frame later, we will still clean this ITD.
===============================================================*/
if ((pCurITd->bfStartFrame + pCurITd->bfFrameCount +1) >= 0xFFFF)
{
if (uFrameNumber <=
pCurITd->bfStartFrame + pCurITd->bfFrameCount +1 - 0xFFFF + 1000)
uFrameNumber += 0xFFFF;
}
//Plus 1 is because ITL be processed after the frame it is dumped.
if (uFrameNumber <= pCurITd->bfStartFrame + pCurITd->bfFrameCount + 1)
return;
//Time to put TD back.
pCurITd->bfConditionCode = 0;
/*================================================================/
(2), update Endpoints TD, put the next in the first place
This place has turned out to be more tricker than before. The
story is we must check both m_TdsPutToITLFirstIndex and
m_TdsPutToITLSecondIndex, if either of them is NOT zero, that
means the next TD has been taken out and saved already. So,
we can't take out the next TD as put it to head position, instead
we should take out 2 of them.
And even tricker is we must check whether we are just in the
right frame to jump 2 frames. As it turned out, if we are late
for many frames, we can't simply jump 2 frames. Cause CheckITL
ITLSecond will be called right after CheckITLFirst.
/=================================================================*/
if (uFrameNumber == pCurITd->bfStartFrame + pCurITd->bfFrameCount + 1 + 1)
{
if((m_TdsPutToITLFirstIndex !=0) && (m_TdsPutToITLSecondIndex !=0))
{
SIsochTransferDescriptor* pNextITd;
pNextITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(pCurITd->paNextTd);
pEndptDesc->paTdQueueHead = pNextITd->paNextTd;
RETAILMSG(0,
(TEXT("PHCD: Jump 2 TD, paCurITd 0x%08X, NextTd 0x%08X, Next-NextTd 0x%08X\r\n"),
paCurITd, pCurITd->paNextTd, pNextITd->paNextTd));
}
else
{
pEndptDesc->paTdQueueHead = pCurITd->paNextTd;
RETAILMSG(0, (TEXT("PHCD: Jump 1 TD, CurITd 0x%08X, NextId 0x%08X\r\n"),
paCurITd, pCurITd->paNextTd));
}
}
else
{
//We have been later now, First compare FirstIndex with SecondIndex
//To determine which is first and then go till the end and reverse
//them and put them to DoneHead
//I presume CheckITLList(m_TdsPutToITLFirstIndex is called
if (m_TdsPutToITLSecondIndex)
{
SIsochTransferDescriptor* pTempITd;
ULONG paTempITd;
paTempITd = m_TdsPutToITLSecond[0];
pTempITd = (SIsochTransferDescriptor*)m_pobMem->PaToVa(paTempITd);
SDevice *pDev;
SEndpoint *pEndpt;
SEndpointDescriptor* pEndptDesc;
EnterCriticalSection(&m_csDeviceListLock);
pDev = m_ppDevices[pTempITd->paBufferPage0 & gcITdAddrMask];
LeaveCriticalSection(&m_csDeviceListLock);
ASSERT(pDev);
EnterCriticalSection(&pDev->csAccessingEndpointArray);
pEndpt = pDev->ppEndpts[
(pTempITd->paBufferPage0 & gcITdEndptMask) >> gcITdAddrBitSize];
LeaveCriticalSection(&pDev->csAccessingEndpointArray);
pEndptDesc = pEndpt->pEd;
//We still don't know which TD is earlier, well, if pTempITd->next is
//pCurITd, TD is Second is indeed earlier.
if (pTempITd->paNextTd == paCurITd)
{
//Assign pTempITd to pCurITd, cause we will operate on pCurITd
pCurITd = pTempITd;
paCurITd = paTempITd;
}
}
//Do a while loop to reach to the bottom
//Put the next to TdQueueHead
pEndptDesc->paTdQueueHead = pCurITd->paNextTd;
//Put itself to DoneHead
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -