[Solved] EHCI: Registers read 0xFFFFFFFF on real hardware

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
GhelloWorld
Member
Member
Posts: 27
Joined: Thu Apr 19, 2018 5:31 am

[Solved] EHCI: Registers read 0xFFFFFFFF on real hardware

Post by GhelloWorld »

Hi There,

It has been a while since I have posted something on this forum but I, once again, need your guys help :(.
Recently I decided to start working on my USB support again. It was working in general but I felt that it could be improved a lot, secondly I needed to add some new functions in order to make my mouse driver work. Re-coding UHCI and OHCI succeeded with some big struggles, but I did manage to get them both working in the end.

After applying some updates to my EHCI driver I decided to test it, and surprise surprise, it actually worked :D. Only on qemu and virtualbox though, real hardware somehow refused to reset and initialize the controller. I did some digging and found out that the following occurred: Every register on the EHCI controller reads as 0xFFFFFFFF (See register dump bellow).

Code: Select all

[590] [Info]: Activating driver EHCI USB Controller
[604] [Info]: EHCI Bar0 -> 0xFFA80800 0x00000000 0x00000400 0 0
[621] [Info]: EHCI regBase -> 0xC1500000
[633] [Info]: ------------------- EHCI Register Dump-----------------------
[653] [Info]: EHCI EHCI_CAPS_CapLength 0xFFFFFFFF
[666] [Info]: EHCI EHCI_CAPS_Reserved 0xFFFFFFFF
[679] [Info]: EHCI EHCI_CAPS_IVersion 0xFFFFFFFF
[692] [Info]: EHCI EHCI_CAPS_HCSParams 0xFFFFFFFF
[706] [Info]: EHCI EHCI_CAPS_HCCParams 0xFFFFFFFF
[719] [Info]: EHCI EHCI_CAPS_HCSPPortRoute 0xFFFFFFFF
[734] [Info]: EHCI EHCI_OPS_USBCommand 0xFFFFFFFF
[747] [Info]: EHCI EHCI_OPS_USBStatus 0xFFFFFFFF
[760] [Info]: EHCI EHCI_OPS_USBInterrupt 0xFFFFFFFF
[774] [Info]: EHCI EHCI_OPS_FrameIndex 0xFFFFFFFF
[788] [Info]: EHCI EHCI_OPS_CtrlDSSegemnt 0xFFFFFFFF
[802] [Info]: EHCI EHCI_OPS_PeriodicListBase 0xFFFFFFFF
[817] [Info]: EHCI EHCI_OPS_AsyncListBase 0xFFFFFFFF
[831] [Info]: EHCI EHCI_OPS_ConfigFlag 0xFFFFFFFF
[844] [Info]: EHCI EHCI_OPS_PortStatus 0xFFFFFFFF
[858] [Info]: -------------------------------------------------------------
[1388] [Error]: driver initialize failed for driver -> EHCI USB Controller 
To be honest I have no idea how this could be happening. I have faced a lot of stupid issues with USB controllers lately but those at least seamed to make sense afterwards.
The initialization code can be found here: https://github.com/Remco123/CactusOS/bl ... ci.cpp#L53
Note: Code works fine on virtual machines and register values are correct

Really hope one of you guys can help me with this!

Thanks in advance,
GhelloWorld/Remco123
Last edited by GhelloWorld on Fri Oct 23, 2020 8:24 am, edited 1 time in total.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by BenLunt »

Really quick, did you enable I/O in the PCI Config Register. Bit 1, if memory serves correctly.

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm
GhelloWorld
Member
Member
Posts: 27
Joined: Thu Apr 19, 2018 5:31 am

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by GhelloWorld »

Hey Ben,

Yes I tried setting both the IO and Memory space bits in the command register. This did not change anything unfortunately.
Perhaps something to note: I have tested the driver on 2 physical machines with the same result so I am pretty sure that the EHCI controller is not broken or something like that.
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by BenLunt »

Since you are reading 'F's, you are reading from non-existent memory, aka, I/O space, so here are a few ideas.

1) is the BAR a 64-bit BAR and you are only using the bottom 32-bits of the address? Not really likely, since most will only use a 32-bit address, even if the BAR is marked 64-bit.
2) check the hardware specs for the device. Some devices use a device specific mechanism to enable its function. For example, there might be a bit in the PCI config space that you must set. This bit will be in a device-specific byte offset within the PCI Config Space.
3) (You already checked?) Make sure the Mem I/O Enable bit is set in the PCI Config register.
4) check your memory read code. If the register is 32-bit read only, yet your compiler is optimizing it byte reads, the hardware might return 'F's. For example:

Code: Select all

   // the following line is coded so that you read a dword and mask off the byte
   byte_val = bar->dword_sized_register & 0xFF;  // mov eax,[address]      mov [byte_val],al
   // however, compilers will optimize the mask to read only a byte from the address
   byte_val = bar->byte_sized_register;         // mov  al,[address]       mov [byte_val],al
If I was to guess, I would think that 2) above is the culprit. I have seen this on about 3 or 4 machines when I was doing my R & R (not specific only to USB either).

Ben
- http://www.fysnet.net/the_universal_serial_bus.htm
GhelloWorld
Member
Member
Posts: 27
Joined: Thu Apr 19, 2018 5:31 am

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by GhelloWorld »

Hello Ben, Thanks for helping me out!

Lets go over each point one by one shall we?
1) The BAR reports it has a 32-bit address so I am pretty sure that I am using the right address. I Also checked it with a linux liveCD and then the linux kernel uses the same address as mine (0xFFA80800).
2) After some searching I found that the controller is a: Intel Corporation NM10/ICH7 Family USB2 EHCI Controller. I could not really found a datasheet for the device except for this one. But that one only describes the registers and is not talking about initialization of the device.
I did however found out that linux had the SERR# bit set in the pci command register, so I decided to check if that would make any difference. It did not change anything though.
3) Yes, I am 100% sure it is enabled. I also tried setting both the IO and Memory bit but that also did not change anything.
4 ) I am pretty sure that if this is the case the code would not work on emulators, but it does. There is also no optimization performed on the kernel so the compiler should not mess with that.

I understand that this is a uncommon issue and difficult to fix but I really appreciate the help.

By the way: Really enjoying your USB book Ben, it is very useful. :D
User avatar
BenLunt
Member
Member
Posts: 941
Joined: Sat Nov 22, 2014 6:33 pm
Location: USA
Contact:

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by BenLunt »

Out of curiosity, what is the "EHCI regBase -> 0xC1500000" line below?

Code: Select all

[590] [Info]: Activating driver EHCI USB Controller
[604] [Info]: EHCI Bar0 -> 0xFFA80800 0x00000000 0x00000400 0 0
[621] [Info]: EHCI regBase -> 0xC1500000
The EHCI Capability Registers start at 0xFFA80800, adding the length retrieved from the LEN field, should be something like 0xFFA80820. The value of 0xC1500000 is a bit off of that point, if in fact, that is the base of the Operational registers. Remember, you have to read the whole DWORD to get the length, then mask off the extra part(s).
GhelloWorld wrote: By the way: Really enjoying your USB book Ben, it is very useful. :D
Thank you for the kind words.

Ben
Gigasoft
Member
Member
Posts: 856
Joined: Sat Nov 21, 2009 5:11 pm

Re: EHCI: Registers read 0xFFFFFFFF on real hardware

Post by Gigasoft »

You forgot to add the low 12 bits of the address.
GhelloWorld
Member
Member
Posts: 27
Joined: Thu Apr 19, 2018 5:31 am

[Solved] Re: EHCI: Registers read 0xFFFFFFFF on real hardwar

Post by GhelloWorld »

So I figured it out, thanks guys! =D>

I always assumed that the address used by memory mapped devices was Page-aligned. When I mapped the physical address of the controller (0xFFA80800) to the virtual address (0xC1500000) I forgot to check for non-aligned addresses. So instead of reading at 0xFFA80800 I was reading registers at 0xFFA80000, which obviously, where not connected to anything.

Problems solved with following code:

Code: Select all

uint32_t memStart = pageRoundDown((uint32_t)BAR0.address); // Assuming 32-Bit address
uint32_t memEnd = pageRoundUp((uint32_t)BAR0.address + BAR0.size);
    
// Allocate virtual chuck of memory that we can use for device
this->regBase = DeviceHeap::AllocateChunck(memEnd - memStart) + ((uint32_t)BAR0.address % PAGE_SIZE);

// Map memory so that we can use it
VirtualMemoryManager::mapVirtualToPhysical((void*)memStart, (void*)this->regBase, memEnd - memStart, true, true);
Post Reply