[USBOHCI]
authorCameron Gutman <aicommander@gmail.com>
Wed, 25 Jan 2012 19:46:44 +0000 (19:46 +0000)
committerCameron Gutman <aicommander@gmail.com>
Wed, 25 Jan 2012 19:46:44 +0000 (19:46 +0000)
- Fix StartController() to perform initialization according to OHCI spec
- Fixes the infamous OHCI initialization hang on real hardware

svn path=/branches/usb-bringup-trunk/; revision=55181

drivers/usb/usbohci/hardware.cpp
drivers/usb/usbohci/hardware.h

index 8d8de64..e935c41 100644 (file)
@@ -495,11 +495,6 @@ CUSBHardwareDevice::StartController(void)
 {
     ULONG Control, NumberOfPorts, Index, Descriptor, FrameInterval, Periodic;
 
-    //
-    // first write address of HCCA
-    //
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET), m_HCCAPhysicalAddress.LowPart);
-
     //
     // lets write physical address of dummy control endpoint descriptor
     //
@@ -511,62 +506,62 @@ CUSBHardwareDevice::StartController(void)
     WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_BULK_HEAD_ED_OFFSET), m_BulkEndpointDescriptor->PhysicalAddress.LowPart);
 
     //
-    // read control register
+    // get frame interval
     //
-    Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET));
+    FrameInterval = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET));
+    FrameInterval = ((FrameInterval & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE);
+    DPRINT1("FrameInterval %x IntervalValue %x\n", FrameInterval, m_IntervalValue);
+    FrameInterval |= OHCI_FSMPS(m_IntervalValue) | m_IntervalValue;
+    DPRINT1("FrameInterval %x\n", FrameInterval);
 
     //
-    // remove flags
-    // 
-    Control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST | OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
+    // write frame interval
+    //
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval);
 
     //
-    // set command status flags
+    // write address of HCCA
     //
-    Control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4 | OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_HCCA_OFFSET), m_HCCAPhysicalAddress.LowPart);
 
     //
-    // now start the controller
+    // now enable the interrupts
     //
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), Control);
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_NORMAL_INTERRUPTS | OHCI_MASTER_INTERRUPT_ENABLE);
 
     //
-    // wait a bit
+    // enable all queues
     //
-    KeStallExecutionProcessor(100);
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), OHCI_ENABLE_LIST);
 
     //
-    // is the controller started
+    // 90 % periodic
     //
-    Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET));
+    Periodic = OHCI_PERIODIC(m_IntervalValue);
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_PERIODIC_START_OFFSET), Periodic);
+    DPRINT1("Periodic Start %x\n", Periodic);
 
     //
-    // assert that the controller has been started
+    // start the controller
     //
-    ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL);
-    ASSERT((Control & OHCI_ENABLE_LIST) == OHCI_ENABLE_LIST);
-    DPRINT1("Control %x\n", Control);
+    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET), OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4 | OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL);
 
     //
-    // get frame interval
+    // wait a bit
     //
-    FrameInterval = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET));
-    FrameInterval = ((FrameInterval & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE);
-    DPRINT1("FrameInterval %x IntervalValue %x\n", FrameInterval, m_IntervalValue);
-    FrameInterval |= OHCI_FSMPS(m_IntervalValue) | m_IntervalValue;
-    DPRINT1("FrameInterval %x\n", FrameInterval);
+    KeStallExecutionProcessor(100);
 
     //
-    // write frame interval
+    // is the controller started
     //
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_FRAME_INTERVAL_OFFSET), FrameInterval);
+    Control = READ_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_CONTROL_OFFSET));
 
     //
-    // 90 % periodic
+    // assert that the controller has been started
     //
-    Periodic = OHCI_PERIODIC(m_IntervalValue);
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_PERIODIC_START_OFFSET), Periodic);
-    DPRINT1("Periodic Start %x\n", Periodic);
+    ASSERT((Control & OHCI_HC_FUNCTIONAL_STATE_MASK) == OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL);
+    ASSERT((Control & OHCI_ENABLE_LIST) == OHCI_ENABLE_LIST);
+    DPRINT1("Control %x\n", Control);
 
     //
     // read descriptor
@@ -593,8 +588,6 @@ CUSBHardwareDevice::StartController(void)
     //
     WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_RH_DESCRIPTOR_A_OFFSET), Descriptor);
 
-
-
     //
     // retrieve number of ports
     //
@@ -638,11 +631,6 @@ CUSBHardwareDevice::StartController(void)
     DPRINT1("NumberOfPorts %lu\n", m_NumberOfPorts);
 
 
-    //
-    // now enable the interrupts
-    //
-    WRITE_REGISTER_ULONG((PULONG)((PUCHAR)m_Base + OHCI_INTERRUPT_ENABLE_OFFSET), OHCI_NORMAL_INTERRUPTS | OHCI_MASTER_INTERRUPT_ENABLE);
-
     //
     // done
     //
index ce6582d..bbc8efe 100644 (file)
                                     | OHCI_WRITEBACK_DONE_HEAD \
                                     | OHCI_RESUME_DETECTED \
                                     | OHCI_UNRECOVERABLE_ERROR \
-                                    | OHCI_ROOT_HUB_STATUS_CHANGE)
+                                    | OHCI_ROOT_HUB_STATUS_CHANGE \
+                                                                       | OHCI_OWNERSHIP_CHANGE)
 
 //
 // FSMPS