⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpipe.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:

    if (pTransfer->lpvControlHeader != NULL) {
        DEBUGCHK( pTransfer->paControlHeader != 0 );
        DEBUGCHK( pTransfer->paControlHeader == m_pCPhysMem->VaToPa(PUCHAR(pTransfer->lpvControlHeader)) );
        m_pCPhysMem->FreeMemory( PUCHAR(pTransfer->lpvControlHeader),
                                 pTransfer->paControlHeader,
                                 GetMemoryAllocationFlags() );
    #ifdef DEBUG
        m_debug_ControlExtraMemoryAllocated -= sizeof( USB_DEVICE_REQUEST );
        DEBUGMSG( ZONE_TRANSFER, (TEXT("CPipe(Control)::FreeTransferMemory - free 1 control header, total bytes = %d\n"), m_debug_ControlExtraMemoryAllocated ));
    #endif // DEBUG
    }

    // Free Transfer Descriptor (TD) list
    if ( pTransfer->vaTDList.td != NULL ) {
        DEBUGCHK( pTransfer->numTDsInList > 0 );
        m_pCPhysMem->FreeMemory( (PUCHAR) pTransfer->vaTDList.td,
                                 m_pCPhysMem->VaToPa( (PUCHAR) pTransfer->vaTDList.td ),
                                 GetMemoryAllocationFlags() );
    #ifdef DEBUG
        m_debug_TDMemoryAllocated -= pTransfer->numTDsInList * GetTdSize();
        DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::FreeTransferMemory - free %d TDs, total bytes = %d\n"), GetPipeType(), pTransfer->numTDsInList, m_debug_TDMemoryAllocated ) );
    #endif // DEBUG
    }
#ifdef DEBUG
    else {
        DEBUGCHK( pTransfer->numTDsInList == 0 );
    }
    pTransfer->vaTDList.td = P_TD( 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_pCPhysMem->FreeMemory( pTransfer->vaActualBuffer,
                                 pTransfer->paActualBuffer,
                                 GetMemoryAllocationFlags() );
    #ifdef DEBUG
        m_debug_BufferMemoryAllocated -= pTransfer->dwBufferSize;
        DEBUGMSG( ZONE_TD, (TEXT("CPipe(%s)::FreeTransferMemory - free buffer of %d, total bytes = %d\n"), GetPipeType(), pTransfer->dwBufferSize, m_debug_BufferMemoryAllocated ) );
        DEBUGCHK( 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: protected static
void CPipe::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
    static UINT numReclamationTransfers = 0;

    DEBUGMSG( ZONE_TRANSFER, (TEXT("+CPipe::HandleReclamationLoadChange - %s\n"), ((fAddingTransfer) ? TEXT("Add Reclamation Transfer") : TEXT("Remove Reclamation Transfer")) ) );

    DEBUGMSG( ZONE_TRANSFER, (TEXT("-CPipe::HandleReclamationLoadChange - %s\n"), ((fAddingTransfer) ? TEXT("Add Reclamation Transfer") : TEXT("Remove Reclamation Transfer")) ) );
}


// ******************************************************************               
// Scope: protected static
void CPipe::InitializeTD( OUT P_TD const pTD,
                          IN       STransfer *pTransfer,
                          IN const P_TD vaNextTD,
                          IN const UCHAR InterruptOnComplete,
                          IN const UCHAR Isochronous,
                          IN const BOOL  LowSpeedControl,
                          IN const DWORD PID,
                          IN const UCHAR Address,
                          IN const UCHAR Endpoint,
                          IN const USHORT DataToggle,
                          IN const DWORD paBuffer,
                          IN const DWORD MaxLength,
                          IN const BOOL bShortPacketOk)
//
// Purpose: Fill in Transfer Descriptor fields
//
// Parameters: pTD - pointer to transfer descriptor to fill in
//
//             Rest of Params - various transfer descriptor fields
//
// Returns: Nothing
//
// Notes: MaxLength field should already be encoded by caller into 
//        (n-1) form
// ******************************************************************
{
    DEBUGCHK( !Isochronous );   // this method must be overridden for OHCI isoch pipes
    DEBUGCHK( pTransfer != NULL );

    // unused bits have already been zeroed by caller!

    // not really part of the TD
    pTD->pTransfer = pTransfer;
    pTD->pNextTd = vaNextTD;
    pTD->pPipe = this;
    pTD->bfIsIsoch = 0;
    pTD->bfDiscard = 0;

    // the actual TD (null is legal for the last TD)
    pTD->paNextTd.phys = vaNextTD ? m_pCPhysMem->VaToPa((PUCHAR)vaNextTD) : 0;

//    DEBUGCHK( InterruptOnComplete == 0 || InterruptOnComplete == 7 );
    pTD->bfShortPacketOk = bShortPacketOk;
    pTD->bfDelayInterrupt = InterruptOnComplete ? gcTdInterruptOnComplete : gcTdNoInterrupt;
    pTD->bfDataToggle = DataToggle;
    pTD->bfErrorCount = 0;
    pTD->bfConditionCode = USB_NOT_ACCESSED_ERROR;

    DEBUGCHK( PID == TD_IN_PID ||
              PID == TD_OUT_PID ||
              PID == TD_SETUP_PID );
    pTD->bfPID = PID;

    if (MaxLength == (DWORD)-1) {
        // zero-length transfer
        pTD->paCurBuffer = 0;
        pTD->paBufferEnd = 0;
    } else {
        DEBUGCHK( MaxLength <= 0x2000 /*8K*/ );
        pTD->paCurBuffer = paBuffer;
        pTD->paBufferEnd = paBuffer+MaxLength;
    }
}

// ******************************************************************               
// Scope: public
CQueuedPipe::CQueuedPipe( IN const LPCUSB_ENDPOINT_DESCRIPTOR lpEndpointDescriptor,
                          IN const BOOL fIsLowSpeed,
                          IN const UCHAR bDeviceAddress )
//
// Purpose: Constructor for CQueuedPipe
//
// Parameters: See CPipe::CPipe
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
: CPipe( lpEndpointDescriptor, fIsLowSpeed, bDeviceAddress )   // constructor for base class
, m_fIsReclamationPipe( FALSE ) // this gets set to TRUE later as need arises
//, m_dataToggle( 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( )
//
// Purpose: Destructor for CQueuedPipe
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: Do not modify static variables here!!
// ******************************************************************
{
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("+CQueuedPipe::~CQueuedPipe\n")) );
    // queue should be freed via ClosePipe before calling destructor
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CQueuedPipe::~CQueuedPipe\n")) );
}

// ******************************************************************               
// Scope: public (Implements CPipe::ClosePipe = 0)
HCD_REQUEST_STATUS CQueuedPipe::ClosePipe( void )
//
// Purpose: Abort any transfers associated with this pipe, and
//          remove its data structures from the schedule
//
// Parameters: None
//
// Returns: requestOK
//
// Notes: 
// ******************************************************************
{
    HCD_REQUEST_STATUS status = requestOK;
    
    DEBUGMSG( ZONE_PIPE, (TEXT("+CQueuedPipe(%s)::ClosePipe\n"), GetPipeType() ) );

    // Don't enter CS before calling AbortTransfer, since
    // that function will need to leave the pipe CS
    // at a certain point to avoid deadlock, and
    // won't be able to do so if the CS is nested.

    AbortTransfer( NULL, // callback function
                   NULL, // callback param
                   m_transfer.lpvCancelId );

    EnterCriticalSection( &m_csPipeLock );

    // transfer was either never issued, finished before we got to
    // this function, or aborted above.
    DEBUGCHK( !m_fTransferInProgress );

    m_pED->bfSkip = 1;
    ULONG *pNextPhys = GetListHead(FALSE);
    CHW::WaitOneFrame();

    ULONG thisPhys = GetQHPhysAddr(m_pED);
    while (*pNextPhys != 0 && *pNextPhys != thisPhys) {
        P_ED pnext = (P_ED) m_pCPhysMem->PaToVa(*pNextPhys);
        pNextPhys = &pnext->paNextEd;
    }
    if (*pNextPhys != 0) {
        DEBUGCHK( *pNextPhys == GetQHPhysAddr(m_pED) );
        *pNextPhys = m_pED->paNextEd;
    } else {
        DEBUGMSG(ZONE_WARNING, (TEXT("!CQueuedPipe(%s)::ClosePipe %08x doesn't exist!\n"), GetPipeType(), m_pED));
        status = requestFailed;
    }

    (void) GetListHead(TRUE);
    LeaveCriticalSection( &m_csPipeLock );

    DEBUGMSG( ZONE_PIPE, (TEXT("-CQueuedPipe(%s)::ClosePipe\n"), GetPipeType() ) );
    return status;
}

// ******************************************************************               
// Scope: public (implements CPipe::AbortTransfer = 0)
HCD_REQUEST_STATUS CQueuedPipe::AbortTransfer( 
                                IN const LPTRANSFER_NOTIFY_ROUTINE lpCancelAddress,
                                IN const LPVOID lpvNotifyParameter,
                                IN LPCVOID lpvCancelId )
//
// Purpose: Abort any transfer on this pipe if its cancel ID matches
//          that which is passed in.
//
// Parameters: lpCancelAddress - routine to callback after aborting transfer
//
//             lpvNotifyParameter - parameter for lpCancelAddress callback
//
//             lpvCancelId - identifier for transfer to abort
//
// Returns: requestOK if transfer aborted
//          requestFailed if lpvCancelId doesn't match currently executing
//                 transfer, or if there is no transfer in progress
//
// Notes:
// ******************************************************************
{
    DEBUGMSG( ZONE_TRANSFER, (TEXT("+CQueuedPipe(%s)::AbortTransfer - lpvCancelId = 0x%x\n"), GetPipeType(), lpvCancelId) );

    HCD_REQUEST_STATUS status = requestFailed;
    STransfer         *pTransfer = 0;

    EnterCriticalSection( &m_csPipeLock );

    if (m_fTransferInProgress) {
        if (m_transfer.lpvCancelId == lpvCancelId) {
            // Now we need to ensure that the hardware is no longer accessing
            // the TDs which made up this transfer. Accomplish this by skipping
            // the ED, relinquishing the critsec, and waiting for the next frame.
            // At the start of the next frame, the WDH interrupt should fire and
            // that will cause the CFDT thread (which has higher priority than
            // whoever is calling AbortTransfer) to run. CFDT will flush leftover
            // TDs (and potentially complete the transfer pre-abortion).
            m_pED->bfSkip = 1;
            LeaveCriticalSection( &m_csPipeLock );
            CHW::WaitOneFrame();
            EnterCriticalSection( &m_csPipeLock );

            if (!m_fTransferInProgress || m_transfer.lpvCancelId != lpvCancelId) {
                // Too late; the transfer already completed.
                m_pED->bfSkip = 0;
                pTransfer = NULL;
            } else {
                // Set the discard bit on any TDs not yet processed in the done queue
                // Since the CFDT thread has higher priority than this thread, the fact
                // that we are executing here means it's OK to tweak the bits.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -