📄 chw.cpp
字号:
32, 6, 0x40, // 0000 0000 bits 7
};
CQH * CPeriodicMgr::QueueQHead(CQH * pQh,UCHAR uInterval,UCHAR offset,BOOL bHighSpeed)
{
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)
{
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))
{
m_pStaticQHead =NULL;
}
CAsyncMgr::~CAsyncMgr()
{
DeInit();
}
BOOL CAsyncMgr::Init()
{
Lock();
m_pStaticQHead = new (m_pCPhysMem) CQH(m_pCDumpPipe);
if (m_pStaticQHead) {
m_pStaticQHead->SetReclamationFlag(TRUE);
m_pStaticQHead ->QueueQHead(m_pStaticQHead); // Point to itself.
Unlock();
return TRUE;
}
Unlock();
return FALSE;
}
void CAsyncMgr::DeInit()
{
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)
{
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)
{
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()
{
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()
{
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
// 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:
// ******************************************************************
{
SetKMode(TRUE);
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();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -