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

📄 chw.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        32,  6, 0x40,       // 0000 0000 bits 7
        
    };

CQH * CPeriodicMgr::QueueQHead(CQH * pQh,UCHAR uInterval,UCHAR offset,BOOL bHighSpeed)
{   
    if (pQh) {
        if (uInterval> PERIOD_TABLE_SIZE)
            uInterval= PERIOD_TABLE_SIZE;
        Lock();
        for (UCHAR bBit=PERIOD_TABLE_SIZE;bBit!=0;bBit>>=1) {
            if ((bBit & uInterval)!=0) { // THis is correct interval
                // Normalize the parameter.
                uInterval = bBit;
                if (offset>=uInterval)
                    offset = uInterval -1;
                CQH * pStaticQH=NULL ;
                UCHAR S_Mask=0;
                if (bHighSpeed) {
                    pStaticQH=m_pStaticQHArray[ periodTable[uInterval+offset].qhIdx +1] ;
                    pQh->SetSMask(periodTable[uInterval+offset].InterruptScheduleMask);
                }
                else 
                    pStaticQH =  m_pStaticQHArray[uInterval+offset];
                if (pStaticQH!=NULL) {
                    pQh->QueueQHead( pStaticQH->GetNextQueueQHead(m_pCPhysMem));
                    pStaticQH->QueueQHead( pQh );
                    Unlock();
                    return pStaticQH;
                }
                else
                    ASSERT(FALSE);                    
            }
        }
        ASSERT(FALSE);
        CQH * pStaticQH = m_pStaticQHArray[1];
        if (pStaticQH!=NULL) {
            pQh->QueueQHead( pStaticQH->GetNextQueueQHead(m_pCPhysMem));
            if (bHighSpeed)
                pQh->SetSMask(0xff);
            pStaticQH->QueueQHead( pQh );
            Unlock();
            return pStaticQH;
        }
        else
            ASSERT(FALSE);                    

        Unlock();
    }
    ASSERT(FALSE);
    return NULL;
    
}

BOOL CPeriodicMgr::DequeueQHead( CQH * pQh)
{
    if (pQh==NULL) {
        ASSERT(FALSE);
        return FALSE;
    }
    Lock();
    for (DWORD dwIndex=PERIOD_TABLE_SIZE;dwIndex<2*PERIOD_TABLE_SIZE;dwIndex ++) {
        CQH *pCurPrev= m_pStaticQHArray[dwIndex];
        if (pCurPrev!=NULL) {
            while (pCurPrev!=NULL) {
                CQH *pCur=pCurPrev->GetNextQueueQHead(m_pCPhysMem);
                if (pCur == pQh)
                    break;
                else
                    pCurPrev = pCur;
            }
            if (pCurPrev!=NULL) { // Found
                ASSERT(pCurPrev->GetNextQueueQHead(m_pCPhysMem) == pQh);
                pCurPrev->QueueQHead(pQh->GetNextQueueQHead(m_pCPhysMem));
                pQh->QueueQHead(NULL);
                Unlock();
                Sleep(2); // Make Sure it outof EHCI Scheduler.
                return TRUE;
            }
                    
        }
        else
            ASSERT(FALSE);
    }
    Unlock();
    ASSERT(FALSE);
    return FALSE;
}


// ************************************CAsyncMgr******************************  


CAsyncMgr::CAsyncMgr(IN CPhysMem * const pCPhysMem)
    :m_pCPhysMem(pCPhysMem)
    , m_pCDumpPipe(new CDummyPipe(pCPhysMem))
{
     m_pStaticQHead =NULL;
}
CAsyncMgr::~CAsyncMgr()
{
    DeInit();
}
BOOL CAsyncMgr::Init()
{
    Lock();
    m_pStaticQHead = new (m_pCPhysMem) CQH(m_pCDumpPipe);
    if (m_pStaticQHead) {
        m_pStaticQHead->SetReclamationFlag(TRUE);
        m_pStaticQHead ->QueueQHead(m_pStaticQHead); // Point to itself.
        Unlock();
        return TRUE;
    }
    Unlock();
    return FALSE;
}
void CAsyncMgr::DeInit()
{
    Lock();
    if (m_pStaticQHead){
        //delete (m_pCPhysMem) m_pStaticQHead;
        m_pStaticQHead->~CQH();
        m_pCPhysMem->FreeMemory((PBYTE)m_pStaticQHead,m_pCPhysMem->VaToPa((PBYTE)m_pStaticQHead),CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK);
    }
    m_pStaticQHead= NULL;
    Unlock();
}
CQH *  CAsyncMgr::QueueQH(CQH * pQHead)
{
    if (m_pStaticQHead && pQHead){
        Lock();
        pQHead->QueueQHead( m_pStaticQHead ->GetNextQueueQHead(m_pCPhysMem));
        m_pStaticQHead ->QueueQHead(pQHead);
        Unlock();
        return m_pStaticQHead;
    };
    return NULL;        
}
BOOL CAsyncMgr::DequeueQHead( CQH * pQh)
{
    CQH * pPrevQH = m_pStaticQHead;
    CQH * pCurQH = NULL;
    Lock();
    for (DWORD dwIndex=0;dwIndex<0x1000;dwIndex++)
        if (pPrevQH) {
            pCurQH= pPrevQH->GetNextQueueQHead(m_pCPhysMem);
            if (pCurQH == m_pStaticQHead || pCurQH == pQh)
                break;
            else
                pPrevQH = pCurQH;
        };
    if ( pCurQH && pPrevQH &&  pCurQH == pQh) {
        pPrevQH->QueueQHead(pCurQH ->GetNextQueueQHead(m_pCPhysMem));
        Unlock();
        return TRUE;
    }
    else
        ASSERT(FALSE);
    Unlock();
    return FALSE;
        
};

// ******************************BusyPipeList****************************
BOOL  CBusyPipeList::Init()
{
    m_fCheckTransferThreadClosing=FALSE;
    m_pBusyPipeList = NULL;
    m_hCheckForDoneTransfersEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
    if ( m_hCheckForDoneTransfersEvent == NULL ) {
        DEBUGMSG(ZONE_ERROR, (TEXT("-CPipe::Initialize. Error creating process done transfers event\n")));
        return FALSE;
    }
#ifdef DEBUG
    m_debug_numItemsOnBusyPipeList=0;
#endif

    // set up our thread to check for done transfers
    // currently, the context passed to CheckForDoneTransfersThread is ignored
    m_hCheckForDoneTransfersThread = CreateThread( 0, 0, CheckForDoneTransfersThreadStub, (PVOID)this, 0, NULL );
    if ( m_hCheckForDoneTransfersThread == NULL ) {
        DEBUGMSG(ZONE_ERROR, (TEXT("-CPipe::Initialize. Error creating process done transfers thread\n")));
        return FALSE;
    }
    CeSetThreadPriority( m_hCheckForDoneTransfersThread, g_IstThreadPriority + RELATIVE_PRIO_CHECKDONE );
    return TRUE;

}
void CBusyPipeList::DeInit()
{
    m_fCheckTransferThreadClosing=TRUE;
    if ( m_hCheckForDoneTransfersEvent != NULL ) {
        SignalCheckForDoneTransfers();
        if ( m_hCheckForDoneTransfersThread ) {
            DWORD dwWaitReturn = WaitForSingleObject( m_hCheckForDoneTransfersThread, 5000 );
            if ( dwWaitReturn != WAIT_OBJECT_0 ) {
                DEBUGCHK( 0 ); // check why thread is blocked
#pragma prefast(suppress: 258, "Try to recover gracefully from a pathological failure")
                TerminateThread( m_hCheckForDoneTransfersThread, DWORD(-1) );
            }
            CloseHandle( m_hCheckForDoneTransfersThread );
            m_hCheckForDoneTransfersThread = NULL;
        }
        CloseHandle( m_hCheckForDoneTransfersEvent );
        m_hCheckForDoneTransfersEvent = NULL;
    }
    
}
// ******************************************************************
// Scope: public static
void CBusyPipeList::SignalCheckForDoneTransfers( void )
//
// Purpose: This function is called when an interrupt is received by
//          the CHW class. We then signal the CheckForDoneTransfersThread
//          to check for any transfers which have completed
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: DO MINIMAL WORK HERE!! Most processing should be handled by
//        The CheckForDoneTransfersThread. If this procedure blocks, it
//        will adversely affect the interrupt processing thread.
// ******************************************************************
{
    DEBUGCHK( m_hCheckForDoneTransfersEvent && m_hCheckForDoneTransfersThread );
    SetEvent( m_hCheckForDoneTransfersEvent );
}
// ******************************************************************
ULONG CALLBACK CBusyPipeList::CheckForDoneTransfersThreadStub( IN PVOID pContext)
{
    return ((CBusyPipeList *)pContext)->CheckForDoneTransfersThread( );
}
// Scope: private static
ULONG CBusyPipeList::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: 
// ******************************************************************
{
    SetKMode(TRUE);

    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("+CPipe::CheckForDoneTransfersThread\n")) );

    PPIPE_LIST_ELEMENT pPrev = NULL;
    PPIPE_LIST_ELEMENT pCurrent = NULL;

    DEBUGCHK( m_hCheckForDoneTransfersEvent != NULL );

    while ( !m_fCheckTransferThreadClosing ) {
        WaitForSingleObject( m_hCheckForDoneTransfersEvent, m_FrameListSize/2 );
        if ( m_fCheckTransferThreadClosing ) {
            break;
        }
        Lock();
    #ifdef DEBUG // make sure m_debug_numItemsOnBusyPipeList is accurate
        {
            int debugCount = 0;
            PPIPE_LIST_ELEMENT pDebugElement = m_pBusyPipeList;
            while ( pDebugElement != NULL ) {
                pDebugElement = pDebugElement->pNext;
                debugCount++;
            }
            DEBUGCHK( debugCount == m_debug_numItemsOnBusyPipeList );
        }
        BOOL fDebugNeedProcessing = m_debug_numItemsOnBusyPipeList > 0;
        DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes to check = %d\n"), m_debug_numItemsOnBusyPipeList) );
        DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && !fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - warning! Called when no pipes were busy\n")) );
    #endif // DEBUG
        pPrev = NULL;
        pCurrent = m_pBusyPipeList;
        while ( pCurrent != NULL ) {
            pCurrent->pPipe->CheckForDoneTransfers();
                // this pipe is still busy. Move to next item
            pPrev = pCurrent;
            pCurrent = pPrev->pNext;
        }
        DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes still busy = %d\n"), m_debug_numItemsOnBusyPipeList) );
        Unlock();
    }
    DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("-CPipe::CheckForDoneTransfersThread\n")) );
    return 0;
}
// ******************************************************************
// Scope: protected static 
BOOL CBusyPipeList::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 ));

    PREFAST_DEBUGCHK( pPipe != NULL );
    BOOL fSuccess = FALSE;

    // make sure there nothing on the pipe already (it only gets officially added after this function succeeds).
    Lock();
#ifdef DEBUG
{
    // make sure this pipe isn't already in the list. That should never happen.
    // also check that our m_debug_numItemsOnBusyPipeList is correct
    PPIPE_LIST_ELEMENT pBusy = m_pBusyPipeList;
    int count = 0;
    while ( pBusy != NULL ) {
        DEBUGCHK( pBusy->pPipe != NULL &&
                  pBusy->pPipe != pPipe );
        pBusy = pBusy->pNext;
        count++;
    }
    DEBUGCHK( m_debug_numItemsOnBusyPipeList == count );
}
#endif // DEBUG
    
    PPIPE_LIST_ELEMENT pNewBusyElement = new PIPE_LIST_ELEMENT;
    if ( pNewBusyElement != NULL ) {
        pNewBusyElement->pPipe = pPipe;
        if ( fHighPriority || m_pBusyPipeList == NULL ) {
            // add pipe to start of list
            pNewBusyElement->pNext = m_pBusyPipeList;
            m_pBusyPipeList = pNewBusyElement;
        } else {
            // add pipe to end of list
            PPIPE_LIST_ELEMENT pLastElement = m_pBusyPipeList;
            while ( pLastElement->pNext != NULL ) {
                pLastElement = pLastElement->pNext;
            }
            pNewBusyElement->pNext = NULL;
            pLastElement->pNext = pNewBusyElement;
        }
        fSuccess = TRUE;
    #ifdef DEBUG
        m_debug_numItemsOnBusyPipeList++;
    #endif // DEBUG
    }
    Unlock();

⌨️ 快捷键说明

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