diff --git a/docs/develop/busses/usb/xhci.txt b/docs/develop/busses/usb/xhci.txt new file mode 100644 index 0000000000..9c8d79cc51 --- /dev/null +++ b/docs/develop/busses/usb/xhci.txt @@ -0,0 +1,47 @@ +anyway, here's the summary of XHCI stuff: +- XHCI operates in units of "TRBs", which consist of a pointer and two 32-bit + fields holding varying types of data based on the TRB type. A "normal" type + TRB usually has a pointer to a physical buffer and then in one of the fields, + an indicator of how many bytes are stored there +- XHCI concept of "rings" is not, as you might expect, circular buffers. + Instead, it uses "Link TRBs", that is, a TRB in which the pointer field + points to the next place the hardware should read TRBs from, and it will do + so until hitting another Link TRB, etc. So it is in fact more like a linked + list. This allows easier management of the event queue, there is no need for + a fixed size ring, managing edge cases when the buffer wraps around, etc. + +The way we handle transfers in the XHCI driver is: +- We allocate a "ring" of a small fixed amount for each endpoint (currently, + defined as XHCI_MAX_TRANSFERS*2+1, because we need 2 TRBs on the "ring" for + each transfer, and 1 at the end for the link to go back to the beginning) +- When the stack calls SubmitTransfer(), we allocate a new run of TRBs to + handle this transfer, and populate them with all the data. Then we insert one + Link TRB on the endpoint ring pointing to the first in the "transfer ring" we + just made, a link TRB at the end of the "transfer ring" pointing back to the + "endpoint ring", and then an "Event Status" TRB on the "endpoint ring" which + tells the XHCI to send an event back to us to tell us the transfer is done +- For easier tracking, the driver also keeps a TD (transfer descriptor), which + is a sideband structure not sent to the hardware, but used to keep track of + the TRBs in a given endpoint ring. + +So under normal circumstances (i.e. all transfers submitted are successful), we +will get back only "Event" TRBs generated by the "Event Data" TRBs from the +"endpoint ring"s, and these will tell us what transfer they correspond to, we +will notify it as successful, and all is well. + +If a transfer fails, then XHCI will generate an event that does *not* +correspond to an Event Status TRB (src/add-ons/kernel/busses/usb/xhci.cpp#L2372). +The pointer field in this TRB will point to the TRB that caused XHCI to +generate the event (i.e. the failed TRB), and so we look through the transfers +in progress on this endpoint and try to find which one corresponds to that TRB. + +However, it seems in your case we are failing to find it, and so we get a +"TRB xxxx was not found in the endpoint!" +Most likely this TRB is on the "endpoint ring" itself. However as noted before, +only 2 TRBs for each transfer are actually on the endpoint ring: the Link TRB +going to the "transfer ring", and the Event Data TRB telling XHCI to fire an +interrupt. + +Valid Link TRBs should never fail to execute; and to my knowledge Event Data +TRBs should not either. +