OSDev.org

The Place to Start for Operating System Developers
It is currently Fri Mar 29, 2024 8:54 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 55 posts ]  Go to page Previous  1, 2, 3, 4  Next
Author Message
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Sun Aug 06, 2017 4:40 pm 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
Are there some other fields in QH/TD that need to be set, like the NAK stuff?


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Mon Aug 07, 2017 11:40 am 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
bump?


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Mon Aug 07, 2017 2:59 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
mariuszp wrote:
bump?

Again, sorry, I don't have the time at the moment to look over your code. However, dump your Queue Head and TD's to DWORDs and post that.

For example:
Code:
0x01234567   <- Queue Head at address 0x76543210
0x87763873   <- TD0 (Setup Packet) at address 0x82349238
               (setup packet contains: 00 00 00 00 00 00 00 00) and is at address 0x23422837
0x82839492   <- TD1 (Status Packet) at address 0x8394832

Ben


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Mon Aug 07, 2017 3:50 pm 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
Here they are:

Code:
Queue Head (before horizontal pointer is set):
   0x01D5E002
   0x0040A000
   0x40000000
   0x00000000
   0x00000001
   0x00000001
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
First TD (SETUP at phys 0x01D5F000):
   0x01D5F020
   0x00000001
   0x00080280
   0x01D5F040
   0x00000000
   0x00000000
   0x00000000
   0x00000000
Second TD (STATUS at phys 0x01D5F020):
   0x00000001
   0x00000001
   0x00000180
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
SETUP packet data at phys 0x01D5F040:
   0x00010500
   0x00000000


That fifth (index 4) DWORD in the queue head is set to 0x01D5F000 right after this (to execute the transaction).

And, as stated before, after doing this, the third DWORD in the first TD changes from 0x00080280 to 0x00080208 (active clear, transaction error set).


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Mon Aug 07, 2017 6:48 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
Code:
Queue Head (before horizontal pointer is set):
   0x01D5E002   horzontal pointer and it is pointing to another QH
   0x0040A000   max len = 0x40, Head = 1, DTC = 0 (see note '1' below), EPS = HS, Endp = 0, Addr = 0
   0x40000000   1 transaction per microframe
   0x00000000   zero
   0x00000001   currently no TD linked
   0x00000001   currently no alt TD linked
   0x00000000   zeros
   0x00000000   
   0x00000000   
   0x00000000   
   0x00000000   
   0x00000000   
First TD (SETUP at phys 0x01D5F000):
   0x01D5F020   next TD (correct address)
   0x00000001   no alt TD
   0x00080280   DT = 0, bytes to transfer = 8, IOC = 0, CPAGE = 0, CERR = 0 (see note '2'), PID = SETUP, Status = 0x80
   0x01D5F040   buffer pointer/current offset (correct)
   0x00000000
   0x00000000
   0x00000000
   0x00000000
Second TD (STATUS at phys 0x01D5F020):
   0x00000001   Done, no more TD's
   0x00000001   no alt TD
   0x00000180   DT = 0 (see note '3'), bytes to transfer = 0, IOC = 0, CPAGE = 0, CERR = 0 (see note '2'), PID = IN, Status = 0x80
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
SETUP packet data at phys 0x01D5F040:
   0x00010500
   0x00000000
If the above is little endian: (and it should be)
     00 = (HOST_TO_DEV | REQ_TYPE_STNDRD | RECPT_DEVICE)
     05 = Set Address
  01 00  = address 1
  00 00  = index = 0
  00 00  = len = 0
 
1: A DTC of zero means to ignore the toggle bit in the TD and start with this one.  I would set
   this bit to 1 and use the Toggle bits within the TD's instead.
2: I would make the CERR field = 3.
3: All STATUS TD's need a DT of '1'
    The SETUP packet has a Data Toggle of '0', then the STATUS packet has a DT of '1'

I quickly went through that, so I hope I got all of it correct. However, it looks like you don't have the Data Toggle correct. A very common mistake for the beginner. Change the QH to let the TD show the Toggle, then set the SETUP toggle to '0' and the STATUS toggle to '1'.

All Control transactions start with a SETUP packet using a DT of 0. Then every packet (TD) after that is toggled. The STATUS TD has a Toggle of '1' no matter the value of that last TD.

Try that.
Ben


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 7:49 am 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
I set all CERR to 3, DTC in the queue head to 1, and DT in sETUP to 0, DT in STATUS to 1. However, the problem still arises: it clears the 'active' bit and sets the 'transaction error' bit. New state:

Code:
Queue Head (before horizontal pointer is set):
   0x01D5E002
   0x0040E000
   0x40000000
   0x00000000
   0x00000001
   0x00000001
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
First TD (SETUP at phys 0x01D5F000):
   0x01D5F020
   0x00000001
   0x00080E80
   0x01D5F040
   0x00000000
   0x00000000
   0x00000000
   0x00000000
Second TD (STATUS at phys 0x01D5F020):
   0x00000001
   0x00000001
   0x80000D80
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
SETUP packet data at phys 0x01D5F040:
   0x00010500
   0x00000000


EDIT: Some more information in case it is needed:

The device in question is a USB Flash Memory. According to the wiki those operate at high-speed so AFAIK i should have no problem with using them with EHCI.

But anyhow, how would I detect that the port must be released? USB 1.0 devices cannot handle high-speed, so does that mean i'd have to detect a stransaction error and then release the port? (And in that case, does OHCI/UHCI see that something was just connected to the port and issue a "port change" interrupt?)

EDIT 2: In addition to this, CERR is not decremented. This is very confusing.
And furthermore, the Queue Head advances (by checking the "current TD" value, I see that it reaches the STATUS packet).


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 9:04 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 999
You have to check the PORTSC register to determine if the device is a low- or full-speed device and release the port via the Port Owner bit if that is the case. That being said I doubt that any non-ancient flash drive does not support full speed.

Do you test in qemu or do you try to run your driver on real hardware? IIRC qemu ignores DT anyways so that cannot be a problem.

AFAIR CERR is not decremented on fatal errors but I'm on mobile and don't have the specs to check that.

_________________
managarm: Microkernel-based OS capable of running a Wayland desktop (Discord: https://discord.gg/7WB6Ur3). My OS-dev projects: [mlibc: Portable C library for managarm, qword, Linux, Sigma, ...] [LAI: AML interpreter] [xbstrap: Build system for OS distributions].


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 9:10 am 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
I am testing in VirtualBox. The flash memory is physical (pass-through to VM).


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 9:16 am 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
mariuszp wrote:
I set all CERR to 3, DTC in the queue head to 1, and DT in sETUP to 0, DT in STATUS to 1. However, the problem still arises: it clears the 'active' bit and sets the 'transaction error' bit.

The device in question is a USB Flash Memory. According to the wiki those operate at high-speed so AFAIK i should have no problem with using them with EHCI.

This is not always the case. I have a thumb drive that is full-speed only. Yes, most devices now are high-speed if not super-speed, but there are still devices that are full-speed only. Cheaper to manufacture.

mariuszp wrote:
But anyhow, how would I detect that the port must be released? USB 1.0 devices cannot handle high-speed, so does that mean i'd have to detect a transaction error and then release the port? (And in that case, does OHCI/UHCI see that something was just connected to the port and issue a "port change" interrupt?)

EDIT 2: In addition to this, CERR is not decremented. This is very confusing.
And furthermore, the Queue Head advances (by checking the "current TD" value, I see that it reaches the STATUS packet).

It has been a little while since I have worked with EHCI, so I would have to pull my notes out and have a look. (I don't have the time at the moment).
So, (quickly) I have a few notes for you.

The companion controller will have its connect status bit set once you release the EHCI's control. However, you should do a port reset anyway to be sure.

Are the ports powered? The EHCI has a bit that tells you if you can control the port's power. If you can, you need to make sure and power the port. You will not get anything back from the device if the port is not powered.

Do a search for the specs on the thumb drive you are using to be sure it is high-speed. This will eliminate that doubt. If you can't find specs, insert it into another machine, then view its name and driver. For example, Windows will show its VENDOR and DEVICE ID in the driver section of the hardware setup. You can then use that to investigate the speed of the device.

Sorry, got to run.
Ben


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 10:19 am 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
The power bit is set, just checked. However is my reset sequence correct?

Code:
                  sleep(100);
                  ehciRegs->ports[i] |= EHCI_PORT_RESET;
                  sleep(50);
                  ehciRegs->ports[i] &= ~EHCI_PORT_RESET;


It seems to me that there is a race condition here where while clearing the "Reset" bit, I might also end up clearing the "Port Enable" bit if the controller sets it at the wrong time...

EDIT: I just changed the rest code to this:

Code:
                  ehciRegs->ports[i] |= EHCI_PORT_RESET;
                  while (ehciRegs->ports[i] & EHCI_PORT_RESET);
                  
                  if ((ehciRegs->ports[i] & EHCI_PORT_ENABLED) == 0)
                  {
                     kprintf("ehci: warning: not high-speed\n");
                     // TODO: port routing
                     continue;
                  };


This seems to work and there is no race condition. Also, since EHCI_PORT_ENABLED gets set, according to the EHCI spec this means that the device is in fact high-speed. However, the transfer descriptor STILL reports the "transaction error".


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 11:53 am 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
Of the four controller types, EHCI is not my favorite. Let me pull out my notes....

While I am thinking about it, how about the Port Owner bit? What value does it hold?

To see if the attached device is a low-speed device, read the Line Status bits. If the value is 01b, you have a low speed device. If not 01b, you have a full- or high-speed device and must do a reset to find out which.

The reset can be complicated.
1) The USBSTS:HcHalted bit must be zero, hence, the schedule must be running
2) Set the Port Reset bit and clear the Port Enabled bit at the same time
3) Since this is a root hub, make sure you assert the reset for 50ms.
4) Wait for the bit to clear
5) Pause for TRSTRCY (recovery time)

Now, if the Enable bit is set, you have a high-speed device. This is what you have stated already, so let's assume so.

Make sure that all QH's and TD's do not cross a 4k boundary, which I think you have already done so.

In your TDs, make sure that the first transfer, the first access of CPAGE and OFFSET doesn't cross to the next 4k page. For example, if your first few bytes to transfer is at 0x123400F8, you can only transfer 8 bytes until the controller moves to the next CPAGE entry. Again, I think you've got this covered.

With all of this in mind, I don't know why you are getting a Transaction Error. I admit though, I don't use Virtual Box. I prefer Bochs when debugging my code. Volker has created the EHCI part of bochs, but has included a lot of my techniques pulled from the UHCI, OHCI, and xHCI code, which I did write. Bochs will allow you to set a DEBUG flag for the EHCI and it will log all errors including current processed TD's, etc.

(Side note: I also have an advantage. The good people at Totalphase sent me a Beagle12 and it has helped with my research more than anything else.)

Have you tried your code on real hardware?

At the moment, and with out actually working with your code, I don't think I have much more for you. I hope that you can get it, and I am interested in your outcome.

Ben


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 12:43 pm 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
All bits are clear, except: Port Power, Port Enabled, Port Connected.


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 1:30 pm 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
Here is the state of everything after the transaction:

Code:
Queue Head (after transaction):
   0x01D5E002
   0x0040E000
   0x40000000
   0x01D5F020
   0x00000001
   0x00000001
   0x80000D08
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
First TD (SETUP at phys 0x01D5F000, after transaction):
   0x01D5F020
   0x00000001
   0x00080E08
   0x01D5F040
   0x00000000
   0x00000000
   0x00000000
   0x00000000
Second TD (STATUS at phys 0x01D5F020, after transaction):
   0x00000001
   0x00000001
   0x80000D08
   0x00000000
   0x00000000
   0x00000000
   0x00000000
   0x00000000
SETUP packet data at phys 0x01D5F040:
   0x00010500
   0x00000000


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 6:03 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 934
Location: USA
Can you make a bootable floppy image, narrowing down the code, printing a line:

"To start the EHCI initialization, press a key"

Then wait for a key press before you start the EHCI stuff.

Then post that floppy image somewhere, or let me know and I can send you an email address. When I get a chance, I can run it through some of my tests and see what is going on.

Ben


Top
 Profile  
 
 Post subject: Re: Setting up EHCI queue heads
PostPosted: Tue Aug 08, 2017 6:32 pm 
Offline
Member
Member

Joined: Sat Oct 16, 2010 3:38 pm
Posts: 587
BenLunt wrote:
Can you make a bootable floppy image, narrowing down the code, printing a line:

"To start the EHCI initialization, press a key"

Then wait for a key press before you start the EHCI stuff.

Then post that floppy image somewhere, or let me know and I can send you an email address. When I get a chance, I can run it through some of my tests and see what is going on.

Ben


I just sent you something very similar in a PM. You can either reply here or in a message. I couldn't post the link publicly as it is on a server that cannot be overloaded too much.

EDIT: I hope you won't have too many problems running this on physical hardware, if you plan to do so. I have recently fixed a whole series of bugs while testing. Also, it can currently only handle a single EHCI controller (I'm now fixing it to handle multiple controllers), so let me know if there are any problems at all.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 55 posts ]  Go to page Previous  1, 2, 3, 4  Next

All times are UTC - 6 hours


Who is online

Users browsing this forum: Google [Bot] and 263 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