1use alloc::{collections::BTreeMap, format, string::String, vec::Vec};
6use core::mem;
7
8use crate::{
9 error::KernelError,
10 services::driver_framework::{Bus, DeviceClass, DeviceId, DeviceInfo, DeviceStatus},
11 sync::once_lock::OnceLock,
12};
13
14#[repr(u16)]
16#[allow(dead_code)] pub enum PciConfigRegister {
18 VendorId = 0x00,
19 DeviceId = 0x02,
20 Command = 0x04,
21 Status = 0x06,
22 RevisionId = 0x08,
23 ProgIf = 0x09,
24 Subclass = 0x0A,
25 ClassCode = 0x0B,
26 CacheLineSize = 0x0C,
27 LatencyTimer = 0x0D,
28 HeaderType = 0x0E,
29 Bist = 0x0F,
30 Bar0 = 0x10,
31 Bar1 = 0x14,
32 Bar2 = 0x18,
33 Bar3 = 0x1C,
34 Bar4 = 0x20,
35 Bar5 = 0x24,
36 CardbusCisPointer = 0x28,
37 SubsystemVendorId = 0x2C,
38 SubsystemId = 0x2E,
39 ExpansionRomBase = 0x30,
40 CapabilitiesPointer = 0x34,
41 InterruptLine = 0x3C,
42 InterruptPin = 0x3D,
43 MinGrant = 0x3E,
44 MaxLatency = 0x3F,
45}
46
47#[allow(dead_code)] pub mod class_codes {
50 pub const UNCLASSIFIED: u8 = 0x00;
51 pub const MASS_STORAGE: u8 = 0x01;
52 pub const NETWORK: u8 = 0x02;
53 pub const DISPLAY: u8 = 0x03;
54 pub const MULTIMEDIA: u8 = 0x04;
55 pub const MEMORY: u8 = 0x05;
56 pub const BRIDGE: u8 = 0x06;
57 pub const COMMUNICATION: u8 = 0x07;
58 pub const SYSTEM: u8 = 0x08;
59 pub const INPUT: u8 = 0x09;
60 pub const DOCKING: u8 = 0x0A;
61 pub const PROCESSOR: u8 = 0x0B;
62 pub const SERIAL_BUS: u8 = 0x0C;
63 pub const WIRELESS: u8 = 0x0D;
64 pub const INTELLIGENT: u8 = 0x0E;
65 pub const SATELLITE: u8 = 0x0F;
66 pub const ENCRYPTION: u8 = 0x10;
67 pub const DATA_ACQUISITION: u8 = 0x11;
68 pub const COPROCESSOR: u8 = 0xFF;
69}
70
71#[allow(dead_code)] pub mod command_flags {
74 pub const IO_SPACE: u16 = 1 << 0;
75 pub const MEMORY_SPACE: u16 = 1 << 1;
76 pub const BUS_MASTER: u16 = 1 << 2;
77 pub const SPECIAL_CYCLES: u16 = 1 << 3;
78 pub const MEMORY_WRITE_INVALIDATE: u16 = 1 << 4;
79 pub const VGA_PALETTE_SNOOP: u16 = 1 << 5;
80 pub const PARITY_ERROR: u16 = 1 << 6;
81 pub const STEPPING: u16 = 1 << 7;
82 pub const SERR: u16 = 1 << 8;
83 pub const FAST_BACK_TO_BACK: u16 = 1 << 9;
84 pub const INTERRUPT_DISABLE: u16 = 1 << 10;
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
89pub struct PciLocation {
90 pub bus: u8,
91 pub device: u8,
92 pub function: u8,
93}
94
95impl PciLocation {
96 pub fn new(bus: u8, device: u8, function: u8) -> Self {
97 Self {
98 bus,
99 device,
100 function,
101 }
102 }
103
104 pub fn to_config_address(&self) -> u32 {
106 0x80000000
107 | ((self.bus as u32) << 16)
108 | ((self.device as u32) << 11)
109 | ((self.function as u32) << 8)
110 }
111}
112
113#[derive(Debug, Clone)]
115pub enum PciBar {
116 Memory {
117 address: u64,
118 size: u64,
119 prefetchable: bool,
120 is_64bit: bool,
121 },
122 Io {
123 address: u32,
124 size: u32,
125 },
126 None,
127}
128
129impl PciBar {
130 pub fn get_memory_address(&self) -> Option<u64> {
132 match self {
133 PciBar::Memory { address, .. } => Some(*address),
134 _ => None,
135 }
136 }
137
138 pub fn get_io_address(&self) -> Option<u32> {
140 match self {
141 PciBar::Io { address, .. } => Some(*address),
142 _ => None,
143 }
144 }
145
146 pub fn is_memory(&self) -> bool {
148 matches!(self, PciBar::Memory { .. })
149 }
150
151 pub fn is_io(&self) -> bool {
153 matches!(self, PciBar::Io { .. })
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct MsiCapability {
160 pub cap_offset: u16,
162 pub is_64bit: bool,
164 pub per_vector_mask: bool,
166 pub max_vectors_log2: u8,
168}
169
170#[derive(Debug, Clone)]
172pub struct MsixCapability {
173 pub cap_offset: u16,
175 pub table_size: u16,
177 pub table_bar: u8,
179 pub table_offset: u32,
181 pub pba_bar: u8,
183 pub pba_offset: u32,
185}
186
187#[derive(Debug, Clone)]
189pub struct PciDevice {
190 pub location: PciLocation,
191 pub vendor_id: u16,
192 pub device_id: u16,
193 pub class_code: u8,
194 pub subclass: u8,
195 pub prog_if: u8,
196 pub revision: u8,
197 pub header_type: u8,
198 pub interrupt_line: u8,
199 pub interrupt_pin: u8,
200 pub bars: Vec<PciBar>,
201 pub enabled: bool,
202 pub msi: Option<MsiCapability>,
204 pub msix: Option<MsixCapability>,
206 pub secondary_bus: Option<u8>,
208}
209
210impl PciDevice {
211 pub fn new(location: PciLocation) -> Self {
213 Self {
214 location,
215 vendor_id: 0,
216 device_id: 0,
217 class_code: 0,
218 subclass: 0,
219 prog_if: 0,
220 revision: 0,
221 header_type: 0,
222 interrupt_line: 0,
223 interrupt_pin: 0,
224 bars: Vec::new(),
225 enabled: false,
226 msi: None,
227 msix: None,
228 secondary_bus: None,
229 }
230 }
231
232 pub fn get_device_class(&self) -> DeviceClass {
234 match self.class_code {
235 class_codes::MASS_STORAGE => DeviceClass::Storage,
236 class_codes::NETWORK => DeviceClass::Network,
237 class_codes::DISPLAY => DeviceClass::Display,
238 class_codes::MULTIMEDIA => DeviceClass::Audio,
239 class_codes::SERIAL_BUS => {
240 match self.subclass {
241 0x03 => DeviceClass::USB, _ => DeviceClass::Other,
243 }
244 }
245 class_codes::BRIDGE => DeviceClass::PCI,
246 _ => DeviceClass::Other,
247 }
248 }
249
250 pub fn is_multifunction(&self) -> bool {
252 self.header_type & 0x80 != 0
253 }
254}
255
256pub struct PciBus {
258 devices: spin::RwLock<BTreeMap<PciLocation, PciDevice>>,
260
261 enumerated: core::sync::atomic::AtomicBool,
263}
264
265impl Default for PciBus {
266 fn default() -> Self {
267 Self::new()
268 }
269}
270
271impl PciBus {
272 pub fn new() -> Self {
274 Self {
275 devices: spin::RwLock::new(BTreeMap::new()),
276 enumerated: core::sync::atomic::AtomicBool::new(false),
277 }
278 }
279
280 #[allow(unused_assignments)]
282 pub fn enumerate_devices(&self) -> Result<(), KernelError> {
283 if self.enumerated.load(core::sync::atomic::Ordering::Acquire) {
284 return Ok(());
285 }
286
287 crate::println!("[PCI] Enumerating PCI devices...");
288 #[allow(unused_variables)]
289 let mut device_count = 0;
290
291 for bus in 0..=255 {
293 for device in 0..32 {
294 let location = PciLocation::new(bus, device, 0);
296 if let Some(mut pci_device) = self.probe_device(location) {
297 self.read_device_config(&mut pci_device);
298
299 crate::println!(
300 "[PCI] Found device at {}:{}:{} - {:04x}:{:04x} (class {:02x})",
301 bus,
302 device,
303 0,
304 pci_device.vendor_id,
305 pci_device.device_id,
306 pci_device.class_code
307 );
308
309 let is_multifunction = pci_device.is_multifunction();
310 let is_bridge = pci_device.secondary_bus.is_some();
311 let secondary_bus = pci_device.secondary_bus;
312 self.devices.write().insert(location, pci_device);
313 device_count += 1;
314
315 if is_bridge {
317 if let Some(sec_bus) = secondary_bus {
318 crate::println!(
319 "[PCI] Scanning secondary bus {} behind bridge {}:{}:0",
320 sec_bus,
321 bus,
322 device
323 );
324 let _ = self.scan_bridge(sec_bus, &mut device_count);
325 }
326 }
327
328 if is_multifunction {
330 for function in 1..8 {
331 let func_location = PciLocation::new(bus, device, function);
332 if let Some(mut func_device) = self.probe_device(func_location) {
333 self.read_device_config(&mut func_device);
334
335 crate::println!(
336 "[PCI] Found device at {}:{}:{} - {:04x}:{:04x} (class {:02x})",
337 bus,
338 device,
339 function,
340 func_device.vendor_id,
341 func_device.device_id,
342 func_device.class_code
343 );
344
345 self.devices.write().insert(func_location, func_device);
346 device_count += 1;
347 }
348 }
349 }
350 }
351 }
352 }
353
354 self.enumerated
355 .store(true, core::sync::atomic::Ordering::Release);
356 crate::println!("[PCI] Enumeration complete: {} devices found", device_count);
357
358 Ok(())
359 }
360
361 fn probe_device(&self, location: PciLocation) -> Option<PciDevice> {
363 let vendor_id = self.read_config_word(location, PciConfigRegister::VendorId);
364
365 if vendor_id == 0xFFFF {
367 return None;
368 }
369
370 let mut device = PciDevice::new(location);
371 device.vendor_id = vendor_id;
372 device.device_id = self.read_config_word(location, PciConfigRegister::DeviceId);
373
374 Some(device)
375 }
376
377 fn read_device_config(&self, device: &mut PciDevice) {
379 let location = device.location;
380
381 device.class_code = self.read_config_byte(location, PciConfigRegister::ClassCode);
382 device.subclass = self.read_config_byte(location, PciConfigRegister::Subclass);
383 device.prog_if = self.read_config_byte(location, PciConfigRegister::ProgIf);
384 device.revision = self.read_config_byte(location, PciConfigRegister::RevisionId);
385 device.header_type = self.read_config_byte(location, PciConfigRegister::HeaderType);
386 device.interrupt_line = self.read_config_byte(location, PciConfigRegister::InterruptLine);
387 device.interrupt_pin = self.read_config_byte(location, PciConfigRegister::InterruptPin);
388
389 device.bars = self.read_bars(location, device.header_type & 0x7F);
391
392 if device.header_type & 0x7F == 1 {
394 let buses = self.read_config_dword(location, 0x18);
396 device.secondary_bus = Some(((buses >> 8) & 0xFF) as u8);
397 }
398
399 let status = self.read_config_dword(location, 0x04) >> 16;
401 if status & (1 << 4) != 0 {
402 self.parse_capabilities(device);
404 }
405 }
406
407 fn parse_capabilities(&self, device: &mut PciDevice) {
409 let location = device.location;
410 let mut cap_ptr = (self
412 .read_config_dword(location, PciConfigRegister::CapabilitiesPointer as u16)
413 & 0xFF) as u16;
414
415 let mut iterations = 0;
417 while cap_ptr != 0 && cap_ptr != 0xFF && iterations < 48 {
418 iterations += 1;
419 let cap_header = self.read_config_dword(location, cap_ptr & !3);
420 let offset_in_dword = (cap_ptr & 3) * 8;
421 let cap_id = ((cap_header >> offset_in_dword) & 0xFF) as u8;
422 let next_ptr = ((cap_header >> (offset_in_dword + 8)) & 0xFF) as u16;
423
424 match cap_id {
425 0x05 => {
426 let msg_ctrl = self.read_config_dword(location, (cap_ptr + 2) & !3);
428 let msg_ctrl_val = ((msg_ctrl >> (((cap_ptr + 2) & 3) * 8)) & 0xFFFF) as u16;
429 device.msi = Some(MsiCapability {
430 cap_offset: cap_ptr,
431 is_64bit: msg_ctrl_val & (1 << 7) != 0,
432 per_vector_mask: msg_ctrl_val & (1 << 8) != 0,
433 max_vectors_log2: ((msg_ctrl_val >> 1) & 0x7) as u8,
434 });
435 }
436 0x11 => {
437 let msg_ctrl = self.read_config_dword(location, (cap_ptr + 2) & !3);
439 let msg_ctrl_val = ((msg_ctrl >> (((cap_ptr + 2) & 3) * 8)) & 0xFFFF) as u16;
440 let table_offset_dword = self.read_config_dword(location, cap_ptr + 4);
441 let pba_offset_dword = self.read_config_dword(location, cap_ptr + 8);
442
443 device.msix = Some(MsixCapability {
444 cap_offset: cap_ptr,
445 table_size: msg_ctrl_val & 0x7FF,
446 table_bar: (table_offset_dword & 0x7) as u8,
447 table_offset: table_offset_dword & !0x7,
448 pba_bar: (pba_offset_dword & 0x7) as u8,
449 pba_offset: pba_offset_dword & !0x7,
450 });
451 }
452 _ => {} }
454
455 cap_ptr = next_ptr;
456 }
457 }
458
459 fn scan_bridge(&self, secondary_bus: u8, device_count: &mut usize) -> Result<(), KernelError> {
461 for device in 0..32 {
462 let location = PciLocation::new(secondary_bus, device, 0);
463 if let Some(mut pci_device) = self.probe_device(location) {
464 self.read_device_config(&mut pci_device);
465
466 crate::println!(
467 "[PCI] Bridge device at {}:{}:{} - {:04x}:{:04x} (class {:02x})",
468 secondary_bus,
469 device,
470 0,
471 pci_device.vendor_id,
472 pci_device.device_id,
473 pci_device.class_code
474 );
475
476 let is_multifunction = pci_device.is_multifunction();
477 let is_bridge = pci_device.secondary_bus.is_some();
478 let sub_bus = pci_device.secondary_bus;
479 self.devices.write().insert(location, pci_device);
480 *device_count += 1;
481
482 if is_bridge {
484 if let Some(sub) = sub_bus {
485 self.scan_bridge(sub, device_count)?;
486 }
487 }
488
489 if is_multifunction {
491 for function in 1..8 {
492 let func_location = PciLocation::new(secondary_bus, device, function);
493 if let Some(mut func_device) = self.probe_device(func_location) {
494 self.read_device_config(&mut func_device);
495 self.devices.write().insert(func_location, func_device);
496 *device_count += 1;
497 }
498 }
499 }
500 }
501 }
502 Ok(())
503 }
504
505 fn read_bars(&self, location: PciLocation, header_type: u8) -> Vec<PciBar> {
507 let mut bars = Vec::new();
508
509 let bar_count = if header_type == 0 { 6 } else { 2 };
511
512 let mut bar_index = 0;
513 while bar_index < bar_count {
514 let bar_offset = PciConfigRegister::Bar0 as u16 + (bar_index * 4) as u16;
515 let bar_value = self.read_config_dword(location, bar_offset);
516
517 if bar_value == 0 {
518 bars.push(PciBar::None);
519 bar_index += 1;
520 continue;
521 }
522
523 if bar_value & 1 == 0 {
524 let is_64bit = (bar_value >> 1) & 3 == 2;
526 let prefetchable = (bar_value >> 3) & 1 != 0;
527
528 self.write_config_dword(location, bar_offset, 0xFFFFFFFF);
530 let size_mask = self.read_config_dword(location, bar_offset);
531 self.write_config_dword(location, bar_offset, bar_value);
532
533 let size = (!size_mask + 1) & 0xFFFFFFF0;
534 let mut address = (bar_value & 0xFFFFFFF0) as u64;
535
536 if is_64bit && bar_index + 1 < bar_count {
537 let upper_bar_offset = bar_offset + 4;
539 let upper_value = self.read_config_dword(location, upper_bar_offset);
540 address |= (upper_value as u64) << 32;
541
542 bars.push(PciBar::Memory {
543 address,
544 size: size as u64,
545 prefetchable,
546 is_64bit: true,
547 });
548
549 bars.push(PciBar::None); bar_index += 2;
551 } else {
552 bars.push(PciBar::Memory {
553 address,
554 size: size as u64,
555 prefetchable,
556 is_64bit: false,
557 });
558 bar_index += 1;
559 }
560 } else {
561 self.write_config_dword(location, bar_offset, 0xFFFFFFFF);
563 let size_mask = self.read_config_dword(location, bar_offset);
564 self.write_config_dword(location, bar_offset, bar_value);
565
566 let size = (!size_mask + 1) & 0xFFFFFFFC;
567 let address = bar_value & 0xFFFFFFFC;
568
569 bars.push(PciBar::Io { address, size });
570 bar_index += 1;
571 }
572 }
573
574 bars
575 }
576
577 fn read_config_byte(&self, location: PciLocation, register: PciConfigRegister) -> u8 {
579 let offset = register as u16;
580 let dword = self.read_config_dword(location, offset & !3);
581 ((dword >> ((offset & 3) * 8)) & 0xFF) as u8
582 }
583
584 fn read_config_word(&self, location: PciLocation, register: PciConfigRegister) -> u16 {
586 let offset = register as u16;
587 let dword = self.read_config_dword(location, offset & !3);
588 ((dword >> ((offset & 3) * 8)) & 0xFFFF) as u16
589 }
590
591 fn read_config_dword(&self, location: PciLocation, offset: u16) -> u32 {
593 let address = location.to_config_address() | (offset as u32 & 0xFC);
594
595 unsafe {
600 crate::arch::outl(0xCF8, address);
602 crate::arch::inl(0xCFC)
604 }
605 }
606
607 fn write_config_dword(&self, location: PciLocation, offset: u16, value: u32) {
609 let address = location.to_config_address() | (offset as u32 & 0xFC);
610
611 unsafe {
615 crate::arch::outl(0xCF8, address);
617 crate::arch::outl(0xCFC, value);
619 }
620 }
621
622 pub fn get_device(&self, location: PciLocation) -> Option<PciDevice> {
624 self.devices.read().get(&location).cloned()
625 }
626
627 pub fn get_all_devices(&self) -> Vec<PciDevice> {
629 self.devices.read().values().cloned().collect()
630 }
631
632 pub fn find_devices_by_class(&self, class_code: u8) -> Vec<PciDevice> {
634 self.devices
635 .read()
636 .values()
637 .filter(|dev| dev.class_code == class_code)
638 .cloned()
639 .collect()
640 }
641
642 pub fn find_devices_by_id(&self, vendor_id: u16, device_id: u16) -> Vec<PciDevice> {
644 self.devices
645 .read()
646 .values()
647 .filter(|dev| dev.vendor_id == vendor_id && dev.device_id == device_id)
648 .cloned()
649 .collect()
650 }
651}
652
653impl Bus for PciBus {
654 fn name(&self) -> &str {
655 "pci"
656 }
657
658 fn scan(&mut self) -> Vec<DeviceInfo> {
659 self.enumerate_devices().unwrap_or_else(|_e| {
661 crate::println!("[PCI] Enumeration failed: {}", _e);
662 });
663
664 let devices = self.devices.read();
665 let mut device_infos = Vec::new();
666
667 for (location, pci_device) in devices.iter() {
668 let device_id = DeviceId {
669 vendor_id: pci_device.vendor_id,
670 device_id: pci_device.device_id,
671 class_code: pci_device.class_code,
672 subclass: pci_device.subclass,
673 prog_if: pci_device.prog_if,
674 revision: pci_device.revision,
675 };
676
677 let mut io_ports = Vec::new();
678 let mut memory_regions = Vec::new();
679
680 for bar in &pci_device.bars {
681 match bar {
682 PciBar::Memory { address, size, .. } => {
683 memory_regions.push((*address, *size));
684 }
685 PciBar::Io { address, size } => {
686 io_ports.push((*address as u16, (*address + *size) as u16));
687 }
688 PciBar::None => {}
689 }
690 }
691
692 let device_info = DeviceInfo {
693 id: ((location.bus as u64) << 16)
694 | ((location.device as u64) << 8)
695 | (location.function as u64),
696 name: format!(
697 "PCI Device {:04x}:{:04x}",
698 pci_device.vendor_id, pci_device.device_id
699 ),
700 class: pci_device.get_device_class(),
701 device_id: Some(device_id),
702 driver: None,
703 bus: String::from("pci"),
704 address: location.to_config_address() as u64,
705 irq: if pci_device.interrupt_line != 0xFF {
706 Some(pci_device.interrupt_line)
707 } else {
708 None
709 },
710 dma_channels: Vec::new(), io_ports,
712 memory_regions,
713 status: DeviceStatus::Uninitialized,
714 };
715
716 device_infos.push(device_info);
717 }
718
719 device_infos
720 }
721
722 fn read_config(&self, device: &DeviceInfo, offset: u16, size: u8) -> Result<u32, KernelError> {
723 let address = device.address as u32;
725 let bus = ((address >> 16) & 0xFF) as u8;
726 let dev = ((address >> 11) & 0x1F) as u8;
727 let func = ((address >> 8) & 0x07) as u8;
728 let location = PciLocation::new(bus, dev, func);
729
730 match size {
731 1 => Ok(self.read_config_byte(location, unsafe {
736 mem::transmute::<u16, PciConfigRegister>(offset)
737 }) as u32),
738 2 => Ok(self.read_config_word(location, unsafe {
740 mem::transmute::<u16, PciConfigRegister>(offset)
741 }) as u32),
742 4 => Ok(self.read_config_dword(location, offset)),
743 _ => Err(KernelError::InvalidArgument {
744 name: "size",
745 value: "must be 1, 2, or 4",
746 }),
747 }
748 }
749
750 fn write_config(
751 &mut self,
752 device: &DeviceInfo,
753 offset: u16,
754 value: u32,
755 size: u8,
756 ) -> Result<(), KernelError> {
757 let address = device.address as u32;
759 let bus = ((address >> 16) & 0xFF) as u8;
760 let dev = ((address >> 11) & 0x1F) as u8;
761 let func = ((address >> 8) & 0x07) as u8;
762 let location = PciLocation::new(bus, dev, func);
763
764 match size {
765 1 => {
766 let current = self.read_config_dword(location, offset & !3);
767 let shift = (offset & 3) * 8;
768 let mask = !(0xFF << shift);
769 let new_value = (current & mask) | ((value & 0xFF) << shift);
770 self.write_config_dword(location, offset & !3, new_value);
771 }
772 2 => {
773 let current = self.read_config_dword(location, offset & !3);
774 let shift = (offset & 3) * 8;
775 let mask = !(0xFFFF << shift);
776 let new_value = (current & mask) | ((value & 0xFFFF) << shift);
777 self.write_config_dword(location, offset & !3, new_value);
778 }
779 4 => self.write_config_dword(location, offset, value),
780 _ => {
781 return Err(KernelError::InvalidArgument {
782 name: "size",
783 value: "must be 1, 2, or 4",
784 })
785 }
786 }
787
788 Ok(())
789 }
790
791 fn enable_device(&mut self, device: &DeviceInfo) -> Result<(), KernelError> {
792 let current_command = self.read_config(device, PciConfigRegister::Command as u16, 2)?;
794 let new_command = current_command
795 | command_flags::IO_SPACE as u32
796 | command_flags::MEMORY_SPACE as u32
797 | command_flags::BUS_MASTER as u32;
798
799 self.write_config(device, PciConfigRegister::Command as u16, new_command, 2)?;
800
801 crate::println!("[PCI] Enabled device {}", device.name);
802 Ok(())
803 }
804
805 fn disable_device(&mut self, device: &DeviceInfo) -> Result<(), KernelError> {
806 let current_command = self.read_config(device, PciConfigRegister::Command as u16, 2)?;
808 let new_command = current_command
809 & !(command_flags::IO_SPACE as u32
810 | command_flags::MEMORY_SPACE as u32
811 | command_flags::BUS_MASTER as u32);
812
813 self.write_config(device, PciConfigRegister::Command as u16, new_command, 2)?;
814
815 crate::println!("[PCI] Disabled device {}", device.name);
816 Ok(())
817 }
818}
819
820static PCI_BUS: OnceLock<spin::Mutex<PciBus>> = OnceLock::new();
822
823pub fn init() {
825 let pci_bus = PciBus::new();
826 let _ = PCI_BUS.set(spin::Mutex::new(pci_bus));
827
828 let driver_framework = crate::services::driver_framework::get_driver_framework();
830
831 let bus_instance = PciBus::new();
834
835 if let Err(_e) = driver_framework.register_bus(alloc::boxed::Box::new(bus_instance)) {
836 crate::println!("[PCI] Failed to register PCI bus: {}", _e);
837 } else {
838 crate::println!("[PCI] PCI bus driver initialized");
839 }
840}
841
842pub fn is_pci_initialized() -> bool {
844 PCI_BUS.get().is_some()
845}
846
847pub fn get_pci_bus() -> &'static spin::Mutex<PciBus> {
849 PCI_BUS.get().expect("PCI bus not initialized")
850}
851
852pub fn probe_known_drivers() {
858 if !is_pci_initialized() {
859 return;
860 }
861 let devices = get_pci_bus().lock().get_all_devices();
862 for dev in &devices {
863 match (dev.vendor_id, dev.device_id) {
864 (0x1AF4, 0x1050) | (0x1AF4, 0x1040) => {
866 crate::println!(
867 " [pci] Probing VirtIO GPU ({:#06x}:{:#06x})",
868 dev.vendor_id,
869 dev.device_id
870 );
871 let _ = crate::drivers::virtio_gpu::init();
872 }
873 (0x1AF4, 0x1041) | (0x1AF4, 0x1000) => {
875 crate::println!(
876 " [pci] Probing VirtIO Net ({:#06x}:{:#06x})",
877 dev.vendor_id,
878 dev.device_id
879 );
880 let _ = crate::drivers::virtio_net::init();
881 }
882 (0x1AF4, 0x1059) => {
884 crate::println!(
885 " [pci] Probing VirtIO Sound ({:#06x}:{:#06x})",
886 dev.vendor_id,
887 dev.device_id
888 );
889 let _ = crate::audio::virtio_sound::init();
890 }
891 (0x1AF4, 0x1042) | (0x1AF4, 0x1001) => {
893 }
895 _ => {}
896 }
897 }
898}
899
900pub fn configure_msi(location: PciLocation, msi: &MsiCapability, vector: u8, dest_apic_id: u8) {
911 let bus = get_pci_bus().lock();
912
913 let msg_addr: u32 = 0xFEE00000 | ((dest_apic_id as u32) << 12);
916
917 let msg_data: u16 = vector as u16;
919
920 bus.write_config_dword(location, msi.cap_offset + 4, msg_addr);
922
923 if msi.is_64bit {
924 bus.write_config_dword(location, msi.cap_offset + 8, 0); let data_dword = bus.read_config_dword(location, (msi.cap_offset + 12) & !3);
927 let shift = ((msi.cap_offset + 12) & 3) * 8;
928 let masked = data_dword & !(0xFFFF << shift);
929 bus.write_config_dword(
930 location,
931 (msi.cap_offset + 12) & !3,
932 masked | ((msg_data as u32) << shift),
933 );
934 } else {
935 let data_dword = bus.read_config_dword(location, (msi.cap_offset + 8) & !3);
937 let shift = ((msi.cap_offset + 8) & 3) * 8;
938 let masked = data_dword & !(0xFFFF << shift);
939 bus.write_config_dword(
940 location,
941 (msi.cap_offset + 8) & !3,
942 masked | ((msg_data as u32) << shift),
943 );
944 }
945
946 let ctrl_dword = bus.read_config_dword(location, (msi.cap_offset + 2) & !3);
948 let ctrl_shift = ((msi.cap_offset + 2) & 3) * 8;
949 let enabled = ctrl_dword | (1 << ctrl_shift); bus.write_config_dword(location, (msi.cap_offset + 2) & !3, enabled);
951
952 crate::println!(
953 "[PCI] MSI configured for {:02x}:{:02x}.{}: vector={}, dest={}",
954 location.bus,
955 location.device,
956 location.function,
957 vector,
958 dest_apic_id
959 );
960}
961
962#[cfg(target_arch = "x86_64")]
971pub fn ecam_read_config(ecam_base: u64, bus: u8, device: u8, func: u8, offset: u16) -> Option<u32> {
972 if offset > 0xFFF {
973 return None;
974 }
975 let phys = ecam_base as usize
978 + ((bus as usize) << 20)
979 + ((device as usize) << 15)
980 + ((func as usize) << 12)
981 + (offset as usize & 0xFFC);
982
983 let virt = crate::arch::x86_64::msr::phys_to_virt(phys)?;
984
985 Some(unsafe { core::ptr::read_volatile(virt as *const u32) })
989}
990
991#[cfg(target_arch = "x86_64")]
993pub fn ecam_write_config(
994 ecam_base: u64,
995 bus: u8,
996 device: u8,
997 func: u8,
998 offset: u16,
999 value: u32,
1000) -> bool {
1001 if offset > 0xFFF {
1002 return false;
1003 }
1004 let phys = ecam_base as usize
1005 + ((bus as usize) << 20)
1006 + ((device as usize) << 15)
1007 + ((func as usize) << 12)
1008 + (offset as usize & 0xFFC);
1009
1010 if let Some(virt) = crate::arch::x86_64::msr::phys_to_virt(phys) {
1011 unsafe {
1013 core::ptr::write_volatile(virt as *mut u32, value);
1014 }
1015 true
1016 } else {
1017 false
1018 }
1019}