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