📄 cpipe.cpp
字号:
}
// allocate Transfer Descriptors
DEBUGCHK( pTransfer->numTDsInList == 0 &&
pTransfer->vaTDList == NULL );
pTransfer->numTDsInList = GetNumTDsNeeded(pTransfer);
DEBUGCHK( pTransfer->numTDsInList > 0 );
if ( !m_pUHCIFrame->m_pCPhysMem->AllocateMemory(
DEBUG_PARAM( TEXT("IssueTransfer TDs"), )
pTransfer->numTDsInList * sizeof( UHCD_TD ),
&pTransfer->vaTDList,
GetMemoryAllocationFlags() ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CPipe(%s)::IssueTransfer - no memory for TD list\n"), GetPipeType() ) );
pTransfer->numTDsInList = 0;
pTransfer->vaTDList = NULL;
goto doneIssueTransfer;
}
#ifdef DEBUG
m_pUHCIFrame->m_debug_TDMemoryAllocated += pTransfer->numTDsInList * sizeof( UHCD_TD );
DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::IssueTransfer - alloc %d TDs, total bytes = %d\n"), GetPipeType(), pTransfer->numTDsInList, m_pUHCIFrame->m_debug_TDMemoryAllocated ) );
#endif // DEBUG
#ifdef DEBUG
if ( pTransfer->dwFlags & USB_IN_TRANSFER ) {
// I am leaving this in for two reasons:
// 1. The memset ought to work even on zero bytes to NULL.
// 2. Why would anyone really want to do a zero length IN?
DEBUGCHK( pTransfer->dwBufferSize > 0 &&
pTransfer->lpvClientBuffer != NULL );
__try { // IN buffer, trash it
memset( PUCHAR( pTransfer->lpvClientBuffer ), GARBAGE, pTransfer->dwBufferSize );
} __except( EXCEPTION_EXECUTE_HANDLER ) {
}
}
#endif // DEBUG
// allocate data buffer if needed
DEBUGCHK( pTransfer->vaActualBuffer == PUCHAR( pTransfer->lpvClientBuffer ) &&
pTransfer->paActualBuffer == pTransfer->paClientBuffer );
if ( pTransfer->dwBufferSize > 0 &&
pTransfer->paClientBuffer == 0 ) {
DEBUGCHK( pTransfer->lpvClientBuffer != NULL );
// ok, there's data on this transfer and the client
// did not specify a physical address for the
// buffer. So, we need to allocate our own.
if ( !m_pUHCIFrame->m_pCPhysMem->AllocateMemory(
DEBUG_PARAM( TEXT("IssueTransfer Buffer"), )
pTransfer->dwBufferSize,
&pTransfer->vaActualBuffer,
GetMemoryAllocationFlags() ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CPipe(%s)::IssueTransfer - no memory for TD buffer\n"), GetPipeType() ) );
pTransfer->vaActualBuffer = NULL;
pTransfer->paActualBuffer = 0;
goto doneIssueTransfer;
}
pTransfer->paActualBuffer = m_pUHCIFrame->m_pCPhysMem->VaToPa( pTransfer->vaActualBuffer );
DEBUGCHK( pTransfer->vaActualBuffer != NULL &&
pTransfer->paActualBuffer != 0 );
#ifdef DEBUG
m_pUHCIFrame->m_debug_BufferMemoryAllocated += pTransfer->dwBufferSize;
DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::IssueTransfer - alloc buffer of %d, total bytes = %d\n"), GetPipeType(), pTransfer->dwBufferSize, m_pUHCIFrame->m_debug_BufferMemoryAllocated ) );
#endif // DEBUG
if ( !(pTransfer->dwFlags & USB_IN_TRANSFER) ) {
__try { // copying client buffer for OUT transfer
memcpy( pTransfer->vaActualBuffer, PUCHAR( pTransfer->lpvClientBuffer ), pTransfer->dwBufferSize );
} __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, returing HCD_REQUEST_STATUS %d\n"), GetPipeType(), address, 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;
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe(%s)::ClearHaltedFlag\n"), GetPipeType()) );
}
// ******************************************************************
// 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
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 );
//DEBUGCHK( !m_fTransferInProgress ); // not a valid assertion when we can queue pending transfers
if (pTransfer->lpvControlHeader != NULL) {
DEBUGCHK( pTransfer->paControlHeader != 0 );
DEBUGCHK( pTransfer->paControlHeader == m_pUHCIFrame->m_pCPhysMem->VaToPa(PUCHAR(pTransfer->lpvControlHeader)) );
m_pUHCIFrame->m_pCPhysMem->FreeMemory( PUCHAR(pTransfer->lpvControlHeader),
pTransfer->paControlHeader,
GetMemoryAllocationFlags() );
#ifdef DEBUG
m_pUHCIFrame->m_debug_ControlExtraMemoryAllocated -= sizeof( USB_DEVICE_REQUEST );
DEBUGMSG( ZONE_TRANSFER, (TEXT("CPipe(Control)::FreeTransferMemory - free 1 control header, total bytes = %d\n"), m_pUHCIFrame->m_debug_ControlExtraMemoryAllocated ));
#endif // DEBUG
}
// Free Transfer Descriptor (TD) list
if ( pTransfer->vaTDList != NULL ) {
DEBUGCHK( pTransfer->numTDsInList > 0 );
m_pUHCIFrame->m_pCPhysMem->FreeMemory( pTransfer->vaTDList,
m_pUHCIFrame->m_pCPhysMem->VaToPa( pTransfer->vaTDList ),
GetMemoryAllocationFlags() );
#ifdef DEBUG
m_pUHCIFrame->m_debug_TDMemoryAllocated -= pTransfer->numTDsInList * sizeof( UHCD_TD );
DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::FreeTransferMemory - free %d TDs, total bytes = %d\n"), GetPipeType(), pTransfer->numTDsInList, m_pUHCIFrame->m_debug_TDMemoryAllocated ) );
DEBUGCHK( m_pUHCIFrame->m_debug_TDMemoryAllocated >= CPIPE_INITIALIZE_TD_MEMORY_NEEDED );
#endif // DEBUG
}
#ifdef DEBUG
else {
DEBUGCHK( pTransfer->numTDsInList == 0 );
}
pTransfer->vaTDList = PUCHAR( 0xdeadbeef );
pTransfer->numTDsInList = 0xbeef;
#endif // DEBUG
// Free data buffer, if we allocated one
if ( pTransfer->paActualBuffer != 0 &&
pTransfer->paActualBuffer != pTransfer->paClientBuffer ) {
DEBUGCHK( pTransfer->vaActualBuffer != NULL &&
pTransfer->lpvClientBuffer != NULL &&
pTransfer->dwBufferSize > 0 ); // we didn't allocate memory if the xfer was 0 bytes
m_pUHCIFrame->m_pCPhysMem->FreeMemory( pTransfer->vaActualBuffer,
pTransfer->paActualBuffer,
GetMemoryAllocationFlags() );
#ifdef DEBUG
m_pUHCIFrame->m_debug_BufferMemoryAllocated -= pTransfer->dwBufferSize;
DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::FreeTransferMemory - free buffer of %d, total bytes = %d\n"), GetPipeType(), pTransfer->dwBufferSize, m_pUHCIFrame->m_debug_BufferMemoryAllocated ) );
DEBUGCHK( m_pUHCIFrame->m_debug_BufferMemoryAllocated >= 0 );
#endif // DEBUG
}
#ifdef DEBUG
pTransfer->vaActualBuffer = PUCHAR( 0xdeadbeef );
pTransfer->paActualBuffer = 0xdeadbeef;
#endif // DEBUG
LeaveCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("-CPipe(%s)::FreeTransferMemory\n"), GetPipeType() ) );
}
// ******************************************************************
// Scope: public
CQueuedPipe::CQueuedPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
IN const BOOL fIsLowSpeed,
IN CUhcd *const pCUhcd )
//
// Purpose: Constructor for CQueuedPipe
//
// Parameters: See CPipe::CPipe
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
: CPipe( lpEndpointDescriptor, fIsLowSpeed, pCUhcd) // constructor for base class
, m_pCUhcd(pCUhcd)
, m_fIsReclamationPipe( FALSE ) // this gets set to TRUE later as need arises
, m_pPipeQH( NULL ) // queue head for this pipe
, m_dataToggleC( 1 ) // data toggle for this pipe
, m_dataToggleQ( 1 ) // data toggle for this pipe
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::CQueuedPipe\n")) );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::CQueuedPipe\n")) );
}
// ******************************************************************
// Scope: public virtual
CQueuedPipe::~CQueuedPipe( )
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -