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