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