foliagecanine wrote:I think I'm starting to get it...
So as long as I'm placing TRBs on the ring as fast or faster than it is consuming them, I'll never need to ring the doorbell again?
In theory, yes. However, when the controller gets to the end of the ring and toggles its internal cycle bit, it will stop when it finds a cycle mismatch, unless of course you correctly place TRBs with the new cycle bit at the first of the ring.
However, this isn't practical and don't rely upon the fact that you can place TRBs on the ring faster than it can consume them.
foliagecanine wrote:
So theoretically, I could do something like this:
Where D = Data TRB, E = Transfer Event TRB, L = Link TRB, and I would just have to flip all the cycle bits every time I get to the Link TRB?
In theory, yes, this would work, but now you are relying on the fact that your code will always be ahead of the controller. This is not the case for many reasons.
What happens when your task scheduler doesn't come back around to your xHCI/Mouse/USB/Whatever task in time? You will continue to place TRBs on the schedule, but now you're not in sync with the controller and it may or may not consume any TDs. The instant the cycle bit is a mismatch, it stops and will not start again until a doorbell is rung. Yet, you are continuing to place TRBs on the ring, overwriting TRBs that may or may not have been consumed.
foliagecanine wrote:Is there a way to execute multiple TRBs in one ESIT interval?
From the quote I mentioned before from the specification, and for what you are asking (you assuming a complete transfer is a TRB, not TD), this is a NO. (Transfer Descriptors can contain multiple TRBs, and the specification states TDs, not TRBs)
Let me quote it again:
If multiple Interrupt TDs are posted to an Interrupt endpoint Transfer Ring, the xHC should consume no more than one TD per ESIT.
...
if the Interrupt TD Transfer Size is greater than the Max ESIT Payload, then the TD may take multiple ESITs to complete.
Since your mouse will most likely only require one TRB per transfer, then the TD will be 1 TRB in size. With this in mind, the controller will only consume 1 TD (and TRB) per interval.
foliagecanine wrote:Also, what happens if there's a NAK? Does it advance to the next TRB or does it just have a different status. In the second case, would the Transfer Event TRB fire an interrupt if its IOC bit were on?
The specification states:
A Short Packet shall terminate an IN Interrupt TD and the next TD (if present) shall be scheduled in the next ESIT.
This is only short packets. I would have to go over my notes for NAKs.
Ben