device.rs 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. use super::{CommonHeader, Header};
  2. use crate::{kernel::mem::PhysAccess as _, sync::fence::memory_barrier};
  3. use alloc::sync::Arc;
  4. use core::{ops::RangeInclusive, sync::atomic::Ordering};
  5. use eonix_mm::address::PAddr;
  6. use eonix_sync::{LazyLock, Spin};
  7. use intrusive_collections::{intrusive_adapter, KeyAdapter, RBTree, RBTreeAtomicLink};
  8. pub(super) static PCIE_DEVICES: LazyLock<Spin<RBTree<PCIDeviceAdapter>>> =
  9. LazyLock::new(|| Spin::new(RBTree::new(PCIDeviceAdapter::new())));
  10. intrusive_adapter!(
  11. pub PCIDeviceAdapter = Arc<PCIDevice<'static>> : PCIDevice { link: RBTreeAtomicLink }
  12. );
  13. #[allow(dead_code)]
  14. pub struct PCIDevice<'a> {
  15. link: RBTreeAtomicLink,
  16. segment_group: SegmentGroup,
  17. config_space: ConfigSpace,
  18. pub header: Header<'a>,
  19. pub vendor_id: u16,
  20. pub device_id: u16,
  21. }
  22. #[allow(dead_code)]
  23. #[derive(Clone)]
  24. pub struct SegmentGroup {
  25. id: usize,
  26. bus_range: RangeInclusive<u8>,
  27. base_address: PAddr,
  28. }
  29. #[allow(dead_code)]
  30. #[derive(Clone)]
  31. pub struct ConfigSpace {
  32. bus: u8,
  33. device: u8,
  34. function: u8,
  35. base: PAddr,
  36. }
  37. impl SegmentGroup {
  38. pub fn new(id: usize, bus_start: u8, bus_end: u8, base_address: PAddr) -> Self {
  39. Self {
  40. id,
  41. bus_range: bus_start..=bus_end,
  42. base_address,
  43. }
  44. }
  45. #[cfg(target_arch = "x86_64")]
  46. pub fn from_entry(entry: &acpi::mcfg::PciConfigEntry) -> Self {
  47. Self {
  48. id: entry.segment_group as usize,
  49. bus_range: entry.bus_range.clone(),
  50. base_address: PAddr::from(entry.physical_address),
  51. }
  52. }
  53. pub fn iter(&self) -> impl Iterator<Item = ConfigSpace> + use<'_> {
  54. self.bus_range
  55. .clone()
  56. .map(move |bus| {
  57. (0..32)
  58. .map(move |device| {
  59. (0..8).map(move |function| ConfigSpace {
  60. bus,
  61. device,
  62. function,
  63. base: self.base_address
  64. + ((bus as usize) << 20)
  65. + ((device as usize) << 15)
  66. + ((function as usize) << 12),
  67. })
  68. })
  69. .flatten()
  70. })
  71. .flatten()
  72. }
  73. }
  74. impl ConfigSpace {
  75. pub fn header<'a>(&self) -> Option<Header<'a>> {
  76. let common_header = unsafe {
  77. // SAFETY: `self.base` is guaranteed to be pointing to a valid
  78. // configuration space area.
  79. self.base.as_ptr::<CommonHeader>().as_ref()
  80. };
  81. if common_header.vendor_id == 0xffff {
  82. return None;
  83. }
  84. // Bit 7 represents whether the device has multiple functions.
  85. let header_type = common_header.header_type & !(1 << 7);
  86. match header_type {
  87. 0 => Some(Header::Endpoint(unsafe {
  88. // SAFETY: `self.base` is guaranteed to be pointing to a valid
  89. // configuration space area.
  90. self.base.as_ptr().as_ref()
  91. })),
  92. 1 | 2 => unimplemented!("Header type 1 and 2"),
  93. _ => Some(Header::Unknown(unsafe {
  94. // SAFETY: `self.base` is guaranteed to be pointing to a valid
  95. // configuration space area.
  96. self.base.as_ptr().as_ref()
  97. })),
  98. }
  99. }
  100. }
  101. impl PCIDevice<'static> {
  102. pub fn new(
  103. segment_group: SegmentGroup,
  104. config_space: ConfigSpace,
  105. header: Header<'static>,
  106. ) -> Arc<Self> {
  107. let common_header = header.common_header();
  108. Arc::new(PCIDevice {
  109. link: RBTreeAtomicLink::new(),
  110. segment_group,
  111. config_space,
  112. vendor_id: common_header.vendor_id,
  113. device_id: common_header.device_id,
  114. header,
  115. })
  116. }
  117. }
  118. #[allow(dead_code)]
  119. impl PCIDevice<'_> {
  120. pub fn enable_bus_mastering(&self) {
  121. let header = self.header.common_header();
  122. header.command().fetch_or(0x04, Ordering::Relaxed);
  123. memory_barrier();
  124. }
  125. }
  126. impl<'a> KeyAdapter<'a> for PCIDeviceAdapter {
  127. type Key = u32;
  128. fn get_key(
  129. &self,
  130. value: &'a <Self::PointerOps as intrusive_collections::PointerOps>::Value,
  131. ) -> Self::Key {
  132. ((value.vendor_id as u32) << 16) | value.device_id as u32
  133. }
  134. }