📄 cpipe.cpp
字号:
PPIPE_LIST_ELEMENT pCurrent = NULL;
DEBUGCHK( m_hCheckForDoneTransfersEvent != NULL );
while ( !m_fCheckTransferThreadClosing ) {
WaitForSingleObject( m_hCheckForDoneTransfersEvent, INFINITE );
if ( m_fCheckTransferThreadClosing ) {
break;
}
EnterCriticalSection( &m_csBusyPipeListLock );
#ifdef DEBUG // make sure m_debug_numItemsOnBusyPipeList is accurate
{
int debugCount = 0;
PPIPE_LIST_ELEMENT pDebugElement = m_pBusyPipeList;
while ( pDebugElement != NULL ) {
pDebugElement = pDebugElement->pNext;
debugCount++;
}
DEBUGCHK( debugCount == m_debug_numItemsOnBusyPipeList );
}
BOOL fDebugNeedProcessing = m_debug_numItemsOnBusyPipeList > 0;
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes to check = %d\n"), m_debug_numItemsOnBusyPipeList) );
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && !fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - warning! Called when no pipes were busy\n")) );
#endif // DEBUG
pPrev = NULL;
pCurrent = m_pBusyPipeList;
while ( pCurrent != NULL ) {
if ( pCurrent->pPipe->CheckForDoneTransfers() ) {
// I was printing pPipe->GetPipeType() in the past
// but, after this thread's priority was accidentally
// set too low, it happened that the pipe was closed
// at exactly this point. That is completely legitimate.
// So, don't access pPipe->Anything past this point!!
DEBUGMSG( ZONE_PIPE, (TEXT("CPipe::CheckForDoneTransfersThread - removing pipe 0x%x from busy list\n"), pCurrent->pPipe) );
#ifdef DEBUG
pCurrent->pPipe = NULL;
#endif // DEBUG
// this pipe is not busy any more. Remove it from the linked list,
// and move to next item
if ( pCurrent == m_pBusyPipeList ) {
DEBUGCHK( pPrev == NULL );
m_pBusyPipeList = m_pBusyPipeList->pNext;
delete pCurrent;
pCurrent = m_pBusyPipeList;
} else {
DEBUGCHK( pPrev != NULL && pPrev->pNext == pCurrent );
pPrev->pNext = pCurrent->pNext;
delete pCurrent;
pCurrent = pPrev->pNext;
}
DEBUGCHK( --m_debug_numItemsOnBusyPipeList >= 0 );
} else {
// this pipe is still busy. Move to next item
pPrev = pCurrent;
pCurrent = pPrev->pNext;
}
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes still busy = %d\n"), m_debug_numItemsOnBusyPipeList) );
LeaveCriticalSection( &m_csBusyPipeListLock );
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("-CPipe::CheckForDoneTransfersThread\n")) );
return 0;
}
// ******************************************************************
// Scope: protected static
BOOL CUHCIFrame::AddToBusyPipeList( IN CPipe * const pPipe,
IN const BOOL fHighPriority )
//
// Purpose: Add the pipe indicated by pPipe to our list of busy pipes.
// This allows us to check for completed transfers after
// getting an interrupt, and being signaled via
// SignalCheckForDoneTransfers
//
// Parameters: pPipe - pipe to add to busy list
//
// fHighPriority - if TRUE, add pipe to start of busy list,
// else add pipe to end of list.
//
// Returns: TRUE if pPipe successfully added to list, else FALSE
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE, (TEXT("+CPipe::AddToBusyPipeList - new pipe(%s) 0x%x, pri %d\n"), pPipe->GetPipeType(), pPipe, fHighPriority ));
DEBUGCHK( pPipe != NULL );
BOOL fSuccess = FALSE;
// make sure there nothing on the pipe already (it only gets officially added after this function succeeds).
DEBUGCHK( !pPipe->m_fTransferInProgress );
EnterCriticalSection( &m_csBusyPipeListLock );
#ifdef DEBUG
{
// make sure this pipe isn't already in the list. That should never happen.
// also check that our m_debug_numItemsOnBusyPipeList is correct
PPIPE_LIST_ELEMENT pBusy = m_pBusyPipeList;
int count = 0;
while ( pBusy != NULL ) {
DEBUGCHK( pBusy->pPipe != NULL &&
pBusy->pPipe != pPipe );
pBusy = pBusy->pNext;
count++;
}
DEBUGCHK( m_debug_numItemsOnBusyPipeList == count );
}
#endif // DEBUG
PPIPE_LIST_ELEMENT pNewBusyElement = new PIPE_LIST_ELEMENT;
if ( pNewBusyElement != NULL ) {
pNewBusyElement->pPipe = pPipe;
if ( fHighPriority || m_pBusyPipeList == NULL ) {
// add pipe to start of list
pNewBusyElement->pNext = m_pBusyPipeList;
m_pBusyPipeList = pNewBusyElement;
} else {
// add pipe to end of list
PPIPE_LIST_ELEMENT pLastElement = m_pBusyPipeList;
while ( pLastElement->pNext != NULL ) {
pLastElement = pLastElement->pNext;
}
pNewBusyElement->pNext = NULL;
pLastElement->pNext = pNewBusyElement;
}
fSuccess = TRUE;
#ifdef DEBUG
m_debug_numItemsOnBusyPipeList++;
#endif // DEBUG
}
LeaveCriticalSection( &m_csBusyPipeListLock );
DEBUGMSG( ZONE_PIPE, (TEXT("-CPipe::AddToBusyPipeList - new pipe(%s) 0x%x, pri %d, returning BOOL %d\n"), pPipe->GetPipeType(), pPipe, fHighPriority, fSuccess) );
return fSuccess;
}
// ******************************************************************
// Scope: protected static
void CUHCIFrame::RemoveFromBusyPipeList( IN CPipe * const pPipe )
//
// Purpose: Remove this pipe from our busy pipe list. This happens if
// the pipe is suddenly aborted or closed while a transfer
// is in progress
//
// Parameters: pPipe - pipe to remove from busy list
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe::RemoveFromBusyPipeList - pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe ) );
EnterCriticalSection( &m_csBusyPipeListLock );
#ifdef DEBUG
BOOL debug_fRemovedPipe = FALSE;
{
// check m_debug_numItemsOnBusyPipeList
PPIPE_LIST_ELEMENT pBusy = m_pBusyPipeList;
int count = 0;
while ( pBusy != NULL ) {
DEBUGCHK( pBusy->pPipe != NULL );
pBusy = pBusy->pNext;
count++;
}
DEBUGCHK( m_debug_numItemsOnBusyPipeList == count );
}
#endif // DEBUG
PPIPE_LIST_ELEMENT pPrev = NULL;
PPIPE_LIST_ELEMENT pCurrent = m_pBusyPipeList;
while ( pCurrent != NULL ) {
if ( pCurrent->pPipe == pPipe ) {
// Remove item from the linked list
if ( pCurrent == m_pBusyPipeList ) {
DEBUGCHK( pPrev == NULL );
m_pBusyPipeList = m_pBusyPipeList->pNext;
} else {
DEBUGCHK( pPrev != NULL &&
pPrev->pNext == pCurrent );
pPrev->pNext = pCurrent->pNext;
}
delete pCurrent;
pCurrent = NULL;
#ifdef DEBUG
debug_fRemovedPipe = TRUE;
DEBUGCHK( --m_debug_numItemsOnBusyPipeList >= 0 );
#endif // DEBUG
break;
} else {
// Check next item
pPrev = pCurrent;
pCurrent = pPrev->pNext;
}
}
LeaveCriticalSection( &m_csBusyPipeListLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE && debug_fRemovedPipe, (TEXT("-CPipe::RemoveFromBusyPipeList, removed pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe));
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE && !debug_fRemovedPipe, (TEXT("-CPipe::RemoveFromBusyPipeList, pipe(%s) 0x%x was not on busy list\n"), pPipe->GetPipeType(), pPipe ));
}
// ******************************************************************
// Scope: private static
void CUHCIFrame::InsertIsochTDIntoFrameList( IN_OUT PUHCD_TD pTD,
IN const DWORD dwFrameIndex )
//
// Purpose: Inserts an isochronous transfer descriptor (TD) into the schedule
//
//
// Parameters: pTD - pointer to TD to insert into schedule. This
// TD will have some of its fields changed by this function.
//
// dwFrameIndex - indicates frame index in which to schedule this TD.
// Caller should ensure 0 <= index < FRAME_LIST_LENGTH
//
// Returns: Nothing
//
// Notes: Assumes m_csFrameListLock is held
// ******************************************************************
{
DEBUGCHK( pTD != NULL &&
pTD->Isochronous == 1 );
DEBUGCHK( dwFrameIndex >= 0 &&
dwFrameIndex < FRAME_LIST_LENGTH );
if ( m_vaFrameList[ dwFrameIndex ] & FRAME_LIST_POINTER_QH ) {
// there are no isoch TDs presently scheduled in this frame
DEBUGCHK( m_vaFrameList[ dwFrameIndex ] == ( GetQHPhysAddr( m_interruptQHTree[ QHTreeEntry( dwFrameIndex ) ] )
| FRAME_LIST_POINTER_QH
| FRAME_LIST_POINTER_VALID ) );
pTD->vaNextTD = NULL;
} else {
// there are already isoch TDs scheduled in this frame
PUHCD_TD vaNextIsochTD = (PUHCD_TD) m_pCPhysMem->PaToVa( m_vaFrameList[ dwFrameIndex ] & FRAME_LIST_POINTER_MASK );
DEBUGCHK( m_vaFrameList[ dwFrameIndex ] == ( GetTDPhysAddr( vaNextIsochTD )
| FRAME_LIST_POINTER_TD
| FRAME_LIST_POINTER_VALID ) );
DEBUGCHK( vaNextIsochTD->Isochronous == 1 &&
vaNextIsochTD->vaPrevIsochTD == NULL );
pTD->vaNextTD = vaNextIsochTD;
vaNextIsochTD->vaPrevIsochTD = pTD;
}
// now insert pTD after the frame list
pTD->vaPrevIsochTD = NULL;
pTD->HW_paLink = m_vaFrameList[ dwFrameIndex ];
m_vaFrameList[ dwFrameIndex ] = GetTDPhysAddr( pTD )
| FRAME_LIST_POINTER_TD
| FRAME_LIST_POINTER_VALID;
}
// ******************************************************************
// Scope: private static
void CUHCIFrame::RemoveIsochTDFromFrameList( IN_OUT PUHCD_TD pTD,
IN const DWORD dwFrameIndex )
//
// Purpose: Removes an isochronous transfer descriptor (TD) from the schedule
//
//
// Parameters: pTD - pointer to TD to remove from schedule. This
// TD will have some of its fields changed by this function.
//
// dwFrameIndex - frame index of this TD. Indicates which frame
// the TD is scheduled in. Caller must ensure that
// 0 <= dwFrameIndex < FRAME_LIST_LENGTH
//
// Returns: Nothing
//
// Notes: Assumes m_csFrameListLock is held
//
// The TD is not deleted or freed - it is just removed from the
// schedule. The caller still needs to ensure that HW is not
// accessing the TD before it can be freed.
// ******************************************************************
{
DEBUGCHK( pTD != NULL &&
pTD->Isochronous == 1 );
DEBUGCHK( dwFrameIndex >= 0 &&
dwFrameIndex < FRAME_LIST_LENGTH );
#ifdef DEBUG
{
// first make sure that this TD is in the given frame
DEBUGCHK( !(m_vaFrameList[ dwFrameIndex ] & FRAME_LIST_POINTER_QH) );
PUHCD_TD pDebugTD = (PUHCD_TD) m_pCPhysMem->PaToVa( m_vaFrameList[ dwFrameIndex ] & FRAME_LIST_POINTER_MASK );
BOOL fFoundTD = FALSE;
while ( pDebugTD != NULL ) {
DEBUGCHK( pDebugTD->vaPrevIsochTD == NULL ||
pDebugTD->vaPrevIsochTD->vaNextTD == pDebugTD );
DEBUGCHK( pDebugTD->vaNextTD == NULL ||
pDebugTD->vaNextTD->vaPrevIsochTD == pDebugTD );
if ( pDebugTD == pTD ) {
fFoundTD = TRUE;
}
pDebugTD = pDebugTD->vaNextTD;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -