establishment: block stops being a name, and enumerate learns to page
P2 of docs/establishment-planes-plan.md. usb-storage serves nameless — one process per stick cannot share an exclusive bind, and a second stick used to die silently on -EBUSY before ever helloing. Its one hello now moves both directions at once: the block-serving endpoint up, its controller channel down. fat finds its volume through the manager — a new `.consumer` role asks for the channel of the driver BOUND TO a device (distinct from the device's reporter), found by enumerating the tree for the mass-storage identity. fat stays single-volume; the boot-volume-by-content choice is M21. The conversion immediately caught a live truncation of exactly the audit's shape: ChildEntry grew to 32 bytes, one enumerate reply holds ~7, and a real tree carries a dozen ACPI nodes before the first USB child — the storage entry silently never fit (the protocol comment already said "paging joins the protocol if a tree ever outgrows one packet"). enumerate is now paged: Header.target is the start cursor, a short page is the end; device-list's page-0 read is unchanged. Grant rows move with the code: the block bind and fat's block open die, fat gains open device-manager. Gate: 18 cases green including the registry trio, device-list, and both IOMMU storage variants.
This commit is contained in:
@@ -63,6 +63,11 @@ pub const Role = enum(u8) {
|
||||
bus = 1,
|
||||
/// Serves one device, reached through a bus's transfer protocol.
|
||||
device = 2,
|
||||
/// Not a spawned driver at all: a party asking for the channel of the
|
||||
/// driver BOUND TO the target device (a service consuming a driver-layer
|
||||
/// contract — fat asking for its volume's block provider). No deadline, no
|
||||
/// state, no driver entry; just establishment by lineage.
|
||||
consumer = 3,
|
||||
};
|
||||
|
||||
// --- the per-operation request parts ----------------------------------------
|
||||
@@ -160,10 +165,18 @@ pub const ChildEntry = extern struct {
|
||||
parent: u64,
|
||||
bus_address: u64,
|
||||
identity: u64,
|
||||
/// The kernel device id this child was registered as (`no_device` for an
|
||||
/// unregistered leaf) — what a `.consumer` hello names as its target to be
|
||||
/// routed to the driver bound to this child.
|
||||
device_id: u64,
|
||||
};
|
||||
|
||||
/// How many `ChildEntry` records one `enumerate` reply can carry. Paging joins
|
||||
/// the protocol if a tree ever outgrows one packet.
|
||||
/// How many `ChildEntry` records one `enumerate` reply can carry. The verb is
|
||||
/// PAGED: the request's `Header.target` is the start index (skip that many
|
||||
/// known children), and a short or empty page means the tree is exhausted — a
|
||||
/// real tree outgrew one packet the day ACPI reported a dozen nodes before
|
||||
/// the first USB child, and an unpaged reply silently truncated exactly the
|
||||
/// entries a consumer was looking for.
|
||||
pub const entries_per_reply: usize = (envelope.packet_maximum - envelope.prefix_size) / @sizeOf(ChildEntry);
|
||||
|
||||
pub const Protocol = envelope.Define(.{
|
||||
|
||||
Reference in New Issue
Block a user