dma.rs 2.3 KB

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