📄 chw.cpp
字号:
}
}
}
//*****************************************************************
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 + -