virtio-blk worked.

This commit is contained in:
Yifan Wu 2020-12-16 10:18:38 +08:00
parent 2d34cab989
commit eca5ee2eb7
12 changed files with 145 additions and 11 deletions

View file

@ -0,0 +1,30 @@
mod virtio_blk;
use lazy_static::*;
use alloc::sync::Arc;
use core::any::Any;
pub trait BlockDevice : Send + Sync + Any {
fn read_block(&self, block_id: usize, buf: &mut [u8]);
fn write_block(&self, block_id: usize, buf: &[u8]);
}
#[cfg(feature = "board_qemu")]
type BlockDeviceImpl = virtio_blk::VirtIOBlock;
lazy_static! {
pub static ref BLOCK_DEVICE: Arc<dyn BlockDevice> = Arc::new(BlockDeviceImpl::new());
}
pub fn block_device_test() {
let block_device = BLOCK_DEVICE.clone();
let mut write_buffer = [0u8; 512];
let mut read_buffer = [0u8; 512];
for i in 0..512 {
for byte in write_buffer.iter_mut() { *byte = i as u8; }
block_device.write_block(i as usize, &write_buffer);
block_device.read_block(i as usize, &mut read_buffer);
assert_eq!(write_buffer, read_buffer);
}
println!("block device test passed!");
}

View file

@ -0,0 +1,71 @@
use virtio_drivers::{VirtIOBlk, VirtIOHeader};
use crate::mm::{
PhysAddr,
VirtAddr,
frame_alloc,
frame_dealloc,
PhysPageNum,
FrameTracker,
StepByOne,
};
use super::BlockDevice;
use spin::Mutex;
use alloc::vec::Vec;
use lazy_static::*;
const VIRTIO0: usize = 0x10001000;
pub struct VirtIOBlock(Mutex<VirtIOBlk<'static>>);
lazy_static! {
static ref QUEUE_FRAMES: Mutex<Vec<FrameTracker>> = Mutex::new(Vec::new());
}
impl BlockDevice for VirtIOBlock {
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
self.0.lock().read_block(block_id, buf).expect("Error when reading VirtIOBlk");
}
fn write_block(&self, block_id: usize, buf: &[u8]) {
self.0.lock().write_block(block_id, buf).expect("Error when writing VirtIOBlk");
}
}
impl VirtIOBlock {
pub fn new() -> Self {
Self(Mutex::new(VirtIOBlk::new(
unsafe { &mut *(VIRTIO0 as *mut VirtIOHeader) }
).unwrap()))
}
}
#[no_mangle]
pub extern "C" fn virtio_dma_alloc(pages: usize) -> PhysAddr {
let mut ppn_base = PhysPageNum(0);
for i in 0..pages {
let frame = frame_alloc().unwrap();
if i == 0 { ppn_base = frame.ppn; }
assert_eq!(frame.ppn.0, ppn_base.0 + i);
QUEUE_FRAMES.lock().push(frame);
}
ppn_base.into()
}
#[no_mangle]
pub extern "C" fn virtio_dma_dealloc(pa: PhysAddr, pages: usize) -> i32 {
let mut ppn_base: PhysPageNum = pa.into();
for _ in 0..pages {
frame_dealloc(ppn_base);
ppn_base.step();
}
0
}
#[no_mangle]
pub extern "C" fn virtio_phys_to_virt(paddr: PhysAddr) -> VirtAddr {
VirtAddr(paddr.0)
}
#[no_mangle]
pub extern "C" fn virtio_virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
PhysAddr(vaddr.0)
}

3
os/src/drivers/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod block;
pub use block::{BLOCK_DEVICE, block_device_test};