1e8308dd1SSamuel Ortiz // Copyright 2018 The Chromium OS Authors. All rights reserved. 2e8308dd1SSamuel Ortiz // Use of this source code is governed by a BSD-style license that can be 3040ea543SSamuel Ortiz // found in the LICENSE-BSD-3-Clause file. 45e9886bbSRuslan Mstoi // 55e9886bbSRuslan Mstoi // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 6e8308dd1SSamuel Ortiz 7e8308dd1SSamuel Ortiz //! Implements pci devices and busses. 8e8308dd1SSamuel Ortiz #[macro_use] 9e8308dd1SSamuel Ortiz extern crate log; 10e8308dd1SSamuel Ortiz 112bb0b22cSJing Liu mod bus; 12e8308dd1SSamuel Ortiz mod configuration; 13e8308dd1SSamuel Ortiz mod device; 14ee39e465SSebastien Boeuf mod msi; 158df05b72SSebastien Boeuf mod msix; 1653ce5298SSamuel Ortiz mod vfio; 179254b74cSRob Bradford mod vfio_user; 18e8308dd1SSamuel Ortiz 19*8c072946SArvind Vasudev use std::fmt::{self, Debug, Display}; 2088a9f799SRob Bradford use std::num::ParseIntError; 2188a9f799SRob Bradford use std::str::FromStr; 2288a9f799SRob Bradford 2388a9f799SRob Bradford use serde::de::Visitor; 2488a9f799SRob Bradford 25833a3d45SRob Bradford pub use self::bus::{PciBus, PciConfigIo, PciConfigMmio, PciRoot, PciRootError}; 26e8308dd1SSamuel Ortiz pub use self::configuration::{ 27827229d8SRob Bradford PciBarConfiguration, PciBarPrefetchable, PciBarRegionType, PciCapability, PciCapabilityId, 28e45e3df6SSebastien Boeuf PciClassCode, PciConfiguration, PciExpressCapabilityId, PciHeaderType, PciMassStorageSubclass, 290b7fb42aSSamuel Ortiz PciNetworkControllerSubclass, PciProgrammingInterface, PciSerialBusSubClass, PciSubclass, 30eae80438SSebastien Boeuf PCI_CONFIGURATION_ID, 31e8308dd1SSamuel Ortiz }; 322bb0b22cSJing Liu pub use self::device::{ 33e91638e6SSebastien Boeuf BarReprogrammingParams, DeviceRelocation, Error as PciDeviceError, PciDevice, 342bb0b22cSJing Liu }; 354bb12a2dSSebastien Boeuf pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig}; 36eae80438SSebastien Boeuf pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE}; 37045964deSAndrew Carp pub use self::vfio::{MmioRegion, VfioDmaMapping, VfioPciDevice, VfioPciError}; 3843365adeSRob Bradford pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError}; 39e8308dd1SSamuel Ortiz 40e8308dd1SSamuel Ortiz /// PCI has four interrupt pins A->D. 41e8308dd1SSamuel Ortiz #[derive(Copy, Clone)] 42e8308dd1SSamuel Ortiz pub enum PciInterruptPin { 43e8308dd1SSamuel Ortiz IntA, 44e8308dd1SSamuel Ortiz IntB, 45e8308dd1SSamuel Ortiz IntC, 46e8308dd1SSamuel Ortiz IntD, 47e8308dd1SSamuel Ortiz } 48e8308dd1SSamuel Ortiz 49e8308dd1SSamuel Ortiz impl PciInterruptPin { to_mask(self) -> u3250e8308dd1SSamuel Ortiz pub fn to_mask(self) -> u32 { 51e8308dd1SSamuel Ortiz self as u32 52e8308dd1SSamuel Ortiz } 53e8308dd1SSamuel Ortiz } 540faa7afaSRob Bradford 550faa7afaSRob Bradford #[cfg(target_arch = "x86_64")] 560faa7afaSRob Bradford pub const PCI_CONFIG_IO_PORT: u64 = 0xcf8; 570faa7afaSRob Bradford #[cfg(target_arch = "x86_64")] 580faa7afaSRob Bradford pub const PCI_CONFIG_IO_PORT_SIZE: u64 = 0x8; 5979e43ac5SRob Bradford 602716bc33SRob Bradford #[derive(Clone, Copy, PartialEq, Eq, PartialOrd)] 6179e43ac5SRob Bradford pub struct PciBdf(u32); 6279e43ac5SRob Bradford 6342b5d4a2SSebastien Boeuf struct PciBdfVisitor; 6442b5d4a2SSebastien Boeuf 650aab960bSRuoqing He impl Visitor<'_> for PciBdfVisitor { 6642b5d4a2SSebastien Boeuf type Value = PciBdf; 6742b5d4a2SSebastien Boeuf expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result6842b5d4a2SSebastien Boeuf fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 6942b5d4a2SSebastien Boeuf formatter.write_str("struct PciBdf") 7042b5d4a2SSebastien Boeuf } 7142b5d4a2SSebastien Boeuf visit_str<E>(self, v: &str) -> Result<Self::Value, E> where E: serde::de::Error,7242b5d4a2SSebastien Boeuf fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> 7342b5d4a2SSebastien Boeuf where 7442b5d4a2SSebastien Boeuf E: serde::de::Error, 7542b5d4a2SSebastien Boeuf { 7642b5d4a2SSebastien Boeuf Ok(v.into()) 7742b5d4a2SSebastien Boeuf } 7842b5d4a2SSebastien Boeuf } 7942b5d4a2SSebastien Boeuf 8042b5d4a2SSebastien Boeuf impl<'de> serde::Deserialize<'de> for PciBdf { deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de>,8142b5d4a2SSebastien Boeuf fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 8242b5d4a2SSebastien Boeuf where 8342b5d4a2SSebastien Boeuf D: serde::Deserializer<'de>, 8442b5d4a2SSebastien Boeuf { 8542b5d4a2SSebastien Boeuf deserializer.deserialize_str(PciBdfVisitor) 8642b5d4a2SSebastien Boeuf } 8742b5d4a2SSebastien Boeuf } 8842b5d4a2SSebastien Boeuf 8942b5d4a2SSebastien Boeuf impl serde::Serialize for PciBdf { serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer,9042b5d4a2SSebastien Boeuf fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 9142b5d4a2SSebastien Boeuf where 9242b5d4a2SSebastien Boeuf S: serde::Serializer, 9342b5d4a2SSebastien Boeuf { 9442b5d4a2SSebastien Boeuf serializer.collect_str(&self.to_string()) 9542b5d4a2SSebastien Boeuf } 9642b5d4a2SSebastien Boeuf } 9742b5d4a2SSebastien Boeuf 9879e43ac5SRob Bradford impl PciBdf { segment(&self) -> u169979e43ac5SRob Bradford pub fn segment(&self) -> u16 { 10079e43ac5SRob Bradford ((self.0 >> 16) & 0xffff) as u16 10179e43ac5SRob Bradford } 10279e43ac5SRob Bradford bus(&self) -> u810379e43ac5SRob Bradford pub fn bus(&self) -> u8 { 10479e43ac5SRob Bradford ((self.0 >> 8) & 0xff) as u8 10579e43ac5SRob Bradford } 10679e43ac5SRob Bradford device(&self) -> u810779e43ac5SRob Bradford pub fn device(&self) -> u8 { 10879e43ac5SRob Bradford ((self.0 >> 3) & 0x1f) as u8 10979e43ac5SRob Bradford } 11079e43ac5SRob Bradford function(&self) -> u811179e43ac5SRob Bradford pub fn function(&self) -> u8 { 11279e43ac5SRob Bradford (self.0 & 0x7) as u8 11379e43ac5SRob Bradford } 11479e43ac5SRob Bradford new(segment: u16, bus: u8, device: u8, function: u8) -> Self11579e43ac5SRob Bradford pub fn new(segment: u16, bus: u8, device: u8, function: u8) -> Self { 11679e43ac5SRob Bradford Self( 117b57cc3d7SRob Bradford ((segment as u32) << 16) 118b57cc3d7SRob Bradford | ((bus as u32) << 8) 119b57cc3d7SRob Bradford | (((device & 0x1f) as u32) << 3) 12079e43ac5SRob Bradford | (function & 0x7) as u32, 12179e43ac5SRob Bradford ) 12279e43ac5SRob Bradford } 12379e43ac5SRob Bradford } 12479e43ac5SRob Bradford 12579e43ac5SRob Bradford impl From<u32> for PciBdf { from(bdf: u32) -> Self12679e43ac5SRob Bradford fn from(bdf: u32) -> Self { 12779e43ac5SRob Bradford Self(bdf) 12879e43ac5SRob Bradford } 12979e43ac5SRob Bradford } 13079e43ac5SRob Bradford 13179e43ac5SRob Bradford impl From<PciBdf> for u32 { from(bdf: PciBdf) -> Self13279e43ac5SRob Bradford fn from(bdf: PciBdf) -> Self { 13379e43ac5SRob Bradford bdf.0 13479e43ac5SRob Bradford } 13579e43ac5SRob Bradford } 13679e43ac5SRob Bradford 13779e43ac5SRob Bradford impl From<&PciBdf> for u32 { from(bdf: &PciBdf) -> Self13879e43ac5SRob Bradford fn from(bdf: &PciBdf) -> Self { 13979e43ac5SRob Bradford bdf.0 14079e43ac5SRob Bradford } 14179e43ac5SRob Bradford } 14279e43ac5SRob Bradford 14379e43ac5SRob Bradford impl From<PciBdf> for u16 { from(bdf: PciBdf) -> Self14479e43ac5SRob Bradford fn from(bdf: PciBdf) -> Self { 14579e43ac5SRob Bradford (bdf.0 & 0xffff) as u16 14679e43ac5SRob Bradford } 14779e43ac5SRob Bradford } 14879e43ac5SRob Bradford 14979e43ac5SRob Bradford impl From<&PciBdf> for u16 { from(bdf: &PciBdf) -> Self15079e43ac5SRob Bradford fn from(bdf: &PciBdf) -> Self { 15179e43ac5SRob Bradford (bdf.0 & 0xffff) as u16 15279e43ac5SRob Bradford } 15379e43ac5SRob Bradford } 15479e43ac5SRob Bradford 155*8c072946SArvind Vasudev impl Debug for PciBdf { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result156*8c072946SArvind Vasudev fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 157*8c072946SArvind Vasudev write!( 158*8c072946SArvind Vasudev f, 159*8c072946SArvind Vasudev "{:04x}:{:02x}:{:02x}.{:01x}", 160*8c072946SArvind Vasudev self.segment(), 161*8c072946SArvind Vasudev self.bus(), 162*8c072946SArvind Vasudev self.device(), 163*8c072946SArvind Vasudev self.function() 164*8c072946SArvind Vasudev ) 165*8c072946SArvind Vasudev } 166*8c072946SArvind Vasudev } 167*8c072946SArvind Vasudev 16879e43ac5SRob Bradford impl Display for PciBdf { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result16979e43ac5SRob Bradford fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 17079e43ac5SRob Bradford write!( 17179e43ac5SRob Bradford f, 17279e43ac5SRob Bradford "{:04x}:{:02x}:{:02x}.{:01x}", 17379e43ac5SRob Bradford self.segment(), 17479e43ac5SRob Bradford self.bus(), 17579e43ac5SRob Bradford self.device(), 17679e43ac5SRob Bradford self.function() 17779e43ac5SRob Bradford ) 17879e43ac5SRob Bradford } 17979e43ac5SRob Bradford } 18042b5d4a2SSebastien Boeuf 18142b5d4a2SSebastien Boeuf impl FromStr for PciBdf { 18242b5d4a2SSebastien Boeuf type Err = ParseIntError; 18342b5d4a2SSebastien Boeuf from_str(s: &str) -> Result<Self, Self::Err>18442b5d4a2SSebastien Boeuf fn from_str(s: &str) -> Result<Self, Self::Err> { 18542b5d4a2SSebastien Boeuf let items: Vec<&str> = s.split('.').collect(); 18642b5d4a2SSebastien Boeuf assert_eq!(items.len(), 2); 18742b5d4a2SSebastien Boeuf let function = u8::from_str_radix(items[1], 16)?; 18842b5d4a2SSebastien Boeuf let items: Vec<&str> = items[0].split(':').collect(); 18942b5d4a2SSebastien Boeuf assert_eq!(items.len(), 3); 19042b5d4a2SSebastien Boeuf let segment = u16::from_str_radix(items[0], 16)?; 19142b5d4a2SSebastien Boeuf let bus = u8::from_str_radix(items[1], 16)?; 19242b5d4a2SSebastien Boeuf let device = u8::from_str_radix(items[2], 16)?; 19342b5d4a2SSebastien Boeuf Ok(PciBdf::new(segment, bus, device, function)) 19442b5d4a2SSebastien Boeuf } 19542b5d4a2SSebastien Boeuf } 19642b5d4a2SSebastien Boeuf 19742b5d4a2SSebastien Boeuf impl From<&str> for PciBdf { from(bdf: &str) -> Self19842b5d4a2SSebastien Boeuf fn from(bdf: &str) -> Self { 19942b5d4a2SSebastien Boeuf Self::from_str(bdf).unwrap() 20042b5d4a2SSebastien Boeuf } 20142b5d4a2SSebastien Boeuf } 202