From 97403a77f1d46f1cf7cb3b339388e5cf0ca31b97 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Tue, 10 Jun 2008 22:07:45 +0000 Subject: [PATCH] * Fix the check after waiting for owner change to happen and don't reset if the handover indeed worked. Doesn't really matter though, as we reset anyway, just not twice in the success case. * Disable all interrupts and clear any pending active interrupts just after taking over the controller. This might fix bug #2361. * Also trace output when the ownership change is successful. * Don't disable interrupts during reset. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25915 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/busses/usb/ohci.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/add-ons/kernel/busses/usb/ohci.cpp b/src/add-ons/kernel/busses/usb/ohci.cpp index 1b1da20420..921c042fc6 100644 --- a/src/add-ons/kernel/busses/usb/ohci.cpp +++ b/src/add-ons/kernel/busses/usb/ohci.cpp @@ -204,7 +204,7 @@ OHCI::OHCI(pci_info *info, Stack *stack) // Determine in what context we are running (Kindly copied from FreeBSD) uint32 control = _ReadReg(OHCI_CONTROL); if (control & OHCI_INTERRUPT_ROUTING) { - TRACE(("usb_ohci: SMM is in control of the host controller\n")); + TRACE(("usb_ohci: smm is in control of the host controller\n")); uint32 status = _ReadReg(OHCI_COMMAND_STATUS); _WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST); for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) { @@ -212,16 +212,22 @@ OHCI::OHCI(pci_info *info, Stack *stack) control = _ReadReg(OHCI_CONTROL); } - if (!(control & OHCI_INTERRUPT_ROUTING)) { - TRACE(("usb_ohci: SMM does not respond. Resetting...\n")); + if ((control & OHCI_INTERRUPT_ROUTING) != 0) { + TRACE_ERROR(("usb_ohci: smm does not respond. resetting...\n")); _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); snooze(USB_DELAY_BUS_RESET); - } + } else + TRACE(("usb_ohci: ownership change successful\n")); } else { TRACE(("usb_ohci: cold started\n")); snooze(USB_DELAY_BUS_RESET); } + // Disable all interrupts and clear any current interrupt status + _WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS + | OHCI_MASTER_INTERRUPT_ENABLE); + _WriteReg(OHCI_INTERRUPT_STATUS, OHCI_ALL_INTERRUPTS); + // This reset should not be necessary according to the OHCI spec, but // without it some controllers do not start. _WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET); @@ -232,7 +238,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval); // Disable interrupts right before we reset - cpu_status former = disable_interrupts(); _WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET); // Nominal time for a reset is 10 us uint32 reset = 0; @@ -244,7 +249,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) } if (reset) { - restore_interrupts(former); TRACE_ERROR(("usb_ohci: Error resetting the host controller (timeout)\n")); return; } @@ -267,8 +271,6 @@ OHCI::OHCI(pci_info *info, Stack *stack) // And finally start the controller _WriteReg(OHCI_CONTROL, control); - restore_interrupts(former); - // The controller is now OPERATIONAL. frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE) ^ OHCI_FRAME_INTERVAL_TOGGLE;