OSDev.org

The Place to Start for Operating System Developers
It is currently Tue Jan 16, 2018 9:22 am

All times are UTC - 6 hours




Post new topic Reply to topic  [ 32 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Thu Nov 30, 2017 3:20 pm 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
Hey everybody,

I am currently implementing the Enhanced Host Controller Interface for USB 2.0 support. Everything is working fine in QEMU. I am even able to read and write sectors using SCSI commands. Trying to get the device descriptor on real hardware results in an NMI (Parity Check bit is set). :o

This is how I read the Device Descriptor after I reset the EHCI:

- Create new Queue Head for the USB devices control endpoint ( device address = 0, endpoint = 0, max packet size = 64 )
- Insert Queue Head
- create SETUP qTD with GetDeviceDescriptor request (data toggle = 0)
- create IN qTD with 18 bytes (data toggle = 1)
- create OUT qTD with 0 bytes (Handshake) (data toggle = 1)
- link SETUP -> IN -> OUT
- Wait until control Queue Head processed all previous qTDs
- Set SETUP qTD as next in Overlay Area

Right after the transaction completes I get the NMI. Did someone have a similar problem? I can't explain why this is happening... Thanks!

//EDIT

The NMI occurs right after the IN qTD is processed. Booting from USB works, so the device is working.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Thu Nov 30, 2017 6:33 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 302
Location: USA
How do you know it is an NMI and the Parity Check Bit is set? Do you get an NMI interrupt? Please explain.

Are you doing all of this in real mode *after* booting from USB on this device? If so, the BIOS could still be monitoring the device and that is why you are getting some errors. If you are doing this in pmode (an probably in real mode too), you should do a hand shake with the BIOS to tell it you now want control of the controller, as well as doing a reset of the controller and then/which will reset the device.

Ben
http://www.fysnet.net/the_universal_serial_bus.htm


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 5:36 am 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
Thanks for your reply.

Yes, this is all done in protected mode. I checked the Extended Capabilites Pointer (HCCPARAMS.EECP) but the first entry I get in PCI space (at offset 0xD1) has Capability ID set to 0, so USB Legacy Support is not present, I think.

Right after the IN qTD I get Interrupt 2, which is NMI. I checked two ports according to the NMI wiki page to get more information.

Quote:
When an NMI occurs you can check the system control port A and B at io addresses 0x92 and 0x61 respectively to get an indication of what caused the error


After reading port B the 7th bit is set, which translates to "Parity Check".


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 11:03 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 423
Is that a PCI expansion card? Legacy support is universally (?) available for EHCI controllers embedded into chipsets.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 11:21 am 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
Korona wrote:
Is that a PCI expansion card? Legacy support is universally (?) available for EHCI controllers embedded into chipsets.


No PCI expansion card. It's a Thinkpad x60s.

//EDIT

PCI reports 8086 as vendor id and 27CC as poduct id, which should be Intel Corporation 82801G (ICH7 Family) USB2 EHCI Controller

Does QEMU support EHCI handoff? I get Capability ID 0 there, too.

//EDIT 2

I read all PCI registers and printed them. QEMU says EECP is at 0xD1.

Image

//EDIT 3

This image is on real hardware (Thinkpad x60s). Here it says EECP is at 0xD0.

Image


Last edited by filkra on Fri Dec 01, 2017 12:06 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 12:04 pm 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 423
Yes, QEMU (I tried 2.8.1) also supports the legacy support capability. Double check that your capability detection is working correctly.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 12:09 pm 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
Note I printed all pci registers backwards, like the tables show on the PCI wiki page.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 12:34 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 302
Location: USA
These are the things I would check.
1) have you (correctly) redirected your PIC? i.e.: is IRQ 2 really 0x22 or is it actually 2?
2) are you using the 8259 PIC or the APIC? IRQ 2 is now available on the APIC and redirection could have already set it to the EHCI (by default)
3) check your EECP detection code to be sure. I also am quite sure that all EHCI's should have BIOS Handoff capabilities...

Usually it is nothing wrong with the transfer. It is always something else when you go to a laptop. Laptops are notorious for having odd-ball "default" settings. I would bet that it is something to do with the (A)PIC.

Ben


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Fri Dec 01, 2017 12:59 pm 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
BenLunt wrote:
These are the things I would check.
1) have you (correctly) redirected your PIC? i.e.: is IRQ 2 really 0x22 or is it actually 2?
2) are you using the 8259 PIC or the APIC? IRQ 2 is now available on the APIC and redirection could have already set it to the EHCI (by default)
3) check your EECP detection code to be sure. I also am quite sure that all EHCI's should have BIOS Handoff capabilities...


1) Yes, hardware interrupts start at 0x20. Keyboard, PIT and RTC interrupts are working correctly.

2) I use the 8259 PIC but did not enable the EHCIs interrupt line. Furthermore I disabled all EHCI interrupts using the USB Interrupt Enable Register.

3) I think my EHCI doesn't support BIOS handoff, as the values at HCCPARAMS.EECP are all 0 :?

This is really confusing... using QEMU, I can read and write USB Mass Storage devices but on real hardware it already fails to read the device descriptor.

I checked the system ports right before trying to get the device descriptor and the Parity Check bit was not set. Right after the transaction it is set and I get an NMI...


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sat Dec 02, 2017 1:28 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8197
Location: At his keyboard!
Hi,

filkra wrote:
3) I think my EHCI doesn't support BIOS handoff, as the values at HCCPARAMS.EECP are all 0 :?


That sounds unlikely to me; and I'm wondering if the BIOS set up the EHCI controller so that all devices get passed through to its companion controller and then did all the SMM/emulation stuff on the companion controller/s alone.

More specifically; I'm wondering if the problem is that you haven't done BIOS handoff on the companion controller/s.


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sat Dec 02, 2017 5:10 am 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
Brendan wrote:
More specifically; I'm wondering if the problem is that you haven't done BIOS handoff on the companion controller/s.


Is it necessary to configure the UHCI companion controllers (I don't want to support USB 1.0/1.1 yet)? In my understanding, if I set CF to 1 all ports should be routed to the EHCI and the UHCI shouldn't receive any events from the ports.

//EDIT

Turns out I used bitsets wrong (I think). I declared the Extended Capabilites Pointer as
Code:
uint32_t        eecp:8;
inside my struct, which then pointed to the wrong address. Now, I use
Code:
uint8_t        eecp:8;
instead and get the right offset in PCI space. The last thing I have to check now is wether I implemented the BIOS handoff correctly. I will keep you updated. Thanks for all the replies! :)


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sat Dec 02, 2017 6:24 am 
Offline
Member
Member
User avatar

Joined: Sat Jan 15, 2005 12:00 am
Posts: 8197
Location: At his keyboard!
Hi,

filkra wrote:
Brendan wrote:
More specifically; I'm wondering if the problem is that you haven't done BIOS handoff on the companion controller/s.


Is it necessary to configure the UHCI companion controllers (I don't want to support USB 1.0/1.1 yet)? In my understanding, if I set CF to 1 all ports should be routed to the EHCI and the UHCI shouldn't receive any events from the ports.


If the BIOS is using the companion controller/s for legacy emulation you should probably disable that legacy emulation in the companion controller/s before you do anything with EHCI (e.g. so that USB devices that the BIOS is controlling don't suddenly vanish when you route all ports to EHCI). Note: In theory this shouldn't be necessary (it wouldn't be much different to unplugging the USB devices) but in practice BIOS support for USB is a buggy mess and shouldn't be trusted.

Of course you can disable the legacy emulation in USB controllers without doing anything else with those USB controllers (and without having any OHCI or UHCI drivers).

In general, my plan is:
  • Disable as much legacy stuff as possible (in USB controllers, IDE/ATA/AHCI controllers, HPET, etc) very early during boot, while disabling all PCI devices that can possibly be disabled
  • Do "actual legacy device" detection and start device drivers for legacy/ISA devices, because this can involve "manual probing" techniques where PCI devices (and their legacy emulation stuff) can interfere and/or cause false positives
  • Start device drivers for PCI devices (including enabling a device if and only if a driver exists for it)


Cheers,

Brendan

_________________
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sat Dec 02, 2017 4:28 pm 
Offline
Member
Member
User avatar

Joined: Sat Nov 22, 2014 6:33 pm
Posts: 302
Location: USA
filkra wrote:
Brendan wrote:
More specifically; I'm wondering if the problem is that you haven't done BIOS handoff on the companion controller/s.

I agree with Brendan on this. Please let us know what you find out.

filkra wrote:
Is it necessary to configure the UHCI companion controllers (I don't want to support USB 1.0/1.1 yet)? In my understanding, if I set CF to 1 all ports should be routed to the EHCI and the UHCI shouldn't receive any events from the ports.

Only if all devices are high- or super-speed devices. As soon as you plug in a full- or low-speed device the EHCI will hand it over to the companion controller. However, newer machines are now including Rate Matching Hubs on port 0 of the EHCI and not including any companion controllers. This is easier and cheaper on the hardware side, but now you must support external hubs.

filkra wrote:
//EDIT

Turns out I used bitsets wrong (I think). I declared the Extended Capabilites Pointer as
Code:
uint32_t        eecp:8;
inside my struct, which then pointed to the wrong address. Now, I use
Code:
uint8_t        eecp:8;
instead and get the right offset in PCI space. The last thing I have to check now is wether I implemented the BIOS handoff correctly. I will keep you updated. Thanks for all the replies! :)

I don't like using "bitsets", AKA Bit Fields. Each compiler implements them differently since they are compiler specific. If you end up continuing to use them, make sure and enclose them in #ifdef/#elif/#endif statements, including an #if for each compiler you want to use (even if only one) and being sure to include the #else and stating "#error, unknown bit field usage...". i.e.:

Code:
#ifdef COMPILER_BRAND_A

  // bit fields go here

#elif defined COMPLER_BRAND_B

  // bit fields go here for this compiler
 
#else
  #error "Hey, you need to specify/define the bitfields for this compiler
#endif

Ben


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sun Dec 03, 2017 5:17 am 
Offline

Joined: Sat Nov 04, 2017 10:53 am
Posts: 15
BenLunt wrote:
Only if all devices are high- or super-speed devices. As soon as you plug in a full- or low-speed device the EHCI will hand it over to the companion controller.


Currently, I am only using high-speed devices (USB thumb drive). Checking the ports line status tells me a high-speed device is connected (not in K-state).

Brendan wrote:
Of course you can disable the legacy emulation in USB controllers without doing anything else with those USB controllers (and without having any OHCI or UHCI drivers).


I found Intels design guide on the UHCI and looked over other operating systems. The use offset 0xC0 for UHCI USB legacy support. I couldn't find this in Intels design guide. Do you know where this number comes from? Also, it is not clear to me how to perform a handoff on UHCI controllers. Is there some document (like the EHCI spec) listing the required steps or registers to use?

BenLunt wrote:
I don't like using "bitsets", AKA Bit Fields. Each compiler implements them differently since they are compiler specific.


I removed all bit fields from my EHCI code and replaced them with bit masks. Now, I can be sure the values I write are written at the right offset :)

//EDIT

I found the UHCI legacy support chapter (Keyboard and Mouse Legacy Support). All bits are listed there but I still can't find any info on BIOS handoff :?


Top
 Profile  
 
 Post subject: Re: USB GetDeviceDescriptor causes NMI (Parity Check)
PostPosted: Sun Dec 03, 2017 5:39 am 
Offline
Member
Member

Joined: Thu May 17, 2007 1:27 pm
Posts: 423
So you still get the NMI after EHCI hand-off works?

UHCI has no hand-off mechanism. You just prevent the BIOS from accessing the controller by disabling SMI on USB-IRQ and the related bits in the legacy support register.

Other things you should check (after you got the UHCI legacy-disabling to work): Is bus-mastering enabled in the PCI control register? Are PCI bridges set up correctly? Are EHCI registers marked as uncacheable in the MTRRs?

Can you test your code on other computers? Do you want me to test it on a desktop? I have a ICH7 desktop that I could run it on and copy/paste serial output and/or screenshots.

EDIT: As a side note: I never got a parity check on real hardware. Even if I disable my UHCI driver (with EHCI still enabled) everything works fine. It might indees be a quirk of that laptop but it would still be interesting to document such quirks.


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

All times are UTC - 6 hours


Who is online

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