Commit c6061ab1 authored by Robert Sprowson's avatar Robert Sprowson

Set up the context correctly for a high->full->low cascade of devices

The context setup code had misinterpreted the XHCI spec's wording when working out the TT hub slot/TT port number; they should refer to the hub where the high speed hub is, not the adjacent hub. This caused problems with some older KVMs (which are typically full speed, and often have low speed keyboard or mice connected). USBDriver would try to get the HID descriptors but actually sent garble to the device at the wrong speed.
From NetBSD revision 1.83, and NetBSD PR/52791.

Fixes Elesar ticket 80E-056-86AB5, where a Trendnet TK-409 caused a hang at power up.

Version 0.25. Tagged as 'XHCIDriver-0_25'
parent 6f14cb53
/* (0.24)
/* (0.25)
*
* This file is automatically maintained by srccommit, do not edit manually.
* Last processed by srccommit version: 1.1.
*
*/
#define Module_MajorVersion_CMHG 0.24
#define Module_MajorVersion_CMHG 0.25
#define Module_MinorVersion_CMHG
#define Module_Date_CMHG 27 Jan 2018
#define Module_Date_CMHG 22 Feb 2018
#define Module_MajorVersion "0.24"
#define Module_Version 24
#define Module_MajorVersion "0.25"
#define Module_Version 25
#define Module_MinorVersion ""
#define Module_Date "27 Jan 2018"
#define Module_Date "22 Feb 2018"
#define Module_ApplicationDate "27-Jan-18"
#define Module_ApplicationDate "22-Feb-18"
#define Module_ComponentName "XHCIDriver"
#define Module_ComponentPath "mixed/RiscOS/Sources/HWSupport/USB/Controllers/XHCIDriver"
#define Module_FullVersion "0.24"
#define Module_HelpVersion "0.24 (27 Jan 2018)"
#define Module_LibraryVersionInfo "0:24"
#define Module_FullVersion "0.25"
#define Module_HelpVersion "0.25 (22 Feb 2018)"
#define Module_LibraryVersionInfo "0:25"
......@@ -1911,11 +1911,12 @@ static usbd_status xhci_new_device_post(usbd_device_handle dev)
{
struct xhci_softc * const sc = dev->bus->hci_private;
struct xhci_slot *xs = dev->hci_private;
usb_device_descriptor_t * const dd = &dev->ddesc;
uint32_t *cp;
struct xhci_trb trb;
usbd_status err;
int speed = dev->speed;
bool ishub = false, usemtt = false;
bool ishub = false, usemtt;
/* No-op for the root hub */
if (dev->depth == 0)
......@@ -1925,6 +1926,7 @@ static usbd_status xhci_new_device_post(usbd_device_handle dev)
cp = xhci_slot_get_icv(sc, xs, XHCI_ICI_INPUT_CONTROL);
cp[0] = htole32(0);
cp[1] = htole32(XHCI_INCTX_1_ADD_MASK(XHCI_DCI_SLOT));
cp[7] = htole32(0);
/* Complete the input slot context now the full descriptor is available */
cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
......@@ -1950,27 +1952,30 @@ static usbd_status xhci_new_device_post(usbd_device_handle dev)
);
}
#define IS_TTHUB(dd) \
((dd)->bDeviceProtocol == UDPROTO_HSHUBSTT || \
(dd)->bDeviceProtocol == UDPROTO_HSHUBMTT)
#define IS_MTTHUB(dd) \
((dd)->bDeviceProtocol == UDPROTO_HSHUBMTT)
/* Use MTT if this is a HS hub with MTT enabled, or
* this is a LS or FS (non hub) device connected to a HS hub
* with MTT enabled.
/*
* MTT flag is set if
* 1. this is HS hub && MTTs are supported and enabled; or
* 2. this is LS or FS device && there is a parent HS hub where MTTs
* are supported and enabled.
*
* XXX enabled is not tested yet
*/
if (ishub && (speed == USB_SPEED_HIGH) && IS_TTHUB(&dev->ddesc)) {
if (ishub && (speed == USB_SPEED_HIGH) && IS_MTTHUB(dd))
usemtt = true;
} else {
if (((speed == USB_SPEED_LOW) || (speed == USB_SPEED_FULL)) &&
(dev->myhsport != NULL) && /* => there is a HS hub somewhere upstream */
(dev->myhub != NULL) &&
(dev->myhub->speed == USB_SPEED_HIGH) && /* => it is our nearest hub */
(dev->myhub->depth != 0) &&
!ishub &&
IS_TTHUB(&dev->myhsport->parent->ddesc)) {
usemtt = true;
}
}
else if ((speed == USB_SPEED_LOW || speed == USB_SPEED_FULL) &&
(dev->myhsport != NULL) && /* => there is a HS hub somewhere upstream */
(dev->myhub->depth != 0) && /* => my parent isn't the root hub */
IS_MTTHUB(&dev->myhsport->parent->ddesc)) /* => it supports MTT */
usemtt = true;
else
usemtt = false
DPRINTFN(4, "class %ju proto %ju ishub %jd usemtt %jd",
dd->bDeviceClass, dd->bDeviceProtocol, ishub, usemtt);
#undef IS_MTTHUB
cp[0] |= htole32(
XHCI_SCTX_0_MTT_SET(usemtt ? 1 : 0) |
......@@ -2599,6 +2604,7 @@ xhci_init_slot(struct xhci_softc * const sc, uint32_t slot, int depth,
cp[0] = htole32(0);
cp[1] = htole32(XHCI_INCTX_1_ADD_MASK(XHCI_DCI_EP_CONTROL)|
XHCI_INCTX_1_ADD_MASK(XHCI_DCI_SLOT));
cp[7] = htole32(0);
/* set up input slot context */
cp = xhci_slot_get_icv(sc, xs, xhci_dci_to_ici(XHCI_DCI_SLOT));
......@@ -2609,19 +2615,20 @@ xhci_init_slot(struct xhci_softc * const sc, uint32_t slot, int depth,
*/
uint8_t hubports = 0, tttime = 0; /* Later */
bool ishub = false, usemtt = false; /* Later */
uint8_t ttportnum = 0, tthubslot = 0; /* Now */
struct xhci_slot * hubxs;
uint8_t ttportnum, tthubslot; /* Now */
if (((speed == USB_SPEED_LOW) || (speed == USB_SPEED_FULL)) &&
(dev->myhsport != NULL) && /* => there is a HS hub somewhere upstream */
(dev->myhub != NULL) &&
(dev->myhub->speed == USB_SPEED_HIGH) && /* => it is our nearest hub */
(dev->myhub->depth != 0)) {
if ((dev->myhsport != NULL) && /* => there is a HS hub somewhere upstream */
(dev->myhub->depth != 0) && /* => my parent isn't the root hub */
((speed == USB_SPEED_LOW) || (speed == USB_SPEED_FULL))) {
/* LS or FS device connected through a (non root) HS hub */
hubxs = dev->myhub->hci_private;
ttportnum = dev->myhsport->portno;
tthubslot = hubxs->xs_idx;
tthubslot = dev->myhsport->parent->address;
} else {
ttportnum = 0;
tthubslot = 0;
}
DPRINTFN(4, "myhsport %#jx ttportnum=%jd tthubslot=%jd",
(uintptr_t)dev->myhsport, ttportnum, tthubslot, 0);
cp[0] = htole32(
XHCI_SCTX_0_CTX_NUM_SET(1) |
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment