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