Autor Thema: USB UHCI problem: IN tokens are ignored!  (Gelesen 5339 mal)

muragavino

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« am: 08. October 2010, 18:01 »
Hi there,

working on a ring0 singletask RTOS I have encountered an annoying problem regarding an USB UHCI controller. Testing board is an Intel Atom board D410PT with 1 EHCI and 4 UHCI companion controllers in the NM10 chipset.

I can send packets to a function, but responding IN packets from the function are ignored. The SETUP packet of the get_device_descriptor() arrives in the function, which then replies with the usual 18 bytes, but UHCI hardware sets the IN transfer descriptor as if nothing would have been sent back (C_ERR runs out and the CRC/Timeout bit is set in the status-field) . I analysed the actual USB data flow by controling the function's source code (on a SiLabs C8051F320 development kit) which works fine with Windows, Mac and Linux. Also the EHCI on the Atom board works fine!

After 2 weeks of searching this error I don't have any ideas left what else to try!

Here the details:

As USB-function I'm using a SiLabs C8051F320DK evaluation board, where I have programmed 2 LEDs to go ON when the GET_DEVICE_DESCRIPTOR has been received and the SET_ADDRESS control transfer has been accomplished. The function has been tested and works fine with Windows XP, Suse Linux and on a Mac.

When booting my Atom Board (D410PT), the BIOS enumerates the function (both LEDs go ON), thus the hardware on my board works perfectly. (BIOS-version is MOPNV10N.86A.0178.2010.0331.0947)
The NM10 chipset of the board includes 1 EHCI with 4 UHCI companion controllers for full- and low-speed transfers.
After my kernel has started, the following is setup (in sequence) for USB usage:

- set the PCI bus master enable and memory space enable bits (if necessary)
- get Host Control Capabilities Register address from PCI (that is EHCI at D29:F7 !)
- check if the BIOS controls the EHCI and set control to OS. This regards bits 16 and 24 of the USB EHCI Legacy Support Extended register (offset 0x68). After this, the BIOS is not more able to enum the USB-function.
- get ehci mem space size, get Host Control Operational Register address and reset the EHCI.
- Next I allocate memory for EHCI and UHCI queues and setup 3 framelists, 1 for EHCI use, and 2 for 2 UHCI controllers (there are 4, but only 2 will be used).
- Register CONFIGFLAG is setup to route all ports to the EHCI first
- The I/O addresses for the 4 UHCI controller are taken from PCI Baseaddress Register (D29:F0/F1/F2/F3) at offset 0x20
- Every UHCI controller is now:
      - stopped and globally reset
      - clear all interrupt- and error-bits (register STS is ANDed with 0x1F)
      - clear legacy support and detach UHCI from BIOS by writing 0x8F00 to the PCI register USB_LEGKEY at offset 0xC0
      - start HCRESET (CMD |= 2) and wait till reset has finished
      - USB registers are cleared (CMD, STS, INTR, FRNUM and PORTSC[0/1] are 0, SOFMOD is 0x40)

At this point I start scanning the 8 ports for attached devices (to easy testing, only 1 device is attached!). If a high-speed device is found, everything runs fine, no problem!
If a full-speed device is found (EHCI port-reset leaves port disabled, ergo it must be full- or low-speed), the following occurs:

   - I release port ownership to a companion host controller by setting EHCI_PORTSC[port] |= (1<<13) and wait for the change to be accomplished
   - Store the frame list base address to the UHCI FRBASEADD register and set FRNUM to 0
   - I set bit PIRQ by writing 0x2000 to the PCI register USB_LEGKEY at offset 0xC0 (enable USB-PCI interrupt, BUT: All is still done by polling, no interrupts are enabled!)
   - I send a resume signal on USB for 20 ms
   - I reset the connected port
   - I start the UHCI controller with max packet size to 64 bytes. (The last 3 items can be exchanged in any manner, the result is allways the same!)

Now I start enumeration by invoking the get_device_descriptor transaction. The 8 bytes of the SETUP token are sent and recived by the function (LED1 goes ON) which replies with the 18 requested bytes of the descriptor. UHCI controller runs out of CERR and returns a CRC/timeout error.
Here the queue transfer definitions with the data before and after transfer:

1st Transfer:          Setup:         After Transfer:
   Link pointer:       0xDEAD0001      0x1EFBFBF4
   Control/Status:   0x18800000      0x18000007
   Token:         0x00E0002D      0x00E0002D
   buffer:         0x0009FB60      0x0009FB60

2nd Transfer:
   Link pointer:       0x1EFBFC14      0x1EFBFC14
   Control/Status:   0x18800000      0x004507FF <--- here the error shows up!!!
   Token:         0x02240069      0x02240069
   buffer:         0x0009FB70      0x0009FB70

3rd Transfer is irrelevant because it has never been arrived there!

Is anybody out there able to give me any hint???

Dispaired and Hopefully,
Michael

Programm Noob

  • Gast
Gespeichert
« Antwort #1 am: 09. October 2010, 12:20 »
This is an German Forum.
an English Forum is here: osdev.org

PNoob

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 09. October 2010, 12:22 »
Ich bin mir sehr sicher, dass Michael das weiß, und nur zu faul war, den auf osdev.org geposteten Text ins deutsche zu übersetzen. ;)
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

Programm Noob

  • Gast
Gespeichert
« Antwort #3 am: 09. October 2010, 12:32 »
Wo genau liegt denn dein Problem. Mein Englsich ist nicht so toll. Vieleicht kann ich dir ja helfen.

PNoob

SHyx0rmZ

  • Beiträge: 67
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 09. October 2010, 18:23 »
IMHO sollten wir auch Englisch akzeptieren. Wer kein Englisch kann hält dann halt einfach ma die Klappe.
@X="krJhbuaesrytre c a cnR.ohut";while@X[/(..)(.)/];@X=@X[3..-1]+$1;print$2;end
"Scheiß auf Perl, wir haben Kekse" - Emperor Ruby

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 09. October 2010, 20:49 »
Hallo,


IMHO sollten wir auch Englisch akzeptieren. Wer kein Englisch kann hält dann halt einfach ma die Klappe.
Dem schließe ich mich zu 100% an, solange Englisch hier nicht zur Hauptsprache wird.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

muragavino

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 15. October 2010, 20:47 »
Also bevor das hier noch ausartet von wegen englisch/deutsch usw, ja ich war so faul und hab einfach den englischen Text hierrein kopiert. Trotzdem nett soviel Antwort zu bekommen.

Also noch mal in Kuerze:
(Deutsche Umlaute hab ich leider auch nicht auf meinem italienischen Laptop 8-))

Ich arbeite auf einem D410PT Intel Atom board, hab den EHCI host sauber am laufen aber ein seltsames Problem mit den 4 UHCI companion controllern. Um die ganze Story etwas abzukuerzen:

Obwohl ich den EHCI korrekt vom BIOS uebernommen habe (via LEG_EXT_CAP register) werden einige UHCI Aktionen (zB STALL wegen falschem toggle bit) immernoch vom BIOS abgefangen, aber nur bei eingeschalteten Interrupts!
Ich habe alle protected mode ISRs umgeleitet um zu sehen wo der interrupt herkommt, aber komm im Moment natuerlich nicht so ohne weiteres and die (alten BIOS-) real-mode ISRs ran (vielleicht im bootloader...).

Hat jemand eine Idee warum das BIOS immernoch die UHCIs kontrolliert? Und wie man das abschalten kann?

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 15. October 2010, 23:23 »
Ich glaube, an USB haben sich bisher nur die wenigstens rangewagt. Wenn überhaupt, könnte ich mir vorstellen, dass XanClic was dazu sagen kann.

Woran stellst du denn fest, dass das BIOS noch seine Finger im Spiel hat? Ist das nur eine Vermutung, weil es sich unerwartet verhält oder hast du da genauere Hinweise? Eigentlich dürfte das BIOS keine Chance mehr haben, mit der Hardware irgendwas interessantes zu machen, sobald du die Interrupts übernommen hast. (Es sei denn, der SMM bietet da irgendwelche tolle Magie an, damit kenne ich mich nicht aus)

Hast du auch die einzelnen UHCIs vom BIOS übernommen und nicht nur den EHCI? (Ich habe keine Ahnung, ob man das bei den Companions muss, aber das wäre das erstbeste, was mir einfällt)
« Letzte Änderung: 15. October 2010, 23:27 von taljeth »
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

erik.vikinger

  • Beiträge: 1 277
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 16. October 2010, 14:16 »
Hallo muragavino,


wenn Du vermutest dass das BIOS die IRQs per SMM abfängt dann versuche doch selber mal einen passenden SMM-Handler zu installieren. Dann solltest Du zumindest sehen ob diese Vermutung stimmt. Ich glaube nicht das SMM einfach ist aber wenn Du schon alle anderen Möglichkeiten abgecheckt hast dann bleibt Dir nicht mehr viel übrig.

Ist auf dem Board vielleicht ein TPM oder irgendwelche LAN-Fernwartungssachen drauf? Wenn ja dann prüfe mal ob es dazugehörige BIOS-Einstellungen gibt. Es könnte ja theoretisch sein dass das BIOS versucht einen "sicheren" Pfad zu Tastatur und Maus aufrecht zu erhalten. Wenn es wirklich irgend sowas ist dann wirst Du eventuell noch viel Spaß mit so Spielereien wie SMM und Ring -1 haben.

Vorher solltest Du aber vielleicht das Zeugs einfach mal ein paar Tage ruhen lassen und danach noch mal gründlich prüfen ob Dein Problem nicht doch irgendwie am USB selber liegt.


Grüße
Erik
Reality is that which, when you stop believing in it, doesn't go away.

muragavino

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 16. October 2010, 16:47 »
Woran stellst du denn fest, dass das BIOS noch seine Finger im Spiel hat? Ist das nur eine Vermutung, weil es sich unerwartet verhält oder hast du da genauere Hinweise? Eigentlich dürfte das BIOS keine Chance mehr haben, mit der Hardware irgendwas interessantes zu machen, sobald du die Interrupts übernommen hast.

Das BIOS kontrolliert den UHCI und kann meine full-speed function (die ich zum debuggen zu einer art usb-hw-monitor unfunktioniert habe) enummerieren. Das geht bis mein kernel via EHCI-PCI register LEG_EXT_CAP dem BIOS mitteilt das er Ownership uebernehmen moechte. Erst danach ist das BIOS nicht mehr am Ruder, d.h. ich kann meine USB-function anstecken ohne das vom BIOS enumeriert wird. Meine Interrupts im protected mode haben damit nichts zu tun (BIOS ISRs sind auf der real-mode Vectorliste).

Nach dem setup der UHCI controller, wird dann waerend dem Enummerieren ein (absichtlicher) Fehler erzeugt, was den Programflow IRGENDWOHIN verschwinden laesst, aber nur mit eingeschalteten interrupts (asm sti). Ob das BIOS da noch eine ISR am laufen hat ist eine Vermutung, allerdings vermute ich, eine Gute.  :wink:

Hast du auch die einzelnen UHCIs vom BIOS übernommen und nicht nur den EHCI? (Ich habe keine Ahnung, ob man das bei den Companions muss, aber das wäre das erstbeste, was mir einfällt)

Gute Frage! Im UHCI Addressspace gibt es z.B. das USB_LEGKEY register. Ich damit rumprobiert, aber ohne Erfolg! Was da sonst noch moeglich ist - boohh!

muragavino

  • Beiträge: 4
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 16. October 2010, 17:01 »
wenn Du vermutest dass das BIOS die IRQs per SMM abfängt dann versuche doch selber mal einen passenden SMM-Handler zu installieren.

Hallo Erik,  jetzt hast du mich haengen! Was ist SMM? So was aehnliches wie SMI?

Ist auf dem Board vielleicht ein TPM oder irgendwelche LAN-Fernwartungssachen drauf? Wenn ja dann prüfe mal ob es dazugehörige BIOS-Einstellungen gibt.

Ich boote via PXE, d.h. LAN. Werd mal ausprobieren ob das selbe Problem auch via SATA- oder USB-boot auftaucht.

Es könnte ja theoretisch sein dass das BIOS versucht einen "sicheren" Pfad zu Tastatur und Maus aufrecht zu erhalten.

Wird ueberprueft!

Wenn es wirklich irgend sowas ist dann wirst Du eventuell noch viel Spaß mit so Spielereien wie SMM und Ring -1 haben.

BITTE NICHT!!! :cry:

Vorher solltest Du aber vielleicht das Zeugs einfach mal ein paar Tage ruhen lassen...

DAS gefaellt mir! :mrgreen:
Danke an alle fuer die Hilfe!

kevin

  • Administrator
  • Beiträge: 2 767
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 16. October 2010, 18:23 »
Das BIOS kontrolliert den UHCI und kann meine full-speed function (die ich zum debuggen zu einer art usb-hw-monitor unfunktioniert habe) enummerieren. Das geht bis mein kernel via EHCI-PCI register LEG_EXT_CAP dem BIOS mitteilt das er Ownership uebernehmen moechte. Erst danach ist das BIOS nicht mehr am Ruder, d.h. ich kann meine USB-function anstecken ohne das vom BIOS enumeriert wird.
Okay, das heißt du kannst das hardwareseitig verifizieren, dass das tatsächlich funktioniert? Das klingt schonmal sehr hilfreich.

Zitat
Meine Interrupts im protected mode haben damit nichts zu tun (BIOS ISRs sind auf der real-mode Vectorliste).
Und dort liegen sie gut. ;)

Solange der Prozessor im Protected Mode ist, interessiert er sich für die IVT überhaupt nicht. Was tatsächlich passiert, ist, dass der UHCI direkt einen SMI auslöst und der Prozessor damit den SMM (System Management Mode) geht. Das ist in UHCI-Spec in Kapitel 5.1.2 beschrieben.

Zitat
Nach dem setup der UHCI controller, wird dann waerend dem Enummerieren ein (absichtlicher) Fehler erzeugt, was den Programflow IRGENDWOHIN verschwinden laesst, aber nur mit eingeschalteten interrupts (asm sti). Ob das BIOS da noch eine ISR am laufen hat ist eine Vermutung, allerdings vermute ich, eine Gute.  :wink:
Das ist der interessante Teil. Eigentlich sollte sich ein cli nicht auf SMIs auswirken. Ich kenne jetzt nicht die genaue Funktionsweise, aber ich nehme an, dass der UHCI gleichzeitig den SMI und den normalen IRQ auslöst. Der Prozessor wechselt dann in den SMM, wo eine BIOS-Interrupttabelle gilt und damit der IRQ von BIOS-Code behandelt wird. Allerdings hat der SMM auch seine eigenen eflags (und IF ist standardmäßig aus), so dass sich dein cli eigentlich nicht auswirken dürfte.

Zitat
Gute Frage! Im UHCI Addressspace gibt es z.B. das USB_LEGKEY register. Ich damit rumprobiert, aber ohne Erfolg! Was da sonst noch moeglich ist - boohh!
Hm, USB_LEGKEY finde ich grad nicht in der Spec. LEGSUP ist was ich meine. Die unteren paar Bits auf 0 setzen (0x2000 dürfte ein guter Wert sein) sollte theoretisch die SMIs abschalten.
« Letzte Änderung: 16. October 2010, 18:35 von taljeth »
Thou shalt not follow the NULL pointer, for chaos and madness await thee at its end.

 

Einloggen