xref: /DragonOS/kernel/src/driver/virtio/virtio_impl.rs (revision 004e86ff19727df303c23b42c7a271b9214c6898)
126d84a31SYJwu2023 use crate::include::bindings::bindings::{
226d84a31SYJwu2023     alloc_pages, free_pages, memory_management_struct, Page, PAGE_2M_SHIFT, PAGE_2M_SIZE,
326d84a31SYJwu2023     PAGE_OFFSET, PAGE_SHARED, ZONE_NORMAL,
426d84a31SYJwu2023 };
5*004e86ffSlogin 
626d84a31SYJwu2023 use core::mem::size_of;
7*004e86ffSlogin use core::ptr::NonNull;
826d84a31SYJwu2023 use virtio_drivers::{BufferDirection, Hal, PhysAddr, VirtAddr, PAGE_SIZE};
926d84a31SYJwu2023 
1026d84a31SYJwu2023 pub struct HalImpl;
1126d84a31SYJwu2023 impl Hal for HalImpl {
1226d84a31SYJwu2023     /// @brief 申请用于DMA的内存页
1326d84a31SYJwu2023     /// @param pages 页数(4k一页)
1426d84a31SYJwu2023     /// @return PhysAddr 获得的内存页的初始物理地址
1526d84a31SYJwu2023     fn dma_alloc(pages: usize) -> PhysAddr {
1626d84a31SYJwu2023         let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
1726d84a31SYJwu2023         let page_num = if reminder > 0 {
1826d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
1926d84a31SYJwu2023         } else {
2026d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
2126d84a31SYJwu2023         };
2226d84a31SYJwu2023 
2326d84a31SYJwu2023         unsafe {
2426d84a31SYJwu2023             let pa = alloc_pages(ZONE_NORMAL, page_num, PAGE_SHARED as u64);
2526d84a31SYJwu2023             let page = *pa;
2626d84a31SYJwu2023             //kdebug!("alloc pages num:{},Phyaddr={}",page_num,page.addr_phys);
2726d84a31SYJwu2023             return page.addr_phys as PhysAddr;
2826d84a31SYJwu2023         }
2926d84a31SYJwu2023     }
3026d84a31SYJwu2023     /// @brief 释放用于DMA的内存页
3126d84a31SYJwu2023     /// @param paddr 起始物理地址 pages 页数(4k一页)
3226d84a31SYJwu2023     /// @return i32 0表示成功
3326d84a31SYJwu2023     fn dma_dealloc(paddr: PhysAddr, pages: usize) -> i32 {
3426d84a31SYJwu2023         let reminder = pages * PAGE_SIZE % (PAGE_2M_SIZE as usize);
3526d84a31SYJwu2023         let page_num = if reminder > 0 {
3626d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize) + 1) as i32
3726d84a31SYJwu2023         } else {
3826d84a31SYJwu2023             (pages * PAGE_SIZE / (PAGE_2M_SIZE as usize)) as i32
3926d84a31SYJwu2023         };
4026d84a31SYJwu2023         unsafe {
4126d84a31SYJwu2023             let pa = (memory_management_struct.pages_struct as usize
4226d84a31SYJwu2023                 + (paddr >> PAGE_2M_SHIFT) * size_of::<Page>()) as *mut Page;
4326d84a31SYJwu2023             //kdebug!("free pages num:{},Phyaddr={}",page_num,paddr);
4426d84a31SYJwu2023             free_pages(pa, page_num);
4526d84a31SYJwu2023         }
4626d84a31SYJwu2023         return 0;
4726d84a31SYJwu2023     }
4826d84a31SYJwu2023     /// @brief 物理地址转换为虚拟地址
4926d84a31SYJwu2023     /// @param paddr 起始物理地址
5026d84a31SYJwu2023     /// @return VirtAddr 虚拟地址
5126d84a31SYJwu2023     fn phys_to_virt(paddr: PhysAddr) -> VirtAddr {
5226d84a31SYJwu2023         paddr + PAGE_OFFSET as usize
5326d84a31SYJwu2023     }
5426d84a31SYJwu2023     /// @brief 与真实物理设备共享
5526d84a31SYJwu2023     /// @param buffer 要共享的buffer _direction:设备到driver或driver到设备
5626d84a31SYJwu2023     /// @return buffer在内存中的物理地址
5726d84a31SYJwu2023     fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr {
5826d84a31SYJwu2023         let vaddr = buffer.as_ptr() as *mut u8 as usize;
5926d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory.
6026d84a31SYJwu2023         virt_to_phys(vaddr)
6126d84a31SYJwu2023     }
6226d84a31SYJwu2023     /// @brief 停止共享(让主机可以访问全部内存的话什么都不用做)
6326d84a31SYJwu2023     fn unshare(_paddr: PhysAddr, _buffer: NonNull<[u8]>, _direction: BufferDirection) {
6426d84a31SYJwu2023         // Nothing to do, as the host already has access to all memory and we didn't copy the buffer
6526d84a31SYJwu2023         // anywhere else.
6626d84a31SYJwu2023     }
6726d84a31SYJwu2023 }
6826d84a31SYJwu2023 
6926d84a31SYJwu2023 /// @brief 虚拟地址转换为物理地址
7026d84a31SYJwu2023 /// @param vaddr 虚拟地址
7126d84a31SYJwu2023 /// @return PhysAddr 物理地址
7226d84a31SYJwu2023 fn virt_to_phys(vaddr: VirtAddr) -> PhysAddr {
7326d84a31SYJwu2023     vaddr - PAGE_OFFSET as usize
7426d84a31SYJwu2023 }
75