1 // Copyright 2018 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE-BSD-3-Clause file. 4 5 //! Implements pci devices and busses. 6 #[macro_use] 7 extern crate log; 8 9 mod bus; 10 mod configuration; 11 mod device; 12 mod msi; 13 mod msix; 14 mod vfio; 15 mod vfio_user; 16 17 pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError}; 18 pub use self::configuration::{ 19 PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityId, 20 PciClassCode, PciConfiguration, PciExpressCapabilityId, PciHeaderType, PciMassStorageSubclass, 21 PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass, 22 PCI_CONFIGURATION_ID, 23 }; 24 pub use self::device::{ 25 BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice, 26 }; 27 pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig}; 28 pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE}; 29 pub use self::vfio::{MmioRegion, VfioDmaMapping, VfioPciDevice, VfioPciError}; 30 pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError}; 31 use serde::de::Visitor; 32 use std::fmt::{self, Display}; 33 use std::num::ParseIntError; 34 use std::str::FromStr; 35 36 /// PCI has four interrupt pins A->D. 37 #[derive(Copy, Clone)] 38 pub enum PciInterruptPin { 39 IntA, 40 IntB, 41 IntC, 42 IntD, 43 } 44 45 impl PciInterruptPin { 46 pub fn to_mask(self) -> u32 { 47 self as u32 48 } 49 } 50 51 #[cfg(target_arch = "x86_64")] 52 pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8; 53 #[cfg(target_arch = "x86_64")] 54 pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8; 55 56 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd)] 57 pub struct PciBdf(u32); 58 59 struct PciBdfVisitor; 60 61 impl<'de> Visitor<'de> for PciBdfVisitor { 62 type Value = PciBdf; 63 64 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 65 formatter.write_str("struct PciBdf") 66 } 67 68 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> 69 where 70 E: serde::de::Error, 71 { 72 Ok(v.into()) 73 } 74 } 75 76 impl<'de> serde::Deserialize<'de> for PciBdf { 77 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 78 where 79 D: serde::Deserializer<'de>, 80 { 81 deserializer.deserialize_str(PciBdfVisitor) 82 } 83 } 84 85 impl serde::Serialize for PciBdf { 86 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 87 where 88 S: serde::Serializer, 89 { 90 serializer.collect_str(&self.to_string()) 91 } 92 } 93 94 impl PciBdf { 95 pub fn segment(&self) -> u16 { 96 ((self.0 >> 16) & 0xffff) as u16 97 } 98 99 pub fn bus(&self) -> u8 { 100 ((self.0 >> 8) & 0xff) as u8 101 } 102 103 pub fn device(&self) -> u8 { 104 ((self.0 >> 3) & 0x1f) as u8 105 } 106 107 pub fn function(&self) -> u8 { 108 (self.0 & 0x7) as u8 109 } 110 111 pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self { 112 Self( 113 (segment as u32) << 16 114 | (bus as u32) << 8 115 | ((device & 0x1f) as u32) << 3 116 | (function & 0x7) as u32, 117 ) 118 } 119 } 120 121 impl From<u32> for PciBdf { 122 fn from(bdf: u32) -> Self { 123 Self(bdf) 124 } 125 } 126 127 impl From<PciBdf> for u32 { 128 fn from(bdf: PciBdf) -> Self { 129 bdf.0 130 } 131 } 132 133 impl From<&PciBdf> for u32 { 134 fn from(bdf: &PciBdf) -> Self { 135 bdf.0 136 } 137 } 138 139 impl From<PciBdf> for u16 { 140 fn from(bdf: PciBdf) -> Self { 141 (bdf.0 & 0xffff) as u16 142 } 143 } 144 145 impl From<&PciBdf> for u16 { 146 fn from(bdf: &PciBdf) -> Self { 147 (bdf.0 & 0xffff) as u16 148 } 149 } 150 151 impl Display for PciBdf { 152 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 153 write!( 154 f, 155 "{:04x}:{:02x}:{:02x}.{:01x}", 156 self.segment(), 157 self.bus(), 158 self.device(), 159 self.function() 160 ) 161 } 162 } 163 164 impl FromStr for PciBdf { 165 type Err = ParseIntError; 166 167 fn from_str(s: &str) -> Result<Self, Self::Err> { 168 let items: Vec<&str> = s.split('.').collect(); 169 assert_eq!(items.len(), 2); 170 let function = u8::from_str_radix(items[1], 16)?; 171 let items: Vec<&str> = items[0].split(':').collect(); 172 assert_eq!(items.len(), 3); 173 let segment = u16::from_str_radix(items[0], 16)?; 174 let bus = u8::from_str_radix(items[1], 16)?; 175 let device = u8::from_str_radix(items[2], 16)?; 176 Ok(PciBdf::new(segment, bus, device, function)) 177 } 178 } 179 180 impl From<&str> for PciBdf { 181 fn from(bdf: &str) -> Self { 182 Self::from_str(bdf).unwrap() 183 } 184 } 185