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

📄 chw.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }
    }
}

//*****************************************************************
void CHW::StartHostController(void)
//
// Purpose: This is to resume the host controller from suspend stage.
//          It would call RunStopUSBController(TRUE) to resume execution
//
// Parameter: 
//
// Returns:
//
//*******************************************************************
{
    int i = 0;
    USBCMD usbcmd=Read_USBCMD();
    USBSTS usbsts=Read_USBSTS();
    
    // Check run bit. Despite what the UHCI spec says, Intel's controller
    // does not always set the HCHALTED bit when the controller is stopped.
    for (UINT port =1; port <= m_NumOfPort; port ++)
    {
        // We need to enable back the SUSP flag before performing reset
        PORTSC portSC = Read_PORTSC(port);      

        if (portSC.bit.Suspend == 1)
        {           
            StallExecution(800);

            portSC.bit.ForcePortResume =1;
            portSC.bit.Suspend = 0;
            Write_PORTSC(port, portSC);

//            StallExecution(800);
        }
                
        do {
            i++;
            portSC = Read_PORTSC(port);            
            if (i > 1000)
            {
                // No matter what we still wake up this device
                // If you connect a device with no driver loaded and then 
                // cancel the dialog for driver input, power saving suspend
                // and it would not wakeup due to SUSPEND = 1 all the time.
                // Resolve that .. let it go.
                if (portSC.bit.ForcePortResume == 0)
                {
                    DEBUGMSG(1, (TEXT("Force WakeUp on Host Suspend(%d), ForcePortResume(%d)\r\n"),
                        portSC.bit.Suspend, portSC.bit.ForcePortResume));
                    break;
                }
                i = 0;
            }
        } while ((portSC.bit.Suspend == 1) || (portSC.bit.ForcePortResume == 1));

        portSC=Read_PORTSC(port);;      
        portSC.bit.EnableChange = 0;
        Write_PORTSC(port, portSC);     
    }

    RunStopUSBController(TRUE);

    DEBUGMSG(1, (TEXT("StartHostController completed\r\n")));
}   

// ******************************************************************
void CHW::StopHostController( void )
//
// Purpose: Signal the host controller to stop processing the schedule
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes:
//
//        This function is static
// ******************************************************************
{
    USBCMD usbcmd=Read_USBCMD();
    // Check run bit. Despite what the UHCI spec says, Intel's controller
    // does not always set the HCHALTED bit when the controller is stopped.
    RunStopUSBController(FALSE);

    for (UINT port =1; port <= m_NumOfPort; port ++) {
        PORTSC portSC=Read_PORTSC(port);;
        // no point doing any work unless the port is enabled
        //RETAILMSG(1, (TEXT("PORTSC before stop 0x%x\r\n"), portSC.ul));
        if ( portSC.bit.Power && portSC.bit.Owner==0 && portSC.bit.Enabled ) {
             //portSC.bit.ConnectStatusChange=0;
             //portSC.bit.EnableChange=1;
             //portSC.bit.OverCurrentChange=0;        
                //
             //portSC.bit.ForcePortResume =0;
             portSC.bit.Suspend=1;
             //portSC.bit.WakeOnConnect = 1;
             //portSC.bit.WakeOnDisconnect =1;
             //portSC.bit.WakeOnOverCurrent =1;
             Write_PORTSC( port, portSC );
        }
    }
}

// ******************************************************************
BOOL CHW::AsyncBell()
//
// Purpose: This function is to enable the interrupt on async advance 
//          doorbell bit on USBCMD.  It would then wait for interrupt coming in.
//        
//          Basically, this is to tell the host controller to issue an
//          interrupt the next time it advances asynchronous schedule.
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes:
//
//********************************************************************
{
    m_DoorBellLock.Lock();
    ResetEvent(m_hAsyncDoorBell);
    USBCMD usbcmd=Read_USBCMD();
    usbcmd.bit.IntOnAADoorbell=1;
    Write_USBCMD( usbcmd );  
    DWORD dwReturn=WaitForSingleObject( m_hAsyncDoorBell,10);
    m_DoorBellLock.Unlock();
    return (dwReturn == WAIT_OBJECT_0);
}

//*************************************************************
BOOL  CHW::AsyncDequeueQH( CQH * pQh) 
//
// Purpose: This function is to de-queue the queue head from the 
//          asynchronous queue manager and wait for Async Bell.
//
// Parameters: pQh - pointer to CQH object to be deqeueue.
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
//
//********************************************************************
{   
    BOOL bReturn= m_cAsyncMgr.DequeueQHead( pQh);
    if (bReturn) {
        AsyncBell();
    }
    return bReturn;
};

//*****************************************************************
BOOL CHW::PeriodQueueITD(CITD * piTD,DWORD FrameIndex) 
//
// Purpose: Queue the transfer descriptor for Isoschronous High Speed Transfer
//
// Parameters: piTD - pointer to CITD object
//             FrameIndex - frame index where to scheudle
//
// Returns: Nothing.
//
// Notes:
//
//********************************************************************
{ 
    FRINDEX frameIndex= Read_FRINDEX();
    if (((FrameIndex  - frameIndex.bit.FrameIndex) & m_FrameListMask) > 1)        
        return  m_cPeriodicMgr.QueueITD(piTD,FrameIndex); 
    else 
        return FALSE;// To Close EHCI 4.7.2.1
};

//******************************************************************
BOOL CHW::PeriodQueueSITD(CSITD * psiTD,DWORD FrameIndex)
//
// Purpose: Queue the transfer descriptor for Isoschronous Full/Low Speed Transfer
//
// Parameters: piTD - pointer to CITD object
//             FrameIndex - frame index where to scheudle
//
// Returns: Nothing.
//
// Notes:
//
//********************************************************************
{ 
    FRINDEX frameIndex= Read_FRINDEX();
    if (((FrameIndex  - frameIndex.bit.FrameIndex) & m_FrameListMask) > 1)        
        return  m_cPeriodicMgr.QueueSITD(psiTD,FrameIndex);
    else
        return FALSE;
};

//****************************************************************************
BOOL CHW::PeriodDeQueueTD(DWORD dwPhysAddr,DWORD FrameIndex) 
//
// Purpose: De-queue the TD from the periodic list
//
// Parameters: dwPhysAddr - Physical address of TD
//             FrameIndex - frame index where to scheudle
//
// Returns: Nothing.
//
// Notes:
//
//********************************************************************
{ 
    FRINDEX frameIndex= Read_FRINDEX();
    
    while (((FrameIndex  - frameIndex.bit.FrameIndex) & m_FrameListMask) <=1)  {
        Sleep(1);
        frameIndex= Read_FRINDEX();
    }
    return  m_cPeriodicMgr.DeQueueTD(dwPhysAddr, FrameIndex); 
};

DWORD CALLBACK CHW::CeResumeThreadStub ( IN PVOID context )
{
    return ((CHW *)context)->CeResumeThread ( );
}
// ******************************************************************
DWORD CHW::CeResumeThread ( )
//
// Purpose: Force the HCD to reset and regenerate itself after power loss.
//
// Parameters: None
//
// Returns: Nothing.
//
// Notes: Because the PDD is probably maintaining pointers to the Hcd and Memory
//   objects, we cannot free/delete them and then reallocate. Instead, we destruct
//   them explicitly and use the placement form of the new operator to reconstruct
//   them in situ. The two flags synchronize access to the objects so that they
//   cannot be accessed before being reconstructed while also guaranteeing that
//   we don't miss power-on events that occur during the reconstruction.
//
//        This function is static
// ******************************************************************
{
    // reconstruct the objects at the same addresses where they were before;
    // this allows us not to have to alert the PDD that the addresses have changed.

    DEBUGCHK( g_fPowerResuming == FALSE );

    // order is important! resuming indicates that the hcd object is temporarily invalid
    // while powerup simply signals that a powerup event has occurred. once the powerup
    // flag is cleared, we will repeat this whole sequence should it get resignalled.
    g_fPowerUpFlag = FALSE;
    g_fPowerResuming = TRUE;

    DeviceDeInitialize();
    while (1) {  // breaks out upon successful reinit of the object

        if (DeviceInitialize())
            break;
        // getting here means we couldn't reinit the HCD object!
        ASSERT(FALSE);
        DEBUGMSG(ZONE_ERROR, (TEXT("USB cannot reinit the HCD at CE resume; retrying...\n")));
        DeviceDeInitialize();
        Sleep(15000);
    }

    // the hcd object is valid again. if a power event occurred between the two flag
    // assignments above then the IST will reinitiate this sequence.
    g_fPowerResuming = FALSE;
    if (g_fPowerUpFlag)
        PowerMgmtCallback(TRUE);
    
    return 0;
}
DWORD CHW::UsbInterruptThreadStub( IN PVOID context )
{
    return ((CHW *)context)->UsbInterruptThread();
}

// ******************************************************************
DWORD CHW::UsbInterruptThread( )
//
// Purpose: Main IST to handle interrupts from the USB host controller
//
// Parameters: context - parameter passed in when starting thread,
//                       (currently unused)
//
// Returns: 0 on thread exit.
//
// Notes:
//
//        This function is private
// ******************************************************************
{
    HANDLE hHost, hXcvr;
    HANDLE hDetach;
    ULONG WaitReturn;
    ULONG ret;
    BOOL bPortChanged;
    BOOL bCableOnly;
    TCHAR szUSBHostObjectName[30];
    TCHAR szUSBXcvrObjectName[30];
    TCHAR szUSBHostDetachName[30];
    DWORD expiretime;
    DWORD currtime;
    BOOL fIdle;
    DWORD timeout = USB_IDLE_TIMEOUT;


    DEBUGMSG(1, (TEXT("USB Interrupt Thread running again IsOTGSupport? %d\r\n"), m_dwOTGSupport));
    if (m_dwOTGSupport) 
    {       
        StringCbCopy(szUSBHostObjectName, sizeof(szUSBHostObjectName), USBHostObjectName);
        StringCbCat(szUSBHostObjectName, sizeof(szUSBHostObjectName), m_szOTGGroup);

        DEBUGMSG(1, (TEXT("CHW: CreateEvent:%s\r\n"), szUSBHostObjectName));
        hHost = CreateEvent(NULL, FALSE, FALSE, szUSBHostObjectName);
        if (GetLastError() == ERROR_ALREADY_EXISTS)
            RETAILMSG(1, (TEXT("USBHost: Opened an existing Func Event\r\n")));
        else
            DEBUGMSG(1, (TEXT("UFN: Created a new Func Event\r\n")));

        if (hHost == NULL)
            DEBUGMSG(1, (TEXT("UFN: Create Event Failed for func!\r\n")));

        StringCbCopy(szUSBXcvrObjectName, sizeof(szUSBXcvrObjectName), USBXcvrObjectName);
        StringCbCat(szUSBXcvrObjectName, sizeof(szUSBXcvrObjectName), m_szOTGGroup);
        DEBUGMSG(1, (TEXT("USBHost: CreateEvent:%s\r\n"), szUSBXcvrObjectName));
        hXcvr = CreateEvent(NULL, FALSE, FALSE, szUSBXcvrObjectName);

        if (GetLastError() == ERROR_ALREADY_EXISTS)
            DEBUGMSG(1, (TEXT("UFN: Opened an existing XCVR Event\r\n")));
        else
            DEBUGMSG(1, (TEXT("UFN: Created a new XCVR Event\r\n")));

        if (hXcvr == NULL)
            DEBUGMSG(1, (TEXT("UFN: Create Event Failed for xcvr!\r\n")));

        StringCbCopy(szUSBHostDetachName, sizeof(szUSBHostDetachName), USBHostDetachName);
        StringCbCat(szUSBHostDetachName, sizeof(szUSBHostDetachName), m_szOTGGroup);
        DEBUGMSG(1, (TEXT("USBHost: CreateEvent:%s\r\n"), szUSBHostDetachName));

        hDetach = CreateEvent(NULL, FALSE, FALSE, szUSBHostDetachName);

        if (GetLastError() == ERROR_ALREADY_EXISTS)
            DEBUGMSG(1, (TEXT("UFN: Opened an existing Detach Event\r\n")));
        else
            DEBUGMSG(1, (TEXT("UFN: Created a new Detach Event\r\n")));

        if (hDetach == NULL)
            DEBUGMSG(1, (TEXT("UFN: Create Event Failed for detach!\r\n")));

XCVR_SIG:
        bInHost = FALSE;
        bPortChanged = FALSE;       
        DEBUGMSG(1, (TEXT("Host: Waiting for signal from XCVR!!!\r\n")));
        WaitReturn = WaitForSingleObject(hHost, INFINITE);

        RETAILMSG(1, (TEXT("Host: Host Driver in charge now!!!\r\n")));
        bInHost = TRUE;

        // We need to setup the host configuration again.       
        ConfigureHS();

        if (!InterruptInitialize(m_dwSysIntr, m_hUsbInterruptEvent, NULL, 0)) 
        {
            RETAILMSG(1, (L"ERROR: UfnPdd_Init: Interrupt initialization failed\r\n"));
            return -1;
        }

        //RETAILMSG(1, (TEXT("USBHost SysIntr:0x%x\r\n"), m_dwSysIntr));        
 

⌨️ 快捷键说明

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