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 }
43
44pub trait Interface: DriverGeneric {
45 fn read(&mut self, address: PciAddress, offset: u16) -> u32;
51
52 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}