Long time no see.
Not so long ago i found myself in possession of a nice little circa-2000 motherboard, that i wanted to put to use.
And i got curious if i can get Aprom, my old OS project, to work the use on it.
I tried getting USB to work before, but failed (in Qemu it worked perfectly, on real HW failed completely).
4 years later, the old bugs are painfully obvious.
New ones, however, are not.
So, the board only have two UHCI controllers, no EHCI.
I had no problems initializing it, finding the devices and making them work.
Not all of them do.
Some devices, like a mouse or a floppy adapter, don't want to return string descriptors, but otherwise work fine.
SETUP packet completes fine, then the data packet reports STALLED (second word of TD is 0x1C4007FF).
Some devices, like most mass storage ones, don't even get through SET_ADDRESS.
The SETUP packet fails with Stalled and CRC/timeout (0x00440007)
Some devices, like a keypad, don't want to return device descriptor.
SETUP packet completes fine, DATA comes in fine, but the last packet reports STALLED (0x1C400003).
Or SETUP completes fine, then there is Stalled and babble (0x18500007)
Every device exhibits exactly the same behaviour in every port every time.
No randomness.
What works work, what doesn't doesn't each time.
I haven't seen any correlation to it being a low speed or full speed device.
The board can run Linux, and in there all the problem devices work just fine, so it's not something wrong with the hardware.
So, what can be the problem?
The code is rather large, is there any parts in particular that i should post?
USB (UHCI) - stalled with some devices, perfect with others.
Re: USB (UHCI) - stalled with some devices, perfect with oth
I always start out with GetDeviceDescriptor as my first usb transaction.
If the SETUP packet fails I would modify the port reset code, perhaps leave the reset signalling on a bit longer.
If SETUP and DATA pass but your STATUS fails, then I would look at the data toggles.
You may also find success by changing the order of your usb transactions.
TomT
If the SETUP packet fails I would modify the port reset code, perhaps leave the reset signalling on a bit longer.
If SETUP and DATA pass but your STATUS fails, then I would look at the data toggles.
You may also find success by changing the order of your usb transactions.
TomT
Re: USB (UHCI) - stalled with some devices, perfect with oth
Ok, focusing on one issue - a USB drive not working even as far as setting the address, with STALLED on SETUP packet.TomT wrote:If the SETUP packet fails I would modify the port reset code, perhaps leave the reset signalling on a bit longer.
Known good under Linux on the same board.
Tried to increase the reset delays to 100ms, no effect.
After the port is enabled there is also a 100ms settling delay before any transactions happen.
I checked the Linux code, and it starts with setting the address of a device just like i do.
Tried to do a get device descriptor first anyway, same result - SETUP packet stalled.
Probably unrelated, but while the mouse works it's kind of strange - it seems to skip every second interrupt transfer, so i get every second event.
Haven't tried any other types of devices in-depth.
Port init and reset code below.
Set address packet structure:
A set of frames contains links to one QH.
QH contains la link to the set of TDs.
TDs are, at the start:
SETUP 0x01848024,0x18800000,0x00E0002D,0x01821780
IN 0x00000005,0x18800000,0x00680069,0x00000000
Or, in human readable:
SETUP:
Depth first, link to second;
3 errors, ACTIVE;
maxlen=7, D=0, addr=0, ep=0, PID=2D;
Buffer specified, contains: req=SR_SET_ADDRESS( 0x05 );req_type=0;value=address;index=0;length=0;
IN:
Depth first, terminal;
3 errors, ACTIVE;
maxlen=3, D=1, addr=0, ep=0, PID=69;
No buffer;
Port init and reset code:
Code: Select all
function uhci_port_reset(uhci:puhci_rec; n:integer):boolean;
var d:integer;
rd:word;
begin
result:=false;
uhci_writeregw_port(uhci, n, PRT_RESET); //Reset
wide_delay(100); //in ms, yields to the other tasks, drivers are voluntarily preemptible
rd := uhci_readregw_port(uhci, n);
uhci_writeregw_port(uhci, n, rd and (not PRT_RESET)); //Clear reset
wide_delay(100);
rd := uhci_readregw_port(uhci, n);
uhci_writeregw_port(uhci, n, rd or PRT_ENABLED); //Enable
d := getdt;
stdt(d); //in us
while ((uhci_readregw_port(uhci, n) and PRT_ENABLED) = 0) and (rtdt(d) < 200000) do skip_tick; //Yields
freedt(d);
rd := uhci_readregw_port(uhci, n);
if (rd and PRT_ENABLED) = 0 then exit;
result:=true;
end;
//Reset the port and add device if present
function uhci_init_port(uhci:puhci_rec; n:integer):pud_rec;
var rd:word;
ls:boolean;
begin
result := nil;
if not uhci_port_reset(uhci, n) then exit;
if (rd and PRT_CON) <> 0 then begin
ls := (rd and PRT_LOWSPEED) <> 0;
wide_delay(100);
result := ut_uhci_add_device(uhci, ls, n);
end;
end;
Re: USB (UHCI) - stalled with some devices, perfect with oth
Concerning mouse - it turned out to be unrelated.
I didn't know i had to toggle the D bit in TD after each successful interrupt transaction, thus losing half of them.
I didn't know i had to toggle the D bit in TD after each successful interrupt transaction, thus losing half of them.