📄 cpipe.cpp
字号:
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvClientBuffer
goto doneIssueTransfer;
}
}
}
#ifdef DEBUG
if (m_fTransferInProgress) {
DEBUGCHK( pTransfer != &m_transfer );
DEBUGCHK( m_pLastTransfer != NULL && m_pLastTransfer->lpNextTransfer == NULL );
} else {
DEBUGCHK( pTransfer == &m_transfer );
DEBUGCHK( m_pLastTransfer == NULL );
}
#endif //DEBUG
// fill in TDs but don't actually make it happen yet
status = AddTransfer(pTransfer);
if (status == requestOK) {
if (m_fTransferInProgress)
m_pLastTransfer->lpNextTransfer = pTransfer;
else
// tell the HC about it
status = ScheduleTransfer();
}
doneIssueTransfer:
DEBUGCHK( (status != requestOK) ||
(status == requestOK && m_fTransferInProgress) );
if ( status != requestOK ) {
FreeTransferMemory(pTransfer);
if (pTransfer != &m_transfer)
delete pTransfer;
} else
m_pLastTransfer = pTransfer;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_TRANSFER, (TEXT("-CPipe(%s)::IssueTransfer - address = %d, xfr %08x can %08x returning STATUS %d\n"), GetPipeType(), address, pTransfer, lpvCancelId, status) );
return status;
}
// ******************************************************************
// Scope: public
HCD_REQUEST_STATUS CPipe::IsPipeHalted( OUT LPBOOL const lpbHalted )
//
// Purpose: Return whether or not this pipe is halted (stalled)
//
// Parameters: lpbHalted - pointer to BOOL which receives
// TRUE if pipe halted, else FALSE
//
// Returns: requestOK
//
// Notes: Caller should check for lpbHalted to be non-NULL
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe(%s)::IsPipeHalted\n"), GetPipeType()) );
DEBUGCHK( lpbHalted ); // should be checked by CUhcd
EnterCriticalSection( &m_csPipeLock );
*lpbHalted = m_fIsHalted;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe(%s)::IsPipeHalted, *lpbHalted = %d, returning HCD_REQUEST_STATUS %d\n"), GetPipeType(), *lpbHalted, requestOK) );
return requestOK;
}
// ******************************************************************
// Scope: public
void CPipe::ClearHaltedFlag( void )
//
// Purpose: Clears the pipe is halted flag
//
// Parameters: None
//
// Returns: Nothing
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe(%s)::ClearHaltedFlag\n"), GetPipeType() ) );
EnterCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_WARNING && !m_fIsHalted, (TEXT("CPipe(%s)::ClearHaltedFlag - warning! Called on non-stalled pipe\n"), GetPipeType()) );
m_fIsHalted = FALSE;
m_pED->bfHalted = 0;
m_pED->bfToggleCarry = 0;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe(%s)::ClearHaltedFlag\n"), GetPipeType()) );
}
#if defined(MIPSIV)
#define __OPT_PLAT_FLAG TRUE
#else // defined(MIPSIV)
#define __OPT_PLAT_FLAG FALSE
#endif // defined(MIPSIV)
#define __OPT_BUGNUMSTRING "27332"
#define __OPT_VER_OFF
#include "optimizer.h"
// ******************************************************************
// Scope: private static
ULONG CALLBACK CPipe::CheckForDoneTransfersThread( IN PVOID )
//
// Purpose: Thread for checking whether busy pipes are done their
// transfers. This thread should be activated whenever we
// get a USB transfer complete interrupt (this can be
// requested by the InterruptOnComplete field of the TD)
//
// Parameters: 32 bit pointer passed when instantiating thread (ignored)
//
// Returns: 0 on thread exit
//
// Notes: Before invoking the CheckForDoneTransfers method on the owning pipe
// (see code), we advance past any additional TDs retired for the same transfer.
// There are two conditions under which this might happen: the more common one
// is that the transfer is not yet complete; this is harmless so long as we
// remember to bump the count of completed TDs. The less common - and more
// dangerous - situation is when a TD for the setup or data stage of a control
// transfer errors out and the Control/Bulk ratio is more than 1/1. In this case
// the HC may attempt to continue processing the ED without remembering that it
// just halted the ED.
// ******************************************************************
{
CeSetThreadPriority( GetCurrentThread(), g_IstThreadPriority + RELATIVE_PRIO_CHECKDONE );
SetKMode(TRUE);
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("+CPipe::CheckForDoneTransfersThread\n")) );
DEBUGCHK( m_hCheckForDoneTransfersEvent != NULL );
while ( !m_fCheckTransferThreadClosing ) {
WaitForSingleObject( m_hCheckForDoneTransfersEvent, INFINITE );
if ( m_fCheckTransferThreadClosing ) {
break;
}
// Must be set when this thread is signalled but under stress conditions
// it could get temporarily unset by the time we get here. If that
// happens then we just wait for the event to get signalled again.
TDLINK pTD;
pTD.td = (P_TD) InterlockedExchange((LPLONG)&m_pDoneHead, 0L);
#ifdef DEBUG
volatile TDLINK pHeadTD = pTD;
#endif // DEBUG
while (pTD.td) {
STransfer *pTransfer0 = pTD.td->bfIsIsoch ? pTD.itd->pTransfer : pTD.td->pTransfer;
STransfer *pTransfer = &(pTD.td->bfIsIsoch ? pTD.itd->pPipe : pTD.td->pPipe)->m_transfer;
// these fields all have the same offsets for TDs and ITDs
if (pTD.td->bfDiscard) {
// the transfer has been aborted already and completed elsewhere
DEBUGMSG(ZONE_WARNING, (TEXT("CPipe::CFDT DISCARDING td %08x nxt %08x xfr %08x\n"), pTD.td, pTD.td->paNextTd.td, pTransfer));
pTD = pTD.td->paNextTd;
continue;
}
DEBUGCHK( pTransfer0 != NULL &&
pTransfer->rPipe != NULL &&
pTransfer->rPipe->m_fTransferInProgress == TRUE &&
pTransfer == &pTransfer->rPipe->m_transfer );
DEBUGCHK( pTransfer->numTDsComplete < pTransfer->numTDsInList );
#ifdef DEBUG
(void) pHeadTD; // reference to please the compiler
// Ensure that this TD actually belongs to the transfer in question
if (pTD.td->bfIsIsoch)
DEBUGCHK( pTD.itd == pTransfer->rPipe->m_pDummyTd.itd ||
pTD.itd == &pTransfer->vaTDList.itd[pTransfer->numTDsComplete] );
else
DEBUGCHK( pTD.td == pTransfer->rPipe->m_pDummyTd.td ||
pTD.td == &pTransfer->vaTDList.td[pTransfer->numTDsComplete] );
#endif // DEBUG
DEBUGMSG(ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("CPipe::CFDT td %08x nxt %08x xfr %08x\n"), pTD.td, pTD.td->paNextTd, pTransfer));
// advance pTD first because it will get freed if it's the last TD of the transfer
// see notes above for why we can and want to advance multiple
pTD = pTD.td->paNextTd; // same offset as for itd
++pTransfer->numTDsComplete;
pTransfer->rPipe->CheckForDoneTransfers();
}
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("-CPipe::CheckForDoneTransfersThread\n")) );
return 0;
}
#if defined(MIPSIV)
#define __OPT_PLAT_FLAG TRUE
#else // defined(MIPSIV)
#define __OPT_PLAT_FLAG FALSE
#endif // defined(MIPSIV)
#define __OPT_BUGNUMSTRING "27332"
#define __OPT_VER_RESTORE
#include "optimizer.h"
// ******************************************************************
// Scope: protected virtual
DWORD CPipe::GetMemoryAllocationFlags( void ) const
//
// Purpose: Get flags for allocating memory from the CPhysMem class.
// Descended pipes can over-ride this if they want to
// specify different memory alloc flags (i.e. block or not,
// high priority or not, etc)
//
// Parameters: None
//
// Returns: DWORD representing memory allocation flags
//
// Notes:
// ******************************************************************
{
// default choice - not high priority, no blocking
return CPHYSMEM_FLAG_NOBLOCK;
}
// ******************************************************************
// Scope: protected static
BOOL CPipe::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
m_debug_numItemsOnBusyPipeList++;
#endif // DEBUG
fSuccess = TRUE;
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 CPipe::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 );
LeaveCriticalSection( &m_csBusyPipeListLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::RemoveFromBusyPipeList, removed pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe));
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::RemoveFromBusyPipeList, pipe(%s) 0x%x was not on busy list\n"), pPipe->GetPipeType(), pPipe ));
}
// ******************************************************************
// Scope: protected
void CPipe::FreeTransferMemory( STransfer *pTransfer )
//
// Purpose: Free all of the memory associated with the current transfer.
// For this function, that would be:
// - Any TDs allocated to carry the transfer request
// - Any data buffer allocated if the client passed
// in paClientBuffer == 0
// - A SETUP buffer for control transfers
//
// Parameters: None - (all are in m_transfer)
//
// Returns: Nothing
//
// Notes: Should only be called when a transfer is NOT in progress!!
// ******************************************************************
{
if (pTransfer == NULL)
pTransfer = &m_transfer;
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("+CPipe(%s)::FreeTransferMemory\n"), GetPipeType() ) );
EnterCriticalSection( &m_csPipeLock );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -