📄 chw.cpp
字号:
// Testing for full speed
//rtSc.bit.PFSC = 0x1;
//portSc.bit.TestControl = 0x6;
//RETAILMSG(1, (TEXT("Power On PortSC b/f =0x%x\r\n"), portSc.ul));
Write_PORTSC(dwPort,portSc);
portSc = Read_PORTSC( dwPort);
//RETAILMSG(1, (TEXT("Power On PortSC after =0x%x\r\n"), portSc.ul));
}
Sleep(50);
return TRUE;
}
//**********************************************************
void CHW::WriteAsyncListAddr(IN const DWORD addr)
//
// Purpose: Setup the address of next asynchronous queue head to be executed.
//
// Parameters: addr - asynchronous address
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
Write_EHCIRegister(ASYNCLISTADDR,addr);
}
// *****************************************************************
BOOL CHW::ConfigureHS()
//
// Purpose: Configure the Host Controller i.e. it would be used for
// OTG transceiver
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
// *****************************************************************
{
{
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;
//Add specific for tdi
//Check the value of USB MODE
// In OTG case, the USBMODE need to set again after reset.
{
DWORD value;
value = Read_EHCIRegister(USBMODE);
//RETAILMSG(1, (TEXT("USBMODE = 0x%x\r\n"), value));
if ((value & 0x3) != 0x3)
{
Write_EHCIRegister(USBMODE, value|0x3);
while ((Read_EHCIRegister(USBMODE) & 0x3) != 0x3);
}
}
//usbcmd.bit.FrameListSize=0;// We use 1k for Periodic List.
usbcmd.bit.FrameListSize=1024;// 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)0x457;
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);
}
#else
RETAILMSG(1, (TEXT("NO ASYNC_PARK_MODE\r\n")));
#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);
}
}
{
TXFILLTUNING txft = Read_TXFILLTUNING();
txft.bit.txfifothres = 0x4;
Write_TXFILLTUNING(txft);
txft = Read_TXFILLTUNING();
}
return TRUE;
}
// ******************************************************************
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")));
// Create a file mapping for USB clock state
USBClockCreateFileMapping();
ConfigureHS();
// 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;
}
if (m_dwOTGSupport)
InterruptDisable(m_dwSysIntr);
else
{
KernelIoControl(IOCTL_HAL_ENABLE_WAKE, &m_dwSysIntr, sizeof(m_dwSysIntr), NULL, 0, NULL);
}
// 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")));
PowerOnAllPorts();
EnableAsyncSchedule();
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;
// Remove file mapping from it
USBClockDeleteFileMapping();
}
// ******************************************************************
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")));
DWORD dwIntThreshCtrl = EHCI_REG_IntThreshCtrl_DEFAULT;
if (!(m_deviceReg.IsKeyOpened() && m_deviceReg.GetRegValue(EHCI_REG_IntThreshCtrl, (LPBYTE)&dwIntThreshCtrl, sizeof(dwIntThreshCtrl)))) {
dwIntThreshCtrl = EHCI_REG_IntThreshCtrl_DEFAULT;
}
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.
usbcmd.bit.IntThreshCtrl = dwIntThreshCtrl; // Setup by registry.
usbcmd.bit.RunStop = 1;
Write_USBCMD( usbcmd );
// According to 21.13.1 of Freescale, set CONFIGFLAG after RUN
Write_EHCIRegister(CONFIGFLAG,1);
// Just for safety, make sure those flags must set properly after enter into operation state
m_bUSBClockStop = FALSE;
m_bUSBPanicMode = TRUE;
DEBUGMSG( ZONE_INIT, (TEXT("-CHW::EnterOperationalState\n")));
}
//************************************************************************
void CHW::RunStopUSBController(BOOL fRun)
//
// Purpose: Start or Stop the USB Host Controller by controlling the run/stop bit
// in USBCMD register.
//
// Parameters: fRun - TRUE: Start to run, FALSE: stop the controller
//
// Returns: Nothing.
//
// ******************************************************************
{
USBCMD usbcmd=Read_USBCMD();
if (fRun)
{
if(usbcmd.bit.RunStop == 0) {
// clear run bit
usbcmd.bit.RunStop= 1;
Write_USBCMD( usbcmd );
USBINTR usbIntr;
usbIntr.ul=0x457;
// clear all interrupts
Write_USBINTR(usbIntr);
// spin until the controller really is stopped
while( Read_USBSTS().bit.HCHalted == 1 )
Sleep(0); //Wait until it stop.
}
}
else
{
if(usbcmd.bit.RunStop) {
// clear run bit
usbcmd.bit.RunStop= 0;
Write_USBCMD( usbcmd );
USBINTR usbIntr;
usbIntr.ul=0x4; // only enable the PORTSTATUS change one.
// clear all interrupts
Write_USBINTR(usbIntr);
// spin until the controller really is stopped
while( Read_USBSTS().bit.HCHalted == 0 ) //Wait until it stop.
Sleep(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -