[USBOHCI]

- Enable global power mode
- Wait untill reset is complete
- Clear reset complete bit when reset is done
- Enable port
- Reset port now works
- USBOHCI still hangs after adding first control request, needs more investigation

svn path=/branches/usb-bringup/; revision=51883
This commit is contained in:
Johannes Anderwald 2011-05-24 12:51:03 +00:00
parent f75cb3d51d
commit b275073474
3 changed files with 94 additions and 23 deletions

View file

@ -489,7 +489,7 @@ CUSBHardwareDevice::GetUSBQueue(
NTSTATUS NTSTATUS
CUSBHardwareDevice::StartController(void) CUSBHardwareDevice::StartController(void)
{ {
ULONG Control, NumberOfPorts, Index, Descriptor; ULONG Control, NumberOfPorts, Index, Descriptor, FrameInterval, Periodic, IntervalValue;
// //
// first write address of HCCA // first write address of HCCA
@ -541,6 +541,48 @@ CUSBHardwareDevice::StartController(void)
// //
ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL); ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL);
//
// get frame interval
//
//FrameInterval = (READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET)) & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE;
//FrameInterval |= OHCI_FSMPS(IntervalValue) | IntervalValue;
//
// write frame interval
//
//WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval);
// 90% periodic
//Periodic = OHCI_PERIODIC(intervalValue);
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + 0x40 /*OHCI_PERIODIC_START_OFFSET*/), 0x3E67);
//
// read descriptor
//
Descriptor = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET));
//
// no over current protection
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET), Descriptor | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
//
// enable power on all ports
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_STATUS_OFFSET), OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
//
// wait a bit
//
KeStallExecutionProcessor(10);
//
// write descriptor
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET), Descriptor);
// //
// retrieve number of ports // retrieve number of ports
// //
@ -913,19 +955,11 @@ CUSBHardwareDevice::ClearPortStatus(
if (PortId > m_NumberOfPorts) if (PortId > m_NumberOfPorts)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
//
// read port status
//
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId))); Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
KeStallExecutionProcessor(100); KeStallExecutionProcessor(100);
if (Status == C_PORT_RESET) if (Status == C_PORT_RESET)
{ {
//
// complete reset
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC);
do do
{ {
// //
@ -945,15 +979,44 @@ CUSBHardwareDevice::ClearPortStatus(
// wait a bit // wait a bit
// //
KeStallExecutionProcessor(100); KeStallExecutionProcessor(100);
DPRINT1("Wait...\n");
}while(Index++ < 10); //DPRINT1("Value %x Index %lu\n", Value, Index);
if ((Value & OHCI_RH_PORTSTATUS_PRS)) }while(TRUE);
//
// check if reset bit is still set
//
if (Value & OHCI_RH_PORTSTATUS_PRS)
{ {
DPRINT1("Failed to reset\n"); //
// reset failed
//
DPRINT1("PortId %lu Reset failed\n", PortId);
return STATUS_UNSUCCESSFUL;
} }
//
// sanity checks
//
ASSERT((Value & OHCI_RH_PORTSTATUS_PRS) == 0);
ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC));
//
// clear reset bit complete
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)), OHCI_RH_PORTSTATUS_PRSC);
//
// read status register
//
Value = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_PORT_STATUS(PortId)));
//
// reset complete bit should be cleared
//
ASSERT((Value & OHCI_RH_PORTSTATUS_PRSC) == 0);
// //
// update port status // update port status
// //
@ -964,13 +1027,15 @@ CUSBHardwareDevice::ClearPortStatus(
// //
ASSERT((Value & OHCI_RH_PORTSTATUS_PES)); ASSERT((Value & OHCI_RH_PORTSTATUS_PES));
if (Value & OHCI_RH_PORTSTATUS_PES) //
{ // port is enabled
// //
// port is enabled m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE;
//
m_PortStatus[PortId].PortStatus |= USB_PORT_STATUS_ENABLE; //
} // re-enable root hub change
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_ROOT_HUB_STATUS_CHANGE);
} }
if (Status == C_PORT_CONNECTION) if (Status == C_PORT_CONNECTION)
@ -1276,6 +1341,12 @@ OhciDefferedRoutine(
// //
DPRINT1("New device arrival at Port %d LowSpeed %x\n", Index, (PortStatus & OHCI_RH_PORTSTATUS_LSDA)); DPRINT1("New device arrival at Port %d LowSpeed %x\n", Index, (PortStatus & OHCI_RH_PORTSTATUS_LSDA));
//
// enable port
//
WRITE_REGISTER_ULONG((PULONG)((PUCHAR)This->m_Base + OHCI_RH_PORT_STATUS(Index)), OHCI_RH_PORTSTATUS_PES);
// //
// store change // store change
// //

View file

@ -100,7 +100,7 @@
// //
// Root Hub status register (section 7.4.3) // Root Hub status register (section 7.4.3)
// //
#define OHCI_RH_STATUS 0x50 #define OHCI_RH_STATUS_OFFSET 0x50
#define OHCI_RH_LOCAL_POWER_STATUS 0x00000001 #define OHCI_RH_LOCAL_POWER_STATUS 0x00000001
#define OHCI_RH_OVER_CURRENT_INDICATOR 0x00000002 #define OHCI_RH_OVER_CURRENT_INDICATOR 0x00000002
#define OHCI_RH_DEVICE_REMOTE_WAKEUP_ENABLE 0x00008000 #define OHCI_RH_DEVICE_REMOTE_WAKEUP_ENABLE 0x00008000

View file

@ -922,9 +922,9 @@ CHubController::HandleClassOther(
case PORT_ENABLE: case PORT_ENABLE:
{ {
// //
// port enable is a no-op for OHCI // port enable
// //
Status = STATUS_SUCCESS; Status = m_Hardware->SetPortFeature(PortId, PORT_ENABLE);
break; break;
} }