Nothing to see here, move along meow
1use crate::mem::addr;
2use crate::mem::phys::BitmapFrameAllocator;
3use crate::mem::virt;
4use x86_64::structures::paging::OffsetPageTable;
5
6#[derive(Debug, Clone, Copy)]
7pub struct EcamAddress {
8 pub ecam_base: u64,
9 pub bus: u8,
10 device: u8,
11 function: u8,
12}
13
14impl EcamAddress {
15 pub fn new(ecam_base: u64, bus: u8, device: u8, function: u8) -> Option<Self> {
16 match device < 32 && function < 8 {
17 true => Some(Self {
18 ecam_base,
19 bus,
20 device,
21 function,
22 }),
23 false => None,
24 }
25 }
26
27 pub fn device(self) -> u8 {
28 self.device
29 }
30
31 pub fn function(self) -> u8 {
32 self.function
33 }
34
35 fn phys_base(self) -> u64 {
36 self.ecam_base
37 + ((self.bus as u64) << 20)
38 + ((self.device as u64) << 15)
39 + ((self.function as u64) << 12)
40 }
41}
42
43pub fn ensure_ecam_mapped(
44 addr: EcamAddress,
45 mapper: &mut OffsetPageTable,
46 allocator: &mut BitmapFrameAllocator,
47 hhdm_offset: u64,
48) -> Result<(), crate::error::KernelError> {
49 let phys = addr.phys_base();
50 virt::map_mmio(mapper, allocator, phys, hhdm_offset)
51}
52
53pub fn read_config_u16(addr: EcamAddress, offset: u16) -> u16 {
54 assert!(offset < 0xFFF && offset & 0x1 == 0);
55 let phys = addr.phys_base() + (offset as u64);
56 let virt = addr::phys_to_virt(x86_64::PhysAddr::new(phys));
57 unsafe { core::ptr::read_volatile(virt.as_ptr::<u16>()) }
58}
59
60pub fn read_config_u32(addr: EcamAddress, offset: u16) -> u32 {
61 assert!(offset <= 0xFFC && offset & 0x3 == 0);
62 let phys = addr.phys_base() + (offset as u64);
63 let virt = addr::phys_to_virt(x86_64::PhysAddr::new(phys));
64 unsafe { core::ptr::read_volatile(virt.as_ptr::<u32>()) }
65}
66
67pub fn write_config_u16(addr: EcamAddress, offset: u16, value: u16) {
68 assert!(offset < 0xFFF && offset & 0x1 == 0);
69 let phys = addr.phys_base() + (offset as u64);
70 let virt = addr::phys_to_virt(x86_64::PhysAddr::new(phys));
71 unsafe { core::ptr::write_volatile(virt.as_mut_ptr::<u16>(), value) }
72}
73
74pub fn write_config_u32(addr: EcamAddress, offset: u16, value: u32) {
75 assert!(offset <= 0xFFC && offset & 0x3 == 0);
76 let phys = addr.phys_base() + (offset as u64);
77 let virt = addr::phys_to_virt(x86_64::PhysAddr::new(phys));
78 unsafe { core::ptr::write_volatile(virt.as_mut_ptr::<u32>(), value) }
79}