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

📄 cpipe.cpp

📁 wince4.2 usb host driver for magic eye mmsp2 platform
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        pTD = pNext;
    }

    // At this point, the list is connected by virtaddrs in forward chronological
    // order of completion. pTail is the va of the most recently completed TD
    // and pPrev is the va of the oldest completed TD.
    //
    // Just in case we took two interrupts before the CFDT thread got a chance
    // to run, let's append our new list to the end of any pre-existing one.
    // We need to steal the list head in order to do that.
    P_TD pOldQueueHead = (P_TD) InterlockedExchange((LPLONG)&m_pDoneHead, 0L);
    P_TD *ppOldQueueTail = &pOldQueueHead;
    while (*ppOldQueueTail)
        ppOldQueueTail = &(*ppOldQueueTail)->paNextTd.td;
    *ppOldQueueTail = pPrev;

    // Now put the new queue back in place. Ignore the old value because we
    // already know that it was zero.
#ifdef DEBUG
    DWORD old = InterlockedExchange((LPLONG)&m_pDoneHead, (LONG)pOldQueueHead);
    DEBUGCHK( old == 0 );
#else
    (void) InterlockedExchange((LPLONG)&m_pDoneHead, (LONG)pOldQueueHead);
#endif

    // Tell the CFDT thread that it has more work to do.
    SetEvent( m_hCheckForDoneTransfersEvent );
}

ULONG CALLBACK CHCCAera::CheckForDoneTransfersThreadStub( IN PVOID context )
{
    return  ((CHCCAera *)context)->CheckForDoneTransfersThread();
}


#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 CHCCAera::CheckForDoneTransfersThread( )
//
// 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.
// ******************************************************************
{
    SetKMode(TRUE);

    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("+CHCCAera::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("-CHCCAera::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 static 
BOOL CHCCAera::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("+CHCCAera::AddToBusyPipeList - new pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe, fHighPriority ));
    UNREFERENCED_PARAMETER(pPipe);
    UNREFERENCED_PARAMETER(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("-CHCCAera::AddToBusyPipeList - new pipe(%s) 0x%x, pri %d, returning BOOL %d\n"), pPipe->GetPipeType(), pPipe, fHighPriority, fSuccess) );
    return fSuccess;
}

// ******************************************************************
// Scope: protected static
void CHCCAera::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("+CHCCAera::RemoveFromBusyPipeList - pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe ) );
    UNREFERENCED_PARAMETER(pPipe);

    EnterCriticalSection( &m_csBusyPipeListLock );
    LeaveCriticalSection( &m_csBusyPipeListLock );

    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CHCCAera::RemoveFromBusyPipeList, removed pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe));
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE, (TEXT("-CHCCAera::RemoveFromBusyPipeList, pipe(%s) 0x%x was not on busy list\n"), pPipe->GetPipeType(), pPipe ));
}


// ******************************************************************               
// Scope: protected static
void CHCCAera::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("+CPipe::HandleReclamationLoadChange - %s\n"), ((fAddingTransfer) ? TEXT("Add Reclamation Transfer") : TEXT("Remove Reclamation Transfer")) ) );
    UNREFERENCED_PARAMETER(fAddingTransfer);

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


#ifdef JEFFRO
// ******************************************************************               
// Scope: private static
void CHCCAera::InsertIsochTDIntoFrameList( IN_OUT P_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
        P_TD vaNextIsochTD = (P_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 CHCCAera::RemoveIsochTDFromFrameList( IN_OUT P_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
//

⌨️ 快捷键说明

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