Bonfra, maybe try modifying this:
Code: Select all
if(i == num_packets - 1)
tds[i].flags |= TD_IOC;
Code: Select all
if(i == num_packets - 1)
tds[i].flags |= TD_IOC;
Yes this is the assumption we are relying on. There is not a 100% confirmation from the BIOS since the config page doesn't show anything about this but the device is found in the port. probably, it's possible to assume that it is in bypass mode.sounds wrote:If I understand correctly, the EHCI controller is in bypass mode, since the UHCI controller detected a device connected on port 0. Someone correct me if that's wrong.
Sadly it didn't change nothing... I'ts like the schedule its ignoring those TDssounds wrote: Bonfra, maybe try modifying this:How about setting TD_IOC for every TD, temporarily at least?Code: Select all
if(i == num_packets - 1) tds[i].flags |= TD_IOC;
Could you please leave the TD_IOC flag set on all packets, temporarily at least, while the driver is getting stuck attempting to initiate the first transfer after a reset? If you didn't revert to setting TD_IOC only on the last TD in the set, perfect.Bonfra wrote:Sadly it didn't change nothing... I'ts like the schedule its ignoring those TDs
That USBCMD doesn't look like HCRESET to me. It looks like Run/Stop in state Run (bit 0).Bonfra wrote:the controllers seems to be entered in HCRESET state and the first td's timeout flag is set
Code: Select all
Registers after 1000000 spins
USBCMD: 0x1
USBSTS: 0x0
USBINTR: 0x0
FRNUM: 0x323
SOFMOD: 0x40
In the screenshot, the IOC bit is only set in the last TD, I reverted the change to post a more coherent screenshot. At the end of this post I'll add on a future edit a screenshot of the logs with the IOC bit set in all packets. Sorry for the misunderstanding.sounds wrote:Could you please leave the TD_IOC flag set on all packets, temporarily at least, while the driver is getting stuck attempting to initiate the first transfer after a reset? If you didn't revert to setting TD_IOC only on the last TD in the set, perfect.
Yea sorry I misread the specs. So even the internal state appears to be fine.sounds wrote:That USBCMD doesn't look like HCRESET to me. It looks like Run/Stop in state Run (bit 0). [...]Also the FRNUM value seems to match about what I'd expect the number of 1 ms frames would be if your code is spinning 10^6 times
Well, it's the last packet of the sequence and it doesn't need any buffer to write anything to. Is that field something more than a buffer? Does it also contain some flags? Not that I think about it I've seen some implementations with that final packet.buffer being set to 0x80000000; is there a specific reason for this?sounds wrote:Lastly, are you sure TD[1]'s BUFPTR value should be 0x0?
This is where I'm really not sure what is the right thing to do. And changing td[1].BUFPTR value probably has nothing to do with why the controller is reporting the timeout error on td[0].Bonfra wrote:Well, it's the last packet of the sequence and it doesn't need any buffer to write anything to. Is that field something more than a buffer? Does it also contain some flags? Not that I think about it I've seen some implementations with that final packet.buffer being set to 0x80000000; is there a specific reason for this?sounds wrote:Lastly, are you sure TD[1]'s BUFPTR value should be 0x0?
That is correct, however it doesn't mean the SMI has given up control of the EHCI and UHCI(s).sounds wrote:If I understand correctly, the EHCI controller is in bypass mode, since the UHCI controller detected a device connected on port 0. Someone correct me if that's wrong.
This should only apply to HDIs so it should not be a problem (since I'm working with an msd) but I've followed your suggestion so it should not interfere.BenLunt wrote: however it doesn't mean the SMI has given up control of the EHCI and UHCI(s).
BenLunt wrote:A simple write to PCI configuration word 0xC0 of 0x8F00 does the trick.
Sorry if I pursued the stack path but I wanted to be 101% sure that it wasn't faulty on that side. Obviously you were right but still some more confirmation doesn't hurt ;PBenLunt wrote: Bonfra, since your stack works as expected on two emulators, may I suggest that it isn't your stack nor your buffers. It is hardware related. At the "Resetting Port 0" stage, print the port's value, before, during, and after. I still think that your code isn't waiting long enough and/or not enabling the port correctly. Does the port actually become enabled? Once it does, do you wait a few mS before you start your schedule?
I am guessing you meant HID instead of HDI. However, with newer firmware, it manages MSDs as well, to be able to boot from them. However, since you sent the "release", I don't think this is a problem.Bonfra wrote:This should only apply to HDIs so it should not be a problem (since I'm working with an msd) but I've followed your suggestion so it should not interfere.BenLunt wrote: however it doesn't mean the SMI has given up control of the EHCI and UHCI(s).BenLunt wrote:A simple write to PCI configuration word 0xC0 of 0x8F00 does the trick.
I don't know where you got the 0xE2 from either. I doubt the port had a value of 0xE2. Place a "printf()" at line 152 and see what value it has. Something that will print the iteration number and the value. For example:Bonfra wrote:After the "Waiting for port to be ready" message 10 iterations are performed spinning on the PORTSC_ENABLE bit sleeping 10ms between each and logging the value each time. I'm not quite sure about that 0xE2 value repeated three times but idk I'm a bit confused
Code: Select all
printf(" %i: 0x%04X\n", iteration++, status); // of course defining 'iteration' as an integer with a value of zero at the top of your function.
Code: Select all
ret = -1;
const bit8u port = ??????; // Bonfra: 'port' = 0x10, 0x12, etc. Modify to match your code...
bit16u val = 0;
// reset the port, holding the bit set at least 50 ms for a root hub
val = inpw(base + port);
outpw(base + port, val | (1<<9));
mdelay(USB_TDRSTR);
// clear the reset bit, do not clear the CSC bit while
// we clear the reset. The controller needs to have
// it cleared (written to) while *not* in reset
// also, write a zero to the enable bit
val = inpw(base + port);
outpw(base + port, val & 0xFCB1);
udelay(300); // note that this is *not* the USB specification delay
// if we wait the recommended USB_TRSTRCY time after clearing the reset,
// the device will not enable when we set the enable bit below.
// the CSC bit must be clear *before* we set the Enable bit
// so clear the CSC bit (Write Clear), then set the Enable bit
val = inpw(base + port);
outpw(base + port, val | 0x0003);
outpw(base + port, val | 0x0005);
// wait for it to be enabled
udelay(50);
// now clear the PEDC bit, and CSC if it still
// happens to be set, while making sure to keep the
// Enable bit and CCS bits set
val = inpw(base + port);
outpw(base + port, val | 0xF);
// short delay before we start sending packets
mdelay(50);
// return successful if the Enabled bit was set
if (inpw(base + port) & (1<<2))
ret = SUCCESS_RESET;
return ret;
I whole-heartedly agree.There are specific rules for how setup packets must be formatted, and I'm not convinced that emulators will check these properly.
It could also be that the USB device was not properly initiated (IOW, the problem is with the USB device, not the UHCI controller). The reset timing needs to be correct, and some devices require longer time than others to be properly initialized. I bet emulators do not handle this the same way as real devices either. Note that for UHCI, it's the OS driver that is responsible for the correct reset timing, not the controller. My reset port for UHCI has a fixed 200 ms delay after the reset command is sent & accepted.BenLunt wrote:I have seen on actual hardware that the Run bit gets set, etc, and the controller tries to execute the schedule for a device. However, the device was not enabled correctly, even though the Enable bit is set, and the schedule is not properly executed for that device. What Bonfra is explaining seems to be exactly what I have witnessed. Even though the Enable bit is set, the device was not correctly enabled, both on the controller side and the device side, and the schedule does not execute correctly.
I am hoping that he tries my posted code and the schedule starts to work as expected. I am not saying that it has to be this, though I have experienced this personally, so this is my current solution, until it proves otherwise.I whole-heartedly agree.There are specific rules for how setup packets must be formatted, and I'm not convinced that emulators will check these properly.
Thanks,
Ben
Agreed, hence the posted reset code. I tested many devices and the timings in that posted code have proved to be sufficient for each.rdos wrote:It could also be that the USB device was not properly initiated (IOW, the problem is with the USB device, not the UHCI controller). The reset timing needs to be correct, and some devices require longer time than others to be properly initialized.
Again, I agree. I have found that 50ms has been enough for all devices I have tried. However, it doesn't hurt one bit to wait the 200ms you suggest. Better safe than sorry.rdos wrote:I bet emulators do not handle this the same way as real devices either. Note that for UHCI, it's the OS driver that is responsible for the correct reset timing, not the controller. My reset port for UHCI has a fixed 200 ms delay after the reset command is sent & accepted.
Yea sorry, little typo. Yes to be sure I'm writing the LEGSUP register before and after the controller initialization.BenLunt wrote: I am guessing you meant HID instead of HDI. However, with newer firmware, it manages MSDs as well, to be able to boot from them. However, since you sent the "release", I don't think this is a problem.
Every log that starts with "PORTSC:" is in that line you asked for. I'm not printing the iteration number but you can assume everything before a message of "No device on port %d" or "Port enable" belongs to the same cycles of iteration.BenLunt wrote: I don't know where you got the 0xE2 from either. I doubt the port had a value of 0xE2. Place a "printf()" at line 152 and see what value it has. Something that will print the iteration number and the value. For example:Code: Select all
printf(" %i: 0x%04X\n", iteration++, status); // of course defining 'iteration' as an integer with a value of zero at the top of your function.
Nope, PCI vendor id (first two words) is 0x8086BenLunt wrote: Curious, is your UHCI an HP brand (vendor id = 0x103C)?
No apology needed.Bonfra wrote:Hi, sorry for my long absence.