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