#![no_std] use hw_virtio::mmio::MmioAccess; use hw_virtio::queue::{QueueAddrs, VirtioQueue}; use hw_virtio::block::{self, DmaAddrs}; use port_block_device::{BlockDevice, SectorId}; use types::address::{PhysicalAddress, VirtualAddress}; const MMIO_BASE: usize = 0x20000; const VQUEUE_VA: usize = 0x21000; const REQ_HDR_VA: usize = 0x23000; const PHYSINFO_VA: usize = 0x24000; const SECTOR_SIZE: usize = 512; struct UserMmio; impl MmioAccess for UserMmio { fn read(&self, offset: usize) -> u32 { unsafe { core::ptr::read_volatile((MMIO_BASE + offset) as *const u32) } } fn write(&self, offset: usize, val: u32) { unsafe { core::ptr::write_volatile((MMIO_BASE + offset) as *mut u32, val) } } } pub struct VirtioBlockDevice { mmio: UserMmio, queue: VirtioQueue, dma: DmaAddrs, } impl VirtioBlockDevice { pub fn new() -> Self { let queue = VirtioQueue::new(QueueAddrs::from_base(VQUEUE_VA)); let (hdr_pa, status_pa, data_pa) = unsafe { let p = PHYSINFO_VA as *const u64; ( core::ptr::read_volatile(p) as usize, core::ptr::read_volatile(p.add(1)) as usize, core::ptr::read_volatile(p.add(2)) as usize, ) }; let dma = DmaAddrs { header_pa: PhysicalAddress::from_raw(hdr_pa), header_va: VirtualAddress::from_raw(REQ_HDR_VA), status_pa: PhysicalAddress::from_raw(status_pa), status_va: VirtualAddress::from_raw(REQ_HDR_VA + 16), data_pa: PhysicalAddress::from_raw(data_pa), data_va: VirtualAddress::from_raw(REQ_HDR_VA + 32), }; Self { mmio: UserMmio, queue, dma } } } impl BlockDevice for VirtioBlockDevice { fn sector_size(&self) -> usize { SECTOR_SIZE } fn sector_count(&self) -> usize { 0xFFFF } fn read_sector(&mut self, sector: SectorId, buf: &mut [u8]) -> bool { if buf.len() < SECTOR_SIZE { return false; } let mut sector_buf = [0u8; SECTOR_SIZE]; if !block::read_sector(&self.mmio, &self.queue, &self.dma, sector.raw(), &mut sector_buf) { return false; } buf[..SECTOR_SIZE].copy_from_slice(§or_buf); true } fn write_sector(&mut self, _sector: SectorId, _buf: &[u8]) -> bool { false } }