📄 ctd.cpp
字号:
//***********************************************************************************
void CSITD::ReInit(CSITransfer * pTransfer,CSITD * pPrev)
//
// Purpose: Re-initalize the low/full speed spilt isoch transfer descriptor
//
// Parameters: pTransfer - pointer to CSITransfer
// pPrev - Previous pointer to CSITD
//
// Returns: Nothing
//
// ******************************************************************
{
ASSERT( pTransfer!=NULL);
nextLinkPointer.dwLinkPointer=1;
m_pTrans=pTransfer;
sITD_CapChar.dwSITD_CapChar=0;
microFrameSchCtrl.dwMicroFrameSchCtrl=0;
sITD_TransferState.dwSITD_TransferState=0;
sITD_BPPage[0].dwSITD_BPPage=0;
sITD_BPPage[1].dwSITD_BPPage=0;
backPointer.dwLinkPointer=1; // Invalid Back Link
UCHAR S_Mask = (m_pTrans?m_pTrans->m_pCPipe->GetSMask():1);
ASSERT(S_Mask!=0);
if (S_Mask==0) // Start Mask has to be present
S_Mask=1;
microFrameSchCtrl.sITD_MFSCContext.SplitStartMask=S_Mask;
microFrameSchCtrl.sITD_MFSCContext.SplitCompletionMask=(m_pTrans?m_pTrans->m_pCPipe->GetCMask():0);
m_pPrev=pPrev;
m_dwPhys = (m_pTrans?(m_pTrans->m_pCPipe->GetCPhysMem())-> VaToPa((PBYTE)this):0);
}
//********************************************************************
#define MAX_SPLIT_TRANSFER_LENGTH 188
DWORD CSITD::IssueTransfer(DWORD dwPhysAddr, DWORD dwEndPhysAddr, DWORD dwLen,BOOL bIoc,BOOL bIn)
//
// Purpose: Perform actual transfer of the data on the high speed isochronous transfer
//
// Parameters: dwPhysAddr - physical address first buffer pointer
// dwEndPhysAddr - physical address of second buffer pointer
// dwLen - total length to transfer
// bIoc - if Interrupt On Completion (IOC) bit should be set
// bIn - IN or OUT transcation
//
// Returns: 1 - success, 0 - failure
//
// ******************************************************************
{
CheckStructure ();
if (dwPhysAddr==0 || dwLen==0|| dwLen > 1024) {
ASSERT(FALSE);
return 0;
}
sITD_BPPage[0].sITD_BPPage0.BufferPointer = ((dwPhysAddr) >> EHCI_PAGE_ADDR_SHIFT);
sITD_BPPage[0].sITD_BPPage0.CurrentOffset = ((dwPhysAddr) & EHCI_PAGE_OFFSET_MASK);
sITD_BPPage[1].sITD_BPPage1.BufferPointer = (dwEndPhysAddr >> EHCI_PAGE_ADDR_SHIFT);
USB_ENDPOINT_DESCRIPTOR endptDesc = m_pTrans->m_pCPipe->GetEndptDescriptor();
sITD_CapChar.sITD_CCContext.DeviceAddress = m_pTrans->m_pCPipe->GetDeviceAddress();
sITD_CapChar.sITD_CCContext.Endpt = endptDesc.bEndpointAddress;
sITD_CapChar.sITD_CCContext.HubAddress = m_pTrans->m_pCPipe->m_bHubAddress;
sITD_CapChar.sITD_CCContext.PortNumber= m_pTrans->m_pCPipe->m_bHubPort;
sITD_CapChar.sITD_CCContext.Direction =(bIn?1:0);
// S-Mask and C-Mask has been initialized
// Status will be inactive and DoStartSlit.
sITD_TransferState.sITD_TSContext.BytesToTransfer = dwLen;
sITD_TransferState.sITD_TSContext.PageSelect=0; // Always use first page first.
sITD_TransferState.sITD_TSContext.IOC= (bIoc?1:0);
//
sITD_BPPage[1].sITD_BPPage1.TP=(dwLen>MAX_SPLIT_TRANSFER_LENGTH?1:0);
DWORD dwSlitCount=( dwLen+MAX_SPLIT_TRANSFER_LENGTH-1) /MAX_SPLIT_TRANSFER_LENGTH;
if (dwSlitCount>6) {
ASSERT(FALSE);
dwSlitCount=6;
}
if(bIn)
dwSlitCount=1;
sITD_BPPage[1].sITD_BPPage1.T_Count = dwSlitCount;
sITD_TransferState.sITD_TSContext.Active=1;
// Setup the back pointer if there is.
if (m_pPrev==NULL || m_pPrev->GetPhysAddr()== 0)
backPointer.dwLinkPointer=1;
else {
CNextLinkPointer backP;
backP.SetNextPointer(m_pPrev->GetPhysAddr(), TYPE_SELECT_SITD, TRUE);
backPointer.dwLinkPointer = backP.GetDWORD();
}
return 1;
};
//***************************************************************************************
CQTD::CQTD( CQTransfer * pTransfer, CQH * pQh)
: m_pTrans(pTransfer)
, m_pQh(pQh)
, m_CheckFlag(CQTD_CHECK_FLAG_VALUE)
//
// Purpose: Constructor for CQTD (Asychronous Queue Transfer descriptor)
//
// Parameters: pTransfer - pointer to CQTransfer object
// pQh - pointer to CQH object
//
// Returns: Nothing
//
// ******************************************************************
{
ASSERT((&(nextLinkPointer.dwLinkPointer))+ 3 == &(qTD_BufferPointer[0].dwQTD_BufferPointer)); // Check for Data Intergraty.
m_pNext=NULL;
altNextQTDPointer.dwLinkPointer=1;
qTD_Token.dwQTD_Token=0;
for (DWORD dwIndex=0;dwIndex<5; dwIndex++)
qTD_BufferPointer[dwIndex].dwQTD_BufferPointer=0;
nextLinkPointer.dwLinkPointer=1;
altNextQTDPointer.dwLinkPointer=1;
qTD_Token.dwQTD_Token=0;
for (dwIndex=0;dwIndex<5;dwIndex++)
qTD_BufferPointer[dwIndex].dwQTD_BufferPointer=0;
m_dwPhys = (m_pTrans->m_pCPipe->GetCPhysMem())-> VaToPa((PBYTE)this);
}
//*********************************************************************************************************************
DWORD CQTD::IssueTransfer(DWORD dwPID, BOOL bToggle1, DWORD dwTransLength, PPhysBufferArray pPhysBufferArray,BOOL bIoc)
//
// Purpose: Perform actual transfer of the data on asynchronous transfer
//
// Parameters: dwPID - Packet ID (Setup, IN or OUT)
// bToggle1 - Data toggle bit should be enabled or not.
// dwTransLenth - total length to transfer
// pPhysBufferArray - pointer to physical address of data buffer
// bIoc - if Interrupt On Completion (IOC) bit should be set
//
// Returns: Total size of data successfully transferred
//
// ******************************************************************
{
CheckStructure ();
if ( pPhysBufferArray ==NULL ) {
ASSERT(FALSE);
return 0;
}
ASSERT((pPhysBufferArray->dwBlockSize== dwTransLength + (pPhysBufferArray ->dwStartOffset & EHCI_PAGE_OFFSET_MASK)) ||
pPhysBufferArray->dwBlockSize == EHCI_PAGE_SIZE);
DWORD dwMaxPacketSize = (m_pTrans->m_pCPipe->GetEndptDescriptor()).wMaxPacketSize & 0x7ff;
DWORD dwMaxPacketNumber=(EHCI_PAGE_SIZE* MAX_QTD_PAGE_SIZE)/dwMaxPacketSize;
DWORD dwTotalTransfer=min(dwTransLength,dwMaxPacketNumber*dwMaxPacketSize);
DWORD dwTotalPage = (pPhysBufferArray ->dwStartOffset + dwTransLength + EHCI_PAGE_SIZE -1)/EHCI_PAGE_SIZE;
//DEBUGMSG(1, (TEXT("QTD Start offset(%d), transfer length(%d)\r\n"), pPhysBufferArray->dwStartOffset, dwTransLength));
ASSERT(dwTotalPage<= (MAX_QTD_PAGE_SIZE+1));
for (DWORD dwIndex=0;dwIndex<dwTotalPage && dwIndex<MAX_QTD_PAGE_SIZE+1;dwIndex++) {
qTD_BufferPointer[dwIndex].dwQTD_BufferPointer = (pPhysBufferArray ->dwArrayBlockAddr[dwIndex] & EHCI_PAGE_ADDR_MASK);
}
qTD_BufferPointer[0].qTD_BPContext.CurrentOffset = pPhysBufferArray ->dwStartOffset & EHCI_PAGE_OFFSET_MASK;
qTD_Token.qTD_TContext.PID = (dwPID== TD_OUT_PID ?0:(dwPID==TD_SETUP_PID?2:1));
qTD_Token.qTD_TContext.CEER = 3;
qTD_Token.qTD_TContext.C_Page= 0;
qTD_Token.qTD_TContext.IOC=((dwTotalTransfer < dwTransLength)?0:(bIoc?1:0));
qTD_Token.qTD_TContext.BytesToTransfer=dwTotalTransfer;
qTD_Token.qTD_TContext.DataToggle=(bToggle1?1:0);
qTD_Token.qTD_TContext.Active = 1;
return dwTotalTransfer;
}
//********************************************************************************
CQTD * CQTD::QueueNextTD(CQTD * pNextTD)
//
// Purpose: Set the next TD on the transfer descriptor list.
//
// Parameters: pNextTD - pointer to TD to be queued
//
// Returns: Pointer to next TD object
//
// ******************************************************************
{
CheckStructure ();
CQTD * pReturn = m_pNext;
m_pNext = pNextTD;
SetNextPointer(pNextTD-> GetPhysAddr(),TYPE_SELECT_ITD,TRUE);
return pReturn;
}
//***********************************************************************************
CQH::CQH(CPipe *pPipe)
: m_pPipe(pPipe)
, m_CheckFlag(CQH_CHECK_FLAG_VALUE)
//
// Purpose: Constructor for class CQH
//
// Parameters: pPipe - Pointer to pipe object to be used
//
// Returns: Nothing
//
// ******************************************************************
{
ASSERT((&(nextLinkPointer.dwLinkPointer))+ 1 == &(qH_StaticEndptState.qH_StaticEndptState[0])); // Check for Data Integrity.
ASSERT((&(qH_StaticEndptState.qH_StaticEndptState[0]))+ 4 == &(qTD_Overlay.altNextQTDPointer.dwLinkPointer)); // Check for Data Integrity.
PREFAST_DEBUGCHK( pPipe );
CheckStructure ();
m_pNextQHead = NULL;
USB_ENDPOINT_DESCRIPTOR endptDesc =pPipe->GetEndptDescriptor();
qH_StaticEndptState.qH_StaticEndptState[0]=0;
qH_StaticEndptState.qH_StaticEndptState[1]=0;
qH_StaticEndptState.qH_SESContext.DeviceAddress= pPipe->GetDeviceAddress();
qH_StaticEndptState.qH_SESContext.I=0;
qH_StaticEndptState.qH_SESContext.Endpt =endptDesc.bEndpointAddress;
qH_StaticEndptState.qH_SESContext.ESP = (pPipe->IsHighSpeed()?2:(pPipe->IsLowSpeed()?1:0));
qH_StaticEndptState.qH_SESContext.DTC = 1; // Enable Data Taggle.
qH_StaticEndptState.qH_SESContext.H=1;
//qH_StaticEndptState.qH_SESContext.H=0;
qH_StaticEndptState.qH_SESContext.MaxPacketLength =endptDesc.wMaxPacketSize & 0x7ff;
qH_StaticEndptState.qH_SESContext.C =
((endptDesc.bmAttributes & USB_ENDPOINT_TYPE_MASK)==USB_ENDPOINT_TYPE_CONTROL && pPipe->IsHighSpeed()!=TRUE ?1:0);
qH_StaticEndptState.qH_SESContext.RL=0x0; // TODO Check this is value is correct or not.
// DWORD 2
qH_StaticEndptState.qH_SESContext.UFrameSMask = pPipe->GetSMask();
qH_StaticEndptState.qH_SESContext.UFrameCMask = pPipe->GetCMask();
qH_StaticEndptState.qH_SESContext.HubAddr = pPipe->m_bHubAddress;
qH_StaticEndptState.qH_SESContext.PortNumber = pPipe->m_bHubPort;
//qH_StaticEndptState.qH_SESContext.Mult = ((endptDesc.wMaxPacketSize>>11) & 3)+1;
qH_StaticEndptState.qH_SESContext.Mult = 1;
currntQTDPointer.dwLinkPointer = 0;
nextQTDPointer.dwLinkPointer = 1; // Terminate;
memset((void *)&qTD_Overlay, 0 , sizeof(QTD));
qTD_Overlay.altNextQTDPointer.dwLinkPointer = 1; // This is For short transfer
qTD_Overlay.qTD_Token.qTD_TContext.Halted = 1;
m_dwPhys = (pPipe->GetCPhysMem())-> VaToPa((PBYTE)this);
// m_pStaticQHead = NULL;
}
//********************************************************************************
BOOL CQH::QueueTD(CQTD * pCurTD)
//
// Purpose: Set up the currentQTD Pointer onto the current QH
//
// Parameters: pCurTD - pointer to TD to be queued
//
// Returns: TRUE - success, FALSE - failure
//
// ******************************************************************
{
CheckStructure ();
if (pCurTD && nextQTDPointer.lpContext.Terminate!=0 && qTD_Overlay.qTD_Token.qTD_TContext.Active == 0 ) { // Queue If they queue is not active.
//memcpy((void *)&qTD_Overlay, pCurTD->GetQTDData(),sizeof(QTD));
currntQTDPointer.dwLinkPointer = 0;
ASSERT((pCurTD->GetPhysAddr() & 0x1f) == 0);
nextQTDPointer.dwLinkPointer =pCurTD->GetPhysAddr(); // This will activate the TD trasnfer.
qTD_Overlay.qTD_Token.qTD_TContext.Halted = 0;
return TRUE;
}
else {
ASSERT(FALSE);
return FALSE;
};
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -