xref: /DragonOS/kernel/src/driver/virtio/virtio_impl.rs (revision 26d84a31393c50063ff416bc509316e8d342028c)
1*26d84a31SYJwu2023 use crate::include::bindings::bindings::{
2*26d84a31SYJwu2023     alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE,
3*26d84a31SYJwu2023     PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL,
4*26d84a31SYJwu2023 };
5*26d84a31SYJwu2023 use crate::kdebug;
6*26d84a31SYJwu2023 use core::mem::size_of;
7*26d84a31SYJwu2023 use core::{ptr::NonNull};
8*26d84a31SYJwu2023 use virtio_drivers::{BufferDirection, Hal, PhysAddr, VirtAddr, PAGE_SIZE};
9*26d84a31SYJwu2023 
10*26d84a31SYJwu2023 pub struct HalImpl;
11*26d84a31SYJwu2023 impl Hal for HalImpl {
12*26d84a31SYJwu2023     /// @brief 申请用于DMA的内存页
13*26d84a31SYJwu2023     /// @param pages 页数(4k一页)
14*26d84a31SYJwu2023     /// @return PhysAddr 获得的内存页的初始物理地址
15*26d84a31SYJwu2023     fn dma_alloc(pages: usize) -> PhysAddr {
16*26d84a31SYJwu2023         let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
17*26d84a31SYJwu2023         let page_num = if reminder > 0 {
18*26d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
19*26d84a31SYJwu2023         } else {
20*26d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
21*26d84a31SYJwu2023         };
22*26d84a31SYJwu2023 
23*26d84a31SYJwu2023         unsafe {
24*26d84a31SYJwu2023             let pa = alloc_pages(ZONE_NORMAL, page_num, PAGE_SHARED as u64);
25*26d84a31SYJwu2023             let page = *pa;
26*26d84a31SYJwu2023             //kdebug!("alloc pages num:{},Phyaddr={}",page_num,page.addr_phys);
27*26d84a31SYJwu2023             return page.addr_phys as PhysAddr;
28*26d84a31SYJwu2023         }
29*26d84a31SYJwu2023     }
30*26d84a31SYJwu2023     /// @brief 释放用于DMA的内存页
31*26d84a31SYJwu2023     /// @param paddr 起始物理地址 pages 页数(4k一页)
32*26d84a31SYJwu2023     /// @return i32 0表示成功
33*26d84a31SYJwu2023     fn dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 {
34*26d84a31SYJwu2023         let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
35*26d84a31SYJwu2023         let page_num = if reminder > 0 {
36*26d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
37*26d84a31SYJwu2023         } else {
38*26d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
39*26d84a31SYJwu2023         };
40*26d84a31SYJwu2023         unsafe {
41*26d84a31SYJwu2023             let pa = (memory_management_struct.pages_struct as usize
42*26d84a31SYJwu2023                 + (paddr >> PAGE_2M_SHIFT) * size_of::<Page>()) as *mut Page;
43*26d84a31SYJwu2023             //kdebug!("free pages num:{},Phyaddr={}",page_num,paddr);
44*26d84a31SYJwu2023             free_pages(pa, page_num);
45*26d84a31SYJwu2023         }
46*26d84a31SYJwu2023         return 0;
47*26d84a31SYJwu2023     }
48*26d84a31SYJwu2023     /// @brief 物理地址转换为虚拟地址
49*26d84a31SYJwu2023     /// @param paddr 起始物理地址
50*26d84a31SYJwu2023     /// @return VirtAddr 虚拟地址
51*26d84a31SYJwu2023     fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
52*26d84a31SYJwu2023         paddr + PAGE_OFFSET as usize
53*26d84a31SYJwu2023 
54*26d84a31SYJwu2023     }
55*26d84a31SYJwu2023     /// @brief 与真实物理设备共享
56*26d84a31SYJwu2023     /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备
57*26d84a31SYJwu2023     /// @return buffer在内存中的物理地址
58*26d84a31SYJwu2023     fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
59*26d84a31SYJwu2023         let vaddr = buffer.as_ptr() as *mut u8 as usize;
60*26d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory.
61*26d84a31SYJwu2023         virt_to_phys(vaddr)
62*26d84a31SYJwu2023     }
63*26d84a31SYJwu2023     /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
64*26d84a31SYJwu2023     fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
65*26d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
66*26d84a31SYJwu2023         // anywhere else.
67*26d84a31SYJwu2023     }
68*26d84a31SYJwu2023 }
69*26d84a31SYJwu2023 
70*26d84a31SYJwu2023 /// @brief 虚拟地址转换为物理地址
71*26d84a31SYJwu2023 /// @param vaddr 虚拟地址
72*26d84a31SYJwu2023 /// @return PhysAddr 物理地址
73*26d84a31SYJwu2023 fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
74*26d84a31SYJwu2023     vaddr - PAGE_OFFSET as usize
75*26d84a31SYJwu2023 }
76