====== Lyx OS – XHCI-Treiber ======
Der XHCI-Treiber (''kernel/xhci.lyx'') implementiert den USB 3.x Host-Controller-Treiber für Lyx OS. Er läuft vollständig in Ring-0 und wird von keiner externen USB-Stack-Library abhängig. Die Ring-3-Syscalls für USB sind noch **nicht vergeben** — Syscalls 150–155 sind durch Vega-Fensterverwaltung (150–152), RAM-Disk (153–154) und IOFS-mkfs (155) belegt. USB-Syscalls werden im XHCI-WP in einem freien Bereich ab 156+ zugewiesen.
→ [[lyxos:syscalls|Syscall-ABI]] · [[lyxos:kernel|Kernel-Interna]] · [[lyxos:start|Übersicht]]
----
===== 1. Überblick =====
XHCI (Extensible Host Controller Interface) ist der USB-Host-Controller-Standard ab USB 3.0. Er ersetzt EHCI (USB 2.0), OHCI und UHCI und unterstützt alle USB-Generationen (1.0–3.2) in einem einzigen Controller.
**Zuständigkeiten des Treibers:**
^ Schicht ^ Zuständigkeit ^
| PCI-Erkennung | XHCI-Controller auf dem PCI-Bus finden (Class 0x0C / Sub 0x03 / ProgIF 0x30) |
| MMIO-Mapping | Capability-, Operational-, Runtime- und Doorbell-Register in Kernel-Address-Space mappen |
| HC-Initialisierung | Controller-Reset, Slot-Enable, Command-Ring und Event-Ring einrichten |
| Port-Management | Port-Reset, Speed-Erkennung, Gerät adressieren |
| Transfer-Engine | TRB-Ringe für Control-, Bulk- und Interrupt-Transfers verwalten |
| Ring-3-Interface | USB-Syscalls TBD (ab 156+, erst mit XHCI-WP vergeben; 150–155 = Vega/RAM-Disk/IOFS) |
**Quelldatei:** ''kernel/xhci.lyx''
----
===== 2. PCI-Erkennung =====
Der XHCI-Controller wird als PCI-Gerät erkannt:
^ Feld ^ Wert ^ Bedeutung ^
| Class Code | 0x0C | Serial Bus Controller |
| Subclass | 0x03 | USB Controller |
| Prog IF | 0x30 | xHCI |
// PCI-Scan: XHCI-Controller finden
con XHCI_PCI_CLASS : int64 := 0x0C;
con XHCI_PCI_SUB : int64 := 0x03;
con XHCI_PCI_PROGIF : int64 := 0x30;
Der Treiber liest die BAR0-Basisadresse aus dem PCI-Konfigurationsraum (BAR0 ist immer MMIO, 64-bit). Die physische Adresse wird via ''sys_mmap_device'' in den Kernel-Address-Space gemappt.
----
===== 3. MMIO-Register-Layout =====
XHCI kennt vier Register-Bereiche, alle relativ zur BAR0-Basisadresse:
BAR0 ──┬── Capability Registers (Offset 0, Länge = CAPLENGTH)
├── Operational Registers (Offset = CAPLENGTH)
├── Runtime Registers (Offset = RTSOFF, aus CapRegs)
└── Doorbell Array (Offset = DBOFF, aus CapRegs)
==== 3.1 Capability Registers (CapRegs) ====
Nur lesbar. Beschreiben die Hardware-Eigenschaften des Controllers.
^ Offset ^ Name ^ Beschreibung ^
| +0 | ''CAPLENGTH'' (uint8) | Länge des CapRegs-Blocks; Startadresse der OpRegs |
| +2 | ''HCIVERSION'' (uint16) | xHCI-Spezifikationsversion (z.B. 0x0100 = v1.0) |
| +4 | ''HCSPARAMS1'' (uint32) | Bits[7:0]=MaxSlots, Bits[18:8]=MaxIntrs, Bits[31:24]=MaxPorts |
| +8 | ''HCSPARAMS2'' (uint32) | IST, ERST_MAX, MAX_SCRATCHPAD_BUFS |
| +12 | ''HCSPARAMS3'' (uint32) | U1/U2-Exit-Latenzzeiten |
| +16 | ''HCCPARAMS1'' (uint32) | Capability-Bits: 64-bit Addressing, BNC, AC64, CSZ usw. |
| +20 | ''DBOFF'' (uint32) | Byte-Offset der Doorbell-Array-Base relativ zu BAR0 |
| +24 | ''RTSOFF'' (uint32) | Byte-Offset der Runtime-Register-Base relativ zu BAR0 |
| +28 | ''HCCPARAMS2'' (uint32) | Erweiterte Capability-Bits (USB 3.1+) |
con XHCI_CAP_CAPLENGTH : int64 := 0;
con XHCI_CAP_HCIVERSION : int64 := 2;
con XHCI_CAP_HCSPARAMS1 : int64 := 4;
con XHCI_CAP_HCSPARAMS2 : int64 := 8;
con XHCI_CAP_HCCPARAMS1 : int64 := 16;
con XHCI_CAP_DBOFF : int64 := 20;
con XHCI_CAP_RTSOFF : int64 := 24;
==== 3.2 Operational Registers (OpRegs) ====
Lese-/schreibbar. Steuern den Controller-Betrieb.
^ Offset ^ Name ^ Beschreibung ^
| +0 | ''USBCMD'' (uint32) | Run/Stop (Bit 0), HC-Reset (Bit 1), Interrupt-Enable (Bit 2) |
| +4 | ''USBSTS'' (uint32) | HCHalted (Bit 0), Host-Error (Bit 2), Event-Int (Bit 3) |
| +8 | ''PAGESIZE'' (uint32) | Bits[15:0]: unterstützte Page-Größen (Bit N = 2^(N+12) Bytes) |
| +20 | ''DNCTRL'' (uint32) | Device-Notification-Control |
| +24 | ''CRCR'' (uint64) | Command-Ring-Control: RCS, CS, CA, CRR, Ring-Pointer |
| +48 | ''DCBAAP'' (uint64) | Device-Context-Base-Address-Array-Pointer |
| +56 | ''CONFIG'' (uint32) | Bits[7:0]: MaxSlotsEn (max. aktivierte Slots) |
con XHCI_OP_USBCMD : int64 := 0;
con XHCI_OP_USBSTS : int64 := 4;
con XHCI_OP_PAGESIZE: int64 := 8;
con XHCI_OP_DNCTRL : int64 := 20;
con XHCI_OP_CRCR : int64 := 24;
con XHCI_OP_DCBAAP : int64 := 48;
con XHCI_OP_CONFIG : int64 := 56;
// USBCMD-Bits
con XHCI_CMD_RUN : int64 := 1; // Run/Stop
con XHCI_CMD_HCRST : int64 := 2; // HC-Reset
con XHCI_CMD_INTE : int64 := 4; // Interrupter-Enable
con XHCI_CMD_HSEE : int64 := 8; // Host-System-Error-Enable
// USBSTS-Bits
con XHCI_STS_HCH : int64 := 1; // HC Halted
con XHCI_STS_HSE : int64 := 4; // Host System Error
con XHCI_STS_EINT : int64 := 8; // Event Interrupt
con XHCI_STS_PCD : int64 := 16; // Port Change Detected
con XHCI_STS_CNR : int64 := 0x800; // Controller Not Ready
==== 3.3 Runtime Registers ====
^ Offset ^ Name ^ Beschreibung ^
| +0 | ''MFINDEX'' (uint32) | Microframe-Index (125 µs-Ticks) |
| +32 | ''IR[0]'' | Interrupter-Register-Set 0 (IMAN, IMOD, ERSTSZ, ERSTBA, ERDP) |
Interrupter-0-Offsets (relativ zu IR[0]-Basis = RTSOFF + 32):
^ Offset ^ Name ^ Beschreibung ^
| +0 | ''IMAN'' (uint32) | Interrupt-Management: IE (Bit 1), IP (Bit 0) |
| +4 | ''IMOD'' (uint32) | Interrupt-Moderation: IMODI (Bits[15:0]) |
| +8 | ''ERSTSZ'' (uint32) | Event-Ring-Segment-Table-Size |
| +16 | ''ERSTBA'' (uint64) | Event-Ring-Segment-Table-Base-Address |
| +24 | ''ERDP'' (uint64) | Event-Ring-Dequeue-Pointer |
con XHCI_RT_MFINDEX : int64 := 0;
con XHCI_RT_IR0 : int64 := 32; // Basis des ersten Interrupters
// Offsets innerhalb IR[0]
con XHCI_IR_IMAN : int64 := 0;
con XHCI_IR_IMOD : int64 := 4;
con XHCI_IR_ERSTSZ : int64 := 8;
con XHCI_IR_ERSTBA : int64 := 16;
con XHCI_IR_ERDP : int64 := 24;
==== 3.4 Doorbell Array ====
Ein 32-bit-Eintrag pro Slot (Slot 0 = Host-Controller-Command-Ring). Schreiben löst einen Transfer aus.
con XHCI_DB_HC : int64 := 0; // Doorbell 0: Command-Ring
// Doorbell N (N = Slot-ID): DB_TARGET = Endpoint-Index (Bits[7:0])
----
===== 4. Datenstrukturen =====
==== 4.1 Transfer Request Block (TRB) ====
Jede Operation in XHCI ist ein 16-Byte-TRB. TRBs werden in Ringen arrangiert.
Byte 0– 7: Parameter (Adresse, Daten, abhängig vom TRB-Typ)
Byte 8–11: Status (Byte-Count, Interrupter-Target)
Byte 12–15: Control (Bits[9:0]=TRB-Typ, Bit15=C=Cycle-Bit, typ-spezifische Flags)
con XHCI_TRB_SIZE : int64 := 16;
// TRB-Typen (Control-Bits[9:0])
con TRB_NORMAL : int64 := 1; // Bulk / Interrupt Transfer
con TRB_SETUP : int64 := 2; // Control Setup-Paket
con TRB_DATA : int64 := 3; // Control Data-Phase
con TRB_STATUS : int64 := 4; // Control Status-Phase
con TRB_ISOCH : int64 := 5; // Isochroner Transfer
con TRB_LINK : int64 := 6; // Ring-Link (letzter TRB im Ring)
con TRB_EVT_DATA : int64 := 7; // Event-Data
con TRB_NOOP : int64 := 8; // No-Op Transfer
con TRB_ENABLE_SLOT : int64 := 9; // Command: Slot aktivieren
con TRB_DISABLE_SLOT : int64 := 10; // Command: Slot deaktivieren
con TRB_ADDRESS_DEV : int64 := 11; // Command: Gerät adressieren
con TRB_CONFIG_EP : int64 := 12; // Command: Endpoint konfigurieren
con TRB_EVAL_CTX : int64 := 13; // Command: Context evaluieren
con TRB_NOOP_CMD : int64 := 23; // No-Op Command
con TRB_XFER_EVENT : int64 := 32; // Event: Transfer abgeschlossen
con TRB_CMD_COMPL : int64 := 33; // Event: Command abgeschlossen
con TRB_PORT_STATUS : int64 := 34; // Event: Port-Status geändert
// TRB-Control-Bits
con TRB_C : int64 := 1; // Cycle-Bit
con TRB_TC : int64 := 2; // Toggle-Cycle (nur LINK-TRB)
con TRB_ISP : int64 := 4; // Interrupt-on-Short-Packet
con TRB_IOC : int64 := 0x20; // Interrupt-on-Completion
con TRB_IDT : int64 := 0x40; // Immediate-Data (≤8 Bytes direkt im TRB)
==== 4.2 Event-Ring-Segment-Table-Eintrag (ERSTE) ====
con XHCI_ERST_SIZE : int64 := 16;
// +0 (uint64): Ring-Segment-Base-Address (4K-aligned)
// +8 (uint32): Ring-Segment-Size (Anzahl TRBs im Segment)
// +12 (uint32): reserviert
==== 4.3 Device-Context-Base-Address-Array (DCBAA) ====
Ein Array von uint64-Zeigern (Slot 0 bis MaxSlots). Slot 0 zeigt auf den Scratchpad-Buffer-Array (oder 0 wenn MaxScratchpad=0). Jeder weitere Eintrag zeigt auf den Output-Device-Context des entsprechenden Slots.
==== 4.4 Input-Context ====
Wird für ''ADDRESS_DEVICE''- und ''CONFIGURE_ENDPOINT''-Commands genutzt. Besteht aus:
* Input-Control-Context (32 Bytes): Drop-Flags + Add-Flags je Endpoint
* Slot-Context (32 Bytes): Geschwindigkeit, Root-Hub-Port, Anzahl Endpoints
* Endpoint-Contexte (32 Bytes je EP): EP-Typ, Max-Packet-Size, TR-Dequeue-Pointer
con XHCI_CTX_SIZE : int64 := 32; // Wenn CSZ=0 in HCCPARAMS1
con XHCI_CTX_SIZE_64 : int64 := 64; // Wenn CSZ=1 (64-Byte-Contexts)
// Slot-Context-Felder (+0 im Slot-Context-Block)
// Bits[19:10] = Root-Hub-Port-Num, Bits[23:20] = NumContextEntries,
// Bits[29:27] = Speed (1=Full, 2=Low, 3=High, 4=SuperSpeed)
con XHCI_SPEED_FS : int64 := 1;
con XHCI_SPEED_LS : int64 := 2;
con XHCI_SPEED_HS : int64 := 3;
con XHCI_SPEED_SS : int64 := 4;
// Endpoint-Typ (EP-Context Bits[5:3])
con XHCI_EP_ISOCH_OUT : int64 := 1;
con XHCI_EP_BULK_OUT : int64 := 2;
con XHCI_EP_INTR_OUT : int64 := 3;
con XHCI_EP_CTRL : int64 := 4;
con XHCI_EP_ISOCH_IN : int64 := 5;
con XHCI_EP_BULK_IN : int64 := 6;
con XHCI_EP_INTR_IN : int64 := 7;
----
===== 5. Initialisierung =====
Die Initialisierungsreihenfolge folgt dem xHCI-Spec §4.2:
1. BAR0 lesen, MMIO mappen
2. Warten bis USBSTS.CNR = 0 (Controller Ready)
3. USBCMD.RUN = 0 setzen → Controller anhalten
4. Warten bis USBSTS.HCH = 1
5. USBCMD.HCRST = 1 → Controller-Reset
6. Warten bis HCRST = 0 und CNR = 0
7. DCBAAP setzen (alloc + nullen)
8. Command-Ring initialisieren (CRCR setzen, Cycle-Bit = 1)
9. Event-Ring initialisieren (ERST alloc, ERSTBA + ERSTSZ im IR[0] setzen)
10. Interrupter-0 aktivieren: IMAN.IE = 1
11. MaxSlotsEn in CONFIG setzen
12. USBCMD.RUN = 1 → Controller starten
13. Warten bis USBSTS.HCH = 0
14. Ports scannen (→ Abschnitt 6)
**Wichtig:** Alle Ring-Puffer müssen physisch kontiguös und auf 64 Bytes aligned sein. Der Treiber nutzt den Kernel-PMM direkt (kein VFS-Alloc).
----
===== 6. Port-Management & Geräteerkennung =====
==== Port-Register-Offsets ====
Jeder Port hat einen 16-Byte-Block ab OpRegs + 0x400:
con XHCI_PORT_BASE : int64 := 0x400; // Offset in OpRegs
con XHCI_PORT_STRIDE : int64 := 16; // Bytes pro Port
// Innerhalb eines Port-Blocks:
con XHCI_PORT_SC : int64 := 0; // Port-Status-and-Control (uint32)
con XHCI_PORT_PMSC : int64 := 4; // Port-Power-Management-Status-and-Control
con XHCI_PORT_LI : int64 := 8; // Port-Link-Info
con XHCI_PORT_HLPMC : int64 := 12; // Port-Hardware-LPM-Control
// PORTSC-Bits
con XHCI_PORTSC_CCS : int64 := 1; // Current Connect Status
con XHCI_PORTSC_PED : int64 := 2; // Port Enabled/Disabled
con XHCI_PORTSC_PR : int64 := 0x10; // Port Reset
con XHCI_PORTSC_PLS : int64 := 0x1E0; // Port-Link-State (Bits[8:5])
con XHCI_PORTSC_PP : int64 := 0x200; // Port Power
con XHCI_PORTSC_SPD : int64 := 0x3C00; // Port-Speed (Bits[13:10])
con XHCI_PORTSC_PRC : int64 := 0x200000; // Port-Reset-Change (quittieren)
==== Geräte-Enumeration (pro Port) ====
1. PORTSC.CCS prüfen → Gerät angeschlossen?
2. PORTSC.PR = 1 setzen → Port-Reset
3. Warten auf PORTSC.PRC = 1 (Reset abgeschlossen), dann quittieren
4. PORTSC.SPD lesen → Geschwindigkeit bestimmen
5. Command: ENABLE_SLOT → Slot-ID erhalten
6. Input-Context allozieren, Slot-Context befüllen (Port, Geschwindigkeit)
7. Control-Endpoint-0-Context befüllen (MaxPacketSize nach Speed)
8. DCBAA[slot_id] = Output-Context-Adresse
9. Command: ADDRESS_DEVICE (BSR=1 = Block Set Address Request für ersten Get-Descriptor)
10. Control-Transfer: GET_DESCRIPTOR (Device, 8 Bytes) → bMaxPacketSize0 lesen
11. Command: ADDRESS_DEVICE (BSR=0) → SET_ADDRESS automatisch vom HC
12. Control-Transfer: GET_DESCRIPTOR (Device, 18 Bytes) → VID/PID, Class, Configs
13. Gerät in interner Tabelle eintragen (vid, pid, slot_id, port)
----
===== 7. Transfer-Mechanismus =====
==== 7.1 Transfer-Ringe ====
Jeder aktive Endpoint hat einen eigenen Transfer-Ring (TR). Der TR ist ein zirkulärer Puffer aus TRBs, abgeschlossen durch einen LINK-TRB der zurück auf den Ring-Anfang zeigt.
Consumer: XHCI-Hardware liest TRBs vom Dequeue-Pointer
Producer: Treiber schreibt TRBs ab Enqueue-Pointer
Cycle-Bit (C): unterscheidet alte von neuen TRBs (toggelt bei jedem Rindumlauf)
==== 7.2 Control Transfer ====
Ein Control-Transfer besteht aus 3 TRBs (Setup → Data → Status):
// 1. Setup-TRB (TRB_SETUP)
// Parameter[0..7] = 8-Byte-USB-Setup-Packet (bmReqType, bReq, wVal, wIdx, wLen)
// Status: Bits[16:0] = 8 (Länge des Setup-Packets)
// Control: TRB_SETUP | IDT=1 (Immediate Data) | TRT (Transfer Type: 2=OUT, 3=IN)
// 2. Data-TRB (TRB_DATA) — optional, nur wenn wLength > 0
// Parameter = physische Adresse des Datenpuffers
// Status: Bits[16:0] = wLength
// Control: TRB_DATA | DIR=1 wenn IN | IOC=1
// 3. Status-TRB (TRB_STATUS)
// Control: TRB_STATUS | DIR (umgekehrt zur Data-Phase) | IOC=1
==== 7.3 Bulk / Interrupt Transfer ====
Einzelner NORMAL-TRB (oder Kette via Chain-Bit für >64 KB):
// Normal-TRB (TRB_NORMAL)
// Parameter = physische Adresse des Datenpuffers
// Status: Bits[16:0] = Byte-Count, Bits[31:22] = Interrupter-Target (0)
// Control: TRB_NORMAL | IOC=1
Nach dem Schreiben des TRB: **Doorbell klingeln** (poke32 auf DB[slot_id], EP-Index).
==== 7.4 Completion-Event abwarten ====
1. ERDP aus IR[0] lesen (aktueller Dequeue-Pointer)
2. Auf TRB_XFER_EVENT oder TRB_CMD_COMPL warten:
- Cycle-Bit am aktuellen ERDP muss gleich dem Producer-Cycle-Bit sein
- Event-TRB enthält: Completion-Code (Bits[31:24] in Status), Slot-ID, EP-Index
3. ERDP um XHCI_TRB_SIZE vorwärtssetzen (mit HC-Handshake-Bit = 1)
4. IMOD-Timer zurücksetzen (IMAN.IP = 1 schreiben)
**Completion-Codes:**
^ Code ^ Wert ^ Bedeutung ^
| ''CC_SUCCESS'' | 1 | Transfer erfolgreich |
| ''CC_DATA_BUFFER_ERROR'' | 2 | DMA-Fehler |
| ''CC_BABBLE_DETECTED'' | 3 | Gerät sendet zu viele Daten |
| ''CC_USB_TRANSACTION_ERROR'' | 4 | USB-Bus-Fehler (CRC, Timeout) |
| ''CC_TRB_ERROR'' | 5 | Ungültiger TRB |
| ''CC_STALL_ERROR'' | 6 | Endpoint STALL |
| ''CC_SHORT_PACKET'' | 13 | Weniger Daten als angefordert (kein Fehler) |
| ''CC_STOPPED'' | 26 | Transfer durch ''STOP_ENDPOINT''-Command gestoppt |
con XHCI_CC_SUCCESS : int64 := 1;
con XHCI_CC_TRB_ERROR : int64 := 5;
con XHCI_CC_STALL : int64 := 6;
con XHCI_CC_SHORT : int64 := 13;
----
===== 8. Ring-3-Syscall-Binding =====
Die USB-Syscall-Nummern sind noch **nicht vergeben**. Syscalls 150–155 sind belegt:
^ Syscall-Nr ^ Belegt durch ^
| 150 | ''sys_win_get_title'' (WP27) |
| 151 | ''sys_win_get_geom'' (WP29) |
| 152 | ''sys_win_get_pid'' (WP29) |
| 153 | ''sys_ramdisk_create'' (WP30) → [[lyxos:ramdisk|RAM-Disk]] |
| 154 | ''sys_ramdisk_fmt'' (WP30) → [[lyxos:ramdisk|RAM-Disk]] |
| 155 | ''sys_mkfs_iofs'' (WP01+WP09) → [[lyxos:iofs|IOFS]] |
Die geplante USB-Ring-3-Schnittstelle wird im XHCI-WP auf freien Nummern ab 156+ definiert:
^ Geplante Funktion ^ Treiber-Funktion ^ Bemerkung ^
| ''sys_usb_enum'' (TBD) | ''XhciEnumDevices(buf, max)'' | Geräteliste in Ring-3-Puffer kopieren |
| ''sys_usb_open'' (TBD) | ''XhciOpenByVidPid(vid, pid)'' | Gerät per VID/PID öffnen → ''usb_fd'' |
| ''sys_usb_ctrl'' (TBD) | ''XhciControlTransfer(slot, setup, data, len)'' | Control Transfer mit Bounce-Buffer |
| ''sys_usb_bulk'' (TBD) | ''XhciBulkTransfer(slot, ep, buf, len)'' | Bulk Transfer via DMA |
| ''sys_usb_intr_read'' (TBD) | ''XhciIntrRead(slot, ep, buf, len)'' | Interrupt-Endpoint, blockierend |
| ''sys_usb_close'' (TBD) | ''XhciClose(slot)'' | ''DISABLE_SLOT'' + Tabellenplatz freigeben |
**Bounce-Buffer-Strategie:** Control-Transfers nutzen einen kleinen Kernel-seitigen Puffer (max. 4096 Bytes), der sicher ins Ring-3-VA zurückkopiert wird. Bulk/Interrupt nutzen direkte DMA auf die physische Adresse des Ring-3-Puffers (Boundary: Ring-3-Seiten müssen im PMM bekannt sein).
----
===== 9. Interne Gerätetabelle =====
Der Treiber hält eine statische Tabelle für max. 32 gleichzeitig angeschlossene Geräte:
// Eintrag: 64 Bytes
// +0 vid (int64)
// +8 pid (int64)
// +16 slot_id (int64) — XHCI-Slot (1–MaxSlots)
// +24 port (int64) — Root-Hub-Port-Nummer
// +32 speed (int64) — XHCI_SPEED_*
// +40 ep0_ring (int64) — physische Adresse des EP0-Transfer-Rings
// +48 state (int64) — 0=frei, 1=aktiv, 2=error
// +56 (reserviert)
con XHCI_DEV_ENTRY_SIZE : int64 := 64;
con XHCI_MAX_DEVICES : int64 := 32;
----
===== 10. Hinweise =====
* **Physisch kontiguöser Speicher:** Alle XHCI-Datenstrukturen (Ringe, Contexts, ERST, DCBAA) müssen physisch kontiguös liegen — kein VFS-Alloc, direkter PMM-Aufruf (''PmmAllocContig'').
* **Alignment:** DCBAA muss 64-byte-aligned sein, Ringe und Contexts ebenfalls 64-byte-aligned; Input-Context sogar 16-byte-aligned nach Spec §6.2.5.
* **Scratchpad Buffers:** Wenn ''HCSPARAMS2.MaxScratchpadBufs > 0'', muss der Treiber entsprechend viele 4K-Seiten allozieren und deren Adressen in ein Array schreiben — Slot-0 des DCBAA zeigt auf dieses Array.
* **Speed-abhängige MaxPacketSize für EP0:** FS=64, LS=8, HS=64, SS=512.
* **USB-2-Ports hinter einem Companion-Controller:** Manche Boards haben EHCI + XHCI parallel. Prüfe HCCPARAMS1.AC64 und Extended Capability List (''HCCPARAMS1 >> 16'' × 4 = Offset der Ext-Cap-Liste) für USB2-Port-Mapping.
* **Polling vs. Interrupt:** Im Kernel läuft der Treiber zunächst im Polling-Modus (busy-wait auf Event-Ring-Cycle-Bit). IRQ-Binding via ''sys_irq_bind'' wird als Ausbaustufe implementiert.
----
===== 11. Quelldatei =====
^ Modul ^ Datei ^
| XHCI-Treiber | ''kernel/xhci.lyx'' |
Letzte Aktualisierung: 2026-06-17