Universal Host Controller Interface — Änderungen 7239 → 7241

Zeile 1: Zeile 1:
 
{{EMEJMM}}
 
{{EMEJMM}}
 
Das UHCI ist neben dem [[Open Host Controller Interface | OHCI]] ein Interface für [[USB]]-1.x-Hostcontroller.
 
Das UHCI ist neben dem [[Open Host Controller Interface | OHCI]] ein Interface für [[USB]]-1.x-Hostcontroller.
 +
 +
== Verwendete Datenstrukturen ==
 +
Relativ wenig der tatsächlichen Steuerung des UHC findet über die unten genannten Register (s. [[#I/O-Raum]]) ab. Er wird meist nur einmal initialisiert und später werden nur Gründe für Interrupts ausgelesen oder der aktuelle Status der Rootports abgefragt.
 +
 +
Die eigentlichen USB-Transaktionen werden jedoch über Datenstrukturen abgewickelt, die im Hauptspeicher liegen und deren Wurzel die Frameliste ist. Diese verzweigt dann zu Warteschlangenköpfen (Queue Heads, QH) und zu Transferdeskriptoren (Transfer Descriptors, TD), welche dann einzelne Transaktionen steuern.
 +
 +
=== Frameliste ===
 +
Die Frameliste ist ein Array mit 1024 Einträgen zu je vier Byte, das im Speicher an einer 4-kB-Grenze liegen muss (die unteren 12 Bit der Adresse sind also 0). Jeder dieser Einträge entspricht einem Frame und weist den Hostcontroller zu bestimmten Transaktionen an (bzw. weist auf den Beginn einer Liste von Transaktionen).
 +
 +
Ein Eintrag ist wie folgt aufgebaut:
 +
{| {{Prettytable}}
 +
! Bits !! Bezeichnung !! Bedeutung
 +
|-
 +
| 31 – 4 || Frame List Pointer || Dieses Feld enthält die physische Adresse eines QH oder eines TD. Der Wert entspricht den Bits 31 – 4 dieser Adresse, welche also an 16 Byte ausgerichtet sein muss.
 +
|-
 +
| 1 || QH/TD Select || Ist dieses Bit gesetzt, dann zeigt der FLP auf einen QH, sonst zeigt er auf einen TD.
 +
|-
 +
| 0 || Terminate || Der Link ist nur gültig, wenn dieses Bit gelöscht ist. Ist es gesetzt, so wird der HC dem Link nicht folgen.
 +
|}
 +
 +
=== Warteschlangenköpfe ===
 +
Jeder QH kann einerseits auf das nächste Element in der Liste (horizontal) und andererseits auf eine Warteschlange zeigen (vertikal). Es muss immer an einer 16-Byte-Grenze im Speicher liegen.
 +
 +
{| {{Prettytable}}
 +
! Offset !! Bezeichnung
 +
|-
 +
| 0x00 || Queue Head Link Pointer (QHLP)
 +
|-
 +
| 0x04 || Queue Element Link Pointer (QELP)
 +
|}
 +
 +
==== QHLP ====
 +
{| {{Prettytable}}
 +
! Bits !! Bezeichnung !! Bedeutung
 +
|-
 +
| 31 – 4 || QHLP || Physische Adresse des nächsten Elements in der horizontalen Liste (entweder ein QH oder ein TD).
 +
|-
 +
| 1 || QH/TD Select || Gibt an, ob es sich um einen QH oder einen TD handelt (wieder 1 für QH und 0 für TD).
 +
|-
 +
| 0 || Terminate || Ist dieses Bit 1, so ist dieser QH das letzte Element in der Liste.
 +
|}
 +
 +
==== QELP ====
 +
{| {{Prettytable}}
 +
! Bits !! Bezeichnung !! Bedeutung
 +
|-
 +
| 31 – 4 || QELP || Physische Adresse des ersten Elements in der hier beginnenden vertikalen Liste (entweder QH oder TD).
 +
|-
 +
| 1 || QH/TD Select || Gibt wieder an, ob es sich um einen QH oder einen TD handelt.
 +
|-
 +
| 0 || Terminate || Der Link ist nur gültig, wenn dieses Bit gelöscht ist (sonst gibt es keine vertikale Liste).
 +
|}
 +
 +
=== Transferdeskriptoren ===
 +
Ein Transferdeskriptor bezeichnet einen einzelnen USB-Transfer (wobei man sich nicht um Dinge wie NAK, ACK oder ähnliches kümmern muss). Solche Transfers sind SETUP-, IN- und OUT-Pakete. Ebenso wie QHs müssen sie immer an 16-Byte-Grenzen im Speicher liegen.
 +
 +
{| {{Prettytable}}
 +
! Offset !! Bezeichnung
 +
|-
 +
| 0x00 || Link Pointer (LP)
 +
|-
 +
| 0x04 || Control and Status
 +
|-
 +
| 0x08 || Token
 +
|-
 +
| 0x0C || Buffer Pointer
 +
|}
 +
 +
==== LP ====
 +
''TODO''
 +
 +
==== Control and Status ====
 +
''TODO''
 +
 +
==== Token ====
 +
''TODO''
 +
 +
==== Buffer Pointer ====
 +
''TODO''
 +
 +
=== Zusammenspiel ===
 +
[[Datei:UHCI-Datenstrukturen.png|thumb|Schema aus der UHCI-Spezifikation]]
 +
 +
Wie spielen nun diese Datenstrukturen zusammen? Wie bereits gesagt ist die Frameliste die Wurzel des ganzen. Dort trägt man in jedes Feld einen Pointer auf die spezifisch in diesem Frame auszuführenden periodischen Transfers (Isochronous-TDs oder Interrupt-QHs mit deren TDs) ein. Am Ende dieser Liste von periodischen Transfers sollte dann der erste QH der aperiodischen Transfers folgen. Womit ein QH korrespondiert, ist ziemlich egal. Er kann einer USB-Pipe entsprechen, man kann aber auch einfach einen einzigen QH für alle aperiodischen Transfers anlegen, an den alle Transferdeskriptoren angehangen werden.
 +
 +
''TODO''
  
 
== Interface ==
 
== Interface ==
Zeile 6: Zeile 92:
  
 
=== I/O-Raum ===
 
=== I/O-Raum ===
−
Jedes UHCI besitzt einen I/O-Raum, der aus dem PCI-Konfigurationsraum ausgelesen werden muss. Dieser ist wie folgt aufgebaut:
+
Jedes UHCI besitzt einen I/O-Raum, der aus dem PCI-Konfigurationsraum ausgelesen werden muss. In ihm kann man den Status der Rootports sowie des Hostcontrollers allgemein auslesen oder verändern, sowie letzteren initialisieren und dabei auch den Beginn der Frameliste eintragen. Dieser ist wie folgt aufgebaut:
 +
 
 
{| {{Prettytable}}
 
{| {{Prettytable}}
 
! Offset !! Name !! Bits !! Bedeutung
 
! Offset !! Name !! Bits !! Bedeutung
Zeile 105: Zeile 192:
  
 
==== PORTSC ====
 
==== PORTSC ====
 +
Wie bereits angedeutet gibt es für jeden Rootport ein solches Register am Ende des I/O-Raums. Laut UHCI-Spezifikation sind dies normalerweise zwei Ports, sodass sich ein PORTSC-Register (PORTSC1) am Offset (im I/O-Raum) 0x10 und das für den zweiten Rootport (PORTSC2) bei 0x12 befindet (PORTSC3 wäre dann bei 0x14, PORTSC4 bei 0x16, usw.).
 +
 
{| {{Prettytable}}
 
{| {{Prettytable}}
 
! Bit !! Name !! Bedeutung
 
! Bit !! Name !! Bedeutung
Zeile 128: Zeile 217:
 
| 0 || Current Connect Status || Ist ein Gerät an diesen Rootport angeschlossen, so ist dieses Bit 1. Es kann vom HCD nicht beschrieben werden.
 
| 0 || Current Connect Status || Ist ein Gerät an diesen Rootport angeschlossen, so ist dieses Bit 1. Es kann vom HCD nicht beschrieben werden.
 
|}
 
|}
−
 
−
== Verwendete Datenstrukturen ==
 
−
Relativ wenig der tatsächlichen Steuerung des UHC findet über die genannten Register ab. Er wird meist nur einmal initialisiert und später werden nur Gründe für Interrupts ausgelesen oder der aktuelle Status der Rootports abgefragt.
 
−
 
−
Die eigentlichen USB-Transaktionen werden jedoch über Datenstrukturen abgewickelt, die im Hauptspeicher liegen und deren Wurzel die Frameliste ist. Diese verzweigt dann zu Warteschlangenköpfen (Queue Heads, QH) und zu Transferdeskriptoren (Transfer Descriptors, TD), welche dann einzelne Transaktionen steuern.
 
−
 
−
=== Frameliste ===
 
−
Die Frameliste ist ein Array mit 1024 Einträgen zu je vier Byte. Jeder dieser Einträge entspricht einem Frame und weist den Hostcontroller zu bestimmten Transaktionen an (bzw. weist auf den Beginn einer Liste von Transaktionen).
 
−
 
−
Ein Eintrag ist wie folgt aufgebaut:
 
−
{| {{Prettytable}}
 
−
! Bits !! Bezeichnung !! Bedeutung
 
−
|-
 
−
| 31 – 4 || Frame List Pointer || Dieses Feld enthält die physische Adresse eines QH oder eines TD. Der Wert entspricht den Bits 31 – 4 dieser Adresse, welche also an 16 Byte ausgerichtet sein muss.
 
−
|-
 
−
| 1 || QH/TD Select || Ist dieses Bit gesetzt, dann zeigt der FLP auf einen QH, sonst zeigt er auf einen TD.
 
−
|-
 
−
| 0 || Terminate || Der Link ist nur gültig, wenn dieses Bit gelöscht ist. Ist es gesetzt, so wird der HC dem Link nicht folgen.
 
−
|}
 
−
 
−
=== Warteschlangenköpfe ===
 
−
Jeder QH kann einerseits auf das nächste Element in der Liste (horizontal) und andererseits auf eine Warteschlange zeigen (vertikal).
 
−
 
−
{| {{Prettytable}}
 
−
! Offset !! Bezeichnung
 
−
|-
 
−
| 0x00 || Queue Head Link Pointer (QHLP)
 
−
|-
 
−
| 0x04 || Queue Element Link Pointer (QELP)
 
−
|}
 
−
 
−
==== QHLP ====
 
−
{| {{Prettytable}}
 
−
! Bits !! Bezeichnung !! Bedeutung
 
−
|-
 
−
| 31 – 4 || QHLP || Physische Adresse des nächsten Elements in der horizontalen Liste (entweder ein QH oder ein TD).
 
−
|-
 
−
| 1 || QH/TD Select || Gibt an, ob es sich um einen QH oder einen TD handelt (wieder 1 für QH und 0 für TD).
 
−
|-
 
−
| 0 || Terminate || Ist dieses Bit 1, so ist dieser QH das letzte Element in der Liste.
 
−
|}
 
−
 
−
==== QELP ====
 
−
{| {{Prettytable}}
 
−
! Bits !! Bezeichnung !! Bedeutung
 
−
|-
 
−
| 31 – 4 || QELP || Physische Adresse des ersten Elements in der hier beginnenden vertikalen Liste (entweder QH oder TD).
 
−
|-
 
−
| 1 || QH/TD Select || Gibt wieder an, ob es sich um einen QH oder einen TD handelt.
 
−
|-
 
−
| 0 || Terminate || Der Link ist nur gültig, wenn dieses Bit gelöscht ist (sonst gibt es keine vertikale Liste).
 
−
|}
 
−
 
−
=== Transferdeskriptoren ===
 
−
Ein Transferdeskriptor bezeichnet einen einzelnen USB-Transfer (wobei man sich nicht um Dinge wie NAK, ACK oder ähnliches kümmern muss). Solche Transfers sind SETUP-, IN- und OUT-Pakete.
 
−
 
−
{| {{Prettytable}}
 
−
! Offset !! Bezeichnung
 
−
|-
 
−
| 0x00 || Link Pointer (LP)
 
−
|-
 
−
| 0x04 || Control and Status
 
−
|-
 
−
| 0x08 || Token
 
−
|-
 
−
| 0x0C || Buffer Pointer
 
−
|}
 
−
 
−
==== LP ====
 
−
''TODO''
 
−
 
−
==== Control and Status ====
 
−
''TODO''
 
−
 
−
==== Token ====
 
−
''TODO''
 
−
 
−
==== Buffer Pointer ====
 
−
''TODO''
 
−
 
−
=== Zusammenspiel ===
 
−
[[Datei:UHCI-Datenstrukturen.png|thumb|Schema aus der UHCI-Spezifikation]]
 
−
 
−
Wie spielen nun diese Datenstrukturen zusammen? Wie bereits gesagt ist die Frameliste die Wurzel des ganzen. Dort trägt man in jedes Feld einen Pointer auf die spezifisch in diesem Frame auszuführenden periodischen Transfers (Isochronous-TDs oder Interrupt-QHs mit deren TDs) ein. Am Ende dieser Liste von periodischen Transfers sollte dann der erste QH der aperiodischen Transfers folgen. Womit ein QH korrespondiert, ist ziemlich egal. Er kann einer USB-Pipe entsprechen, man kann aber auch einfach einen einzigen QH für alle aperiodischen Transfers anlegen, an den alle Transferdeskriptoren angehangen werden.
 
−
 
−
''TODO''
 
  
 
== Weblinks ==
 
== Weblinks ==