xref: /DragonOS/kernel/src/driver/net/dma.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1 use crate::arch::mm::kernel_page_flags;
2 
3 use crate::arch::MMArch;
4 
5 use crate::mm::kernel_mapper::KernelMapper;
6 use crate::mm::page::{page_manager_lock_irqsave, EntryFlags};
7 use crate::mm::{
8     allocator::page_frame::{
9         allocate_page_frames, deallocate_page_frames, PageFrameCount, PhysPageFrame,
10     },
11     MemoryManagementArch, PhysAddr, VirtAddr,
12 };
13 use core::ptr::NonNull;
14 const PAGE_SIZE: usize = 4096;
15 /// @brief 申请用于DMA的内存页
16 /// @param pages 页数(4k一页)
17 /// @return PhysAddr 获得的内存页的初始物理地址
dma_alloc(pages: usize) -> (usize, NonNull<u8>)18 pub fn dma_alloc(pages: usize) -> (usize, NonNull<u8>) {
19     let page_num = PageFrameCount::new(
20         (pages * PAGE_SIZE)
21             .div_ceil(MMArch::PAGE_SIZE)
22             .next_power_of_two(),
23     );
24     unsafe {
25         let (paddr, count) = allocate_page_frames(page_num).expect("e1000e: alloc page failed");
26         let virt = MMArch::phys_2_virt(paddr).unwrap();
27         // 清空这块区域,防止出现脏数据
28         core::ptr::write_bytes(virt.data() as *mut u8, 0, count.data() * MMArch::PAGE_SIZE);
29 
30         let dma_flags: EntryFlags<MMArch> = EntryFlags::mmio_flags();
31 
32         let mut kernel_mapper = KernelMapper::lock();
33         let kernel_mapper = kernel_mapper.as_mut().unwrap();
34         let flusher = kernel_mapper
35             .remap(virt, dma_flags)
36             .expect("e1000e: remap failed");
37         flusher.flush();
38         return (
39             paddr.data(),
40             NonNull::new(MMArch::phys_2_virt(paddr).unwrap().data() as _).unwrap(),
41         );
42     }
43 }
44 /// @brief 释放用于DMA的内存页
45 /// @param paddr 起始物理地址 pages 页数(4k一页)
46 /// @return i32 0表示成功
dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i3247 pub unsafe fn dma_dealloc(paddr: usize, vaddr: NonNull<u8>, pages: usize) -> i32 {
48     let page_count = PageFrameCount::new(
49         (pages * PAGE_SIZE)
50             .div_ceil(MMArch::PAGE_SIZE)
51             .next_power_of_two(),
52     );
53 
54     // 恢复页面属性
55     let vaddr = VirtAddr::new(vaddr.as_ptr() as usize);
56     let mut kernel_mapper = KernelMapper::lock();
57     let kernel_mapper = kernel_mapper.as_mut().unwrap();
58     let flusher = kernel_mapper
59         .remap(vaddr, kernel_page_flags(vaddr))
60         .expect("e1000e: remap failed");
61     flusher.flush();
62 
63     unsafe {
64         deallocate_page_frames(
65             PhysPageFrame::new(PhysAddr::new(paddr)),
66             page_count,
67             &mut page_manager_lock_irqsave(),
68         );
69     }
70     return 0;
71 }
72