os/drivers/block/
virtio_blk.rs1use super::BlockDevice;
2use crate::mm::{
3 FrameTracker, PageTable, PhysAddr, PhysPageNum, StepByOne, VirtAddr, frame_alloc,
4 frame_dealloc, kernel_token,
5};
6use crate::sync::UPSafeCell;
7use alloc::vec::Vec;
8use lazy_static::*;
9use virtio_drivers::{Hal, VirtIOBlk, VirtIOHeader};
10
11#[allow(unused)]
12const VIRTIO0: usize = 0x10001000;
13
14pub struct VirtIOBlock(UPSafeCell<VirtIOBlk<'static, VirtioHal>>);
15
16lazy_static! {
17 static ref QUEUE_FRAMES: UPSafeCell<Vec<FrameTracker>> = unsafe { UPSafeCell::new(Vec::new()) };
18}
19
20impl BlockDevice for VirtIOBlock {
21 fn read_block(&self, block_id: usize, buf: &mut [u8]) {
22 self.0
23 .exclusive_access()
24 .read_block(block_id, buf)
25 .expect("Error when reading VirtIOBlk");
26 }
27 fn write_block(&self, block_id: usize, buf: &[u8]) {
28 self.0
29 .exclusive_access()
30 .write_block(block_id, buf)
31 .expect("Error when writing VirtIOBlk");
32 }
33}
34
35impl VirtIOBlock {
36 #[allow(unused)]
37 pub fn new() -> Self {
38 unsafe {
39 Self(UPSafeCell::new(
40 VirtIOBlk::<VirtioHal>::new(&mut *(VIRTIO0 as *mut VirtIOHeader)).unwrap(),
41 ))
42 }
43 }
44}
45
46pub struct VirtioHal;
47
48impl Hal for VirtioHal {
49 fn dma_alloc(pages: usize) -> usize {
50 let mut ppn_base = PhysPageNum(0);
51 for i in 0..pages {
52 let frame = frame_alloc().unwrap();
53 if i == 0 {
54 ppn_base = frame.ppn;
55 }
56 assert_eq!(frame.ppn.0, ppn_base.0 + i);
57 QUEUE_FRAMES.exclusive_access().push(frame);
58 }
59 let pa: PhysAddr = ppn_base.into();
60 pa.0
61 }
62
63 fn dma_dealloc(pa: usize, pages: usize) -> i32 {
64 let pa = PhysAddr::from(pa);
65 let mut ppn_base: PhysPageNum = pa.into();
66 for _ in 0..pages {
67 frame_dealloc(ppn_base);
68 ppn_base.step();
69 }
70 0
71 }
72
73 fn phys_to_virt(addr: usize) -> usize {
74 addr
75 }
76
77 fn virt_to_phys(vaddr: usize) -> usize {
78 PageTable::from_token(kernel_token())
79 .translate_va(VirtAddr::from(vaddr))
80 .unwrap()
81 .0
82 }
83}