Artemis Milestone 2b complete: xHCI PCI discovery and BAR0 mapping
New src/starkernel/usb/ subsystem directory (added to both LOADER_SRCS_BASE and KERNEL_SRCS_BASE wildcards in Makefile.starkernel, matching the existing virtio/*.c pattern). xhci_find_and_map() locates the controller via the already-generic pci_find_first(), enables it, maps BAR0 via the already-generic pci_map_bar(), and fills in all four register-region pointers (cap/op/runtime/doorbell) plus max_slots/ max_ports/max_intrs from HCSPARAMS1 -- ready for controller bring-up (2c) to consume directly. No pci.c extension needed, per 2a's finding that PCI discovery here is ID-based lookup (already generic), not class-code scanning. Verified: clean standalone syntax check, full amd64 kernel build with zero warnings, live boot still reaches POST 1012/0/0 unaffected (nothing calls xhci_find_and_map() yet, so this is purely additive). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
94345c24b7
commit
5970c54912
+22
-10
@@ -3093,16 +3093,28 @@ match" not "class code match"), and `pci_bar()`/`pci_map_bar()`/`pci_enable()` a
|
|||||||
generic, reusable as-is for the xHCI BAR0 mapping and bus-master enable. 2b is smaller than
|
generic, reusable as-is for the xHCI BAR0 mapping and bus-master enable. 2b is smaller than
|
||||||
originally scoped.
|
originally scoped.
|
||||||
|
|
||||||
**2b. PCI discovery**
|
**2b. PCI discovery ✅ DONE 2026-08-22**
|
||||||
- [ ] Extend `src/starkernel/pci/pci.c`'s enumeration to recognize the xHCI PCI class code
|
- [x] No `pci.c` extension needed after all (per 2a's bonus finding — `pci_find_first()` is
|
||||||
(Serial Bus Controller / USB Controller / xHCI programming interface) the same way it
|
already generic ID-based lookup). New files instead: `include/starkernel/xhci_driver.h`
|
||||||
already recognizes whatever device classes it currently handles (need to read
|
(driver state struct `xhci_dev_t` + public API) and `src/starkernel/usb/xhci.c`
|
||||||
`pci.c`'s current class-match logic before extending it, not written from scratch)
|
(`xhci_find_and_map()`) — new `usb/` subsystem directory, added to both
|
||||||
- [ ] Read and store the xHCI controller's BAR (memory-mapped I/O base address) from PCI
|
`LOADER_SRCS_BASE` and `KERNEL_SRCS_BASE` wildcards in `Makefile.starkernel`, matching
|
||||||
config space
|
the existing `virtio/*.c` wildcard pattern exactly.
|
||||||
- [ ] Map that MMIO region into kernel virtual address space (via `vmm.c`'s existing
|
- [x] BAR0 read via the existing `pci_bar()` — no new code needed, direct reuse.
|
||||||
page-table machinery — confirm the right mapping-request function to call, matching
|
- [x] BAR0 mapped via the existing `pci_map_bar()` — no new code needed, direct reuse. Mapping
|
||||||
how virtio-blk's MMIO region gets mapped today as the closest existing precedent)
|
size is a documented, explicit fixed assumption (`XHCI_BAR0_MAP_SIZE`, 64 KiB) rather
|
||||||
|
than real PCI BAR-size probing, since xHCI has no self-describing capability-region
|
||||||
|
length the way virtio PCI capabilities do (that mechanism was `virtio_blk.c`'s approach,
|
||||||
|
not available here) — flagged in a comment as a revisit point if it proves insufficient,
|
||||||
|
not swept under the rug.
|
||||||
|
|
||||||
|
`xhci_find_and_map()` fills in all four register-region pointers (`cap`/`op`/`runtime`/
|
||||||
|
`doorbell`) plus `max_slots`/`max_ports`/`max_intrs` from `HCSPARAMS1`, ready for 2c's
|
||||||
|
controller bring-up to consume directly. Verified: standalone syntax check clean (`gcc -Wall
|
||||||
|
-Wextra -fsyntax-only`), full amd64 kernel build succeeds with zero warnings (both loader and
|
||||||
|
kernel compilation passes), and a live amd64 boot still reaches POST 1012/0/0 and `ok>`
|
||||||
|
unaffected (expected — nothing calls `xhci_find_and_map()` yet, so this is purely additive
|
||||||
|
until 2c wires it in).
|
||||||
|
|
||||||
**2c. Controller bring-up**
|
**2c. Controller bring-up**
|
||||||
- [ ] Read Capability Registers to learn controller parameters (max device slots, max ports,
|
- [ ] Read Capability Registers to learn controller parameters (max device slots, max ports,
|
||||||
|
|||||||
@@ -395,6 +395,7 @@ LOADER_SRCS_BASE := \
|
|||||||
$(wildcard $(KERNEL_SRC)/capsule/*.c) \
|
$(wildcard $(KERNEL_SRC)/capsule/*.c) \
|
||||||
$(wildcard $(KERNEL_SRC)/pci/*.c) \
|
$(wildcard $(KERNEL_SRC)/pci/*.c) \
|
||||||
$(wildcard $(KERNEL_SRC)/virtio/*.c) \
|
$(wildcard $(KERNEL_SRC)/virtio/*.c) \
|
||||||
|
$(wildcard $(KERNEL_SRC)/usb/*.c) \
|
||||||
$(KERNEL_SRC)/repl.c \
|
$(KERNEL_SRC)/repl.c \
|
||||||
$(KERNEL_SRC)/doe_log.c \
|
$(KERNEL_SRC)/doe_log.c \
|
||||||
$(KERNEL_SRC)/heartbeat.c
|
$(KERNEL_SRC)/heartbeat.c
|
||||||
@@ -444,6 +445,7 @@ KERNEL_SRCS_BASE := \
|
|||||||
$(wildcard $(KERNEL_SRC)/capsule/*.c) \
|
$(wildcard $(KERNEL_SRC)/capsule/*.c) \
|
||||||
$(wildcard $(KERNEL_SRC)/pci/*.c) \
|
$(wildcard $(KERNEL_SRC)/pci/*.c) \
|
||||||
$(wildcard $(KERNEL_SRC)/virtio/*.c) \
|
$(wildcard $(KERNEL_SRC)/virtio/*.c) \
|
||||||
|
$(wildcard $(KERNEL_SRC)/usb/*.c) \
|
||||||
$(wildcard $(KERNEL_SRC)/arch/$(ARCH)/*.c) \
|
$(wildcard $(KERNEL_SRC)/arch/$(ARCH)/*.c) \
|
||||||
$(KERNEL_SRC)/repl.c \
|
$(KERNEL_SRC)/repl.c \
|
||||||
$(KERNEL_SRC)/doe_log.c \
|
$(KERNEL_SRC)/doe_log.c \
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Capsule Block Manifest — Auto-generated
|
# Capsule Block Manifest — Auto-generated
|
||||||
<!-- Generated by mkcapsule --manifest 2026-08-22T11:46:44Z -->
|
<!-- Generated by mkcapsule --manifest 2026-08-22T11:56:55Z -->
|
||||||
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
|
||||||
<!-- Hand-written justifications and immutability notes live -->
|
<!-- Hand-written justifications and immutability notes live -->
|
||||||
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
<!-- in MANIFEST.md alongside this auto-generated index. -->
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* xhci_driver.h — xHCI USB host controller driver public API for StarKernel
|
||||||
|
*
|
||||||
|
* Register-layout definitions live in xhci.h; this header is the driver's
|
||||||
|
* own state and public entry points, matching virtio_blk.h's split.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef STARKERNEL_XHCI_DRIVER_H
|
||||||
|
#define STARKERNEL_XHCI_DRIVER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "starkernel/pci.h"
|
||||||
|
#include "starkernel/xhci.h"
|
||||||
|
|
||||||
|
/* Driver state for one xHCI controller instance. Only one controller is
|
||||||
|
* supported (matches virtio_blk's single-device precedent). */
|
||||||
|
typedef struct {
|
||||||
|
PciDevice pci;
|
||||||
|
uint64_t bar0_phys; /* physical MMIO base, BAR0 */
|
||||||
|
xhci_cap_regs_t *cap; /* BAR0 + 0 */
|
||||||
|
xhci_op_regs_t *op; /* BAR0 + cap->cap_length */
|
||||||
|
xhci_runtime_regs_t *runtime; /* BAR0 + cap->rts_off */
|
||||||
|
xhci_doorbell_t *doorbell; /* BAR0 + cap->db_off */
|
||||||
|
uint32_t max_slots;
|
||||||
|
uint32_t max_ports;
|
||||||
|
uint32_t max_intrs;
|
||||||
|
} xhci_dev_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* xhci_find_and_map — locate the xHCI controller on PCI bus 0, enable it
|
||||||
|
* (I/O+MEM+bus-master), map its BAR0 MMIO region, and
|
||||||
|
* fill in the four register-region pointers in *dev.
|
||||||
|
*
|
||||||
|
* dev must point to a zero-initialised xhci_dev_t.
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
* Returns -1 if no xHCI device was found on the PCI bus.
|
||||||
|
* Returns -2 if the BAR0 mapping failed.
|
||||||
|
*/
|
||||||
|
int xhci_find_and_map(xhci_dev_t *dev);
|
||||||
|
|
||||||
|
#endif /* STARKERNEL_XHCI_DRIVER_H */
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* xhci.c — xHCI USB host controller driver for StarKernel: discovery and
|
||||||
|
* register-region mapping (Milestone 2b). Controller bring-up (2c) and
|
||||||
|
* beyond follow in later increments.
|
||||||
|
*
|
||||||
|
* Memory model: BAR0 is mapped identity (virtual address == physical
|
||||||
|
* address), matching virtio_blk.c's precedent and pci_map_bar()'s own
|
||||||
|
* documented behavior (amd64: vmm_map_range(phys, phys, ...); other
|
||||||
|
* arches: no-op, UEFI identity map already covers it).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __STARKERNEL__
|
||||||
|
#error "xhci.c is kernel-only"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "starkernel/pci.h"
|
||||||
|
#include "starkernel/xhci.h"
|
||||||
|
#include "starkernel/xhci_driver.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
/* Conservative fixed BAR0 mapping size. xHCI has no self-describing
|
||||||
|
* capability-region length the way virtio PCI capabilities do (that's
|
||||||
|
* virtio_blk.c's approach, not available here) — 64 KiB comfortably
|
||||||
|
* covers Capability + Operational + Port registers + Runtime + Doorbell
|
||||||
|
* Array + typical extended-capability space for QEMU's qemu-xhci and for
|
||||||
|
* real hardware controllers with modest port counts. Revisit if a real
|
||||||
|
* device's actual BAR size (via PCI BAR-sizing probe, not yet
|
||||||
|
* implemented in pci.c) proves this insufficient. */
|
||||||
|
#define XHCI_BAR0_MAP_SIZE 0x10000ull
|
||||||
|
|
||||||
|
int xhci_find_and_map(xhci_dev_t *dev)
|
||||||
|
{
|
||||||
|
if (!dev) return -1;
|
||||||
|
|
||||||
|
if (pci_find_first(XHCI_PCI_VENDOR_ID, XHCI_PCI_DEVICE_ID, &dev->pci) != 0) {
|
||||||
|
console_println("xhci: no controller found on PCI bus 0");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_enable(&dev->pci);
|
||||||
|
|
||||||
|
dev->bar0_phys = pci_bar(&dev->pci, 0);
|
||||||
|
if (!dev->bar0_phys) {
|
||||||
|
console_println("xhci: BAR0 read failed (zero or I/O BAR)");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pci_map_bar(dev->bar0_phys, XHCI_BAR0_MAP_SIZE) != 0) {
|
||||||
|
console_println("xhci: BAR0 mapping failed");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->cap = (xhci_cap_regs_t *)(uintptr_t)dev->bar0_phys;
|
||||||
|
dev->op = (xhci_op_regs_t *)((uint8_t *)dev->cap + dev->cap->cap_length);
|
||||||
|
dev->runtime = (xhci_runtime_regs_t *)((uint8_t *)dev->cap +
|
||||||
|
(dev->cap->rts_off & ~0x1Fu));
|
||||||
|
dev->doorbell = (xhci_doorbell_t *)((uint8_t *)dev->cap +
|
||||||
|
(dev->cap->db_off & ~0x3u));
|
||||||
|
|
||||||
|
uint32_t hcs1 = dev->cap->hcs_params1;
|
||||||
|
dev->max_slots = XHCI_HCSPARAMS1_MAX_SLOTS(hcs1);
|
||||||
|
dev->max_intrs = XHCI_HCSPARAMS1_MAX_INTRS(hcs1);
|
||||||
|
dev->max_ports = XHCI_HCSPARAMS1_MAX_PORTS(hcs1);
|
||||||
|
|
||||||
|
console_println("xhci: controller found, BAR0 mapped");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user