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
65impl PcieController {
66    pub fn new(chip: impl Interface) -> Self {
67        Self {
68            chip: Arc::new(ChipRaw::new(chip)),
69            bar_allocator: None,
70        }
71    }
72    pub fn typed_ref<T: Interface>(&self) -> Option<&T> {
73        self.raw_any()?.downcast_ref()
74    }
75    pub fn typed_mut<T: Interface>(&mut self) -> Option<&mut T> {
76        self.raw_any_mut()?.downcast_mut()
77    }
78
79    fn as_mut(&mut self) -> &mut dyn Interface {
80        unsafe { &mut *self.chip.0.get() }.as_mut()
81    }
82
83    pub fn config_access(&mut self, address: PciAddress) -> ConfigAccess {
84        ConfigAccess {
85            address,
86            chip: self.chip.clone(),
87        }
88    }
89
90    pub fn set_mem32(&mut self, space: PciMem32, perfetchable: bool) {
91        let al = self.bar_allocator.get_or_insert_default();
92        al.set_mem32(space, perfetchable).unwrap();
93    }
94
95    pub fn set_mem64(&mut self, space: PciMem64, perfetchable: bool) {
96        let al = self.bar_allocator.get_or_insert_default();
97        al.set_mem64(space, perfetchable).unwrap();
98    }
99}
100
101impl ConfigRegionAccess for PcieController {
102    unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
103        unsafe { (*self.chip.0.get()).read(address, offset) }
104    }
105
106    unsafe fn write(&self, address: PciAddress, offset: u16, value: u32) {
107        unsafe { (*self.chip.0.get()).write(address, offset, value) }
108    }
109}
110
111pub struct ConfigAccess {
112    address: PciAddress,
113    chip: Arc<ChipRaw>,
114}
115
116impl ConfigRegionAccess for ConfigAccess {
117    unsafe fn read(&self, address: PciAddress, offset: u16) -> u32 {
118        assert!(address == self.address);
119        unsafe { (*self.chip.0.get()).read(self.address, offset) }
120    }
121
122    unsafe fn write(&self, address: PciAddress, offset: u16, value: u32) {
123        assert!(address == self.address);
124        unsafe { (*self.chip.0.get()).write(self.address, offset, value) }
125    }
126}
127
128struct ChipRaw(UnsafeCell<Box<dyn Interface>>);
129
130unsafe impl Send for ChipRaw {}
131unsafe impl Sync for ChipRaw {}
132
133impl ChipRaw {
134    fn new(chip: impl Interface) -> Self {
135        Self(UnsafeCell::new(Box::new(chip)))
136    }
137}