1*ed78a018SJohn Hubbard // SPDX-License-Identifier: GPL-2.0 2*ed78a018SJohn Hubbard 3*ed78a018SJohn Hubbard //! PCI device identifiers and related types. 4*ed78a018SJohn Hubbard //! 5*ed78a018SJohn Hubbard //! This module contains PCI class codes and supporting types. 6*ed78a018SJohn Hubbard 7*ed78a018SJohn Hubbard use crate::{bindings, error::code::EINVAL, error::Error, prelude::*}; 8*ed78a018SJohn Hubbard use core::fmt; 9*ed78a018SJohn Hubbard 10*ed78a018SJohn Hubbard /// PCI device class codes. 11*ed78a018SJohn Hubbard /// 12*ed78a018SJohn Hubbard /// Each entry contains the full 24-bit PCI class code (base class in bits 13*ed78a018SJohn Hubbard /// 23-16, subclass in bits 15-8, programming interface in bits 7-0). 14*ed78a018SJohn Hubbard /// 15*ed78a018SJohn Hubbard /// # Examples 16*ed78a018SJohn Hubbard /// 17*ed78a018SJohn Hubbard /// ``` 18*ed78a018SJohn Hubbard /// # use kernel::{device::Core, pci::{self, Class}, prelude::*}; 19*ed78a018SJohn Hubbard /// fn probe_device(pdev: &pci::Device<Core>) -> Result { 20*ed78a018SJohn Hubbard /// let pci_class = pdev.pci_class(); 21*ed78a018SJohn Hubbard /// dev_info!( 22*ed78a018SJohn Hubbard /// pdev.as_ref(), 23*ed78a018SJohn Hubbard /// "Detected PCI class: {}\n", 24*ed78a018SJohn Hubbard /// pci_class 25*ed78a018SJohn Hubbard /// ); 26*ed78a018SJohn Hubbard /// Ok(()) 27*ed78a018SJohn Hubbard /// } 28*ed78a018SJohn Hubbard /// ``` 29*ed78a018SJohn Hubbard #[derive(Clone, Copy, PartialEq, Eq)] 30*ed78a018SJohn Hubbard #[repr(transparent)] 31*ed78a018SJohn Hubbard pub struct Class(u32); 32*ed78a018SJohn Hubbard 33*ed78a018SJohn Hubbard /// PCI class mask constants for matching [`Class`] codes. 34*ed78a018SJohn Hubbard #[repr(u32)] 35*ed78a018SJohn Hubbard #[derive(Debug, Clone, Copy, PartialEq, Eq)] 36*ed78a018SJohn Hubbard pub enum ClassMask { 37*ed78a018SJohn Hubbard /// Match the full 24-bit class code. 38*ed78a018SJohn Hubbard Full = 0xffffff, 39*ed78a018SJohn Hubbard /// Match the upper 16 bits of the class code (base class and subclass only) 40*ed78a018SJohn Hubbard ClassSubclass = 0xffff00, 41*ed78a018SJohn Hubbard } 42*ed78a018SJohn Hubbard 43*ed78a018SJohn Hubbard macro_rules! define_all_pci_classes { 44*ed78a018SJohn Hubbard ( 45*ed78a018SJohn Hubbard $($variant:ident = $binding:expr,)+ 46*ed78a018SJohn Hubbard ) => { 47*ed78a018SJohn Hubbard impl Class { 48*ed78a018SJohn Hubbard $( 49*ed78a018SJohn Hubbard #[allow(missing_docs)] 50*ed78a018SJohn Hubbard pub const $variant: Self = Self(Self::to_24bit_class($binding)); 51*ed78a018SJohn Hubbard )+ 52*ed78a018SJohn Hubbard } 53*ed78a018SJohn Hubbard }; 54*ed78a018SJohn Hubbard } 55*ed78a018SJohn Hubbard 56*ed78a018SJohn Hubbard /// Once constructed, a [`Class`] contains a valid PCI class code. 57*ed78a018SJohn Hubbard impl Class { 58*ed78a018SJohn Hubbard /// Create a [`Class`] from a raw 24-bit class code. 59*ed78a018SJohn Hubbard #[inline] 60*ed78a018SJohn Hubbard pub(super) fn from_raw(class_code: u32) -> Self { 61*ed78a018SJohn Hubbard Self(class_code) 62*ed78a018SJohn Hubbard } 63*ed78a018SJohn Hubbard 64*ed78a018SJohn Hubbard /// Get the raw 24-bit class code value. 65*ed78a018SJohn Hubbard #[inline] 66*ed78a018SJohn Hubbard pub const fn as_raw(self) -> u32 { 67*ed78a018SJohn Hubbard self.0 68*ed78a018SJohn Hubbard } 69*ed78a018SJohn Hubbard 70*ed78a018SJohn Hubbard // Converts a PCI class constant to 24-bit format. 71*ed78a018SJohn Hubbard // 72*ed78a018SJohn Hubbard // Many device drivers use only the upper 16 bits (base class and subclass), 73*ed78a018SJohn Hubbard // but some use the full 24 bits. In order to support both cases, store the 74*ed78a018SJohn Hubbard // class code as a 24-bit value, where 16-bit values are shifted up 8 bits. 75*ed78a018SJohn Hubbard const fn to_24bit_class(val: u32) -> u32 { 76*ed78a018SJohn Hubbard if val > 0xFFFF { 77*ed78a018SJohn Hubbard val 78*ed78a018SJohn Hubbard } else { 79*ed78a018SJohn Hubbard val << 8 80*ed78a018SJohn Hubbard } 81*ed78a018SJohn Hubbard } 82*ed78a018SJohn Hubbard } 83*ed78a018SJohn Hubbard 84*ed78a018SJohn Hubbard impl fmt::Debug for Class { 85*ed78a018SJohn Hubbard fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 86*ed78a018SJohn Hubbard write!(f, "0x{:06x}", self.0) 87*ed78a018SJohn Hubbard } 88*ed78a018SJohn Hubbard } 89*ed78a018SJohn Hubbard 90*ed78a018SJohn Hubbard impl fmt::Display for Class { 91*ed78a018SJohn Hubbard fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 92*ed78a018SJohn Hubbard <Self as fmt::Debug>::fmt(self, f) 93*ed78a018SJohn Hubbard } 94*ed78a018SJohn Hubbard } 95*ed78a018SJohn Hubbard 96*ed78a018SJohn Hubbard impl ClassMask { 97*ed78a018SJohn Hubbard /// Get the raw mask value. 98*ed78a018SJohn Hubbard #[inline] 99*ed78a018SJohn Hubbard pub const fn as_raw(self) -> u32 { 100*ed78a018SJohn Hubbard self as u32 101*ed78a018SJohn Hubbard } 102*ed78a018SJohn Hubbard } 103*ed78a018SJohn Hubbard 104*ed78a018SJohn Hubbard impl TryFrom<u32> for ClassMask { 105*ed78a018SJohn Hubbard type Error = Error; 106*ed78a018SJohn Hubbard 107*ed78a018SJohn Hubbard fn try_from(value: u32) -> Result<Self, Self::Error> { 108*ed78a018SJohn Hubbard match value { 109*ed78a018SJohn Hubbard 0xffffff => Ok(ClassMask::Full), 110*ed78a018SJohn Hubbard 0xffff00 => Ok(ClassMask::ClassSubclass), 111*ed78a018SJohn Hubbard _ => Err(EINVAL), 112*ed78a018SJohn Hubbard } 113*ed78a018SJohn Hubbard } 114*ed78a018SJohn Hubbard } 115*ed78a018SJohn Hubbard 116*ed78a018SJohn Hubbard define_all_pci_classes! { 117*ed78a018SJohn Hubbard NOT_DEFINED = bindings::PCI_CLASS_NOT_DEFINED, // 0x000000 118*ed78a018SJohn Hubbard NOT_DEFINED_VGA = bindings::PCI_CLASS_NOT_DEFINED_VGA, // 0x000100 119*ed78a018SJohn Hubbard 120*ed78a018SJohn Hubbard STORAGE_SCSI = bindings::PCI_CLASS_STORAGE_SCSI, // 0x010000 121*ed78a018SJohn Hubbard STORAGE_IDE = bindings::PCI_CLASS_STORAGE_IDE, // 0x010100 122*ed78a018SJohn Hubbard STORAGE_FLOPPY = bindings::PCI_CLASS_STORAGE_FLOPPY, // 0x010200 123*ed78a018SJohn Hubbard STORAGE_IPI = bindings::PCI_CLASS_STORAGE_IPI, // 0x010300 124*ed78a018SJohn Hubbard STORAGE_RAID = bindings::PCI_CLASS_STORAGE_RAID, // 0x010400 125*ed78a018SJohn Hubbard STORAGE_SATA = bindings::PCI_CLASS_STORAGE_SATA, // 0x010600 126*ed78a018SJohn Hubbard STORAGE_SATA_AHCI = bindings::PCI_CLASS_STORAGE_SATA_AHCI, // 0x010601 127*ed78a018SJohn Hubbard STORAGE_SAS = bindings::PCI_CLASS_STORAGE_SAS, // 0x010700 128*ed78a018SJohn Hubbard STORAGE_EXPRESS = bindings::PCI_CLASS_STORAGE_EXPRESS, // 0x010802 129*ed78a018SJohn Hubbard STORAGE_OTHER = bindings::PCI_CLASS_STORAGE_OTHER, // 0x018000 130*ed78a018SJohn Hubbard 131*ed78a018SJohn Hubbard NETWORK_ETHERNET = bindings::PCI_CLASS_NETWORK_ETHERNET, // 0x020000 132*ed78a018SJohn Hubbard NETWORK_TOKEN_RING = bindings::PCI_CLASS_NETWORK_TOKEN_RING, // 0x020100 133*ed78a018SJohn Hubbard NETWORK_FDDI = bindings::PCI_CLASS_NETWORK_FDDI, // 0x020200 134*ed78a018SJohn Hubbard NETWORK_ATM = bindings::PCI_CLASS_NETWORK_ATM, // 0x020300 135*ed78a018SJohn Hubbard NETWORK_OTHER = bindings::PCI_CLASS_NETWORK_OTHER, // 0x028000 136*ed78a018SJohn Hubbard 137*ed78a018SJohn Hubbard DISPLAY_VGA = bindings::PCI_CLASS_DISPLAY_VGA, // 0x030000 138*ed78a018SJohn Hubbard DISPLAY_XGA = bindings::PCI_CLASS_DISPLAY_XGA, // 0x030100 139*ed78a018SJohn Hubbard DISPLAY_3D = bindings::PCI_CLASS_DISPLAY_3D, // 0x030200 140*ed78a018SJohn Hubbard DISPLAY_OTHER = bindings::PCI_CLASS_DISPLAY_OTHER, // 0x038000 141*ed78a018SJohn Hubbard 142*ed78a018SJohn Hubbard MULTIMEDIA_VIDEO = bindings::PCI_CLASS_MULTIMEDIA_VIDEO, // 0x040000 143*ed78a018SJohn Hubbard MULTIMEDIA_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_AUDIO, // 0x040100 144*ed78a018SJohn Hubbard MULTIMEDIA_PHONE = bindings::PCI_CLASS_MULTIMEDIA_PHONE, // 0x040200 145*ed78a018SJohn Hubbard MULTIMEDIA_HD_AUDIO = bindings::PCI_CLASS_MULTIMEDIA_HD_AUDIO, // 0x040300 146*ed78a018SJohn Hubbard MULTIMEDIA_OTHER = bindings::PCI_CLASS_MULTIMEDIA_OTHER, // 0x048000 147*ed78a018SJohn Hubbard 148*ed78a018SJohn Hubbard MEMORY_RAM = bindings::PCI_CLASS_MEMORY_RAM, // 0x050000 149*ed78a018SJohn Hubbard MEMORY_FLASH = bindings::PCI_CLASS_MEMORY_FLASH, // 0x050100 150*ed78a018SJohn Hubbard MEMORY_CXL = bindings::PCI_CLASS_MEMORY_CXL, // 0x050200 151*ed78a018SJohn Hubbard MEMORY_OTHER = bindings::PCI_CLASS_MEMORY_OTHER, // 0x058000 152*ed78a018SJohn Hubbard 153*ed78a018SJohn Hubbard BRIDGE_HOST = bindings::PCI_CLASS_BRIDGE_HOST, // 0x060000 154*ed78a018SJohn Hubbard BRIDGE_ISA = bindings::PCI_CLASS_BRIDGE_ISA, // 0x060100 155*ed78a018SJohn Hubbard BRIDGE_EISA = bindings::PCI_CLASS_BRIDGE_EISA, // 0x060200 156*ed78a018SJohn Hubbard BRIDGE_MC = bindings::PCI_CLASS_BRIDGE_MC, // 0x060300 157*ed78a018SJohn Hubbard BRIDGE_PCI_NORMAL = bindings::PCI_CLASS_BRIDGE_PCI_NORMAL, // 0x060400 158*ed78a018SJohn Hubbard BRIDGE_PCI_SUBTRACTIVE = bindings::PCI_CLASS_BRIDGE_PCI_SUBTRACTIVE, // 0x060401 159*ed78a018SJohn Hubbard BRIDGE_PCMCIA = bindings::PCI_CLASS_BRIDGE_PCMCIA, // 0x060500 160*ed78a018SJohn Hubbard BRIDGE_NUBUS = bindings::PCI_CLASS_BRIDGE_NUBUS, // 0x060600 161*ed78a018SJohn Hubbard BRIDGE_CARDBUS = bindings::PCI_CLASS_BRIDGE_CARDBUS, // 0x060700 162*ed78a018SJohn Hubbard BRIDGE_RACEWAY = bindings::PCI_CLASS_BRIDGE_RACEWAY, // 0x060800 163*ed78a018SJohn Hubbard BRIDGE_OTHER = bindings::PCI_CLASS_BRIDGE_OTHER, // 0x068000 164*ed78a018SJohn Hubbard 165*ed78a018SJohn Hubbard COMMUNICATION_SERIAL = bindings::PCI_CLASS_COMMUNICATION_SERIAL, // 0x070000 166*ed78a018SJohn Hubbard COMMUNICATION_PARALLEL = bindings::PCI_CLASS_COMMUNICATION_PARALLEL, // 0x070100 167*ed78a018SJohn Hubbard COMMUNICATION_MULTISERIAL = bindings::PCI_CLASS_COMMUNICATION_MULTISERIAL, // 0x070200 168*ed78a018SJohn Hubbard COMMUNICATION_MODEM = bindings::PCI_CLASS_COMMUNICATION_MODEM, // 0x070300 169*ed78a018SJohn Hubbard COMMUNICATION_OTHER = bindings::PCI_CLASS_COMMUNICATION_OTHER, // 0x078000 170*ed78a018SJohn Hubbard 171*ed78a018SJohn Hubbard SYSTEM_PIC = bindings::PCI_CLASS_SYSTEM_PIC, // 0x080000 172*ed78a018SJohn Hubbard SYSTEM_PIC_IOAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOAPIC, // 0x080010 173*ed78a018SJohn Hubbard SYSTEM_PIC_IOXAPIC = bindings::PCI_CLASS_SYSTEM_PIC_IOXAPIC, // 0x080020 174*ed78a018SJohn Hubbard SYSTEM_DMA = bindings::PCI_CLASS_SYSTEM_DMA, // 0x080100 175*ed78a018SJohn Hubbard SYSTEM_TIMER = bindings::PCI_CLASS_SYSTEM_TIMER, // 0x080200 176*ed78a018SJohn Hubbard SYSTEM_RTC = bindings::PCI_CLASS_SYSTEM_RTC, // 0x080300 177*ed78a018SJohn Hubbard SYSTEM_PCI_HOTPLUG = bindings::PCI_CLASS_SYSTEM_PCI_HOTPLUG, // 0x080400 178*ed78a018SJohn Hubbard SYSTEM_SDHCI = bindings::PCI_CLASS_SYSTEM_SDHCI, // 0x080500 179*ed78a018SJohn Hubbard SYSTEM_RCEC = bindings::PCI_CLASS_SYSTEM_RCEC, // 0x080700 180*ed78a018SJohn Hubbard SYSTEM_OTHER = bindings::PCI_CLASS_SYSTEM_OTHER, // 0x088000 181*ed78a018SJohn Hubbard 182*ed78a018SJohn Hubbard INPUT_KEYBOARD = bindings::PCI_CLASS_INPUT_KEYBOARD, // 0x090000 183*ed78a018SJohn Hubbard INPUT_PEN = bindings::PCI_CLASS_INPUT_PEN, // 0x090100 184*ed78a018SJohn Hubbard INPUT_MOUSE = bindings::PCI_CLASS_INPUT_MOUSE, // 0x090200 185*ed78a018SJohn Hubbard INPUT_SCANNER = bindings::PCI_CLASS_INPUT_SCANNER, // 0x090300 186*ed78a018SJohn Hubbard INPUT_GAMEPORT = bindings::PCI_CLASS_INPUT_GAMEPORT, // 0x090400 187*ed78a018SJohn Hubbard INPUT_OTHER = bindings::PCI_CLASS_INPUT_OTHER, // 0x098000 188*ed78a018SJohn Hubbard 189*ed78a018SJohn Hubbard DOCKING_GENERIC = bindings::PCI_CLASS_DOCKING_GENERIC, // 0x0a0000 190*ed78a018SJohn Hubbard DOCKING_OTHER = bindings::PCI_CLASS_DOCKING_OTHER, // 0x0a8000 191*ed78a018SJohn Hubbard 192*ed78a018SJohn Hubbard PROCESSOR_386 = bindings::PCI_CLASS_PROCESSOR_386, // 0x0b0000 193*ed78a018SJohn Hubbard PROCESSOR_486 = bindings::PCI_CLASS_PROCESSOR_486, // 0x0b0100 194*ed78a018SJohn Hubbard PROCESSOR_PENTIUM = bindings::PCI_CLASS_PROCESSOR_PENTIUM, // 0x0b0200 195*ed78a018SJohn Hubbard PROCESSOR_ALPHA = bindings::PCI_CLASS_PROCESSOR_ALPHA, // 0x0b1000 196*ed78a018SJohn Hubbard PROCESSOR_POWERPC = bindings::PCI_CLASS_PROCESSOR_POWERPC, // 0x0b2000 197*ed78a018SJohn Hubbard PROCESSOR_MIPS = bindings::PCI_CLASS_PROCESSOR_MIPS, // 0x0b3000 198*ed78a018SJohn Hubbard PROCESSOR_CO = bindings::PCI_CLASS_PROCESSOR_CO, // 0x0b4000 199*ed78a018SJohn Hubbard 200*ed78a018SJohn Hubbard SERIAL_FIREWIRE = bindings::PCI_CLASS_SERIAL_FIREWIRE, // 0x0c0000 201*ed78a018SJohn Hubbard SERIAL_FIREWIRE_OHCI = bindings::PCI_CLASS_SERIAL_FIREWIRE_OHCI, // 0x0c0010 202*ed78a018SJohn Hubbard SERIAL_ACCESS = bindings::PCI_CLASS_SERIAL_ACCESS, // 0x0c0100 203*ed78a018SJohn Hubbard SERIAL_SSA = bindings::PCI_CLASS_SERIAL_SSA, // 0x0c0200 204*ed78a018SJohn Hubbard SERIAL_USB_UHCI = bindings::PCI_CLASS_SERIAL_USB_UHCI, // 0x0c0300 205*ed78a018SJohn Hubbard SERIAL_USB_OHCI = bindings::PCI_CLASS_SERIAL_USB_OHCI, // 0x0c0310 206*ed78a018SJohn Hubbard SERIAL_USB_EHCI = bindings::PCI_CLASS_SERIAL_USB_EHCI, // 0x0c0320 207*ed78a018SJohn Hubbard SERIAL_USB_XHCI = bindings::PCI_CLASS_SERIAL_USB_XHCI, // 0x0c0330 208*ed78a018SJohn Hubbard SERIAL_USB_CDNS = bindings::PCI_CLASS_SERIAL_USB_CDNS, // 0x0c0380 209*ed78a018SJohn Hubbard SERIAL_USB_DEVICE = bindings::PCI_CLASS_SERIAL_USB_DEVICE, // 0x0c03fe 210*ed78a018SJohn Hubbard SERIAL_FIBER = bindings::PCI_CLASS_SERIAL_FIBER, // 0x0c0400 211*ed78a018SJohn Hubbard SERIAL_SMBUS = bindings::PCI_CLASS_SERIAL_SMBUS, // 0x0c0500 212*ed78a018SJohn Hubbard SERIAL_IPMI_SMIC = bindings::PCI_CLASS_SERIAL_IPMI_SMIC, // 0x0c0700 213*ed78a018SJohn Hubbard SERIAL_IPMI_KCS = bindings::PCI_CLASS_SERIAL_IPMI_KCS, // 0x0c0701 214*ed78a018SJohn Hubbard SERIAL_IPMI_BT = bindings::PCI_CLASS_SERIAL_IPMI_BT, // 0x0c0702 215*ed78a018SJohn Hubbard 216*ed78a018SJohn Hubbard WIRELESS_RF_CONTROLLER = bindings::PCI_CLASS_WIRELESS_RF_CONTROLLER, // 0x0d1000 217*ed78a018SJohn Hubbard WIRELESS_WHCI = bindings::PCI_CLASS_WIRELESS_WHCI, // 0x0d1010 218*ed78a018SJohn Hubbard 219*ed78a018SJohn Hubbard INTELLIGENT_I2O = bindings::PCI_CLASS_INTELLIGENT_I2O, // 0x0e0000 220*ed78a018SJohn Hubbard 221*ed78a018SJohn Hubbard SATELLITE_TV = bindings::PCI_CLASS_SATELLITE_TV, // 0x0f0000 222*ed78a018SJohn Hubbard SATELLITE_AUDIO = bindings::PCI_CLASS_SATELLITE_AUDIO, // 0x0f0100 223*ed78a018SJohn Hubbard SATELLITE_VOICE = bindings::PCI_CLASS_SATELLITE_VOICE, // 0x0f0300 224*ed78a018SJohn Hubbard SATELLITE_DATA = bindings::PCI_CLASS_SATELLITE_DATA, // 0x0f0400 225*ed78a018SJohn Hubbard 226*ed78a018SJohn Hubbard CRYPT_NETWORK = bindings::PCI_CLASS_CRYPT_NETWORK, // 0x100000 227*ed78a018SJohn Hubbard CRYPT_ENTERTAINMENT = bindings::PCI_CLASS_CRYPT_ENTERTAINMENT, // 0x100100 228*ed78a018SJohn Hubbard CRYPT_OTHER = bindings::PCI_CLASS_CRYPT_OTHER, // 0x108000 229*ed78a018SJohn Hubbard 230*ed78a018SJohn Hubbard SP_DPIO = bindings::PCI_CLASS_SP_DPIO, // 0x110000 231*ed78a018SJohn Hubbard SP_OTHER = bindings::PCI_CLASS_SP_OTHER, // 0x118000 232*ed78a018SJohn Hubbard 233*ed78a018SJohn Hubbard ACCELERATOR_PROCESSING = bindings::PCI_CLASS_ACCELERATOR_PROCESSING, // 0x120000 234*ed78a018SJohn Hubbard 235*ed78a018SJohn Hubbard OTHERS = bindings::PCI_CLASS_OTHERS, // 0xff0000 236*ed78a018SJohn Hubbard } 237