?? chw.cpp
字號:
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::UsbAdjustFrameLengthThreadStub(PVOID context)
{
return ((CHW *)context)->UsbAdjustFrameLengthThread( );
}
// ******************************************************************
DWORD CHW::UsbAdjustFrameLengthThread( )
//
// 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
// ******************************************************************
{
DEBUGMSG(ZONE_REGISTERS && ZONE_VERBOSE, (TEXT("+CHW::Entered UsbAdjustFrameLengthThread\n")));
#ifdef JEFFRO
DEBUGCHK( m_fFrameLengthIsBeingAdjusted &&
!m_fStopAdjustingFrameLength &&
m_hAdjustDoneCallbackEvent != NULL &&
m_uNewFrameLength >= UHCD_SOFMOD_MINIMUM_LENGTH &&
m_uNewFrameLength <= UHCD_SOFMOD_MAXIMUM_LENGTH );
const UCHAR uRequiredSOFMOD = UCHAR( m_uNewFrameLength - UHCD_SOFMOD_MINIMUM_LENGTH );
// if the interrupt thread is closing, or we're signaled
// to stop adjusting the frame length, stop!
while ( !m_fStopAdjustingFrameLength &&
!m_fUsbInterruptThreadClosing ) {
UCHAR uCurrentSOFMOD = Read_SOFMOD() & UHCD_SOFMOD_MASK;
DEBUGMSG(ZONE_REGISTERS, (TEXT("CHW::UsbAdjustFrameLengthThread, current length = %d, required = %d\n"), UHCD_SOFMOD_MINIMUM_LENGTH + uCurrentSOFMOD, UHCD_SOFMOD_MINIMUM_LENGTH + uRequiredSOFMOD ));
if ( uCurrentSOFMOD == uRequiredSOFMOD ) {
// ok, we're done
__try {
SetEvent( m_hAdjustDoneCallbackEvent );
} __except(EXCEPTION_EXECUTE_HANDLER) {
}
break;
} else if ( uCurrentSOFMOD > uRequiredSOFMOD ) {
uCurrentSOFMOD--;
} else {
DEBUGCHK( uCurrentSOFMOD < uRequiredSOFMOD );
uCurrentSOFMOD++;
}
// USB spec 1.1, section 7.1.12 says we can't adjust
// the frame length by more than 1 bit every 6 frames.
// Assuming a maximum frame length of 12063 bits, plus
// 15 bits error, that totals 6.039ms. So, just to
// be safe, we'll sleep 7 ms before adjusting the length.
Sleep( 7 );
Write_SOFMOD( uCurrentSOFMOD );
}
// set m_fFrameLengthIsBeingAdjusted to FALSE
InterlockedExchange( &m_fFrameLengthIsBeingAdjusted, FALSE );
DEBUGMSG(ZONE_REGISTERS, (TEXT("-CHW::UsbAdjustFrameLengthThread\n")));
#endif //JEFFRO
return (0);
}
// ******************************************************************
BOOL CHW::DidPortStatusChange( IN const UCHAR port )
//
// Purpose: Determine whether the status of root hub port # "port" changed
//
// Parameters: port - 0 for the hub itself, otherwise the hub port number
//
// Returns: TRUE if status changed, else FALSE
//
// Notes:
// ******************************************************************
{
USB_HUB_AND_PORT_STATUS s;
CHW::GetPortStatus(port, s);
return s.change.word ? TRUE : FALSE;
}
// ******************************************************************
BOOL CHW::GetPortStatus( IN const UCHAR port,
OUT USB_HUB_AND_PORT_STATUS& rStatus )
//
// Purpose: This function will return the current root hub port
// status in a non-hardware specific format
//
// Parameters: port - 0 for the hub itself, otherwise the hub port number
//
// rStatus - reference to USB_HUB_AND_PORT_STATUS to get the
// status
//
// Returns: TRUE
//
// Notes:
// ******************************************************************
{
memset( &rStatus, 0, sizeof( USB_HUB_AND_PORT_STATUS ) );
if ( port > 0 ) {
// request refers to a root hub port
DEBUGCHK ( port <= m_portBase->HcRhDescriptorA.NDP );
// read the port status register (compiler complains when we do it the easy way)
union HcRegisters::HcRhPortStatus sr;
sr.reg = m_portBase->HcRhPortStatus[port-1].reg;
// Now fill in the USB_HUB_AND_PORT_STATUS structure
rStatus.change.port.ConnectStatusChange = sr.CSC;
rStatus.change.port.PortEnableChange = sr.PESC;
rStatus.change.port.OverCurrentChange = sr.OCIC;
rStatus.change.port.SuspendChange = sr.PSSC;
rStatus.change.port.ResetChange = sr.PRSC;
rStatus.status.port.DeviceIsLowSpeed = sr.LSDA;
rStatus.status.port.PortConnected = sr.CCS;
rStatus.status.port.PortEnabled = sr.PES;
rStatus.status.port.PortOverCurrent = sr.POCI;
// we assume root hub ports are always powered, but believe the HW.
rStatus.status.port.PortPower = sr.PPS;
rStatus.status.port.PortReset = sr.PRS;
rStatus.status.port.PortSuspended = sr.PSS;
}
#ifdef DEBUG // these are available in OHCI but this driver doesn't use them
else {
// request is to Hub. rStatus was already memset to 0 above.
DEBUGCHK( port == 0 );
// local power supply good
DEBUGCHK( rStatus.status.hub.LocalPowerStatus == 0 );
// no over current condition
DEBUGCHK( rStatus.status.hub.OverCurrentIndicator == 0 );
// no change in power supply status
DEBUGCHK( rStatus.change.hub.LocalPowerChange == 0 );
// no change in over current status
DEBUGCHK( rStatus.change.hub.OverCurrentIndicatorChange == 0 );
}
#endif // DEBUG
return TRUE;
}
// ******************************************************************
void CHW::GetRootHubDescriptor( OUT USB_HUB_DESCRIPTOR &descriptor )
//
// Purpose: Calculate and return a hub descriptor for the root hub so
// that the upper-level code can pretend it's an external hub.
//
// Parameters: a reference to a descriptor to fill in.
//
// Returns: nothing
//
// Notes: assumes the hardware is sufficiently initialized.
// ******************************************************************
{
DEBUGCHK ( m_portBase != 0 );
descriptor.bNumberOfPorts = m_portBase->HcRhDescriptorA.NDP;
DEBUGCHK( descriptor.bNumberOfPorts >= 1 && descriptor.bNumberOfPorts <= 15 );
// root hub is not part of a compound device (per OHCI 7.4.1)
DEBUGCHK( m_portBase->HcRhDescriptorA.DT == 0 );
descriptor.wHubCharacteristics =
(m_portBase->HcRhDescriptorA.NPS
? USB_HUB_CHARACTERISTIC_NO_POWER_SWITCHING
: m_portBase->HcRhDescriptorA.PSM
? USB_HUB_CHARACTERISTIC_INDIVIDUAL_POWER_SWITCHING
: USB_HUB_CHARACTERISTIC_GANGED_POWER_SWITCHING) |
USB_HUB_CHARACTERISTIC_NOT_PART_OF_COMPOUND_DEVICE |
(m_portBase->HcRhDescriptorA.NOCP
? USB_HUB_CHARACTERISTIC_NO_OVER_CURRENT_PROTECTION
: m_portBase->HcRhDescriptorA.OCPM
? USB_HUB_CHARACTERISTIC_INDIVIDUAL_OVER_CURRENT_PROTECTION
: USB_HUB_CHARACTERISTIC_GLOBAL_OVER_CURRENT_PROTECTION);
descriptor.bPowerOnToPowerGood = m_portBase->HcRhDescriptorA.POTPGT;
descriptor.bHubControlCurrent = 0;
int bmsize = 1 + descriptor.bNumberOfPorts / 8; // bytes to represent nports+1 bits
for (int i=0; i<bmsize; ++i) {
descriptor.bRemoveAndPowerMask[i] = (UCHAR) (m_portBase->HcRhDescriptorB.DR >> i) & 0xFF;
descriptor.bRemoveAndPowerMask[i+bmsize] = 0xFF; // must be 0xFF, USB spec 1.1, table 11-8
}
// min size assumes seven or fewer ports so we must account for more.
descriptor.bDescriptorLength = USB_HUB_DESCRIPTOR_MINIMUM_SIZE + (bmsize-1)*2;
descriptor.bDescriptorType = USB_HUB_DESCRIPTOR_TYPE;
}
// ******************************************************************
BOOL CHW::RootHubFeature( IN const UCHAR port,
IN const UCHAR setOrClearFeature,
IN const USHORT feature )
//
// Purpose: This function clears all the status change bits associated with
// the specified root hub port.
//
// Parameters: port - 0 for the hub itself, otherwise the hub port number
//
// Returns: TRUE iff the requested operation is valid, FALSE otherwise.
//
// Notes: Assume that caller has already verified the parameters from a USB
// perspective. The HC hardware may only support a subset of that
// (which is indeed the case for UHCI).
// ******************************************************************
{
if (port == 0) {
// request is to Hub
return FALSE;
}
DEBUGCHK( port >= 1 && port <= m_portBase->HcRhDescriptorA.NDP );
DWORD dwPortStatus = 0;
if (setOrClearFeature == USB_REQUEST_SET_FEATURE)
switch (feature) {
case USB_HUB_FEATURE_PORT_RESET: dwPortStatus = HcRegisters::HcRhPortStatus::SPR; break;
case USB_HUB_FEATURE_PORT_SUSPEND: dwPortStatus = HcRegisters::HcRhPortStatus::SPS; break;
case USB_HUB_FEATURE_PORT_POWER: dwPortStatus = HcRegisters::HcRhPortStatus::SPP; break;
case USB_HUB_FEATURE_PORT_ENABLE: dwPortStatus = HcRegisters::HcRhPortStatus::SPE; break;
default: return FALSE;
}
else
switch (feature) {
case USB_HUB_FEATURE_PORT_ENABLE: dwPortStatus = HcRegisters::HcRhPortStatus::CPE; break;
case USB_HUB_FEATURE_PORT_SUSPEND: dwPortStatus = HcRegisters::HcRhPortStatus::CPS; break;
case USB_HUB_FEATURE_C_PORT_CONNECTION: dwPortStatus = HcRegisters::HcRhPortStatus::CCSC; break;
case USB_HUB_FEATURE_C_PORT_ENABLE: dwPortStatus = HcRegisters::HcRhPortStatus::CPESC; break;
case USB_HUB_FEATURE_C_PORT_RESET: dwPortStatus = HcRegisters::HcRhPortStatus::CPRSC; break;
case USB_HUB_FEATURE_C_PORT_SUSPEND: dwPortStatus = HcRegisters::HcRhPortStatus::CPSSC; break;
case USB_HUB_FEATURE_C_PORT_OVER_CURRENT: dwPortStatus = HcRegisters::HcRhPortStatus::COCIC; break;
case USB_HUB_FEATURE_PORT_POWER: dwPortStatus = HcRegisters::HcRhPortStatus::CPP; break;
default: return FALSE;
}
m_portBase->HcRhPortStatus[port-1].reg = dwPortStatus;
return TRUE;
}
// ******************************************************************
BOOL CHW::ResetAndEnablePort( IN const UCHAR port )
//
// Purpose: reset/enable device on the given port so that when this
// function completes, the device is listening on address 0
//
// Parameters: port - root hub port # to reset/enable
//
// Returns: TRUE if port reset and enabled, else FALSE
//
// Notes: This function takes approx 60 ms to complete, and assumes
// that the caller is handling any critical section issues
// so that two different ports (i.e. root hub or otherwise)
// are not reset at the same time.
// ******************************************************************
{
BOOL fSuccess = TRUE;
DEBUGCHK( port >= 1 && port <= m_portBase->HcRhDescriptorA.NDP );
// turn on reset bit
RootHubFeature(port, USB_REQUEST_SET_FEATURE, USB_HUB_FEATURE_PORT_RESET);
// USB 1.1 spec section 7.1.7.3 recommends 50ms for root hub ports
// but OHCI hardware clears reset after only 10ms.
Sleep( 10 );
while (m_portBase->HcRhPortStatus[port-1].PRS) Sleep( 1 );
// Verify that the port has finished resetting and enabling itself
DEBUGCHK ( m_portBase->HcRhPortStatus[port-1].PRS == 0 );
DEBUGCHK ( m_portBase->HcRhPortStatus[port-1].PRSC == 1 );
RootHubFeature(port, USB_REQUEST_CLEAR_FEATURE, USB_HUB_FEATURE_C_PORT_RESET);
DEBUGCHK ( m_portBase->HcRhPortStatus[port-1].PRSC == 0 );
RootHubFeature(port, USB_REQUEST_SET_FEATURE, USB_HUB_FEATURE_PORT_ENABLE);
DEBUGCHK ( m_portBase->HcRhPortStatus[port-1].PES == 1 );
// USB 1.1 spec, 7.1.7.3 - device may take up to 10 ms
// to recover after reset is removed
Sleep( 10 );
DEBUGMSG( ZONE_REGISTERS, (TEXT("Root hub, after reset & enable, port %d \n"), port) );
return fSuccess;
}
// ******************************************************************
void CHW::DisablePort( IN const UCHAR port )
//
// Purpose: disable the given root hub port
//
// Parameters: port - port # to disable
//
// Returns: nothing
//
// Notes: This function will take about 10ms to complete
// ******************************************************************
{
RootHubFeature(port, USB_REQUEST_CLEAR_FEATURE, USB_HUB_FEATURE_PORT_ENABLE);
}
#ifdef DEBUG
// ******************************************************************
void CHW::DumpAllRegisters( void )
//
// Purpose: Queries Host Controller for all registers, and prints
// them to DEBUG output. Register definitions are in UHCI spec 2.1
//
// Parameters: None
//
// Returns: Nothing
//
// Notes: used in DEBUG mode only
//
// This function is static
// ******************************************************************
{
DEBUGMSG(ZONE_REGISTERS, (TEXT("CHW - DUMP REGISTERS BEGIN\n")));
for ( USHORT port = 1; port <= UHCD_NUM_ROOT_HUB_PORTS; port++ ) {
;
}
DEBUGMSG(ZONE_REGISTERS, (TEXT("CHW - DUMP REGISTERS DONE\n")));
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -