* 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
This commit is contained in:
Michael Lotz
2008-06-10 22:07:45 +00:00
parent 0e0d9290e0
commit 97403a77f1
+10 -8
View File
@@ -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;