OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Apr 19, 2024 12:40 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
 Post subject: UHCI root hub port reset (quirk?)
PostPosted: Wed Mar 16, 2011 3:27 pm 
Offline

Joined: Wed Mar 16, 2011 2:25 pm
Posts: 3
Hi,
I've seen problems similar to mine here and elsewhere but was unable to find a definite answer.
I'm part of a team bringing USB support to an academic OS, and so far everything was good.
We got several devices working and tested on real hw (mouse, keyboard, hubs), however some are causing problems (namely Microsoft IntelliMouse Optical).
After plugging in the mouse it responds to the first SETUP packet with Timeout/CRC and ultimately Stall, exact value of of TD status field is 4450007 (LOW SPEED, STALL, CRC/TIMEOUT, RESERVED BIT, 8 bytes transfered, what is this thing with reserved status bit(bit 16) set?)

Funny thing is that it works with other devices that i tried, Logitech keyboard, Genius mouse, usb hubs. The fact that the same microsoft mouse works when connected via another hub, has led me to believe that problem is with UHCI port reset routine (it's the only thing that differs).
my reset routine, called immediately after CSC bit is detected and bit 0 indicates there is a device connected:
Code:
mwait(100) /* 100ms, my understanding is that this one is not necessary and 100ms timeout shall be provided by UHCI before indicating the device presence, but can't hurt */

port_write(0x0200) /* starts reset signaling */
mwait(50) /* 50 ms, USB spec 7.1.7.3 mentions that reset from root hub ports should be 50 ms, however OHCI does not do it, and sends reset signal for 10ms  (UHCI 1.0a p. 131) */
port_write(0) /* stops reset signaling, keeps CSC, and possibly PCE bits untouched */

p = port_read()
p |= 0x4
port_write(p); /* this sets port to enabled state, and clears WC bits */

mwait(10)   /* 10 ms reset recovery */

the first SETUP packet requests 8 bytes of device descriptor. (and succeeds if this mouse is connected via external hub)

during my experiments I found out that devices react differently to incorrect/absent reset, some worked even without a reset signal, some responded NAK to everything, and some responded the same way as this MS mouse (another thing that let me believe there is something wrong with reset sequence)

is there something I missed, or some kind of quirk that certain devices need?
any input is welcome as I am stuck on this.
thanks

PS: The mouse works well with both Linux and Windows,
out of 3(different models) Microsoft optical mice I tried, only one worked, other devices I tried don't have this problem


Top
 Profile  
 
 Post subject: Re: UHCI root hub port reset (quirk?)
PostPosted: Thu Mar 17, 2011 9:33 am 
Offline
Member
Member
User avatar

Joined: Tue Oct 17, 2006 9:29 pm
Posts: 2426
Location: Canada
Several OS's deviate from that 50ms standards requirement, as a workaround for buggy devices, try 100 or 150.

Microsoft USB devices are always flaky btw, this isn't news.

_________________
Image
Twitter: @canadianbryan. Award by smcerm, I stole it. Original was larger.


Top
 Profile  
 
 Post subject: Re: UHCI root hub port reset (quirk?)
PostPosted: Fri Mar 18, 2011 6:46 pm 
Offline

Joined: Wed Mar 16, 2011 2:25 pm
Posts: 3
Thanks for your reply, I tried several timing settings, from 10ms to 1s and it did not help.

I dug into several uhci drivers and checked the timings used there:
OS | reset duration | post reset wait
DOS: 55ms 55ms (comments say > 50ms)
Apple: 10ms 100ms
HAIKU: 250ms 1ms (then waits 50ms to confirm port enabled)
Linux(2.6.38): 50ms 10us

I tried all of the combinations and none worked.
Funny thing is that once it somehow worked, but I have been unable to replicate this ever since.

I use linux daily and tried haiku live CD, the mouse works in both.

When the initialization sequence was repeated 100 times(100ms and 1s pauses) I got 100 errors. (that should rule out some random timing error).
I did not check connections status between iterations and after removing the mouse it continued with the same error (i.e. the mouse is dead and refuses to communicate).

All UHCI root ports are powered(no way to change it), and I do not touch suspend/resume bits.


Top
 Profile  
 
 Post subject: Re: UHCI root hub port reset (quirk?) [solved]
PostPosted: Sun May 08, 2011 1:59 pm 
Offline

Joined: Wed Mar 16, 2011 2:25 pm
Posts: 3
OK I finally figured this one.
For those who are interested:
I got reset recovery period wrong, I used it to wait after reset before enabling the port, while it should be the time from reset to data communication with the device. On the other hand USB specification mentions(7.1.7.4) that device that must be in suspended state after 10ms.
Thus, these devices (Microsoft mice and a Kingston flash disk) were in suspend state by the time the host tried to communicate. I don't know why those devices failed to resume when the idle signalling ceased (as specified in 7.1.7.5).

The solution was to wait the right amount of time between the end of reset signalling and port enabling. If it is done immediately, the port fails to enable, too much time, and devices enter suspend state.

Hope this helps somebody.

PS: I should mention that this: http://www.seabios.org/pipermail/seabio ... 00321.html
Don't leave USB UHCI ports disabled for extended time during reset.

Disabling the port will cause device to go into suspend - so don't do
that during the reset sequence

pointed me in the right direction


Top
 Profile  
 
 Post subject: Re: UHCI root hub port reset (quirk?)
PostPosted: Mon Aug 29, 2011 3:30 pm 
Offline
Member
Member
User avatar

Joined: Tue Feb 01, 2011 6:18 pm
Posts: 31
Location: London, UK
This was very helpful, thank you. I was experiencing the exact same symptoms with a few of my USB peripherals.

So, what worked for me was:

1. Set reset bit
2. Wait 50ms
3. Clear reset bit
4. Set enabled bit
5. Wait 10ms
6. Proceed with enumeration

Cheers! =D>
Andy


Top
 Profile  
 
 Post subject: Re: UHCI root hub port reset (quirk?)
PostPosted: Thu Dec 31, 2015 2:13 pm 
Offline

Joined: Sat Aug 14, 2010 9:49 pm
Posts: 20
I don't want to bump an old thread, but for anyone who's interested.

@ orome
Quote:
The solution was to wait the right amount of time between the end of reset signalling and port enabling. If it is done immediately, the port fails to enable, too much time, and devices enter suspend state.


I have found that waiting for a connect status change works best.

Quote:
Disabling the port will cause device to go into suspend - so don't do
that during the reset sequence


The UHCI specification states that "When in the Reset State, the port is disabled and sends the USB Reset signaling", so that should not be a problem.

@ andymc

Quote:
1. Set reset bit
2. Wait 50ms
3. Clear reset bit
4. Set enabled bit
5. Wait 10ms
6. Proceed with enumeration


Most of my flash drives was timing out because of step 5 (Wait 10ms). I increased it to 24ms and they stopped timing out.

@ All

So what works for me is:

1. Set reset bit.
2. Wait 58ms.
3. Clear reset bit.
4. Wait for connect status change.
5. Set enable bit.
6. Wait for enable bit to actually change.
7. Wait 24ms.
8. Proceed with enumeration.

Some Code:

Code:
/* Turning reset off causes a port connect status change. */
ERROR API uhci_WaitForCSC(PUHCI HC, BYTE Port)
{
   WORD I, Status;

   for (I = 0; I < 100; I++) // Timeout at 400ms (4ms * 100).
   {
      Sleep(4);
      Status = InW(HC->BAR + UHCI_PORTSC1 + (2*Port));
      if (Status & UHCI_PORT_CS_CHANGE) return ERROR_NONE;
   }

   return ERROR_USB_TIMEOUT;
}

/* UHCI_PORT_ENABLE Bit does not change until the port state actually changes. */
ERROR API uhci_WaitForEnabledPort(PUHCI HC, BYTE Port)
{
   WORD I, Status;

   for (I = 0; I < 100; I++) // Timeout at 200ms (2ms * 100).
   {
      Sleep(2);
      Status = InW(HC->BAR + UHCI_PORTSC1 + (2*Port));
      if (Status & UHCI_PORT_ENABLE) return ERROR_NONE;
   }

   return ERROR_USB_TIMEOUT;
}

VOID API uhci_ResetPort(PUHCI HC, BYTE Port)
{
   // Reset.
   OutW(HC->BAR + UHCI_PORTSC1 + (2*Port), UHCI_PORT_RESET);

   // Wait.
   Sleep(58);

   // Clear Reset Bit.
   OutW(HC->BAR + UHCI_PORTSC1 + (2*Port), InW(HC->BAR + UHCI_PORTSC1 + (2*Port)) & ~UHCI_PORT_RESET);

   // Wait for a connect status change. HP's server management chip requires a longer delay.
   uhci_WaitForCSC(HC, Port);

   // Enable, and Clear Change-Bits (Connected & Enabled).
   OutW(HC->BAR + UHCI_PORTSC1 + (2*Port), UHCI_PORT_CS_CHANGE|UHCI_PORT_ENABLE|UHCI_PORT_ENABLE_CHANGE);

   // Wait for the port to become enabled.
   uhci_WaitForEnabledPort(HC, Port);

   //Wait.
   Sleep(24);
}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 101 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group