Hello,

My uplcom(4) does not work correctly with Etron EJ168 xhci.
It is attached correctly, but cannot be opened.
If it is attached to other xHCI or EHCI, it works.

When ucom is opened, bulk-in endpoint is configured at first, then
bulk-out one is configured. The former has DCI=7 and the latter has
DCI=4 (see below).  Most of xHCIs allow to use this DCI value as a
Context Entries in the Slot Context.  But Etron EJ168 does not allow,
that is, it requires the Context Entries shall be "Maximum DCI of
configured endpoint contexts", as the specification 4.5.2 suggests.
Otherwise it will generate Parameter Error(17).
In my uplcom case, software should configure the bulk-in endpoint with
Context Entries=7, and the bulk-out endpoint with Context Entries=7.


xhci2 at pci5 dev 0 function 0 "Etron EJ168 xHCI" rev 0x01: msi, xHCI 1.0
xhci2: CAPLENGTH=0x20
xhci2: DOORBELL=0x3000
xhci2: RUNTIME=0x2000
xhci2: 64 bytes context
xhci2: supported page size 0x00000001
xhci2: 4 ports and 64 slots
xhci2: 4 scratch pages, ETE=0, IST=0x7
usb2 at xhci2: USB revision 3.0
uhub2 at usb2 configuration 1 interface 0 "Etron xHCI root hub" rev 3.00/1.00 
addr 1
xhci2: DCBAAP=00xda0d5000
xhci2: CRCR=00 (00000000da0d6000)
xhci2: ERSTBA=00xd9f3e000
xhci2: ERDP=00xda0d7000
xhci2: USBCMD=0x5
xhci2: IMAN=0x2

# xhci2: port=2 change=0x04
xhci2: port=2 change=0x04
xhci2: xhci_cmd_slot_control
xhci2: dev 1, input=0xfffffd80dbe00000 slot=0xfffffd80dbe00040 
ep0=0xfffffd80dbe00080
xhci2: dev 1, setting DCBAA to 0x00000000dbe01000
xhci_pipe_init: pipe=0xffff80000050b000 addr=0 depth=1 port=2 speed=2 dev 1 dci 
1 (epAddr=0x0)
xhci2: xhci_cmd_set_address BSR=1
xhci2: xhci_cmd_set_address BSR=0
xhci2: dev 1 addr 1
uplcom0 at uhub2 port 2 configuration 1 interface 0 "Prolific Technology Inc. 
USB-Serial Controller" rev 1.10/3.00 addr 2
ucom0 at uplcom0

# cu -s115200 -lttyU0
xhci_pipe_init: pipe=0xffff80000081a000 addr=2 depth=1 port=2 speed=2 dev 1 dci 
7 (epAddr=0x83)
xhci2: xhci_cmd_configure_ep dev 1
xhci_pipe_init: pipe=0xffff80000081b000 addr=2 depth=1 port=2 speed=2 dev 1 dci 
4 (epAddr=0x2)
xhci2: xhci_cmd_configure_ep dev 1
xhci2: event error code=17, result=33
trb=0xffff800022376430 (0x00000000da0d6040 0x11000000 0x1008401<CYCLE>)
xhci2: xhci_cmd_slot_control
xhci2: xhci_cmd_configure_ep dev 1
xhci2: event error code=11, result=33
trb=0xffff800022376530 (0x00000000da0d6060 0x0b000000 0x1008401<CYCLE>)
xhci2: error clearing ep (7)
cu: open("/dev/ttyU0"): Input/output error


To fix the problem, set the maximum value between the DCI of the last
valid Endpoint Context and the DCI to be configured to the DCI to be
configured.


--- sys/dev/usb/xhci.c.orig     Wed Dec  4 22:32:43 2019
+++ sys/dev/usb/xhci.c  Sun Dec  8 03:24:00 2019
@@ -1330,7 +1330,7 @@ xhci_pipe_maxburst(struct usbd_pipe *pipe)
 int
 xhci_context_setup(struct xhci_softc *sc, struct usbd_pipe *pipe)
 {
-       struct xhci_pipe *xp = (struct xhci_pipe *)pipe;
+       struct xhci_pipe *lxp, *xp = (struct xhci_pipe *)pipe;
        struct xhci_soft_dev *sdev = &sc->sc_sdevs[xp->slot];
        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
        uint32_t mps = UGETW(ed->wMaxPacketSize);
@@ -1338,6 +1338,7 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_
        uint8_t speed, cerr = 0;
        uint32_t route = 0, rhport = 0;
        struct usbd_device *hub;
+       int i;
 
        /*
         * Calculate the Route String.  Assume that there is no hub with
@@ -1393,9 +1394,16 @@ xhci_context_setup(struct xhci_softc *sc, struct usbd_
        sdev->input_ctx->drop_flags = 0;
        sdev->input_ctx->add_flags = htole32(XHCI_INCTX_MASK_DCI(xp->dci));
 
+       /* Find the last valid Endpoint Context */
+       for (i = 30; i >= 0; i--) {
+               lxp = sdev->pipes[i];
+               if (lxp != NULL && lxp != xp)
+                       break;
+       }
+
        /* Setup the slot context */
        sdev->slot_ctx->info_lo = htole32(
-           XHCI_SCTX_DCI(xp->dci) | XHCI_SCTX_SPEED(speed) |
+           XHCI_SCTX_DCI(max(lxp->dci, xp->dci)) | XHCI_SCTX_SPEED(speed) |
            XHCI_SCTX_ROUTE(route)
        );
        sdev->slot_ctx->info_hi = htole32(XHCI_SCTX_RHPORT(rhport));


Reply via email to