📄 chw.cpp
字号:
}
// ******************************************************************
ULONG CALLBACK CBusyPipeList::CheckForDoneTransfersThreadStub( IN PVOID pContext)
{
return ((CBusyPipeList *)pContext)->CheckForDoneTransfersThread( );
}
// Scope: private static
ULONG CBusyPipeList::CheckForDoneTransfersThread( )
//
// Purpose: Thread for checking whether busy pipes are done their
// transfers. This thread should be activated whenever we
// get a USB transfer complete interrupt (this can be
// requested by the InterruptOnComplete field of the TD)
//
// Parameters: 32 bit pointer passed when instantiating thread (ignored)
//
// Returns: 0 on thread exit
//
// Notes:
// ******************************************************************
{
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("+CPipe::CheckForDoneTransfersThread\n")) );
PPIPE_LIST_ELEMENT pPrev = NULL;
PPIPE_LIST_ELEMENT pCurrent = NULL;
DEBUGCHK( m_hCheckForDoneTransfersEvent != NULL );
while ( !m_fCheckTransferThreadClosing ) {
WaitForSingleObject( m_hCheckForDoneTransfersEvent, m_FrameListSize/2 );
if ( m_fCheckTransferThreadClosing ) {
break;
}
Lock();
#ifdef DEBUG // make sure m_debug_numItemsOnBusyPipeList is accurate
{
int debugCount = 0;
PPIPE_LIST_ELEMENT pDebugElement = m_pBusyPipeList;
while ( pDebugElement != NULL ) {
pDebugElement = pDebugElement->pNext;
debugCount++;
}
DEBUGCHK( debugCount == m_debug_numItemsOnBusyPipeList );
}
BOOL fDebugNeedProcessing = m_debug_numItemsOnBusyPipeList > 0;
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes to check = %d\n"), m_debug_numItemsOnBusyPipeList) );
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && !fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - warning! Called when no pipes were busy\n")) );
#endif // DEBUG
pPrev = NULL;
pCurrent = m_pBusyPipeList;
while ( pCurrent != NULL ) {
pCurrent->pPipe->CheckForDoneTransfers();
// this pipe is still busy. Move to next item
pPrev = pCurrent;
pCurrent = pPrev->pNext;
}
// DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE && fDebugNeedProcessing, (TEXT("CPipe::CheckForDoneTransfersThread - #pipes still busy = %d\n"), m_debug_numItemsOnBusyPipeList) );
Unlock();
}
DEBUGMSG( ZONE_TRANSFER && ZONE_VERBOSE, (TEXT("-CPipe::CheckForDoneTransfersThread\n")) );
return 0;
}
// ******************************************************************
// Scope: protected static
BOOL CBusyPipeList::AddToBusyPipeList( IN CPipe * const pPipe,
IN const BOOL fHighPriority )
//
// Purpose: Add the pipe indicated by pPipe to our list of busy pipes.
// This allows us to check for completed transfers after
// getting an interrupt, and being signaled via
// SignalCheckForDoneTransfers
//
// Parameters: pPipe - pipe to add to busy list
//
// fHighPriority - if TRUE, add pipe to start of busy list,
// else add pipe to end of list.
//
// Returns: TRUE if pPipe successfully added to list, else FALSE
//
// Notes:
// ******************************************************************
{
//DEBUGMSG( ZONE_PIPE, (TEXT("+CPipe::AddToBusyPipeList - new pipe(%s) 0x%x, pri %d\n"), pPipe->GetPipeType(), pPipe, fHighPriority ));
PREFAST_DEBUGCHK( pPipe != NULL );
BOOL fSuccess = FALSE;
// make sure there nothing on the pipe already (it only gets officially added after this function succeeds).
Lock();
#ifdef DEBUG
{
// make sure this pipe isn't already in the list. That should never happen.
// also check that our m_debug_numItemsOnBusyPipeList is correct
PPIPE_LIST_ELEMENT pBusy = m_pBusyPipeList;
int count = 0;
while ( pBusy != NULL ) {
DEBUGCHK( pBusy->pPipe != NULL &&
pBusy->pPipe != pPipe );
pBusy = pBusy->pNext;
count++;
}
DEBUGCHK( m_debug_numItemsOnBusyPipeList == count );
}
#endif // DEBUG
PPIPE_LIST_ELEMENT pNewBusyElement = new PIPE_LIST_ELEMENT;
if ( pNewBusyElement != NULL ) {
pNewBusyElement->pPipe = pPipe;
if ( fHighPriority || m_pBusyPipeList == NULL ) {
// add pipe to start of list
pNewBusyElement->pNext = m_pBusyPipeList;
m_pBusyPipeList = pNewBusyElement;
} else {
// add pipe to end of list
PPIPE_LIST_ELEMENT pLastElement = m_pBusyPipeList;
while ( pLastElement->pNext != NULL ) {
pLastElement = pLastElement->pNext;
}
pNewBusyElement->pNext = NULL;
pLastElement->pNext = pNewBusyElement;
}
fSuccess = TRUE;
#ifdef DEBUG
m_debug_numItemsOnBusyPipeList++;
#endif // DEBUG
}
Unlock();
// 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 ));
}
#ifdef ASYNC_PARK_MODE
#undef ASYNC_PARK_MODE
#endif
#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,
IN LPCTSTR lpDeviceRegistry)
: m_cBusyPipeList(FRAME_LIST_SIZE)
, m_cPeriodicMgr (pCPhysMem,FRAME_LIST_SIZE)
, m_cAsyncMgr(pCPhysMem)
, m_deviceReg(HKEY_LOCAL_MACHINE,lpDeviceRegistry)
//
// Purpose: Constructor for CHW
//
// Parameters:
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
// definitions for static variables
DEBUGMSG( ZONE_INIT, (TEXT("+CHW::CHW base=0x%x, intr=0x%x\n"), portBase, dwSysIntr));
//RETAILMSG(1, (TEXT("CHW::CHW created 0x%x\r\n"), this));
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_bUSBClockStop = FALSE;
m_bUSBPanicMode = TRUE;
m_bUSBIdleSuspend = FALSE;
SetForceReAttach(0);
m_dwOTGSupport = ((SEHCDPdd *)(pvUhcdPddObject))->dwOTGSupport;
DEBUGMSG(1, (TEXT("OTG Support = %d\r\n"), m_dwOTGSupport));
StringCbCopy(m_szOTGGroup, sizeof(m_szOTGGroup), ((SEHCDPdd *)(pvUhcdPddObject))->szOTGGroup);
m_hAsyncDoorBell=CreateEvent(NULL, FALSE,FALSE,NULL);
InitializeCriticalSection( &m_csFrameCounter );
}
//*********************************************************
CHW::~CHW()
//
// Purpose: Destructor of CHW object
//
// Parameters:
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
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 );
//RETAILMSG(1, (TEXT("CHW::~CHW created 0x%x\r\n"), this));
}
// **************************************************************
BOOL CHW::DisableAsyncSchedule()
//
// Purpose: Request controller to skip the process of asynchronous scheduling
// This is used during the setup.
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
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=0;
Write_USBCMD(usbcmd);
}
while (usbcmd.bit.ASchedEnable!= Read_USBSTS().bit.ASStatus)
Sleep(1);
return TRUE;
}
//*********************************************************************
BOOL CHW::EnableAsyncSchedule()
//
// Purpose: Request controller to enable the process of asynchronous scheduling
// This is used during the setup and necessary for Asynchronous Transfer.
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
#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);
}
return TRUE;
}
//******************************************************************
BOOL CHW::PowerOnAllPorts()
//
// Purpose: Power on all the USB ports on the controller
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
//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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -