//! The block-device wire protocol — what a filesystem (the FAT server) says to a //! block driver (usb-storage) over its well-known `.block` endpoint. A protocol //! module like vfs-protocol / usb-transfer-protocol: extern-struct messages, an //! `Operation` tag, everything in one IPC message. //! //! Data path: read and write move whole blocks to or from a **caller-owned DMA //! buffer**, named by its physical address — the same physical-address handoff //! usb-storage already uses toward the controller, one layer up. So a 512-byte //! sector never has to cross the 256-byte IPC boundary; only the small request / //! reply headers do. Under an enforcing IOMMU the buffer's physical addresses are //! only reachable by the device once the filesystem has `attach`ed the buffer's //! capability (the block server forwards it to the controller); see docs/driver-model.md. pub const Operation = enum(u32) { /// geometry() -> { block_size, block_count } geometry = 0, /// read(lba, count, physical): read `count` blocks from `lba` into the buffer read = 1, /// write(lba, count, physical): write `count` blocks at `lba` from the buffer write = 2, /// flush(): commit any device write cache to stable media (no data transfer). /// A filesystem calls this to make prior writes durable — e.g. before power-off, /// so a shutdown-time write isn't lost in the USB flash controller's cache. flush = 3, /// attach(): the caller's DMA-region capability rides the call's cap slot; the /// block server forwards it to the controller so the buffer's physical addresses /// (named in later read/write) are reachable by the device under an enforcing /// IOMMU. Call once per buffer before using it in a transfer. attach = 4, }; pub const Request = extern struct { operation: u32, reserved: u32 = 0, lba: u64, count: u32, // number of blocks (read/write) reserved2: u32 = 0, physical: u64, // caller's DMA buffer physical address (read/write) }; pub const Reply = extern struct { status: i32, // 0 on success, negative on failure reserved: u32 = 0, block_size: u32, // geometry: bytes per block (512) reserved2: u32 = 0, block_count: u64, // geometry: total blocks; read/write: blocks moved }; pub const message_maximum: usize = 256; pub const request_size: usize = @sizeOf(Request); pub const reply_size: usize = @sizeOf(Reply);