📄 chw.cpp
字号:
32, 4, 0x01, // 0000 0000 bits 0
32, 6, 0x01, // 0000 0000 bits 0
32, 3, 0x10, // 0000 0000 bits 4
32, 5, 0x10, // 0000 0000 bits 4
32, 4, 0x10, // 0000 0000 bits 4
32, 6, 0x10, // 0000 0000 bits 4
32, 3, 0x04, // 0000 0000 bits 2
32, 5, 0x04, // 0000 0000 bits 2
32, 4, 0x04, // 0000 0000 bits 2
32, 6, 0x04, // 0000 0000 bits 2
32, 3, 0x40, // 0000 0000 bits 6
32, 5, 0x40, // 0000 0000 bits 6
32, 4, 0x40, // 0000 0000 bits 6
32, 6, 0x40, // 0000 0000 bits 6
32, 3, 0x02, // 0000 0000 bits 1
32, 5, 0x02, // 0000 0000 bits 1
32, 4, 0x02, // 0000 0000 bits 1
32, 6, 0x02, // 0000 0000 bits 1
32, 3, 0x20, // 0000 0000 bits 5
32, 5, 0x20, // 0000 0000 bits 5
32, 4, 0x20, // 0000 0000 bits 5
32, 6, 0x20, // 0000 0000 bits 5
32, 3, 0x04, // 0000 0000 bits 3
32, 5, 0x04, // 0000 0000 bits 3
32, 4, 0x04, // 0000 0000 bits 3
32, 6, 0x04, // 0000 0000 bits 3
32, 3, 0x40, // 0000 0000 bits 7
32, 5, 0x40, // 0000 0000 bits 7
32, 4, 0x40, // 0000 0000 bits 7
32, 6, 0x40, // 0000 0000 bits 7
};
//*************************************************************************************
CQH * CPeriodicMgr::QueueQHead(CQH * pQh,UCHAR uInterval,UCHAR offset,BOOL bHighSpeed)
//
// Purpose: Periodic Manager: Queue the queue head for the Periodic Transfer
//
// Parameters:
//
// Returns: Pointer to the object CQH
//
// Notes:
//******************************************************************
{
if (pQh) {
if (uInterval> PERIOD_TABLE_SIZE)
uInterval= PERIOD_TABLE_SIZE;
Lock();
for (UCHAR bBit=PERIOD_TABLE_SIZE;bBit!=0;bBit>>=1) {
if ((bBit & uInterval)!=0) { // THis is correct interval
// Normalize the parameter.
uInterval = bBit;
if (offset>=uInterval)
offset = uInterval -1;
CQH * pStaticQH=NULL ;
UCHAR S_Mask=0;
if (bHighSpeed) {
pStaticQH=m_pStaticQHArray[ periodTable[uInterval+offset].qhIdx +1] ;
pQh->SetSMask(periodTable[uInterval+offset].InterruptScheduleMask);
}
else
pStaticQH = m_pStaticQHArray[uInterval+offset];
if (pStaticQH!=NULL) {
pQh->QueueQHead( pStaticQH->GetNextQueueQHead(m_pCPhysMem));
pStaticQH->QueueQHead( pQh );
Unlock();
return pStaticQH;
}
else
ASSERT(FALSE);
}
}
ASSERT(FALSE);
CQH * pStaticQH = m_pStaticQHArray[1];
if (pStaticQH!=NULL) {
pQh->QueueQHead( pStaticQH->GetNextQueueQHead(m_pCPhysMem));
if (bHighSpeed)
pQh->SetSMask(0xff);
pStaticQH->QueueQHead( pQh );
Unlock();
return pStaticQH;
}
else
ASSERT(FALSE);
Unlock();
}
ASSERT(FALSE);
return NULL;
}
//**********************************************************************
BOOL CPeriodicMgr::DequeueQHead( CQH * pQh)
//
// Purpose: CPeriodicMgr: Dequeue the queue head after transfer completed
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure, not found
//
// Notes:
// ******************************************************************
{
if (pQh==NULL) {
ASSERT(FALSE);
return FALSE;
}
Lock();
for (DWORD dwIndex=PERIOD_TABLE_SIZE;dwIndex<2*PERIOD_TABLE_SIZE;dwIndex ++) {
CQH *pCurPrev= m_pStaticQHArray[dwIndex];
if (pCurPrev!=NULL) {
while (pCurPrev!=NULL) {
CQH *pCur=pCurPrev->GetNextQueueQHead(m_pCPhysMem);
if (pCur == pQh)
break;
else
pCurPrev = pCur;
}
if (pCurPrev!=NULL) { // Found
ASSERT(pCurPrev->GetNextQueueQHead(m_pCPhysMem) == pQh);
pCurPrev->QueueQHead(pQh->GetNextQueueQHead(m_pCPhysMem));
pQh->QueueQHead(NULL);
Unlock();
Sleep(2); // Make Sure it outof EHCI Scheduler.
return TRUE;
}
}
else
ASSERT(FALSE);
}
Unlock();
ASSERT(FALSE);
return FALSE;
}
// ************************************CAsyncMgr******************************
//********************************************************************
CAsyncMgr::CAsyncMgr(IN CPhysMem * const pCPhysMem)
:m_pCPhysMem(pCPhysMem)
, m_pCDumpPipe(new CDummyPipe(pCPhysMem))
//
// Purpose: Constructor for Asynchronous Manager
//
// Parameters: pCPhysMem - Pointer to CPhysMem object
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
m_pStaticQHead =NULL;
}
//*******************************************************************
CAsyncMgr::~CAsyncMgr()
//
// Purpose: Decontructor :Asynchronous Manager
//
// Parameters:
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
DeInit();
}
//********************************************************************
BOOL CAsyncMgr::Init()
//
// Purpose: Initialize the Asychronous Manager including setting up CQH,
// queue head.
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
Lock();
m_pStaticQHead = new (m_pCPhysMem) CQH(m_pCDumpPipe);
if (m_pStaticQHead) {
//RETAILMSG(1, (TEXT("Set Queue Head with H = 1 at 0x%x\r\n"), m_pStaticQHead->GetPhysAddr()));
m_pStaticQHead->SetReclamationFlag(TRUE);
m_pStaticQHead ->QueueQHead(m_pStaticQHead); // Point to itself.
Unlock();
return TRUE;
}
Unlock();
return FALSE;
}
//********************************************************************
void CAsyncMgr::DeInit()
//
// Purpose: De-initialize the Asychronous Manager
//
// Parameters:
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
Lock();
if (m_pStaticQHead){
//delete (m_pCPhysMem) m_pStaticQHead;
m_pStaticQHead->~CQH();
m_pCPhysMem->FreeMemory((PBYTE)m_pStaticQHead,m_pCPhysMem->VaToPa((PBYTE)m_pStaticQHead),CPHYSMEM_FLAG_HIGHPRIORITY | CPHYSMEM_FLAG_NOBLOCK);
}
m_pStaticQHead= NULL;
Unlock();
}
//**********************************************************************
CQH * CAsyncMgr::QueueQH(CQH * pQHead)
//
// Purpose: Put the new queue head into the Asychronous Manager to be transferred
//
// Parameters: pQHead - Pointer to CQH object
//
// Returns: Pointer to the first object of linked-list of queue head, NULL - failure
//
// Notes:
// ******************************************************************
{
if (m_pStaticQHead && pQHead){
Lock();
pQHead->QueueQHead( m_pStaticQHead ->GetNextQueueQHead(m_pCPhysMem));
m_pStaticQHead ->QueueQHead(pQHead);
Unlock();
return m_pStaticQHead;
};
return NULL;
}
//***********************************************************************
BOOL CAsyncMgr::DequeueQHead( CQH * pQh)
//
// Purpose: Dequeue the queue head from the Asynchronous Manager
//
// Parameters: pQh - Queue head to be dequeue
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
CQH * pPrevQH = m_pStaticQHead;
CQH * pCurQH = NULL;
Lock();
for (DWORD dwIndex=0;dwIndex<0x1000;dwIndex++)
if (pPrevQH) {
pCurQH= pPrevQH->GetNextQueueQHead(m_pCPhysMem);
if (pCurQH == m_pStaticQHead || pCurQH == pQh)
break;
else
pPrevQH = pCurQH;
};
if ( pCurQH && pPrevQH && pCurQH == pQh) {
pPrevQH->QueueQHead(pCurQH ->GetNextQueueQHead(m_pCPhysMem));
Unlock();
return TRUE;
}
else
ASSERT(FALSE);
Unlock();
return FALSE;
};
// ******************************BusyPipeList****************************
//*******************************************************************
BOOL CBusyPipeList::Init()
//
// Purpose: Initialize the CBusyPipeList class. The busy pipe list class is to
// spawn out a thread keeping on monitoring all the created pipes and see
// if the USB transfer has been completed.
//
// Parameters:
//
// Returns: TRUE - success, FALSE - failure
//
// Notes:
// ******************************************************************
{
m_fCheckTransferThreadClosing=FALSE;
m_pBusyPipeList = NULL;
m_hCheckForDoneTransfersEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( m_hCheckForDoneTransfersEvent == NULL ) {
DEBUGMSG(ZONE_ERROR, (TEXT("-CPipe::Initialize. Error creating process done transfers event\n")));
return FALSE;
}
#ifdef DEBUG
m_debug_numItemsOnBusyPipeList=0;
#endif
// set up our thread to check for done transfers
// currently, the context passed to CheckForDoneTransfersThread is ignored
m_hCheckForDoneTransfersThread = CreateThread( 0, 0, CheckForDoneTransfersThreadStub, (PVOID)this, 0, NULL );
if ( m_hCheckForDoneTransfersThread == NULL ) {
DEBUGMSG(ZONE_ERROR, (TEXT("-CPipe::Initialize. Error creating process done transfers thread\n")));
return FALSE;
}
CeSetThreadPriority( m_hCheckForDoneTransfersThread, g_IstThreadPriority + RELATIVE_PRIO_CHECKDONE );
return TRUE;
}
//**********************************************************************************
void CBusyPipeList::DeInit()
//
// Purpose: Deinitialize the busy pipe list and close the CheckForDoneTransfersThread
//
// Parameters:
//
// Returns: Nothing
//
// Notes:
// ******************************************************************
{
m_fCheckTransferThreadClosing=TRUE;
if ( m_hCheckForDoneTransfersEvent != NULL ) {
SignalCheckForDoneTransfers();
if ( m_hCheckForDoneTransfersThread ) {
DWORD dwWaitReturn = WaitForSingleObject( m_hCheckForDoneTransfersThread, 5000 );
if ( dwWaitReturn != WAIT_OBJECT_0 ) {
DEBUGCHK( 0 ); // check why thread is blocked
#pragma prefast(suppress: 258, "Try to recover gracefully from a pathological failure")
TerminateThread( m_hCheckForDoneTransfersThread, DWORD(-1) );
}
CloseHandle( m_hCheckForDoneTransfersThread );
m_hCheckForDoneTransfersThread = NULL;
}
CloseHandle( m_hCheckForDoneTransfersEvent );
m_hCheckForDoneTransfersEvent = NULL;
}
}
// ******************************************************************
// Scope: public static
void CBusyPipeList::SignalCheckForDoneTransfers( void )
//
// Purpose: This function is called when an interrupt is received by
// the CHW class. We then signal the CheckForDoneTransfersThread
// to check for any transfers which have completed
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: DO MINIMAL WORK HERE!! Most processing should be handled by
// The CheckForDoneTransfersThread. If this procedure blocks, it
// will adversely affect the interrupt processing thread.
// ******************************************************************
{
DEBUGCHK( m_hCheckForDoneTransfersEvent && m_hCheckForDoneTransfersThread );
SetEvent( m_hCheckForDoneTransfersEvent );
}
// ******************************************************************
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -