summaryrefslogtreecommitdiffstats
path: root/rsnix/src/pci.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--rsnix/src/pci.rs33
1 files changed, 33 insertions, 0 deletions
diff --git a/rsnix/src/pci.rs b/rsnix/src/pci.rs
index 2d201f3..efdbc01 100644
--- a/rsnix/src/pci.rs
+++ b/rsnix/src/pci.rs
@@ -57,6 +57,39 @@ pub fn config_read(bus: u8, device: u8, func: u8, reg: u8) -> u32 {
57 inl(CONFIG_DATA) 57 inl(CONFIG_DATA)
58} 58}
59 59
60/// Write a dword to a device's config space (`reg` must be dword-aligned).
61pub fn config_write(bus: u8, device: u8, func: u8, reg: u8, val: u32) {
62 let addr = 0x8000_0000
63 | ((bus as u32) << 16)
64 | ((device as u32) << 11)
65 | ((func as u32) << 8)
66 | ((reg as u32) & 0xFC);
67 outl(CONFIG_ADDRESS, addr);
68 outl(CONFIG_DATA, val)
69}
70
71/// Read a memory BAR (index 0-5) as a 64-bit address, handling 32/64-bit
72/// BARs. Returns None for I/O BARs or invalid values.
73pub fn bar64(bus: u8, device: u8, func: u8, bar_index: u8) -> Option<u64> {
74 let reg_off = 0x10 + bar_index * 4;
75 let lo = config_read(bus, device, func, reg_off);
76 if lo & 1 == 1 {
77 return None; // I/O BAR
78 }
79 let kind = (lo >> 1) & 0x3;
80 let hi = if kind == 2 {
81 config_read(bus, device, func, reg_off + 4)
82 } else {
83 0
84 };
85 let base = ((hi as u64) << 32) | (lo as u64 & 0xFFFF_FFF0);
86 if base == 0 {
87 None
88 } else {
89 Some(base)
90 }
91}
92
60/// Enumerate every device/function present on all buses. 93/// Enumerate every device/function present on all buses.
61pub fn probe() -> alloc::vec::Vec<DeviceInfo> { 94pub fn probe() -> alloc::vec::Vec<DeviceInfo> {
62 let mut out = alloc::vec::Vec::new(); 95 let mut out = alloc::vec::Vec::new();