From 12a80667260a99d59aab0f477cbc3d3150a2267d Mon Sep 17 00:00:00 2001
From: Akshay Jaggi <akshay1994.leo@gmail.com>
Date: Fri, 11 Jul 2014 14:25:14 +0000
Subject: [PATCH] XHCI-More-Fixes
- Fix device speed idtification
- Fix Max Packet Size for Full-Speed Devices
- Fix IRQ rate
- Update slot context for LS/FS devices connected to non-root HS hub
---
src/add-ons/kernel/bus_managers/usb/Hub.cpp | 3 +
src/add-ons/kernel/busses/usb/xhci.cpp | 82 ++++++++++++++++++++-------
src/add-ons/kernel/busses/usb/xhci_hardware.h | 2 +-
3 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/src/add-ons/kernel/bus_managers/usb/Hub.cpp b/src/add-ons/kernel/bus_managers/usb/Hub.cpp
index 3190018..dea45e9 100644
a
|
b
|
Hub::Explore(change_item **changeList)
|
258 | 258 | } |
259 | 259 | |
260 | 260 | usb_speed speed = USB_SPEED_FULLSPEED; |
| 261 | // Hack - We currently do not support USB3.0 Hubs |
| 262 | // This is for XHCI, which anyway rechecks the port speed |
| 263 | // This will in no way work for non-root USB3.0 Hubs |
261 | 264 | if (fDeviceDescriptor.usb_version == 0x300) |
262 | 265 | speed = USB_SPEED_SUPER; |
263 | 266 | else if (fPortStatus[i].status & PORT_STATUS_LOW_SPEED) |
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp
index 2d1ca46..bc81362 100644
a
|
b
|
XHCI::Start()
|
511 | 511 | fCmdRing[XHCI_MAX_COMMANDS - 1].qwtrb0 = dmaAddress; |
512 | 512 | |
513 | 513 | TRACE("setting interrupt rate\n"); |
514 | | WriteRunReg32(XHCI_IMOD(0), 160); // 25000 irq/s |
| 514 | |
| 515 | //Setting IMOD below 0x3F8 on Intel Lynx Point can cause IRQ lockups |
| 516 | if(fPCIInfo->vendor_id == PCI_VENDOR_ID_INTEL |
| 517 | && (fPCIInfo->device_id == PCI_DEVICE_ID_INTEL_PANTHER_POINT_XHCI |
| 518 | || fPCIInfo->device_id == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI |
| 519 | || fPCIInfo->device_id == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI)) { |
| 520 | |
| 521 | WriteRunReg32(XHCI_IMOD(0), 0x000003F8U); // 4000 irq/s |
| 522 | } |
| 523 | else |
| 524 | { |
| 525 | WriteRunReg32(XHCI_IMOD(0), 0x000001F4U); // 8000 irq/s |
| 526 | } |
515 | 527 | |
516 | 528 | TRACE("enabling interrupt\n"); |
517 | 529 | WriteRunReg32(XHCI_IMAN(0), ReadRunReg32(XHCI_IMAN(0)) | IMAN_INTR_ENA); |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1032 | 1044 | { |
1033 | 1045 | TRACE("AllocateDevice hubAddress %d hubPort %d speed %d\n", hubAddress, |
1034 | 1046 | hubPort, speed); |
1035 | | GetPortSpeed(hubPort - 1, &speed); |
1036 | | TRACE("speed %d\n", speed); |
1037 | 1047 | |
1038 | 1048 | uint8 slot = XHCI_MAX_SLOTS; |
1039 | 1049 | if (EnableSlot(&slot) != B_OK) { |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1087 | 1097 | routePort = hubDevice->HubPort(); |
1088 | 1098 | } |
1089 | 1099 | |
| 1100 | // Get speed of port, only if device connected to root hub port |
| 1101 | // Else we have to rely on value reported by Hub Explore Thread |
| 1102 | if(route == 0) |
| 1103 | { |
| 1104 | GetPortSpeed(hubPort - 1, &speed); |
| 1105 | TRACE("speed updated %d\n", speed); |
| 1106 | } |
| 1107 | |
1090 | 1108 | device->input_ctx->slot.dwslot0 = SLOT_0_NUM_ENTRIES(1) | SLOT_0_ROUTE(route); |
1091 | 1109 | |
1092 | 1110 | // add the speed |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1110 | 1128 | |
1111 | 1129 | device->input_ctx->slot.dwslot1 = SLOT_1_RH_PORT(rhPort); // TODO enable power save |
1112 | 1130 | device->input_ctx->slot.dwslot2 = SLOT_2_IRQ_TARGET(0); |
1113 | | if (0) |
| 1131 | |
| 1132 | // If LS/FS device connected to non-root HS device |
| 1133 | if((route != 0) && (parent->Speed() == USB_SPEED_HIGHSPEED) |
| 1134 | && (speed == USB_SPEED_LOWSPEED |
| 1135 | || speed == USB_SPEED_FULLSPEED)) { |
| 1136 | |
| 1137 | struct xhci_device *parenthub = (struct xhci_device *) parent->ControllerCookie(); |
1114 | 1138 | device->input_ctx->slot.dwslot2 |= SLOT_2_PORT_NUM(hubPort); |
| 1139 | device->input_ctx->slot.dwslot2 |= SLOT_2_TT_HUB_SLOT(parenthub->slot); |
| 1140 | } |
| 1141 | |
1115 | 1142 | device->input_ctx->slot.dwslot3 = SLOT_3_SLOT_STATE(0) |
1116 | 1143 | | SLOT_3_DEVICE_ADDRESS(0); |
1117 | 1144 | |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1240 | 1267 | TRACE("device_class: %d device_subclass %d device_protocol %d\n", |
1241 | 1268 | deviceDescriptor.device_class, deviceDescriptor.device_subclass, |
1242 | 1269 | deviceDescriptor.device_protocol); |
| 1270 | |
| 1271 | if(speed == USB_SPEED_FULLSPEED && deviceDescriptor.max_packet_size_0 != 8) |
| 1272 | { |
| 1273 | TRACE("Full speed device with different max packet size for Endpoint 0\n"); |
| 1274 | device->input_ctx->endpoints[0].dwendpoint1 &= ~ENDPOINT_1_MAXPACKETSIZE(0xFFFF); |
| 1275 | device->input_ctx->endpoints[0].dwendpoint1 |= ENDPOINT_1_MAXPACKETSIZE(deviceDescriptor.max_packet_size_0); |
| 1276 | device->input_ctx->input.dropFlags = 0; |
| 1277 | device->input_ctx->input.addFlags = (1<<1); |
| 1278 | EvaluateContext(device->input_ctx_addr, device->slot); |
| 1279 | } |
1243 | 1280 | |
1244 | 1281 | if(deviceDescriptor.device_class==0x09) |
1245 | 1282 | { |
… |
… |
XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, u
|
1574 | 1611 | status_t |
1575 | 1612 | XHCI::GetPortSpeed(uint8 index, usb_speed *speed) |
1576 | 1613 | { |
1577 | | if (fPortSpeeds[index] == USB_SPEED_SUPER) |
1578 | | *speed = USB_SPEED_SUPER; |
1579 | | else { |
1580 | | uint32 portStatus = ReadOpReg(XHCI_PORTSC(index)); |
| 1614 | uint32 portStatus = ReadOpReg(XHCI_PORTSC(index)); |
1581 | 1615 | |
1582 | | switch (PS_SPEED_GET(portStatus)) { |
1583 | | case 3: |
1584 | | *speed = USB_SPEED_HIGHSPEED; |
1585 | | break; |
1586 | | case 2: |
1587 | | *speed = USB_SPEED_LOWSPEED; |
1588 | | break; |
1589 | | case 1: |
1590 | | *speed = USB_SPEED_FULLSPEED; |
1591 | | break; |
1592 | | default: |
1593 | | *speed = USB_SPEED_SUPER; |
1594 | | } |
| 1616 | switch (PS_SPEED_GET(portStatus)) { |
| 1617 | case 3: |
| 1618 | *speed = USB_SPEED_HIGHSPEED; |
| 1619 | break; |
| 1620 | case 2: |
| 1621 | *speed = USB_SPEED_LOWSPEED; |
| 1622 | break; |
| 1623 | case 1: |
| 1624 | *speed = USB_SPEED_FULLSPEED; |
| 1625 | break; |
| 1626 | case 4: |
| 1627 | *speed = USB_SPEED_SUPER; |
| 1628 | break; |
| 1629 | default: |
| 1630 | TRACE("Non Standard Port Speed\n"); |
| 1631 | TRACE("Assuming Superspeed\n"); |
| 1632 | *speed = USB_SPEED_SUPER; |
| 1633 | break; |
1595 | 1634 | } |
| 1635 | |
1596 | 1636 | return B_OK; |
1597 | 1637 | } |
1598 | 1638 | |
diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h b/src/add-ons/kernel/busses/usb/xhci_hardware.h
index 64c282a..8bf4aca 100644
a
|
b
|
struct xhci_slot_ctx {
|
342 | 342 | #define SLOT_1_NUM_PORTS_GET(x) (((x) >> 24) & 0xFF) |
343 | 343 | |
344 | 344 | #define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF) |
345 | | #define SLOT_2_TT_HUB_SLOT(x) ((x) & 0xFF) |
| 345 | #define SLOT_2_TT_HUB_SLOT_GET(x) ((x) & 0xFF) |
346 | 346 | #define SLOT_2_PORT_NUM(x) (((x) & 0xFF) << 8) |
347 | 347 | #define SLOT_2_PORT_NUM_GET(x) (((x) >> 8) & 0xFF) |
348 | 348 | #define SLOT_2_TT_TIME(x) (((x) & 0x3) << 16) |