-
Notifications
You must be signed in to change notification settings - Fork 437
Expand file tree
/
Copy pathpci.rs
More file actions
129 lines (121 loc) · 4.37 KB
/
Copy pathpci.rs
File metadata and controls
129 lines (121 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{prelude::*, AllDevices};
use axhal::mem::{phys_to_virt, PhysAddr};
use driver_pci::{
BarInfo, Cam, Command, DeviceFunction, HeaderType, MemoryBarType, PciRangeAllocator, PciRoot,
};
const PCI_BAR_NUM: u8 = 6;
fn config_pci_device(
root: &mut PciRoot,
bdf: DeviceFunction,
allocator: &mut Option<PciRangeAllocator>,
) -> DevResult {
let mut bar = 0;
while bar < PCI_BAR_NUM {
let info = root.bar_info(bdf, bar).unwrap();
if let BarInfo::Memory {
address_type,
address,
size,
..
} = info
{
// if the BAR address is not assigned, call the allocator and assign it.
if size > 0 && address == 0 {
let new_addr = allocator
.as_mut()
.expect("No memory ranges available for PCI BARs!")
.alloc(size as _)
.ok_or(DevError::NoMemory)?;
if address_type == MemoryBarType::Width32 {
root.set_bar_32(bdf, bar, new_addr as _);
} else if address_type == MemoryBarType::Width64 {
root.set_bar_64(bdf, bar, new_addr);
}
}
}
// read the BAR info again after assignment.
let info = root.bar_info(bdf, bar).unwrap();
match info {
BarInfo::IO { address, size } => {
if address > 0 && size > 0 {
debug!(" BAR {}: IO [{:#x}, {:#x})", bar, address, address + size);
}
}
BarInfo::Memory {
address_type,
prefetchable,
address,
size,
} => {
if address > 0 && size > 0 {
debug!(
" BAR {}: MEM [{:#x}, {:#x}){}{}",
bar,
address,
address + size as u64,
if address_type == MemoryBarType::Width64 {
" 64bit"
} else {
""
},
if prefetchable { " pref" } else { "" },
);
}
}
}
bar += 1;
if info.takes_two_entries() {
bar += 1;
}
}
// Enable the device.
let (_status, cmd) = root.get_status_command(bdf);
root.set_command(
bdf,
cmd | Command::IO_SPACE | Command::MEMORY_SPACE | Command::BUS_MASTER,
);
Ok(())
}
impl AllDevices {
pub(crate) fn probe_bus_devices(&mut self) {
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86_64")] {
let pci_ecam_base = PhysAddr::from(axhal::get_ecam_address().unwrap() as usize);
} else {
let pci_ecam_base = axconfig::PCI_ECAM_BASE.into();
}
}
let base_vaddr = phys_to_virt(pci_ecam_base);
let mut root = unsafe { PciRoot::new(base_vaddr.as_mut_ptr(), Cam::Ecam) };
// PCI 32-bit MMIO space
let mut allocator = axconfig::PCI_RANGES
.get(1)
.map(|range| PciRangeAllocator::new(range.0 as u64, range.1 as u64));
for bus in 0..=axconfig::PCI_BUS_END as u8 {
for (bdf, dev_info) in root.enumerate_bus(bus) {
debug!("PCI {}: {}", bdf, dev_info);
if dev_info.header_type != HeaderType::Standard {
continue;
}
match config_pci_device(&mut root, bdf, &mut allocator) {
Ok(_) => for_each_drivers!(type Driver, {
if let Some(dev) = Driver::probe_pci(&mut root, bdf, &dev_info) {
info!(
"registered a new {:?} device at {}: {:?}",
dev.device_type(),
bdf,
dev.device_name(),
);
self.add_device(dev);
continue; // skip to the next device
}
}),
Err(e) => warn!(
"failed to enable PCI device at {}({}): {:?}",
bdf, dev_info, e
),
}
}
}
}
}