refactor: unsafe only in adapter + libkos; forbid(unsafe_code) everywhere else; libkos Window (volatile, bounds-checked MMIO/DMA/shared mem), entry!, thread::spawn; MapRegion returns pages; kernel const-built (with_cores/install_platform); newtype addrs
This commit is contained in:
@@ -1,29 +1,20 @@
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use hw_virtio::mmio::MmioAccess;
|
||||
use hw_virtio::queue::{QueueAddrs, VirtioQueue};
|
||||
use hw_virtio::block::{self, DmaAddrs};
|
||||
use hw_virtio::mmio::{MmioAccess, Registers};
|
||||
use hw_virtio::queue::VirtioQueue;
|
||||
use port_block_device::{BlockDevice, SectorId};
|
||||
use types::address::{PhysicalAddress, VirtualAddress};
|
||||
use types::bounded::PageCount;
|
||||
|
||||
const MMIO_BASE: usize = 0x20000;
|
||||
const VQUEUE_VA: usize = 0x21000;
|
||||
const REQ_HDR_VA: usize = 0x23000;
|
||||
const MMIO_VA: VirtualAddress = VirtualAddress::from_raw(0x20000);
|
||||
const VQUEUE_VA: VirtualAddress = VirtualAddress::from_raw(0x21000);
|
||||
const REQ_HDR_VA: VirtualAddress = VirtualAddress::from_raw(0x23000);
|
||||
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,
|
||||
mmio: Registers,
|
||||
queue: VirtioQueue,
|
||||
dma: DmaAddrs,
|
||||
sectors: usize,
|
||||
@@ -33,31 +24,31 @@ impl VirtioBlockDevice {
|
||||
/// Takes over the virtio block device behind `mmio`. `None` if it is
|
||||
/// not one or any step fails.
|
||||
pub fn new(mmio: types::bounded::CapSlot) -> Option<Self> {
|
||||
libkos::device::map_mmio(mmio, MMIO_BASE).ok()?;
|
||||
let regs = UserMmio;
|
||||
let regs = Registers::new(libkos::device::map_mmio(mmio, MMIO_VA).ok()?);
|
||||
if regs.read(hw_virtio::mmio::REG_MAGIC) != hw_virtio::mmio::MAGIC
|
||||
|| regs.read(hw_virtio::mmio::REG_DEVICE_ID) != hw_virtio::mmio::DEVICE_ID_BLOCK
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let vq_pa = libkos::device::dma(2, VQUEUE_VA).ok()?;
|
||||
let hdr_pa = libkos::device::dma(1, REQ_HDR_VA).ok()?;
|
||||
hw_virtio::mmio::init_legacy_device(®s, vq_pa, hw_virtio::queue::QUEUE_SIZE as u32);
|
||||
let rings = libkos::device::dma(PageCount::new(2)?, VQUEUE_VA).ok()?;
|
||||
let req = libkos::device::dma(PageCount::new(1)?, REQ_HDR_VA).ok()?;
|
||||
hw_virtio::mmio::init_legacy_device(®s, rings.physical, hw_virtio::queue::QUEUE_SIZE as u32);
|
||||
|
||||
// Header, status byte and one sector share the request page.
|
||||
let at = |offset: usize| PhysicalAddress::from_raw(req.physical.raw() + offset);
|
||||
let dma = DmaAddrs {
|
||||
header_pa: PhysicalAddress::from_raw(hdr_pa),
|
||||
header_va: VirtualAddress::from_raw(REQ_HDR_VA),
|
||||
status_pa: PhysicalAddress::from_raw(hdr_pa + 16),
|
||||
status_va: VirtualAddress::from_raw(REQ_HDR_VA + 16),
|
||||
data_pa: PhysicalAddress::from_raw(hdr_pa + 32),
|
||||
data_va: VirtualAddress::from_raw(REQ_HDR_VA + 32),
|
||||
header_pa: at(0),
|
||||
header: req.window.sub(0, 16),
|
||||
status_pa: at(16),
|
||||
status: req.window.sub(16, 1),
|
||||
data_pa: at(32),
|
||||
data: req.window.sub(32, SECTOR_SIZE),
|
||||
};
|
||||
let capacity = regs.read(block::CONFIG_CAPACITY) as u64
|
||||
| (regs.read(block::CONFIG_CAPACITY + 4) as u64) << 32;
|
||||
Some(Self {
|
||||
mmio: UserMmio,
|
||||
queue: VirtioQueue::new(QueueAddrs::from_base(VQUEUE_VA)),
|
||||
mmio: regs,
|
||||
queue: VirtioQueue::new(rings.window),
|
||||
dma,
|
||||
sectors: usize::try_from(capacity).ok()?,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user