rdif_pcie/
lib.rs

1#![no_std]
2
3extern crate alloc;
4
5use core::cell::UnsafeCell;
6
7use alloc::{boxed::Box, sync::Arc};
8use pci_types::ConfigRegionAccess;
9pub use pci_types::PciAddress;
10pub use rdif_base::{DriverGeneric, KError};
11
12mod addr_alloc;
13mod bar_alloc;
14
15pub use bar_alloc::SimpleBarAllocator;
16
17#[derive(Debug, Clone, Copy)]
18pub struct PciMem32 {
19    pub address: u32,
20    pub size: u32,
21}
22
23#[derive(Debug, Clone, Copy)]
24pub struct PciMem64 {
25    pub address: u64,
26    pub size: u64,
27}
28
29impl rdif_base::DriverGeneric for PcieController {
30    fn open(&mut self) -> Result<(), rdif_base::KError> {
31        self.as_mut().open()
32    }
33    fn close(&mut self) -> Result<(), rdif_base::KError> {
34        self.as_mut().close()
35    }
36    // fn raw_any(&self) -> Option<&dyn core::any::Any> {
37    //     Some(self.chip.as_mut() as &dyn core::any::Any)
38    // }
39    // fn raw_any_mut(&mut self) -> Option<&mut dyn core::any::Any> {
40    //     Some(self.chip.as_mut() as &mut dyn core::any::Any)
41    // }
42}
43
44pub trait Interface: DriverGeneric {
45    /// Performs a PCI read at `address` with `offset`.
46    ///
47    /// # Safety
48    ///
49    /// `address` and `offset` must be valid for PCI reads.
50    fn read(&mut self, address: PciAddress, offset: u16) -> u32;
51
52    /// Performs a PCI write at `address` with `offset`.
53    ///
54    /// # Safety
55    ///
56    /// `address` and `offset` must be valid for PCI writes.
57    fn write(&mut self, address: PciAddress, offset: u16, value: u32);
58}
59
60pub struct PcieController {
61    chip: Arc<ChipRaw>,
62    pub bar_allocator: Option<SimpleBarAllocator>,
63}
64
65pub struct PcieSpaceSet {
66    pub pci_space32_perfetch: Option<PciMem32>,
67    pub pci_space32: Option<PciMem32>,
68    pub pci_space64_perfetch: Option<PciMem64>,
69    pub pci_space64: Option<PciMem64>,
70}
71
72impl PcieController {
73    pub fn new(chip: impl Interface) -> Self {
74        Self {
75            chip: Arc::new(ChipRaw::new(chip)),
76            bar_allocator: None,
77        }
78    }
79    pub fn typed_ref<T: Interface>(&self) -> Option<&T> {
80        self.raw_any()?.downcast_ref()
81    }
82    pub fn typed_mut<T: Interface>(&mut self) -> Option<&mut T> {
83        self.raw_any_mut()?.downcast_mut()
84    }
85
86    fn as_mut(&mut self) -> &mut dyn Interface {
87        unsafe { &mut *self.chip.0.get() }.as_mut()
88    }
89
90    pub fn config_access(&mut self, address: PciAddress) -> ConfigAccess {
91        ConfigAccess {
92            address,
93            chip: self.chip.clone(),
94        }
95    }
96
97    pub fn set_mem32(&mut self, space: PciMem32, perfetchable: bool) {
98        let al = self.bar_allocator.get_or_insert_default();
99        al.set_mem32(space, perfetchable).unwrap();
100    }
101
102    pub fn set_mem64(&mut self, space: PciMem64, perfetchable: bool) {
103        let al = self.bar_allocator.get_or_insert_default();
104        al.set_mem64(space, perfetchable).unwrap();
105    }
106}
107
108impl ConfigRegionAccess for PcieController {
109    unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
110        unsafe { (*self.chip.0.get()).read(address, offset) }
111    }
112
113    unsafe fn write(&self, address: PciAddress, offset: u16, value: u32) {
114        unsafe { (*self.chip.0.get()).write(address, offset, value) }
115    }
116}
117
118pub struct ConfigAccess {
119    address: PciAddress,
120    chip: Arc<ChipRaw>,
121}
122
123impl ConfigRegionAccess for ConfigAccess {
124    unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
125        assert!(address == self.address);
126        unsafe { (*self.chip.0.get()).read(self.address, offset) }
127    }
128
129    unsafe fn write(&self, address: PciAddress, offset: u16, value: u32) {
130        assert!(address == self.address);
131        unsafe { (*self.chip.0.get()).write(self.address, offset, value) }
132    }
133}
134
135struct ChipRaw(UnsafeCell<Box<dyn Interface>>);
136
137unsafe impl Send for ChipRaw {}
138unsafe impl Sync for ChipRaw {}
139
140impl ChipRaw {
141    fn new(chip: impl Interface) -> Self {
142        Self(UnsafeCell::new(Box::new(chip)))
143    }
144}