According to the USB Mass Storage Class Bulk Only Transport spec, when I want to read a block of data from a USB flash drive, I do the following:
Note that none of this factors in any STALL conditions - in these cases, let's assume that we are just clearing both endpoints and trying the commands again.
Now, in the XHCI controller interface, I am able to encode these bulk-in and bulk-out requests as TRBs (section 4.11 of the XHCI spec) and place them in ring buffer queues. The XHCI controller will parse all of these requests and trigger an interrupt when data is available.
So, does this mean that if I were to, say, enqueue the following three read CBWs to the Bulk-Out TRB queue of my USB storage device:
and I were to enqueue these six TRBs to the Bulk-In queue of my USB storage device:
then, given no STALLs or other errors, can I safely assume that the data for request 1 will end up at address 0x10000, the data for request 2 will end up at address 0x20000, the data for request 3 will end up at address 0x30000, and the CBWs for those requests will end up at addresses 0x1000, 0x2000, and 0x3000 respectively?
If that is not the case, then how do I ensure correlation with multiple enqueued requests, if that is even possible? I do see that the CSW is supposed to contain a tag value copied from the CBW, but I don't see how that helps me when I am expected to read the arbitrarily-sized, arbitrarily-encoded data from the Bulk-In endpoint before I read the CSW.
(I should mention that I'm assuming that enqueuing multiple requests like this is necessary to use USB mass storage drives efficiently - to my current understanding, if only one transfer can be executed at a time, then we need to wait for an interrupt to come back for each request, which limits the potential transfer speed to max_size_per_transfer
× (interrupts_per_second
÷ 3).)
Upon further review of the spec, I found this paragraph:
3.4 Command Queuing
The host shall not transfer a CBW to the device until the host has received the CSW for any outstanding CBW. If the host issues two consecutive CBWs without an intervening CSW or reset, the device response to the second CBW is indeterminate.
In other words, the three-request transfer pattern given in the question is not allowed. Requests made to a USB mass storage device must be made one at a time, further meaning that the maximum transfer speed for a USB mass storage device can only be realized if using single, large, contiguous blocks.