From dc23d2f22cafeb6b97ba460789a834a6c586314d Mon Sep 17 00:00:00 2001 From: salmonik Date: Fri, 31 Jul 2026 19:53:53 +0200 Subject: ahci: SATA driver + FAT32 persistent disk mounted at /disk - ahci.rs: polling AHCI on PCI class 1/6/1, bus mastering + ABAR map, port 0 up, IDENTIFY + READ/WRITE DMA EXT through one 4KiB DMA buffer - fat.rs: BPB parse, whole-FAT RAM cache with write-back to both copies, LFN read/write, dirs, multi-cluster files, FSInfo free-count sync, space-padded dot entries ('..' = cluster 0 under root), fsck-clean - fs.rs: /disk mount node + 24-slot ephemeral node pool; ls/cat/hexdump/ echo/mkdir/touch/rm/edit all work on disk paths unchanged - QEMU: explicit bus assignment (disk=ide.0, ESP=ide.1); the implicit fat:rw:esp drive was stealing AHCI port 0 - Debugged against QEMU source: header DW0 is CFL in bits 4:0 / PRDTL in bits 31:16 (Linux libahci layout), FIS count at bytes 12-13, device at byte 7; QEMU rejects H2D FIS flags bits 6:4, so direction is the header W bit only - Verified: full shell round-trip on /disk, reboot persistence (poweroff then mdir/mtype and a fresh boot), fsck.fat clean --- rsnix/src/pci.rs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'rsnix/src/pci.rs') diff --git a/rsnix/src/pci.rs b/rsnix/src/pci.rs index 2d201f3..efdbc01 100644 --- a/rsnix/src/pci.rs +++ b/rsnix/src/pci.rs @@ -57,6 +57,39 @@ pub fn config_read(bus: u8, device: u8, func: u8, reg: u8) -> u32 { inl(CONFIG_DATA) } +/// Write a dword to a device's config space (`reg` must be dword-aligned). +pub fn config_write(bus: u8, device: u8, func: u8, reg: u8, val: u32) { + let addr = 0x8000_0000 + | ((bus as u32) << 16) + | ((device as u32) << 11) + | ((func as u32) << 8) + | ((reg as u32) & 0xFC); + outl(CONFIG_ADDRESS, addr); + outl(CONFIG_DATA, val) +} + +/// Read a memory BAR (index 0-5) as a 64-bit address, handling 32/64-bit +/// BARs. Returns None for I/O BARs or invalid values. +pub fn bar64(bus: u8, device: u8, func: u8, bar_index: u8) -> Option { + let reg_off = 0x10 + bar_index * 4; + let lo = config_read(bus, device, func, reg_off); + if lo & 1 == 1 { + return None; // I/O BAR + } + let kind = (lo >> 1) & 0x3; + let hi = if kind == 2 { + config_read(bus, device, func, reg_off + 4) + } else { + 0 + }; + let base = ((hi as u64) << 32) | (lo as u64 & 0xFFFF_FFF0); + if base == 0 { + None + } else { + Some(base) + } +} + /// Enumerate every device/function present on all buses. pub fn probe() -> alloc::vec::Vec { let mut out = alloc::vec::Vec::new(); -- cgit v1.2.3