From c4c6d229c06ee191c1ff78da8b924b11da58170a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= <jerome.duval@gmail.com>
Date: Sun, 14 Dec 2014 12:52:54 +0100
Subject: [PATCH] EHCI USB: process the extended capabilities chain
...instead of the first one only.
---
src/add-ons/kernel/busses/usb/ehci.cpp | 69 +++++++++++++--------------
src/add-ons/kernel/busses/usb/ehci_hardware.h | 1 +
2 files changed, 35 insertions(+), 35 deletions(-)
diff --git a/src/add-ons/kernel/busses/usb/ehci.cpp b/src/add-ons/kernel/busses/usb/ehci.cpp
index dfa51f8..6748173 100644
a
|
b
|
EHCI::EHCI(pci_info *info, Stack *stack)
|
252 | 252 | |
253 | 253 | uint32 extendedCapPointer = ReadCapReg32(EHCI_HCCPARAMS) >> EHCI_ECP_SHIFT; |
254 | 254 | extendedCapPointer &= EHCI_ECP_MASK; |
255 | | if (extendedCapPointer > 0) { |
| 255 | for (uint32 eec = extendedCapPointer; eec != 0; extendedCapPointer = EHCI_EECP_NEXT(eec)) { |
256 | 256 | TRACE("extended capabilities register at %" B_PRIu32 "\n", |
257 | 257 | extendedCapPointer); |
258 | 258 | |
259 | | uint32 legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, |
| 259 | eec = sPCIModule->read_pci_config(fPCIInfo->bus, |
260 | 260 | fPCIInfo->device, fPCIInfo->function, extendedCapPointer, 4); |
261 | | if ((legacySupport & EHCI_LEGSUP_CAPID_MASK) == EHCI_LEGSUP_CAPID) { |
262 | | if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) != 0) { |
263 | | TRACE_ALWAYS("the host controller is bios owned, claiming" |
264 | | " ownership\n"); |
265 | 261 | |
266 | | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
267 | | fPCIInfo->function, extendedCapPointer + 3, 1, 1); |
| 262 | if ((eec & EHCI_LEGSUP_CAPID_MASK) != EHCI_LEGSUP_CAPID) |
| 263 | continue; |
268 | 264 | |
269 | | for (int32 i = 0; i < 20; i++) { |
270 | | legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, |
271 | | fPCIInfo->device, fPCIInfo->function, |
272 | | extendedCapPointer, 4); |
| 265 | uint32 legacySupport = eec; |
273 | 266 | |
274 | | if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) == 0) |
275 | | break; |
| 267 | if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) != 0) { |
| 268 | TRACE_ALWAYS("the host controller is bios owned, claiming" |
| 269 | " ownership\n"); |
276 | 270 | |
277 | | TRACE_ALWAYS("controller is still bios owned, waiting\n"); |
278 | | snooze(50000); |
279 | | } |
280 | | } |
| 271 | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
| 272 | fPCIInfo->function, extendedCapPointer + 3, 1, 1); |
281 | 273 | |
282 | | if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { |
283 | | TRACE_ERROR("bios won't give up control over the host " |
284 | | "controller (ignoring)\n"); |
285 | | } else if (legacySupport & EHCI_LEGSUP_OSOWNED) { |
286 | | TRACE_ALWAYS( |
287 | | "successfully took ownership of the host controller\n"); |
| 274 | for (int32 i = 0; i < 20; i++) { |
| 275 | legacySupport = sPCIModule->read_pci_config(fPCIInfo->bus, |
| 276 | fPCIInfo->device, fPCIInfo->function, |
| 277 | extendedCapPointer, 4); |
| 278 | |
| 279 | if ((legacySupport & EHCI_LEGSUP_BIOSOWNED) == 0) |
| 280 | break; |
| 281 | |
| 282 | TRACE_ALWAYS("controller is still bios owned, waiting\n"); |
| 283 | snooze(50000); |
288 | 284 | } |
| 285 | } |
289 | 286 | |
290 | | // Force off the BIOS owned flag, and clear all SMIs. Some BIOSes |
291 | | // do indicate a successful handover but do not remove their SMIs |
292 | | // and then freeze the system when interrupts are generated. |
293 | | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
294 | | fPCIInfo->function, extendedCapPointer + 2, 1, 0); |
295 | | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
296 | | fPCIInfo->function, extendedCapPointer + 4, 4, 0); |
297 | | } else { |
| 287 | if (legacySupport & EHCI_LEGSUP_BIOSOWNED) { |
| 288 | TRACE_ERROR("bios won't give up control over the host " |
| 289 | "controller (ignoring)\n"); |
| 290 | } else if (legacySupport & EHCI_LEGSUP_OSOWNED) { |
298 | 291 | TRACE_ALWAYS( |
299 | | "extended capability is not a legacy support register\n"); |
| 292 | "successfully took ownership of the host controller\n"); |
300 | 293 | } |
301 | | } else { |
302 | | TRACE_ALWAYS("no extended capabilities register\n"); |
| 294 | |
| 295 | // Force off the BIOS owned flag, and clear all SMIs. Some BIOSes |
| 296 | // do indicate a successful handover but do not remove their SMIs |
| 297 | // and then freeze the system when interrupts are generated. |
| 298 | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
| 299 | fPCIInfo->function, extendedCapPointer + 2, 1, 0); |
| 300 | sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device, |
| 301 | fPCIInfo->function, extendedCapPointer + 4, 4, 0); |
303 | 302 | } |
304 | 303 | |
305 | 304 | // disable interrupts |
diff --git a/src/add-ons/kernel/busses/usb/ehci_hardware.h b/src/add-ons/kernel/busses/usb/ehci_hardware.h
index 1348303..79be0b3 100644
a
|
b
|
|
103 | 103 | // Extended Capabilities |
104 | 104 | #define EHCI_ECP_SHIFT 8 // Extended Capability Pointer |
105 | 105 | #define EHCI_ECP_MASK 0xff |
| 106 | #define EHCI_EECP_NEXT(x) (((x) >> 8) & 0xff) |
106 | 107 | #define EHCI_LEGSUP_CAPID_MASK 0xff |
107 | 108 | #define EHCI_LEGSUP_CAPID 0x01 |
108 | 109 | #define EHCI_LEGSUP_OSOWNED (1 << 24) // OS Owned Semaphore |