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

📄 chw.cpp

📁 嵌入式操作系统WINCE5.0下的USB驱动程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    DEBUGMSG( ZONE_PIPE, (TEXT("-CPipe::AddToBusyPipeList - new pipe(%s) 0x%x, pri %d, returning BOOL %d\n"), pPipe->GetPipeType(), pPipe, fHighPriority, fSuccess) );
    return fSuccess;
}

// ******************************************************************
// Scope: protected static
void CBusyPipeList::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("+CPipe::RemoveFromBusyPipeList - pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe ) );
    Lock();
#ifdef DEBUG
    BOOL debug_fRemovedPipe = FALSE;
{
    // check m_debug_numItemsOnBusyPipeList
    PPIPE_LIST_ELEMENT pBusy = m_pBusyPipeList;
    int count = 0;
    while ( pBusy != NULL ) {
        DEBUGCHK( pBusy->pPipe != NULL );
        pBusy = pBusy->pNext;
        count++;
    }
    DEBUGCHK( m_debug_numItemsOnBusyPipeList == count );
}
#endif // DEBUG
    PPIPE_LIST_ELEMENT pPrev = NULL;
    PPIPE_LIST_ELEMENT pCurrent = m_pBusyPipeList;
    while ( pCurrent != NULL ) {
        if ( pCurrent->pPipe == pPipe ) {
            // Remove item from the linked list
            if ( pCurrent == m_pBusyPipeList ) {
                DEBUGCHK( pPrev == NULL );
                m_pBusyPipeList = m_pBusyPipeList->pNext;
            } else {
                DEBUGCHK( pPrev != NULL &&
                          pPrev->pNext == pCurrent );
                pPrev->pNext = pCurrent->pNext;
            }
            delete pCurrent;
            pCurrent = NULL;
        #ifdef DEBUG
            debug_fRemovedPipe = TRUE;
            DEBUGCHK( --m_debug_numItemsOnBusyPipeList >= 0 );
        #endif // DEBUG
            break;
        } else {
            // Check next item
            pPrev = pCurrent;
            pCurrent = pPrev->pNext;
        }
    }
    Unlock();
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE && debug_fRemovedPipe, (TEXT("-CPipe::RemoveFromBusyPipeList, removed pipe(%s) 0x%x\n"), pPipe->GetPipeType(), pPipe));
    DEBUGMSG( ZONE_PIPE && ZONE_VERBOSE && !debug_fRemovedPipe, (TEXT("-CPipe::RemoveFromBusyPipeList, pipe(%s) 0x%x was not on busy list\n"), pPipe->GetPipeType(), pPipe ));
}

#define ASYNC_PARK_MODE 1
#define FRAME_LIST_SIZE 0x400

// ************************************CHW ******************************  

CHW::CHW( IN const REGISTER portBase,
                              IN const DWORD dwSysIntr,
                              IN CPhysMem * const pCPhysMem,
                              //IN CUhcd * const pHcd,
                              IN LPVOID pvUhcdPddObject )
: m_cBusyPipeList(FRAME_LIST_SIZE)
, m_cPeriodicMgr (pCPhysMem,FRAME_LIST_SIZE)
, m_cAsyncMgr(pCPhysMem)
{
// definitions for static variables
    DEBUGMSG( ZONE_INIT, (TEXT("+CHW::CHW base=0x%x, intr=0x%x\n"), portBase, dwSysIntr));
    g_fPowerUpFlag = FALSE;
    g_fPowerResuming = FALSE;
    m_capBase = portBase;
        m_portBase = portBase+Read_CapLength();//EHCI 2.2.1   
    m_NumOfPort=Read_HCSParams().bit.N_PORTS;
    
    //m_pHcd = pHcd;
    m_pMem = pCPhysMem;
    m_pPddContext = pvUhcdPddObject;
    m_frameCounterHighPart = 0;
    m_frameCounterLowPart = 0;
    m_FrameListMask = FRAME_LIST_SIZE-1;  
    m_pFrameList = 0;

    m_dwSysIntr = dwSysIntr;
    m_hUsbInterruptEvent = NULL;
    m_hUsbHubChangeEvent = NULL;
    m_hUsbInterruptThread = NULL;
    m_fUsbInterruptThreadClosing = FALSE;

    m_fFrameLengthIsBeingAdjusted = FALSE;
    m_fStopAdjustingFrameLength = FALSE;
    m_hAdjustDoneCallbackEvent = NULL;
    m_uNewFrameLength = 0;
    m_dwCapability = 0;
    m_bDoResume=FALSE;

    m_hAsyncDoorBell=CreateEvent(NULL, FALSE,FALSE,NULL);
    InitializeCriticalSection( &m_csFrameCounter );
}
CHW::~CHW()
{
    if (m_dwSysIntr)
        KernelIoControl(IOCTL_HAL_DISABLE_WAKE, &m_dwSysIntr, sizeof(m_dwSysIntr), NULL, 0, NULL);
    DeInitialize();
    if (m_hAsyncDoorBell)
        CloseHandle(m_hAsyncDoorBell);
    DeleteCriticalSection( &m_csFrameCounter );
}

// ******************************************************************
BOOL CHW::Initialize( )
// Purpose: Reset and Configure the Host Controller with the schedule.
//
// Parameters: portBase - base address for host controller registers
//
//             dwSysIntr - system interrupt number to use for USB
//                         interrupts from host controller
//
//             frameListPhysAddr - physical address of frame list index
//                                 maintained by CPipe class
//
//             pvUhcdPddObject - PDD specific structure used during suspend/resume
//
// Returns: TRUE if initialization succeeded, else FALSE
//
// Notes: This function is only called from the CUhcd::Initialize routine.
//
//        This function is static
// ******************************************************************
{
    DEBUGMSG( ZONE_INIT, (TEXT("+CHW::Initialize\n")));

    DEBUGCHK( m_frameCounterLowPart == 0 &&
              m_frameCounterHighPart == 0 );

    // set up the frame list area.
    if ( m_portBase == 0 || 
            m_cPeriodicMgr.Init()==FALSE ||
            m_cAsyncMgr.Init() == FALSE ||
            m_cBusyPipeList.Init()==FALSE) {
        DEBUGMSG( ZONE_ERROR, (TEXT("-CHW::Initialize - zero Register Base or CeriodicMgr or CAsyncMgr fails\n")));
        ASSERT(FALSE);
        return FALSE;
    }
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS, (TEXT("CHW::Initialize - signalling global reset\n")));
    {
        USBCMD usbcmd=Read_USBCMD();
        usbcmd.bit.HCReset=1;
        Write_USBCMD(usbcmd);
        for (DWORD dwCount=0;dwCount<50 && (Read_USBCMD().bit.HCReset!=0);dwCount++)
            Sleep( 20 );
        usbcmd=Read_USBCMD();
        if (usbcmd.bit.HCReset!=0) // If can not reset within 1 second, we assume this is bad device.
            return FALSE;
        usbcmd.bit.FrameListSize=0;// We use 1k for Periodic List.
        m_FrameListMask = 0x3ff;  // Available Bit in 
        Write_USBCMD(usbcmd);
    }
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS, (TEXT("CHW::Initialize - end signalling global reset\n")));
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS, (TEXT("CHW::Initialize - setting USBINTR to all interrupts on\n")));
    {
        USBINTR usbint;
        // initialize interrupt register - set all interrupts to enabled
        usbint.ul=(DWORD)-1;
        usbint.bit.Reserved=0;
        Write_USBINTR(usbint );
    }
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::Initialize - setting FRNUM = 0\n")));
    // initialize FRNUM register with index 0 of frame list
    {
        FRINDEX frindex;
        frindex.ul=0;
        Write_FRINDEX(frindex);
    }
    Write_EHCIRegister(CTLDSSEGMENT,0);//We only support 32-bit address space now.
    // initialize FLBASEADD with address of frame list
    {
        ULONG frameListPhysAddr = m_cPeriodicMgr.GetFrameListPhysAddr();
        DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::Initialize - setting FLBASEADD = 0x%X\n"), frameListPhysAddr));
        DEBUGCHK( frameListPhysAddr != 0 );
        // frame list should be aligned on a 4Kb boundary
        DEBUGCHK( (frameListPhysAddr & EHCD_FLBASEADD_MASK) == frameListPhysAddr );
        Write_EHCIRegister(PERIODICLISTBASE,frameListPhysAddr);
        // Follow the rule in 4.8 EHCI
        USBCMD usbcmd=Read_USBCMD();
        while (usbcmd.bit.PSchedEnable!= Read_USBSTS().bit.PSStatus)
            Sleep(1);
        if (usbcmd.bit.PSchedEnable!=1) {
            usbcmd.bit.PSchedEnable=1;
            Write_USBCMD(usbcmd);
        }
    }
    // Initial Async Shedule to Enable.
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::Initialize - Enable Async Sched \n")));
    {
        Write_EHCIRegister(ASYNCLISTADDR,m_cAsyncMgr.GetPhysAddr());
#ifdef ASYNC_PARK_MODE
        if (Read_HHCCP_CAP().bit.Async_Park) {
            USBCMD usbcmd=Read_USBCMD();
            usbcmd.bit.ASchedPMEnable=1;
            usbcmd.bit.ASchedPMCount =3;
            Write_USBCMD(usbcmd);
        }
#endif
        USBCMD usbcmd=Read_USBCMD();
        // Follow the rule in 4.8 EHCI
        while (usbcmd.bit.ASchedEnable!= Read_USBSTS().bit.ASStatus)
            Sleep(1);
        if (usbcmd.bit.ASchedEnable!=1) {
            usbcmd.bit.ASchedEnable=1;
            Write_USBCMD(usbcmd);
        }
    }    
    // m_hUsbInterrupt - Auto Reset, and Initial State = non-signaled
    DEBUGCHK( m_hUsbInterruptEvent == NULL );
    m_hUsbInterruptEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
    m_hUsbHubChangeEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
    if ( m_hUsbInterruptEvent == NULL || m_hUsbHubChangeEvent==NULL ) {
        DEBUGMSG(ZONE_ERROR, (TEXT("-CHW::Initialize. Error creating USBInterrupt or USBHubInterrupt event\n")));
        return FALSE;
    }

    InterruptDisable( m_dwSysIntr ); // Just to make sure this is really ours.
    // Initialize Interrupt. When interrupt id # m_sysIntr is triggered,
    // m_hUsbInterruptEvent will be signaled. Last 2 params must be NULL
    if ( !InterruptInitialize( m_dwSysIntr, m_hUsbInterruptEvent, NULL, NULL) ) {
        DEBUGMSG(ZONE_ERROR, (TEXT("-CHW::Initialize. Error on InterruptInitialize\r\n")));
        return FALSE;
    }
    // Start up our IST - the parameter passed to the thread
    // is unused for now
    DEBUGCHK( m_hUsbInterruptThread == NULL &&
              m_fUsbInterruptThreadClosing == FALSE );
    if (m_hUsbInterruptThread==NULL)
        m_hUsbInterruptThread = CreateThread( 0, 0, UsbInterruptThreadStub, this, 0, NULL );
    if ( m_hUsbInterruptThread == NULL ) {
        DEBUGMSG(ZONE_ERROR, (TEXT("-CHW::Initialize. Error creating IST\n")));
        return FALSE;
    }
    CeSetThreadPriority( m_hUsbInterruptThread, g_IstThreadPriority );
    // Initial All port route to this host.
    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::Initialize - Initial All port route \n")));
    {
        Write_EHCIRegister(CONFIGFLAG,1);
        // Power On all the port.
        for (DWORD dwPort=1; dwPort <= m_NumOfPort ; dwPort ++ ) {
            PORTSC portSc = Read_PORTSC( dwPort);
            portSc.bit.Power=1;
            portSc.bit.Owner=0;
            // Do not touch write to clean register
            portSc.bit.ConnectStatusChange=0;
            portSc.bit.EnableChange=0;
            portSc.bit.OverCurrentChange=0;
            
            Write_PORTSC(dwPort,portSc);                
        }
        Sleep(50); // Port need to 50 ms to reset.
    }    
    
    DEBUGMSG( ZONE_INIT, (TEXT("-CHW::Initialize, success!\n")));
    return TRUE;
}
// ******************************************************************
void CHW::DeInitialize( void )
//
// Purpose: Delete any resources associated with static members
//
// Parameters: none
//
// Returns: nothing
//
// Notes: This function is only called from the ~CUhcd() routine.
//
//        This function is static
// ******************************************************************
{
    m_fUsbInterruptThreadClosing = TRUE; // tell USBInterruptThread that we are closing
    // m_hAdjustDoneCallbackEvent <- don't need to do anything to this
    // m_uNewFrameLength <- don't need to do anything to this

    // Wake up the interrupt thread and give it time to die.
    if ( m_hUsbInterruptEvent ) {
        SetEvent(m_hUsbInterruptEvent);
        if ( m_hUsbInterruptThread ) {
            DWORD dwWaitReturn = WaitForSingleObject(m_hUsbInterruptThread, 1000);
            if ( dwWaitReturn != WAIT_OBJECT_0 ) {
                DEBUGCHK( 0 );
#pragma prefast(suppress: 258, "Try to recover gracefully from a pathological failure")
                TerminateThread(m_hUsbInterruptThread, DWORD(-1));
            }
            CloseHandle(m_hUsbInterruptThread);
            m_hUsbInterruptThread = NULL;
        }
        // we have to close our interrupt before closing the event!
        InterruptDisable( m_dwSysIntr );

        CloseHandle(m_hUsbInterruptEvent);
        m_hUsbInterruptEvent = NULL;
    } else {
        InterruptDisable( m_dwSysIntr );
    }
    // Stop The Controller.
    {
        USBCMD usbcmd=Read_USBCMD();
        usbcmd.bit.RunStop=0;
        Write_USBCMD(usbcmd);
        while( Read_USBSTS().bit.HCHalted == 0 ) //Wait until it stop.
            Sleep(1);
    }
    m_cPeriodicMgr.DeInit();
    m_cAsyncMgr.DeInit();
    m_cBusyPipeList.DeInit();
    // no need to free the frame list; the entire pool will be freed as a unit.
    m_pFrameList = 0;
    m_fUsbInterruptThreadClosing = FALSE;
    m_frameCounterLowPart = 0;
    m_frameCounterHighPart = 0;
}

// ******************************************************************
void CHW::EnterOperationalState( void )
//
// Purpose: Signal the host controller to start processing the schedule
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes: This function is only called from the CUhcd::Initialize routine.
//        It assumes that CPipe::Initialize and CHW::Initialize
//        have already been called.
//
//        This function is static
// ******************************************************************
{
    DEBUGMSG( ZONE_INIT, (TEXT("+CHW::EnterOperationalState\n")));

    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::EnterOperationalState - clearing status reg\n")));
    Clear_USBSTS( );
    USBCMD usbcmd=Read_USBCMD();

    DEBUGMSG(ZONE_INIT && ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("CHW::EnterOperationalState - setting USBCMD run bit\n")));
    usbcmd.bit.FrameListSize = 0; // 1k Flame Entry. Sync with Initialization.

⌨️ 快捷键说明

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