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