|
2 | 2 |
|
3 | 3 | //! PCI Bus specific protocols.
|
4 | 4 |
|
| 5 | +use core::cmp::Ordering; |
| 6 | + |
5 | 7 | use uefi_raw::protocol::pci::root_bridge::PciRootBridgeIoProtocolWidth;
|
6 | 8 |
|
7 | 9 | pub mod root_bridge;
|
8 | 10 |
|
9 | 11 | /// IO Address for PCI/register IO operations
|
10 | 12 | #[repr(C, packed)]
|
11 |
| -#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 13 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
12 | 14 | pub struct PciIoAddress {
|
13 | 15 | /// Register number within the PCI device.
|
14 | 16 | pub reg: u8,
|
@@ -54,9 +56,37 @@ impl PciIoAddress {
|
54 | 56 | }
|
55 | 57 | }
|
56 | 58 |
|
| 59 | +impl From<u64> for PciIoAddress { |
| 60 | + fn from(value: u64) -> Self { |
| 61 | + let raw = value.to_ne_bytes(); |
| 62 | + Self { |
| 63 | + reg: raw[0], |
| 64 | + fun: raw[1], |
| 65 | + dev: raw[2], |
| 66 | + bus: raw[3], |
| 67 | + ext_reg: u32::from_ne_bytes([raw[4], raw[5], raw[6], raw[7]]), |
| 68 | + } |
| 69 | + } |
| 70 | +} |
| 71 | + |
57 | 72 | impl From<PciIoAddress> for u64 {
|
58 | 73 | fn from(value: PciIoAddress) -> Self {
|
59 |
| - unsafe { core::mem::transmute(value) } |
| 74 | + let ereg = value.ext_reg.to_ne_bytes(); |
| 75 | + u64::from_ne_bytes([ |
| 76 | + value.reg, value.fun, value.dev, value.bus, ereg[0], ereg[1], ereg[2], ereg[3], |
| 77 | + ]) |
| 78 | + } |
| 79 | +} |
| 80 | + |
| 81 | +impl PartialOrd for PciIoAddress { |
| 82 | + fn partial_cmp(&self, other: &Self) -> Option<Ordering> { |
| 83 | + Some(self.cmp(other)) |
| 84 | + } |
| 85 | +} |
| 86 | + |
| 87 | +impl Ord for PciIoAddress { |
| 88 | + fn cmp(&self, other: &Self) -> Ordering { |
| 89 | + u64::from(*self).cmp(&u64::from(*other)) |
60 | 90 | }
|
61 | 91 | }
|
62 | 92 |
|
@@ -95,3 +125,24 @@ fn encode_io_mode_and_unit<U: PciIoUnit>(mode: PciIoMode) -> PciRootBridgeIoProt
|
95 | 125 | _ => unreachable!("Illegal PCI IO-Mode / Unit combination"),
|
96 | 126 | }
|
97 | 127 | }
|
| 128 | + |
| 129 | +#[cfg(test)] |
| 130 | +mod tests { |
| 131 | + use super::PciIoAddress; |
| 132 | + use core::mem; |
| 133 | + |
| 134 | + #[test] |
| 135 | + fn test_pci_ioaddr_raw_conversion() { |
| 136 | + assert_eq!(mem::size_of::<u64>(), mem::size_of::<PciIoAddress>()); |
| 137 | + let srcaddr = PciIoAddress { |
| 138 | + reg: 0x11, |
| 139 | + fun: 0x33, |
| 140 | + dev: 0x55, |
| 141 | + bus: 0x77, |
| 142 | + ext_reg: 0x99bbddff, |
| 143 | + }; |
| 144 | + let rawaddr: u64 = srcaddr.into(); |
| 145 | + let dstaddr = PciIoAddress::from(rawaddr); |
| 146 | + assert_eq!(srcaddr, dstaddr); |
| 147 | + } |
| 148 | +} |
0 commit comments