From 51c413efb64f3bd7cf01a972a1a6c143daa9302a Mon Sep 17 00:00:00 2001
From: Akshay Jaggi <akshay1994.leo@gmail.com>
Date: Sat, 2 Aug 2014 19:15:25 +0530
Subject: [PATCH] XHCI
* Fix Endpoint Context Initialisation (Refer xHCI v1.1 - 6.2.3)
* Fix Interval Calculation (Refer xHCI v1.1 - 6.2.3.6 , USB 2.0 - 9.6.6 page 271)
* Fix MaxBurst, MaxPacketSize Calculation (Refer xHCI v1.1 - 6.2.3.5, USB 2.0 - 9.6.6 page 271)
* Fix MaxESITPayload Calculation (Refer xHCI v1.1 - 4.14.2)
* Remove Link TRBs as they were never being used
* Increase Number of TRBs per endpoint (to utilise the whole area allocated for Device TRBs)
* Fix usage of XHCI_MAX_ENDPOINTS (most of the checks were failing at corner cases)
* Few Coding Guideline fixes (reported by style checker script)
---
src/add-ons/kernel/busses/usb/xhci.cpp | 163 +++++++++++++++-----------
src/add-ons/kernel/busses/usb/xhci.h | 6 +-
src/add-ons/kernel/busses/usb/xhci_hardware.h | 2 +-
3 files changed, 99 insertions(+), 72 deletions(-)
diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp
index dbfd2b4..1e3e349 100644
a
|
b
|
XHCI::Start()
|
497 | 497 | TRACE("setting CRCR addr = 0x%" B_PRIxPHYSADDR "\n", dmaAddress); |
498 | 498 | WriteOpReg(XHCI_CRCR_LO, (uint32)dmaAddress | CRCR_RCS); |
499 | 499 | WriteOpReg(XHCI_CRCR_HI, /*(uint32)(dmaAddress >> 32)*/0); |
500 | | //link trb |
| 500 | // link trb |
501 | 501 | fCmdRing[XHCI_MAX_COMMANDS - 1].qwtrb0 = dmaAddress; |
502 | 502 | |
503 | 503 | TRACE("setting interrupt rate\n"); |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1149 | 1149 | return NULL; |
1150 | 1150 | } |
1151 | 1151 | |
1152 | | for (uint32 i = 0; i < XHCI_MAX_ENDPOINTS; i++) { |
1153 | | struct xhci_trb *linkTrb = device->trbs + (i + 1) * XHCI_MAX_TRANSFERS - 1; |
1154 | | linkTrb->qwtrb0 = device->trb_addr |
1155 | | + i * XHCI_MAX_TRANSFERS * sizeof(xhci_trb); |
1156 | | linkTrb->dwtrb2 = TRB_2_IRQ(0); |
1157 | | linkTrb->dwtrb3 = TRB_3_CYCLE_BIT | TRB_3_TYPE(TRB_TYPE_LINK); |
1158 | | } |
1159 | | |
1160 | 1152 | // set up slot pointer to device context |
1161 | 1153 | fDcba->baseAddress[slot] = device->device_ctx_addr; |
1162 | 1154 | |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1175 | 1167 | } |
1176 | 1168 | |
1177 | 1169 | // configure the Control endpoint 0 (type 4) |
1178 | | if (ConfigureEndpoint(slot, 0, 4, device->trb_addr, 0, 1, 1, 0, |
1179 | | maxPacketSize, maxPacketSize, speed) != B_OK) { |
| 1170 | if (ConfigureEndpoint(slot, 0, 4, device->trb_addr, 0, |
| 1171 | maxPacketSize, maxPacketSize & 0x7ff, speed) != B_OK) { |
1180 | 1172 | TRACE_ERROR("unable to configure default control endpoint\n"); |
1181 | 1173 | device->state = XHCI_STATE_DISABLED; |
1182 | 1174 | delete_area(device->input_ctx_area); |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1215 | 1207 | // Create a temporary pipe with the new address |
1216 | 1208 | ControlPipe pipe(parent); |
1217 | 1209 | pipe.SetControllerCookie(&device->endpoints[0]); |
1218 | | pipe.InitCommon(device->address + 1, 0, speed, Pipe::Default, 8, 0, |
| 1210 | pipe.InitCommon(device->address + 1, 0, speed, Pipe::Default, maxPacketSize, 0, |
1219 | 1211 | hubAddress, hubPort); |
1220 | 1212 | |
1221 | 1213 | // Get the device descriptor |
… |
… |
XHCI::AllocateDevice(Hub *parent, int8 hubAddress, uint8 hubPort,
|
1245 | 1237 | return NULL; |
1246 | 1238 | } |
1247 | 1239 | |
1248 | | TRACE("device_class: %d device_subclass %d device_protocol %d\n", |
1249 | | deviceDescriptor.device_class, deviceDescriptor.device_subclass, |
1250 | | deviceDescriptor.device_protocol); |
| 1240 | TRACE("\tlength:..............%d\n", deviceDescriptor.length); |
| 1241 | TRACE("\tdescriptor_type:.....0x%04x\n", deviceDescriptor.descriptor_type); |
| 1242 | TRACE("\tusb_version:.........0x%04x\n", deviceDescriptor.usb_version); |
| 1243 | TRACE("\tdevice_class:........0x%02x\n", deviceDescriptor.device_class); |
| 1244 | TRACE("\tdevice_subclass:.....0x%02x\n", deviceDescriptor.device_subclass); |
| 1245 | TRACE("\tdevice_protocol:.....0x%02x\n", deviceDescriptor.device_protocol); |
| 1246 | TRACE("\tmax_packet_size_0:...%d\n", deviceDescriptor.max_packet_size_0); |
1251 | 1247 | |
1252 | 1248 | if (speed == USB_SPEED_FULLSPEED && deviceDescriptor.max_packet_size_0 != 8) { |
1253 | 1249 | TRACE("Full speed device with different max packet size for Endpoint 0\n"); |
… |
… |
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
1351 | 1347 | } |
1352 | 1348 | |
1353 | 1349 | uint8 id = XHCI_ENDPOINT_ID(pipe) - 1; |
1354 | | if (id >= XHCI_MAX_ENDPOINTS) |
| 1350 | if (id >= XHCI_MAX_ENDPOINTS - 1) |
1355 | 1351 | return B_BAD_VALUE; |
1356 | 1352 | |
1357 | 1353 | if (id > 0) { |
… |
… |
XHCI::_InsertEndpointForPipe(Pipe *pipe)
|
1403 | 1399 | |
1404 | 1400 | if (ConfigureEndpoint(device->slot, id, type, |
1405 | 1401 | device->endpoints[id].trb_addr, pipe->Interval(), |
1406 | | 1, 1, 0, pipe->MaxPacketSize(), pipe->MaxPacketSize(), |
| 1402 | pipe->MaxPacketSize(), pipe->MaxPacketSize() & 0x7ff, |
1407 | 1403 | usbDevice->Speed()) != B_OK) { |
1408 | 1404 | TRACE_ERROR("unable to configure endpoint\n"); |
1409 | 1405 | return B_ERROR; |
… |
… |
XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
|
1444 | 1440 | { |
1445 | 1441 | TRACE("_LinkDescriptorForPipe\n"); |
1446 | 1442 | MutexLocker endpointLocker(endpoint->lock); |
1447 | | if (endpoint->used >= XHCI_MAX_TRANSFERS) { |
| 1443 | if (endpoint->used > XHCI_MAX_TRANSFERS) { |
1448 | 1444 | TRACE_ERROR("_LinkDescriptorForPipe max transfers count exceeded\n"); |
1449 | 1445 | return B_BAD_VALUE; |
1450 | 1446 | } |
… |
… |
XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
|
1457 | 1453 | endpoint->td_head = descriptor; |
1458 | 1454 | |
1459 | 1455 | uint8 current = endpoint->current; |
1460 | | uint8 next = (current + 1) % (XHCI_MAX_TRANSFERS - 1); |
| 1456 | uint8 next = (current + 1) % (XHCI_MAX_TRANSFERS); |
1461 | 1457 | |
1462 | 1458 | TRACE("_LinkDescriptorForPipe current %d, next %d\n", current, next); |
1463 | 1459 | |
… |
… |
XHCI::_UnlinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
|
1513 | 1509 | |
1514 | 1510 | |
1515 | 1511 | status_t |
1516 | | XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, uint16 interval, |
1517 | | uint8 maxPacketCount, uint8 mult, uint8 fpsShift, uint16 maxPacketSize, |
1518 | | uint16 maxFrameSize, usb_speed speed) |
| 1512 | XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, |
| 1513 | uint16 interval, uint16 maxPacketSize, uint16 maxFrameSize, usb_speed speed) |
1519 | 1514 | { |
1520 | | struct xhci_device *device = &fDevices[slot]; |
1521 | | struct xhci_endpoint_ctx *endpoint = &device->input_ctx->endpoints[number]; |
| 1515 | struct xhci_device* device = &fDevices[slot]; |
| 1516 | struct xhci_endpoint_ctx* endpoint = &device->input_ctx->endpoints[number]; |
1522 | 1517 | |
1523 | | if (mult == 0 || maxPacketCount == 0) |
1524 | | return B_BAD_VALUE; |
| 1518 | uint8 maxBurst = (maxPacketSize & 0x1800) >> 11; |
| 1519 | maxPacketSize = (maxPacketSize & 0x7ff); |
1525 | 1520 | |
1526 | | maxPacketCount--; |
| 1521 | endpoint->dwendpoint0 = 0; |
| 1522 | endpoint->dwendpoint1 = 0; |
| 1523 | endpoint->qwendpoint2 = 0; |
| 1524 | endpoint->dwendpoint4 = 0; |
1527 | 1525 | |
1528 | | endpoint->dwendpoint0 = ENDPOINT_0_STATE(0) | ENDPOINT_0_MAXPSTREAMS(0); |
1529 | | // add mult for isochronous and interrupt types |
1530 | | switch (speed) { |
1531 | | case USB_SPEED_LOWSPEED: |
1532 | | case USB_SPEED_FULLSPEED: |
1533 | | fpsShift += 3; |
1534 | | break; |
1535 | | default: |
1536 | | break; |
| 1526 | // Assigning Interval |
| 1527 | |
| 1528 | uint16 calcInterval = 0; |
| 1529 | |
| 1530 | if (speed == USB_SPEED_HIGHSPEED |
| 1531 | && (type == 4 || type == 2)) |
| 1532 | { |
| 1533 | if (interval != 0) |
| 1534 | { |
| 1535 | while ((1<<calcInterval) <= interval) |
| 1536 | { |
| 1537 | calcInterval++; |
| 1538 | } |
| 1539 | calcInterval--; |
| 1540 | } |
1537 | 1541 | } |
1538 | | switch (type) { |
1539 | | case 1: |
1540 | | case 5: |
1541 | | if (fpsShift > 3) |
1542 | | fpsShift--; |
1543 | | case 3: |
1544 | | case 7: |
1545 | | endpoint->dwendpoint0 |= ENDPOINT_0_INTERVAL(fpsShift); |
1546 | | break; |
1547 | | default: |
1548 | | break; |
| 1542 | if ((type & 0x3) == 3 |
| 1543 | && (speed == USB_SPEED_FULLSPEED || speed == USB_SPEED_LOWSPEED)) |
| 1544 | { |
| 1545 | while ((1<<calcInterval) <= interval * 8) |
| 1546 | { |
| 1547 | calcInterval++; |
| 1548 | } |
| 1549 | calcInterval--; |
| 1550 | } |
| 1551 | if ((type & 0x3) == 1 && speed == USB_SPEED_FULLSPEED) |
| 1552 | { |
| 1553 | calcInterval = interval + 2; |
| 1554 | } |
| 1555 | if ( ((type & 0x3) == 1 || (type & 0x3) == 3) |
| 1556 | && (speed == USB_SPEED_HIGHSPEED || speed == USB_SPEED_SUPER) ) |
| 1557 | { |
| 1558 | calcInterval = interval - 1; |
| 1559 | } |
| 1560 | |
| 1561 | endpoint->dwendpoint0 |= ENDPOINT_0_INTERVAL(calcInterval); |
| 1562 | |
| 1563 | // Assigning CERR for non-isoch endpoints |
| 1564 | if ((type & 0x3) != 1) |
| 1565 | { |
| 1566 | endpoint->dwendpoint1 |= ENDPOINT_1_CERR(3); |
| 1567 | } |
| 1568 | |
| 1569 | endpoint->dwendpoint1 |= ENDPOINT_1_EPTYPE(type); |
| 1570 | |
| 1571 | // Assigning MaxBurst for HighSpeed |
| 1572 | if (speed == USB_SPEED_HIGHSPEED |
| 1573 | && ((type & 0x3) == 1 || (type & 0x3) == 3)) |
| 1574 | { |
| 1575 | endpoint->dwendpoint1 |= ENDPOINT_1_MAXBURST(maxBurst); |
1549 | 1576 | } |
1550 | | // add interval |
1551 | | endpoint->dwendpoint1 = ENDPOINT_1_EPTYPE(type) |
1552 | | | ENDPOINT_1_MAXBURST(maxPacketCount) |
1553 | | | ENDPOINT_1_MAXPACKETSIZE(maxPacketSize) |
1554 | | | ENDPOINT_1_CERR(3); |
1555 | | endpoint->qwendpoint2 = ENDPOINT_2_DCS_BIT | ringAddr; |
1556 | | // 8 for Control endpoint |
| 1577 | |
| 1578 | // TODO Assign MaxBurst for SuperSpeed |
| 1579 | |
| 1580 | endpoint->dwendpoint1 |= ENDPOINT_1_MAXPACKETSIZE(maxPacketSize); |
| 1581 | endpoint->qwendpoint2 |= ENDPOINT_2_DCS_BIT | ringAddr; |
| 1582 | |
| 1583 | // Assign MaxESITPayload |
| 1584 | // Assign AvgTRBLength |
1557 | 1585 | switch (type) { |
1558 | 1586 | case 4: |
1559 | 1587 | endpoint->dwendpoint4 = ENDPOINT_4_AVGTRBLENGTH(8); |
… |
… |
XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, u
|
1563 | 1591 | case 5: |
1564 | 1592 | case 7: |
1565 | 1593 | endpoint->dwendpoint4 = ENDPOINT_4_AVGTRBLENGTH(min_c(maxFrameSize, |
1566 | | B_PAGE_SIZE)) | ENDPOINT_4_MAXESITPAYLOAD(maxFrameSize); |
| 1594 | B_PAGE_SIZE)) | ENDPOINT_4_MAXESITPAYLOAD(( (maxBurst+1) * maxPacketSize )); |
1567 | 1595 | break; |
1568 | 1596 | default: |
1569 | 1597 | endpoint->dwendpoint4 = ENDPOINT_4_AVGTRBLENGTH(B_PAGE_SIZE); |
… |
… |
XHCI::ConfigureEndpoint(uint8 slot, uint8 number, uint8 type, uint64 ringAddr, u
|
1578 | 1606 | |
1579 | 1607 | |
1580 | 1608 | status_t |
1581 | | XHCI::GetPortSpeed(uint8 index, usb_speed *speed) |
| 1609 | XHCI::GetPortSpeed(uint8 index, usb_speed* speed) |
1582 | 1610 | { |
1583 | 1611 | uint32 portStatus = ReadOpReg(XHCI_PORTSC(index)); |
1584 | 1612 | |
… |
… |
XHCI::GetPortSpeed(uint8 index, usb_speed *speed)
|
1607 | 1635 | |
1608 | 1636 | |
1609 | 1637 | status_t |
1610 | | XHCI::GetPortStatus(uint8 index, usb_port_status *status) |
| 1638 | XHCI::GetPortStatus(uint8 index, usb_port_status* status) |
1611 | 1639 | { |
1612 | 1640 | if (index >= fPortCount) |
1613 | 1641 | return B_BAD_INDEX; |
… |
… |
XHCI::ControllerReset()
|
1795 | 1823 | |
1796 | 1824 | |
1797 | 1825 | int32 |
1798 | | XHCI::InterruptHandler(void *data) |
| 1826 | XHCI::InterruptHandler(void* data) |
1799 | 1827 | { |
1800 | | return ((XHCI *)data)->Interrupt(); |
| 1828 | return ((XHCI*)data)->Interrupt(); |
1801 | 1829 | } |
1802 | 1830 | |
1803 | 1831 | |
… |
… |
XHCI::Ring(uint8 slot, uint8 endpoint)
|
1843 | 1871 | TRACE("Ding Dong! slot:%d endpoint %d\n", slot, endpoint) |
1844 | 1872 | if ((slot == 0 && endpoint > 0) || (slot > 0 && endpoint == 0)) |
1845 | 1873 | panic("Ring() invalid slot/endpoint combination\n"); |
1846 | | if (slot > fSlotCount || endpoint > XHCI_MAX_ENDPOINTS) |
| 1874 | if (slot > fSlotCount || endpoint >= XHCI_MAX_ENDPOINTS) |
1847 | 1875 | panic("Ring() invalid slot or endpoint\n"); |
1848 | 1876 | WriteDoorReg32(XHCI_DOORBELL(slot), XHCI_DOORBELL_TARGET(endpoint) |
1849 | 1877 | | XHCI_DOORBELL_STREAMID(0)); |
… |
… |
XHCI::Ring(uint8 slot, uint8 endpoint)
|
1853 | 1881 | |
1854 | 1882 | |
1855 | 1883 | void |
1856 | | XHCI::QueueCommand(xhci_trb *trb) |
| 1884 | XHCI::QueueCommand(xhci_trb* trb) |
1857 | 1885 | { |
1858 | 1886 | uint8 i, j; |
1859 | 1887 | uint32 temp; |
… |
… |
XHCI::QueueCommand(xhci_trb *trb)
|
1896 | 1924 | |
1897 | 1925 | |
1898 | 1926 | void |
1899 | | XHCI::HandleCmdComplete(xhci_trb *trb) |
| 1927 | XHCI::HandleCmdComplete(xhci_trb* trb) |
1900 | 1928 | { |
1901 | 1929 | if (fCmdAddr == trb->qwtrb0) { |
1902 | 1930 | TRACE("Received command event\n"); |
… |
… |
XHCI::HandleCmdComplete(xhci_trb *trb)
|
1909 | 1937 | |
1910 | 1938 | |
1911 | 1939 | void |
1912 | | XHCI::HandleTransferComplete(xhci_trb *trb) |
| 1940 | XHCI::HandleTransferComplete(xhci_trb* trb) |
1913 | 1941 | { |
1914 | 1942 | TRACE("HandleTransferComplete trb %p\n", trb); |
1915 | 1943 | addr_t source = trb->qwtrb0; |
… |
… |
XHCI::HandleTransferComplete(xhci_trb *trb)
|
1920 | 1948 | |
1921 | 1949 | if (slot > fSlotCount) |
1922 | 1950 | TRACE_ERROR("invalid slot\n"); |
1923 | | if (endpointNumber == 0 || endpointNumber > XHCI_MAX_ENDPOINTS) |
| 1951 | if (endpointNumber == 0 || endpointNumber >= XHCI_MAX_ENDPOINTS) |
1924 | 1952 | TRACE_ERROR("invalid endpoint\n"); |
1925 | 1953 | |
1926 | 1954 | xhci_device *device = &fDevices[slot]; |
… |
… |
XHCI::HandleTransferComplete(xhci_trb *trb)
|
1945 | 1973 | |
1946 | 1974 | |
1947 | 1975 | status_t |
1948 | | XHCI::DoCommand(xhci_trb *trb) |
| 1976 | XHCI::DoCommand(xhci_trb* trb) |
1949 | 1977 | { |
1950 | 1978 | if (!Lock()) |
1951 | 1979 | return B_ERROR; |
… |
… |
XHCI::Noop()
|
1996 | 2024 | |
1997 | 2025 | |
1998 | 2026 | status_t |
1999 | | XHCI::EnableSlot(uint8 *slot) |
| 2027 | XHCI::EnableSlot(uint8* slot) |
2000 | 2028 | { |
2001 | 2029 | TRACE("Enable Slot\n"); |
2002 | 2030 | xhci_trb trb; |
… |
… |
XHCI::CompleteEvents()
|
2157 | 2185 | |
2158 | 2186 | while (1) { |
2159 | 2187 | uint32 temp = fEventRing[i].dwtrb3; |
2160 | | TRACE_ALWAYS("event[%u] = %u (0x%016" B_PRIx64 " 0x%08" B_PRIx32 " 0x%08" |
| 2188 | TRACE("event[%u] = %u (0x%016" B_PRIx64 " 0x%08" B_PRIx32 " 0x%08" |
2161 | 2189 | B_PRIx32 ")\n", i, (uint8)TRB_3_TYPE_GET(temp), fEventRing[i].qwtrb0, |
2162 | 2190 | fEventRing[i].dwtrb2, fEventRing[i].dwtrb3); |
2163 | 2191 | uint8 k = (temp & TRB_3_CYCLE_BIT) ? 1 : 0; |
… |
… |
XHCI::FinishTransfers()
|
2296 | 2324 | } |
2297 | 2325 | } |
2298 | 2326 | |
| 2327 | |
2299 | 2328 | inline void |
2300 | 2329 | XHCI::WriteOpReg(uint32 reg, uint32 value) |
2301 | 2330 | { |
diff --git a/src/add-ons/kernel/busses/usb/xhci.h b/src/add-ons/kernel/busses/usb/xhci.h
index 0b130f0..ade72ff 100644
a
|
b
|
public:
|
102 | 102 | usb_speed speed); |
103 | 103 | status_t ConfigureEndpoint(uint8 slot, uint8 number, |
104 | 104 | uint8 type, uint64 ringAddr, |
105 | | uint16 interval, uint8 maxPacketCount, |
106 | | uint8 mult, uint8 fpsShift, |
107 | | uint16 maxPacketSize, uint16 maxFrameSize, |
108 | | usb_speed speed); |
| 105 | uint16 interval, uint16 maxPacketSize, |
| 106 | uint16 maxFrameSize, usb_speed speed); |
109 | 107 | virtual void FreeDevice(Device *device); |
110 | 108 | |
111 | 109 | status_t _InsertEndpointForPipe(Pipe *pipe); |
diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h b/src/add-ons/kernel/busses/usb/xhci_hardware.h
index 669c569..a62adf2 100644
a
|
b
|
|
278 | 278 | #define XHCI_MAX_ENDPOINTS 32 |
279 | 279 | #define XHCI_MAX_SCRATCHPADS 32 |
280 | 280 | #define XHCI_MAX_DEVICES 128 |
281 | | #define XHCI_MAX_TRANSFERS 4 |
| 281 | #define XHCI_MAX_TRANSFERS 8 |
282 | 282 | #define XHCI_MAX_TRBS_PER_TD 18 |
283 | 283 | |
284 | 284 | |