📄 cpipe.cpp
字号:
DEBUGCHK( fFoundTD );
}
#endif // DEBUG
if ( pTD->vaNextTD != NULL ) {
DEBUGCHK( pTD->vaNextTD->Isochronous == 1 );
DEBUGCHK( pTD->vaNextTD->vaPrevIsochTD == pTD );
DEBUGCHK( pTD->HW_paLink == ( GetTDPhysAddr( pTD->vaNextTD )
| TD_LINK_POINTER_TD
| TD_LINK_POINTER_VALID ) );
pTD->vaNextTD->vaPrevIsochTD = pTD->vaPrevIsochTD;
}
#ifdef DEBUG
else {
// this TD should point into the QH tree
DEBUGCHK( pTD->HW_paLink == ( GetQHPhysAddr( m_interruptQHTree[ QHTreeEntry( dwFrameIndex ) ] )
| TD_LINK_POINTER_QH
| TD_LINK_POINTER_VALID ) );
}
#endif // DEBUG
if ( pTD->vaPrevIsochTD != NULL ) {
// this TD is after another Isoch TD
DEBUGCHK( pTD->vaPrevIsochTD->Isochronous == 1 );
DEBUGCHK( pTD->vaPrevIsochTD->vaNextTD == pTD );
DEBUGCHK( pTD->vaPrevIsochTD->HW_paLink == ( GetTDPhysAddr( pTD )
| TD_LINK_POINTER_VALID
| TD_LINK_POINTER_TD ) );
pTD->vaPrevIsochTD->vaNextTD = pTD->vaNextTD;
pTD->vaPrevIsochTD->HW_paLink = pTD->HW_paLink;
} else {
// this TD is right after the frame list
DEBUGCHK( m_vaFrameList[ dwFrameIndex ] == ( GetTDPhysAddr( pTD )
| FRAME_LIST_POINTER_TD
| FRAME_LIST_POINTER_VALID ) );
m_vaFrameList[ dwFrameIndex ] = pTD->HW_paLink;
}
pTD->vaPrevIsochTD = NULL;
pTD->vaNextTD = NULL;
// don't change pTD->HW_paLink because the host controller
// may still be accessing this TD. Caller will take care of
// this issue.
}
// ******************************************************************
// Scope: protected static
void CUHCIFrame::HandleReclamationLoadChange( IN const BOOL fAddingTransfer )
//
// Purpose: This function is called whenever transfers which use bandwidth
// reclamation (high speed Bulk/Control) are added/removed.
// If there are transfers for which reclamation is needed, this
// function will clear the termination bit of m_pFinalQH. Otherwise,
// it will set the termination bit to prevent infinite QH processing.
//
// Parameters: fAddingTransfer - if TRUE, a reclamation transfer is being added
// to the schedule. If FALSE, a reclamation transfer
// has just finished/aborted
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
// important that this be static - this variable tracks the total
// number of reclamation transfers in progress on the USB
DEBUGMSG( ZONE_TRANSFER, (TEXT("+CUHCIFrame::HandleReclamationLoadChange - %s\n"), ((fAddingTransfer) ? TEXT("Add Reclamation Transfer") : TEXT("Remove Reclamation Transfer")) ) );
EnterCriticalSection( &m_csQHScheduleLock );
#ifdef DEBUG
{
UINT numReclamationQHs = 0;
PUHCD_QH pQH = m_interruptQHTree[ 0 ]->vaNextQH;
while ( pQH != m_pFinalQH ) {
DEBUGCHK( pQH->vaPrevQH->vaNextQH == pQH &&
pQH->vaNextQH->vaPrevQH == pQH );
pQH = pQH->vaNextQH;
numReclamationQHs++;
}
DEBUGCHK( numReclamationTransfers <= numReclamationQHs );
}
#endif // DEBUG
if ( fAddingTransfer ) {
if ( numReclamationTransfers++ == 0 ) {
// terminate bit should be set already, and we just need to turn it off.
DEBUGCHK( m_pFinalQH->HW_paHLink == (GetQHPhysAddr( m_interruptQHTree[ 0 ] )
| QUEUE_HEAD_LINK_POINTER_QH
| QUEUE_HEAD_LINK_POINTER_TERMINATE) );
m_pFinalQH->HW_paHLink ^= QUEUE_HEAD_LINK_POINTER_TERMINATE;
}
DEBUGCHK( m_pFinalQH->HW_paHLink == (GetQHPhysAddr( m_interruptQHTree[ 0 ] )
| QUEUE_HEAD_LINK_POINTER_QH
| QUEUE_HEAD_LINK_POINTER_VALID) );
} else {
DEBUGCHK( numReclamationTransfers > 0 );
// terminate bit should not be set yet
DEBUGCHK( m_pFinalQH->HW_paHLink == (GetQHPhysAddr( m_interruptQHTree[ 0 ] )
| QUEUE_HEAD_LINK_POINTER_QH
| QUEUE_HEAD_LINK_POINTER_VALID) );
if ( --numReclamationTransfers == 0 ) {
// there are no more reclamation transfers, so set terminate bit
m_pFinalQH->HW_paHLink |= QUEUE_HEAD_LINK_POINTER_TERMINATE;
DEBUGCHK( m_pFinalQH->HW_paHLink == (GetQHPhysAddr( m_interruptQHTree[ 0 ] )
| QUEUE_HEAD_LINK_POINTER_QH
| QUEUE_HEAD_LINK_POINTER_TERMINATE) );
}
}
LeaveCriticalSection( &m_csQHScheduleLock );
DEBUGMSG( ZONE_TRANSFER, (TEXT("-CUHCIFrame::HandleReclamationLoadChange - %s\n"), ((fAddingTransfer) ? TEXT("Add Reclamation Transfer") : TEXT("Remove Reclamation Transfer")) ) );
}
// ******************************************************************
// Scope: public
CPipe::CPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
IN const BOOL fIsLowSpeed ,IN CUHCIFrame *const pUHCIFrame)
//
// Purpose: constructor for CPipe
//
// Parameters: lpEndpointDescriptor - pointer to endpoint descriptor for
// this pipe (assumed non-NULL)
//
// fIsLowSpeed - indicates if this pipe is low speed
//
// Returns: Nothing.
//
// Notes: Most of the work associated with setting up the pipe
// should be done via OpenPipe. The constructor actually
// does very minimal work.
//
// Do not modify static variables here!!!!!!!!!!!
// ******************************************************************
: CPipeAbs(lpEndpointDescriptor->bEndpointAddress )
, m_usbEndpointDescriptor( *lpEndpointDescriptor )
, m_pUHCIFrame(pUHCIFrame)
, m_fIsLowSpeed( !!fIsLowSpeed ) // want to ensure m_fIsLowSpeed is 0 or 1
, m_fIsHalted( FALSE )
, m_fTransferInProgress( FALSE )
, m_pLastTransfer ( NULL )
, m_bEndpointAddress( lpEndpointDescriptor->bEndpointAddress )
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe::CPipe\n")) );
// CPipe::Initialize should already have been called by now
// to set up the schedule and init static variables
DEBUGCHK( pUHCIFrame->m_debug_fInitializeAlreadyCalled );
InitializeCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::CPipe\n")) );
}
// ******************************************************************
// Scope: public virtual
CPipe::~CPipe( )
//
// Purpose: Destructor for CPipe
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes: Most of the work associated with destroying the Pipe
// should be done via ClosePipe
//
// Do not delete static variables here!!!!!!!!!!!
// ******************************************************************
{
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CPipe::~CPipe\n")) );
// transfers should be aborted or closed before deleting object
DEBUGCHK( m_fTransferInProgress == FALSE );
DeleteCriticalSection( &m_csPipeLock );
DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CPipe::~CPipe\n")) );
}
// ******************************************************************
// Scope: public
HCD_REQUEST_STATUS CPipe::IssueTransfer(
IN const UCHAR address,
IN LPTRANSFER_NOTIFY_ROUTINE const lpStartAddress,
IN LPVOID const lpvNotifyParameter,
IN const DWORD dwFlags,
IN LPCVOID const lpvControlHeader,
IN const DWORD dwStartingFrame,
IN const DWORD dwFrames,
IN LPCDWORD const aLengths,
IN const DWORD dwBufferSize,
IN_OUT LPVOID const lpvClientBuffer,
IN const ULONG paBuffer,
IN LPCVOID const lpvCancelId,
OUT LPDWORD const adwIsochErrors,
OUT LPDWORD const adwIsochLengths,
OUT LPBOOL const lpfComplete,
OUT LPDWORD const lpdwBytesTransferred,
OUT LPDWORD const lpdwError )
//
// Purpose: Issue a Transfer on this pipe
//
// Parameters: address - USB address to send transfer to
//
// OTHER PARAMS - see comment in CUhcd::IssueTransfer
//
// Returns: requestOK if transfer issued ok, else requestFailed
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER, (TEXT("+CPipe(%s)::IssueTransfer, address = %d\n"), GetPipeType(), address) );
STransfer *pTransfer;
HCD_REQUEST_STATUS status = requestFailed;
EnterCriticalSection( &m_csPipeLock );
if ( m_fTransferInProgress ) {
pTransfer = new STransfer;
if (pTransfer == NULL) {
DEBUGMSG( ZONE_ERROR, (TEXT("-CPipe(%s)::IssueTransfer cannot allocate transfer params!")
TEXT(" returning Failed\n"), GetPipeType() ) );
LeaveCriticalSection( &m_csPipeLock );
return requestFailed;
}
} else
pTransfer = &m_transfer;
#ifdef DEBUG
memset( pTransfer, GARBAGE, sizeof( *pTransfer ) );
#endif // DEBUG
// IssueTransfer params
pTransfer->address = address;
pTransfer->lpfnCallback = lpStartAddress;
pTransfer->lpvCallbackParameter = lpvNotifyParameter;
pTransfer->dwFlags = dwFlags;
pTransfer->lpvControlHeader = lpvControlHeader;
pTransfer->dwStartingFrame = dwStartingFrame;
pTransfer->dwFrames = dwFrames;
pTransfer->aLengths = aLengths;
pTransfer->dwBufferSize = dwBufferSize;
pTransfer->lpvClientBuffer = lpvClientBuffer;
pTransfer->paClientBuffer = paBuffer;
pTransfer->lpvCancelId = lpvCancelId;
pTransfer->adwIsochErrors = adwIsochErrors;
pTransfer->adwIsochLengths = adwIsochLengths;
pTransfer->lpfComplete = lpfComplete;
pTransfer->lpdwBytesTransferred = lpdwBytesTransferred;
pTransfer->lpdwError = lpdwError;
// non IssueTransfer params
pTransfer->vaTDList = NULL;
pTransfer->numTDsInList = 0;
pTransfer->vaActualBuffer = PUCHAR( pTransfer->lpvClientBuffer );
pTransfer->paActualBuffer = pTransfer->paClientBuffer;
pTransfer->dwCurrentPermissions = GetCurrentPermissions();
pTransfer->lpNextTransfer = NULL;
// We must allocate the control header memory here so that cleanup works later.
if (pTransfer->lpvControlHeader != NULL) {
PUCHAR pSetup;
// This must be a control transfer. It is asserted elsewhere,
// but the worst case is we needlessly allocate some physmem.
if ( !m_pUHCIFrame->m_pCPhysMem->AllocateMemory(
DEBUG_PARAM( TEXT("IssueTransfer SETUP Buffer"), )
sizeof(USB_DEVICE_REQUEST),
&pSetup,
GetMemoryAllocationFlags() ) ) {
DEBUGMSG( ZONE_WARNING, (TEXT("CPipe(%s)::IssueTransfer - no memory for SETUP buffer\n"), GetPipeType() ) );
pTransfer->lpvControlHeader = NULL;
pTransfer->paControlHeader = 0;
goto doneIssueTransfer;
}
pTransfer->paControlHeader = m_pUHCIFrame->m_pCPhysMem->VaToPa( pSetup );
DEBUGCHK( pSetup != NULL && pTransfer->paControlHeader != 0 );
#ifdef DEBUG
m_pUHCIFrame->m_debug_ControlExtraMemoryAllocated += sizeof( USB_DEVICE_REQUEST );
DEBUGMSG( ZONE_TRANSFER, (TEXT("CPipe(Control)::IssueTransfer - alloc 1 control header, total bytes = %d\n"), m_pUHCIFrame->m_debug_ControlExtraMemoryAllocated ));
#endif // DEBUG
__try {
memcpy( pSetup, PUCHAR( pTransfer->lpvControlHeader ), sizeof(USB_DEVICE_REQUEST) );
pTransfer->lpvControlHeader = pSetup;
} __except( EXCEPTION_EXECUTE_HANDLER ) {
// bad lpvControlHeader
pTransfer->lpvControlHeader = pSetup; // so we can free what we allocated
goto doneIssueTransfer;
}
}
if ( AreTransferParametersValid(pTransfer) ) {
__try { // initializing transfer status parameters
*pTransfer->lpfComplete = FALSE;
*pTransfer->lpdwBytesTransferred = 0;
*pTransfer->lpdwError = USB_NOT_COMPLETE_ERROR;
} __except( EXCEPTION_EXECUTE_HANDLER ) {
goto doneIssueTransfer;
}
} else {
DEBUGCHK( 0 ); // either we're checking params wrong,
// or the caller is passing bad arguments
goto doneIssueTransfer;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -