nvme/hosted/memory/
mod.rs

1use crate::ds::{cmd::PrpListOrBuffer, queue::subentry::Dptr, Address};
2
3pub struct VirtualRegion<P: PhysicalPageCollection> {
4    virt: *mut u8,
5    _cache_type: CacheType,
6    phys_page_list: P,
7    len: usize,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
11pub enum PrpMode {
12    Single,
13    Double,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
17pub enum DptrMode {
18    Prp(PrpMode),
19    Sgl,
20}
21
22pub trait PhysicalPageCollection {
23    type DmaType;
24    fn get_prp_list_or_buffer(
25        &mut self,
26        mode: PrpMode,
27        dma: Self::DmaType,
28    ) -> Option<PrpListOrBuffer>;
29
30    fn get_dptr(&mut self, mode: DptrMode, dma: Self::DmaType) -> Option<Dptr> {
31        if let DptrMode::Prp(prp_mode) = mode {
32            let prp = self.get_prp_list_or_buffer(prp_mode, dma)?;
33            match prp {
34                PrpListOrBuffer::PrpList(address) => Some(Dptr::Prp(address, 0)),
35                PrpListOrBuffer::Buffer(address) => Some(Dptr::Prp(address, 0)),
36                PrpListOrBuffer::PrpFirstAndList(first, list) => Some(Dptr::Prp(first, list)),
37            }
38        } else {
39            todo!()
40        }
41    }
42}
43
44pub enum CacheType {
45    WriteBack,
46    WriteThrough,
47    Uncacheable,
48}
49
50impl PrpListOrBuffer {
51    pub fn address(&self) -> Address {
52        match self {
53            PrpListOrBuffer::PrpList(a) => *a,
54            PrpListOrBuffer::PrpFirstAndList(_, _) => panic!("cannot get single address"),
55            PrpListOrBuffer::Buffer(a) => *a,
56        }
57    }
58
59    pub fn is_list(&self) -> bool {
60        match self {
61            PrpListOrBuffer::PrpList(_) => true,
62            PrpListOrBuffer::PrpFirstAndList(_, _) => true,
63            PrpListOrBuffer::Buffer(_) => false,
64        }
65    }
66}
67
68impl<P: PhysicalPageCollection> VirtualRegion<P> {
69    pub fn len(&self) -> usize {
70        self.len
71    }
72
73    pub unsafe fn new(
74        virt: *mut u8,
75        len: usize,
76        _cache_type: CacheType,
77        phys_page_list: P,
78    ) -> Self {
79        Self {
80            len,
81            virt,
82            _cache_type,
83            phys_page_list,
84        }
85    }
86
87    pub fn base<T>(&self) -> *const T {
88        self.virt as *const T
89    }
90
91    pub fn base_mut<T>(&mut self) -> *mut T {
92        self.virt as *mut T
93    }
94
95    pub fn get_prp_list_or_buffer<D>(
96        &mut self,
97        mode: PrpMode,
98        dma: P::DmaType,
99    ) -> Option<PrpListOrBuffer> {
100        self.phys_page_list.get_prp_list_or_buffer(mode, dma)
101    }
102
103    pub fn get_dptr(&mut self, mode: DptrMode, dma: P::DmaType) -> Option<Dptr> {
104        self.phys_page_list.get_dptr(mode, dma)
105    }
106}