Skip to main content

rdif_pcie/
lib.rs

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