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