⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chw.cpp

📁 Intel PXA270 Wince5.0 BSP
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        m_portBase->HcControl.CLE=fEnable;
        if (fFill) m_portBase->HcCommandStatus.CLF=1;
    }
    if (bfList & LIST_BULK) {
        if (fEnable && !m_portBase->HcControl.BLE)
            m_portBase->HcBulkCurrentED = 0;
        m_portBase->HcControl.BLE=fEnable;
        if (fFill) m_portBase->HcCommandStatus.BLF=1;
    }
    if (bfList & LIST_INTERRUPT) {
        m_portBase->HcControl.PLE=fEnable;
    }
    if (bfList & LIST_ISOCH) {
        if (fEnable)
            m_portBase->HcControl.PLE=fEnable;
        m_portBase->HcControl.IE=fEnable;
    }
}

// ******************************************************************
DWORD CHW::UsbInterruptThreadStub( IN PVOID context )
//
// 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
// ******************************************************************
{
    CeSetThreadPriority( GetCurrentThread(), g_IstThreadPriority );

    DEBUGMSG(ZONE_INIT && ZONE_VERBOSE, (TEXT("+CHW::Entered USBInterruptThread\n")));

    while ( !m_fUsbInterruptThreadClosing ) {
        WaitForSingleObject(m_hUsbInterruptEvent, INFINITE);
        if ( m_fUsbInterruptThreadClosing ) {
            break;
        }


        // the cast is used here to remove the volatile qualifier so we can cache the register
        union HcRegisters::HcInterruptStatus usbsts = const_cast<HcRegisters *>(m_portBase)->HcInterruptStatus;
#ifdef DEBUG
        DWORD dwFrame = GetFrameNumber(); // calls UpdateFrameCounter
        DEBUGMSG( ZONE_REGISTERS, (TEXT("!!!interrupt!!!! on frame index + 1 = 0x%08x, USBSTS = 0x%08x\n"), dwFrame, usbsts.reg ) );
#else
        UpdateFrameCounter();
#endif // DEBUG


		//RETAILMSG(1,(TEXT("bpc CHW::UsbInterruptThreadStub: HcInterruptStatus is %08x.\r\n"), usbsts.reg ));


        if(g_fPowerUpFlag)
        {
			RETAILMSG(1,(TEXT("bpc CHW::UsbInterruptThreadStub: g_fPowerUpFlag is set.\r\n")));
            g_fPowerUpFlag = FALSE;
            HcdPdd_InitiatePowerUp((DWORD) context);
        }

        if (usbsts.RHSC) {
        }
        DWORD paDoneHead = m_pHCCA->HccaDoneHead & ~1; // ignore LSb (see OHCI figure 4-5)
        DEBUGCHK( (paDoneHead & 0xF) == 0 );
        if (paDoneHead) {
            DEBUGCHK(usbsts.WDH);
            m_pHCCA->HccaDoneHead = 0;
            CPipe::SignalCheckForDoneTransfers( paDoneHead );
        }

        // Acknowledge the interrupt(s)
        m_portBase->HcInterruptStatus.reg = usbsts.reg;
        InterruptDone(m_dwSysIntr);
    }

    DEBUGMSG(ZONE_INIT && ZONE_VERBOSE, (TEXT("-CHW::Leaving USBInterruptThread\n")));

    return (0);
}

// ******************************************************************
void CHW::UpdateFrameCounter( void )
//
// Purpose: Updates our internal frame counter
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: The OHCI frame number register is 16 bits long.
//        Thus, the counter will wrap approx. every 64 seconds.
//        We maintain an additional 16 bits internally so we
//        needn't wrap for 50 days.
//
//        This function should be called at least once a minute;
//        otherwise we could miss frames.
//
// ******************************************************************
{
#ifdef DEBUG
    static DWORD dwTickCountLastTime = GetTickCount();
#endif
    static WORD lastFn = 0;

    EnterCriticalSection( &m_csFrameCounter );

#ifdef DEBUG
    // If this fails, we haven't been called in a long time,
    // so the frame number is no longer accurate
    if (GetTickCount() - dwTickCountLastTime >= 64000 )
        DEBUGMSG(1, (TEXT("!UHCI - CHW::UpdateFrameCounter missed frame count;")
                     TEXT(" isoch packets may have been dropped.\n")));
    dwTickCountLastTime = GetTickCount();
#endif // DEBUG

    WORD fn = m_pHCCA->HccaFrameNumber;
    if (fn < lastFn)
        ++m_wFrameHigh;
    lastFn = fn;

    LeaveCriticalSection( &m_csFrameCounter );
}

// ******************************************************************
DWORD CHW::GetFrameNumber( void )
//
// Purpose: Return the current frame number
//
// Parameters: None
//
// Returns: 32 bit current frame number
//
// Notes: See also comment in UpdateFrameCounter
// ******************************************************************
{
    UpdateFrameCounter();
    return ((DWORD) m_wFrameHigh << 16) | m_pHCCA->HccaFrameNumber ;
}

// ******************************************************************
BOOL CHW::WaitOneFrame( void )
//
// Purpose: Block the current thread until the HC hardware is
//          no longer processing the current USB frame.
//
// Parameters: None
//
// Returns: TRUE on success, FALSE if the HW is unavailable or not running.
//
// Notes:
// ******************************************************************
{
    // is the host controller operational?
    if ( m_portBase != 0 ) {
        if(m_portBase->HcControl.HCFS != HcRegisters::HcControl::HCFS_OPERATIONAL) {
            // no, just wait a short while and return
            Sleep(10);
			RETAILMSG(1,(TEXT("CHW::WaitOneFrame: no m_portBase, done waiting.\r\n")));
            return TRUE;
        }
    }

    // The OS' system clock - prior to CE3.0 - has 25ms granularity
    // which is just too high. Later versions have a 1ms clock.
    //
    // Sleep may not be enough if the frame has been made longer
    // so we poll after the 1ms. If the frame has been made shorter
    // then this will just take too long.
    m_pHCCA->HccaPad1 = 1; // HC will write 0 here when updating FN (OHCI Figure 4-5)
#ifndef CE_PREv3
  Sleep(1);
// if we just do a tight spin, it will probably improve
// the mouse performance, but doom the overall system
// performance...
#endif

	// added a check for the OHCI FmNumber.FN register
	// in addition to the clearing of the m_pHCCA->HccaPad1
	// field because, in Bulverde A0, an USB OHCI master
	// abort can cause the m_pHCCA->HccaPad1 to stop updating.
	{
		unsigned long	ulFN;

		ulFN = m_portBase->HcFmNumber.FN;
		while (m_pHCCA->HccaPad1)
		{
			if( m_portBase->HcFmNumber.FN != ulFN )
				break;
		}
	}

    return TRUE;
}

// ******************************************************************
USHORT CHW::GetFrameLength( void )
//
// Purpose: Return the current frame length in 12 MHz clocks
//          (i.e. 12000 = 1ms)
//
// Parameters: None
//
// Returns: frame length
//
// Notes:
// ******************************************************************
{
    return m_portBase->HcFmInterval.FI;
}

// ******************************************************************
BOOL CHW::SetFrameLength( IN HANDLE hEvent,
                          IN const USHORT uFrameLength )
//
// Purpose: Set the Frame Length in 12 Mhz clocks. i.e. 12000 = 1ms
//
// Parameters:  hEvent - event to set when frame has reached required
//                       length
//
//              uFrameLength - new frame length
//
// Returns: TRUE if frame length changed, else FALSE
//
// Notes:
// ******************************************************************
{
    BOOL fSuccess = FALSE;

    // to prevent multiple threads from simultaneously adjusting the
    // frame length, InterlockedTestExchange is used. This is
    // cheaper than using a critical section.
#ifdef JEFFRO
    if ( FALSE == InterlockedTestExchange( &m_fFrameLengthIsBeingAdjusted,
                                           FALSE, // Test value (Old value)
                                           TRUE ) ) { // New value

        // m_fFrameLengthIsBeingAdjusted was set to TRUE
        // by the InterlockedTestExchange
        if ( uFrameLength >= UHCD_SOFMOD_MINIMUM_LENGTH &&
             uFrameLength <= UHCD_SOFMOD_MAXIMUM_LENGTH &&
             hEvent != NULL ) {

            // ok, all the params are fine
            m_hAdjustDoneCallbackEvent = hEvent;
            m_uNewFrameLength = uFrameLength;
            InterlockedExchange( &m_fStopAdjustingFrameLength, FALSE );

            // the frame length needs to be adjusted over
            // many frames, so we need a separate thread

            HANDLE hWorkerThread = CreateThread( 0, 0, UsbAdjustFrameLengthThread, (LPVOID) 0xdeadbeef, 0, NULL );
            if ( hWorkerThread != NULL ) {
                CloseHandle( hWorkerThread );
                hWorkerThread = NULL;
                fSuccess = TRUE;
            }
        }
        if ( !fSuccess ) {
            // we didn't succeed, so change m_fFrameLengthIsBeingAdjusted
            // back to FALSE
        #ifdef DEBUG
            LONG oldValue =
        #endif // DEBUG
                InterlockedExchange( &m_fFrameLengthIsBeingAdjusted, FALSE );
            DEBUGCHK( oldValue );
        }
    }
#endif //JEFFRO
    return fSuccess;
}

// ******************************************************************
BOOL CHW::StopAdjustingFrame( void )
//
// Purpose: Stop modifying the host controller frame length
//
// Parameters: None
//
// Returns: TRUE
//
// Notes:
// ******************************************************************
{
    InterlockedExchange( &m_fStopAdjustingFrameLength, TRUE );
    return TRUE;
}

// ******************************************************************
DWORD CHW::UsbAdjustFrameLengthThread( IN PVOID context )
//
// Purpose: Worker thread to handle frame length adjustment
//
// Parameters: context - parameter passed in when starting thread,
//                       (currently unused)
//
// Returns: 0 on thread exit.
//
// Notes:
//
//        This function is private
// ******************************************************************
{
    CeSetThreadPriority( GetCurrentThread(), g_IstThreadPriority + RELATIVE_PRIO_ADJUST_FRAME );

    DEBUGMSG(ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("+CHW::Entered UsbAdjustFrameLengthThread\n")));

#ifdef JEFFRO
    // context isn't used right now
    DEBUGCHK( DWORD( context ) == 0xdeadbeef );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -