reorg: move mmio into library/device and spell out its API

mmio is device-driver code, so it joins the other domains under
library/device/mmio/ (module name "mmio" unchanged — a pure relocation, only
the build paths move). And its abbreviated function names are spelled out per
docs/coding-standards.md:

  read  -> readRegister          mb  -> memoryBarrier
  write -> writeRegister         rmb -> readMemoryBarrier
                                 wmb -> writeMemoryBarrier

All call sites updated (virtio-gpu, usb-xhci-library, pci.Function); the two
display-driver placeholders import mmio but use nothing, so they're untouched.
Docs (driver-model graph, README layout, drivers.md, the FHS note) follow the
new path and names.

zig build + test green; virtio-gpu, display-native, display-reattach, usb-hid,
usb-hub, usb-storage, pci-scan pass.
This commit is contained in:
Daniel Samson
2026-07-22 21:28:32 +01:00
parent 7d540c4b2f
commit 5b874fc756
9 changed files with 82 additions and 83 deletions
@@ -162,7 +162,7 @@ const ProducerRing = struct {
// holds it) is written after `parameter`/`status`, with a barrier between.
slot.parameter = trb.parameter;
slot.status = trb.status;
mmio.wmb();
mmio.writeMemoryBarrier();
slot.control = control;
const physical = self.region.physical + index * @sizeOf(Trb);
self.enqueue_index += 1;
@@ -628,10 +628,10 @@ pub const Controller = struct {
// interrupter is enabled, so a hot-plug port-change event is silently
// dropped otherwise. Enabling it is harmless to a polling driver.
write32(self.interrupter(interrupter_management), 1 << 1); // IE
mmio.wmb();
mmio.writeMemoryBarrier();
// Run.
mmio.wmb();
mmio.writeMemoryBarrier();
write32(self.operational(op_usbcmd), read32(self.operational(op_usbcmd)) | usbcmd_run | usbcmd_interrupter_enable);
if (!waitClear(self.operational(op_usbsts), usbsts_halted)) return null;
@@ -699,7 +699,7 @@ pub const Controller = struct {
/// address of the enqueued TRB (which the Command Completion Event echoes).
fn submitCommand(self: *Controller, trb: Trb) u64 {
const physical = self.command_ring.push(trb);
mmio.wmb();
mmio.writeMemoryBarrier();
self.ringDoorbell(0, 0); // doorbell 0, target 0 = command ring
return physical;
}
@@ -711,7 +711,7 @@ pub const Controller = struct {
const slot = &ring[self.event_ring.dequeue_index];
const control = slot.control;
if ((control & cycle_bit != 0) == self.event_ring.cycle) {
mmio.rmb();
mmio.readMemoryBarrier();
const event = Trb{ .parameter = slot.parameter, .status = slot.status, .control = control };
self.event_ring.dequeue_index += 1;
if (self.event_ring.dequeue_index >= trbs_per_ring) {
@@ -1216,7 +1216,7 @@ pub const Controller = struct {
.control = trbControl(.status_stage, status_direction | (1 << 5)), // DIR | IOC
});
mmio.wmb();
mmio.writeMemoryBarrier();
self.ringDoorbell(device.slot_id, 1); // DCI 1 = EP0
const code = self.awaitTransfer(device.slot_id, 1, @intCast(data.len)) orelse return false;
if (code != @intFromEnum(CompletionCode.success) and code != @intFromEnum(CompletionCode.short_packet)) return false;
@@ -1457,7 +1457,7 @@ pub const Controller = struct {
.status = length,
.control = trbControl(.normal, (1 << 5)), // IOC
});
mmio.wmb();
mmio.writeMemoryBarrier();
const number: u8 = endpoint.address & 0x0F;
const direction_in = endpoint.address & 0x80 != 0;
const dci = doorbellContextIndex(number, direction_in);
@@ -1507,7 +1507,7 @@ pub const Controller = struct {
.status = subscription.max_length,
.control = trbControl(.normal, (1 << 5)), // IOC
});
mmio.wmb();
mmio.writeMemoryBarrier();
self.ringDoorbell(subscription.slot_id, subscription.dci);
}