Hello everyone,
I managed to activate the bulk endpoints for my Mass Storage Class device on XHCI.
This device has two endpoints: bulk IN and bulk OUT.
I tested the endpoint rings by sending a NO-OP command to both of the rings and they responded as expected.
Now I was wondering how can I send bulk data to the device and how to get data back.
I can imagine I first push a TRB to the OUT ring and then push a TRB to the IN ring to read data back.
Is my assumption right?
And which TRB types should I use?
Can I use a normal_trb and a status_trb for the in and out requests?
If it is:
What should I fill in for TD Size? For me, it is not very clear what they mean by it.
The same question about "Evaluate Next TRB" and "Chain bit": do I need to use them for bulk transport?
Thank you in advantage
XHCI: bulk endpoint, how to send and receive data
Re: XHCI: bulk endpoint, how to send and receive data
Hi, and sorry for my late reply. I was on a well deserved vacation, enjoying the company of my grandchildren.
Assuming you are using the BBB protocol, you send a 31-byte command packet to the device using a NORMAL TRB (on the OUT EP). Then you send or receive zero or more NORMAL TRBs for the data, followed by receiving a 31-byte packet, again, a NORMAL TRB (on the IN EP). If you would like, and it is normal practice to do so, append an EVENT_DATA TRB at the end of each Transfer Descriptor so that you can acquire the status of the transfer. (See below for the definition of a Transfer Descriptor).
STATUS TRBs are only used on the Control pipe, not Bulk pipes.
The Evaluate Next TRB (or ENT) bit is (mostly) optional, but is used by the controller to see if the Transfer Descriptor can be processed within the time limit of this frame, so to speak. Read section 4.12.3 for more information. Also, the status is not updated until the next TRB is fetched when the ENT bit is set, which means that it could possibly be a whole frame away. I set the ENT bit in all but the last of the NORMAL TRBs and clear it in the EVENT_DATA TRB that makes up a Transfer Descriptor.
As for the TD Size, it is exactly what is specified: "This is the number of packets remaining in the TD (Transfer Descriptor)". In the example above using four TRBs, the first NORMAL TRB will indicate that there are three more, the second will indicate there are two more, the third one more, and the last will indicate no more.
Also, the direction bit is not used in NORMAL TRBs since the Endpoint is directional. However, since Control pipes use NORMAL TRBs, the first Control DATA TRB has a direction bit, while the remaining NORMAL TRBs do not. With this in mind, you can use the same code (with minor modifications) to do the Data portion of the Control transfers and Bulk transfers described above.
Hope this helps,
Ben
- https://www.fysnet.net/the_universal_serial_bus.htm
You are mostly correct.SanderR wrote:I managed to activate the bulk endpoints for my Mass Storage Class device on XHCI.
This device has two endpoints: bulk IN and bulk OUT.
I tested the endpoint rings by sending a NO-OP command to both of the rings and they responded as expected.
Now I was wondering how can I send bulk data to the device and how to get data back.
I can imagine I first push a TRB to the OUT ring and then push a TRB to the IN ring to read data back.
Is my assumption right?
And which TRB types should I use?
Can I use a normal_trb and a status_trb for the in and out requests?
Assuming you are using the BBB protocol, you send a 31-byte command packet to the device using a NORMAL TRB (on the OUT EP). Then you send or receive zero or more NORMAL TRBs for the data, followed by receiving a 31-byte packet, again, a NORMAL TRB (on the IN EP). If you would like, and it is normal practice to do so, append an EVENT_DATA TRB at the end of each Transfer Descriptor so that you can acquire the status of the transfer. (See below for the definition of a Transfer Descriptor).
STATUS TRBs are only used on the Control pipe, not Bulk pipes.
First, let me describe a Transfer Descriptor, which is one or more TRBs, chained together to form a single transfer. Using the Chain bit, you link these TRBs together. For example, if the IN endpoint has a max packet size of 128 bytes (for example), you will need four NORMAL TRBs to transfer a 512-byte sector, plus another for the EVENT_DATA TRB. These five TRBs create a Transfer Descriptor when the first four have the chain bit set, and the last has the chain bit clear. (Remember to watch for the Chain Bit when using Link TRBs)SanderR wrote: What should I fill in for TD Size? For me, it is not very clear what they mean by it.
The same question about "Evaluate Next TRB" and "Chain bit": do I need to use them for bulk transport?
The Evaluate Next TRB (or ENT) bit is (mostly) optional, but is used by the controller to see if the Transfer Descriptor can be processed within the time limit of this frame, so to speak. Read section 4.12.3 for more information. Also, the status is not updated until the next TRB is fetched when the ENT bit is set, which means that it could possibly be a whole frame away. I set the ENT bit in all but the last of the NORMAL TRBs and clear it in the EVENT_DATA TRB that makes up a Transfer Descriptor.
As for the TD Size, it is exactly what is specified: "This is the number of packets remaining in the TD (Transfer Descriptor)". In the example above using four TRBs, the first NORMAL TRB will indicate that there are three more, the second will indicate there are two more, the third one more, and the last will indicate no more.
Also, the direction bit is not used in NORMAL TRBs since the Endpoint is directional. However, since Control pipes use NORMAL TRBs, the first Control DATA TRB has a direction bit, while the remaining NORMAL TRBs do not. With this in mind, you can use the same code (with minor modifications) to do the Data portion of the Control transfers and Bulk transfers described above.
Hope this helps,
Ben
- https://www.fysnet.net/the_universal_serial_bus.htm
Re: XHCI: bulk endpoint, how to send and receive data
You don't need four TRBs in the example above. Multiple TRBs are needed if the host buffer is discontinuous or crosses a 64K page. One thing you need to take care of is that you can't have a Link TRB in the middle of a burst, nor can you have the IOC bit set in the middle of a burst (with a burst being defined as (Max Burst Size + 1) * Max Packet Size bytes).
About the TD size field, to be clear, let's say the max packet size is 128, and you have a chain of TRBs of 4096, 1024, 128, 100 and 500 bytes. The TD size fields would be 31, 13, 5, 5 and 0 respectively.
About the TD size field, to be clear, let's say the max packet size is 128, and you have a chain of TRBs of 4096, 1024, 128, 100 and 500 bytes. The TD size fields would be 31, 13, 5, 5 and 0 respectively.
Re: XHCI: bulk endpoint, how to send and receive data
You're absolutely right, though I was hoping to not overwhelm with great detail. Simple steps make progress when you are just starting.Gigasoft wrote:You don't need four TRBs in the example above. Multiple TRBs are needed if the host buffer is discontinuous or crosses a 64K page. One thing you need to take care of is that you can't have a Link TRB in the middle of a burst, nor can you have the IOC bit set in the middle of a burst (with a burst being defined as (Max Burst Size + 1) * Max Packet Size bytes).
About the TD size field, to be clear, let's say the max packet size is 128, and you have a chain of TRBs of 4096, 1024, 128, 100 and 500 bytes. The TD size fields would be 31, 13, 5, 5 and 0 respectively.
Ben