UHCI setup packet stalls for all devices most of the time
Posted: Sun Nov 07, 2021 3:18 am
I've been at this for months now, and while there's been progress, I couldn't fix this issue in particular, so I came here.
I'm trying to perform a GetDescriptor request via UHCI, and the very first setup TD stalls.
Here's the strategy:
1. Write 0x8F00 to LEGSUP
2. Enable controller reset bit
3. Wait until the bit resets
4. Set conventional configuration
5. Set port reset bit
6. Wait 100ms
7. Reset port reset bit
8. Set port enabled bit
9. Wait 10ms
10. Check connect status at bit 0
11. Run the following TD in this manner:
The above sequence actually worked for my two test devices! Twice.. and then never again. And when it doesn't, td->control is 0x00450007, which means Stalled, CRC, actual length 8 (?!?!), PORTSC is 0x0093, USBSTS is 0x0002, which indicates a USB error interrupt and USBCMD is 0x0001.
That was yesterday. I tried it again today and it worked once. At the beginning, too. And that's what gets me, because this suggests to me that it's not just a timing error. I've tried other wait times, like 50ms&10ms, 150ms&20ms, but only the one above gave me at least some results. My brain is scrambled and I may have forgotten to give other information, so do ask.
Works always in an emulator.
I'm trying to perform a GetDescriptor request via UHCI, and the very first setup TD stalls.
Here's the strategy:
1. Write 0x8F00 to LEGSUP
2. Enable controller reset bit
3. Wait until the bit resets
4. Set conventional configuration
5. Set port reset bit
6. Wait 100ms
7. Reset port reset bit
8. Set port enabled bit
9. Wait 10ms
10. Check connect status at bit 0
11. Run the following TD in this manner:
Code: Select all
QH *qh = (QH*) &buf[0];
TD *td = (TD*) &buf[16];
td->link = 1;
td->control = (1 << 23) | (3 << 27);
td->token = (7 << 21) | (0 << 19) | 0x2D;
td->buffer = (uint32_t) Virt2Phys(&buf[32]);
buf[32] = 128; /* Device to host */
buf[33] = 6; /* Get descriptor */
buf[34] = 0; /* Descriptor index */
buf[35] = 1; /* Device descriptor type */
buf[36] = 0; /* Language ID */
buf[37] = 0;
buf[38] = 18; /* Length */
buf[39] = 0;
qh->link = 1;
qh->element = Virt2Phys(td);
frameList[0] = (uint32_t) Virt2Phys(qh) | 2;
/* Wait until inactive */
do {
asm volatile(: : : "memory");
} while((td->control & (1 << 23)) != 0);
That was yesterday. I tried it again today and it worked once. At the beginning, too. And that's what gets me, because this suggests to me that it's not just a timing error. I've tried other wait times, like 50ms&10ms, 150ms&20ms, but only the one above gave me at least some results. My brain is scrambled and I may have forgotten to give other information, so do ask.
Works always in an emulator.