1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Abstractions for the PCI bus. 4 //! 5 //! C header: [`include/linux/pci.h`](srctree/include/linux/pci.h) 6 7 use crate::{ 8 bindings, container_of, device, 9 device::Bound, 10 device_id::{RawDeviceId, RawDeviceIdIndex}, 11 devres, driver, 12 error::{from_result, to_result, Result}, 13 irq::{self, IrqRequest}, 14 str::CStr, 15 sync::aref::ARef, 16 types::Opaque, 17 ThisModule, 18 }; 19 use core::{ 20 marker::PhantomData, 21 ops::RangeInclusive, 22 ptr::{addr_of_mut, NonNull}, 23 }; 24 use kernel::prelude::*; 25 26 mod id; 27 mod io; 28 29 pub use self::id::{Class, ClassMask, Vendor}; 30 pub use self::io::Bar; 31 32 /// IRQ type flags for PCI interrupt allocation. 33 #[derive(Debug, Clone, Copy)] 34 pub enum IrqType { 35 /// INTx interrupts. 36 Intx, 37 /// Message Signaled Interrupts (MSI). 38 Msi, 39 /// Extended Message Signaled Interrupts (MSI-X). 40 MsiX, 41 } 42 43 impl IrqType { 44 /// Convert to the corresponding kernel flags. 45 const fn as_raw(self) -> u32 { 46 match self { 47 IrqType::Intx => bindings::PCI_IRQ_INTX, 48 IrqType::Msi => bindings::PCI_IRQ_MSI, 49 IrqType::MsiX => bindings::PCI_IRQ_MSIX, 50 } 51 } 52 } 53 54 /// Set of IRQ types that can be used for PCI interrupt allocation. 55 #[derive(Debug, Clone, Copy, Default)] 56 pub struct IrqTypes(u32); 57 58 impl IrqTypes { 59 /// Create a set containing all IRQ types (MSI-X, MSI, and Legacy). 60 pub const fn all() -> Self { 61 Self(bindings::PCI_IRQ_ALL_TYPES) 62 } 63 64 /// Build a set of IRQ types. 65 /// 66 /// # Examples 67 /// 68 /// ```ignore 69 /// // Create a set with only MSI and MSI-X (no legacy interrupts). 70 /// let msi_only = IrqTypes::default() 71 /// .with(IrqType::Msi) 72 /// .with(IrqType::MsiX); 73 /// ``` 74 pub const fn with(self, irq_type: IrqType) -> Self { 75 Self(self.0 | irq_type.as_raw()) 76 } 77 78 /// Get the raw flags value. 79 const fn as_raw(self) -> u32 { 80 self.0 81 } 82 } 83 84 /// An adapter for the registration of PCI drivers. 85 pub struct Adapter<T: Driver>(T); 86 87 // SAFETY: A call to `unregister` for a given instance of `RegType` is guaranteed to be valid if 88 // a preceding call to `register` has been successful. 89 unsafe impl<T: Driver + 'static> driver::RegistrationOps for Adapter<T> { 90 type RegType = bindings::pci_driver; 91 92 unsafe fn register( 93 pdrv: &Opaque<Self::RegType>, 94 name: &'static CStr, 95 module: &'static ThisModule, 96 ) -> Result { 97 // SAFETY: It's safe to set the fields of `struct pci_driver` on initialization. 98 unsafe { 99 (*pdrv.get()).name = name.as_char_ptr(); 100 (*pdrv.get()).probe = Some(Self::probe_callback); 101 (*pdrv.get()).remove = Some(Self::remove_callback); 102 (*pdrv.get()).id_table = T::ID_TABLE.as_ptr(); 103 } 104 105 // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 106 to_result(unsafe { 107 bindings::__pci_register_driver(pdrv.get(), module.0, name.as_char_ptr()) 108 }) 109 } 110 111 unsafe fn unregister(pdrv: &Opaque<Self::RegType>) { 112 // SAFETY: `pdrv` is guaranteed to be a valid `RegType`. 113 unsafe { bindings::pci_unregister_driver(pdrv.get()) } 114 } 115 } 116 117 impl<T: Driver + 'static> Adapter<T> { 118 extern "C" fn probe_callback( 119 pdev: *mut bindings::pci_dev, 120 id: *const bindings::pci_device_id, 121 ) -> c_int { 122 // SAFETY: The PCI bus only ever calls the probe callback with a valid pointer to a 123 // `struct pci_dev`. 124 // 125 // INVARIANT: `pdev` is valid for the duration of `probe_callback()`. 126 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 127 128 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `struct pci_device_id` and 129 // does not add additional invariants, so it's safe to transmute. 130 let id = unsafe { &*id.cast::<DeviceId>() }; 131 let info = T::ID_TABLE.info(id.index()); 132 133 from_result(|| { 134 let data = T::probe(pdev, info)?; 135 136 pdev.as_ref().set_drvdata(data); 137 Ok(0) 138 }) 139 } 140 141 extern "C" fn remove_callback(pdev: *mut bindings::pci_dev) { 142 // SAFETY: The PCI bus only ever calls the remove callback with a valid pointer to a 143 // `struct pci_dev`. 144 // 145 // INVARIANT: `pdev` is valid for the duration of `remove_callback()`. 146 let pdev = unsafe { &*pdev.cast::<Device<device::CoreInternal>>() }; 147 148 // SAFETY: `remove_callback` is only ever called after a successful call to 149 // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called 150 // and stored a `Pin<KBox<T>>`. 151 let data = unsafe { pdev.as_ref().drvdata_obtain::<Pin<KBox<T>>>() }; 152 153 T::unbind(pdev, data.as_ref()); 154 } 155 } 156 157 /// Declares a kernel module that exposes a single PCI driver. 158 /// 159 /// # Examples 160 /// 161 ///```ignore 162 /// kernel::module_pci_driver! { 163 /// type: MyDriver, 164 /// name: "Module name", 165 /// authors: ["Author name"], 166 /// description: "Description", 167 /// license: "GPL v2", 168 /// } 169 ///``` 170 #[macro_export] 171 macro_rules! module_pci_driver { 172 ($($f:tt)*) => { 173 $crate::module_driver!(<T>, $crate::pci::Adapter<T>, { $($f)* }); 174 }; 175 } 176 177 /// Abstraction for the PCI device ID structure ([`struct pci_device_id`]). 178 /// 179 /// [`struct pci_device_id`]: https://docs.kernel.org/PCI/pci.html#c.pci_device_id 180 #[repr(transparent)] 181 #[derive(Clone, Copy)] 182 pub struct DeviceId(bindings::pci_device_id); 183 184 impl DeviceId { 185 const PCI_ANY_ID: u32 = !0; 186 187 /// Equivalent to C's `PCI_DEVICE` macro. 188 /// 189 /// Create a new `pci::DeviceId` from a vendor and device ID. 190 #[inline] 191 pub const fn from_id(vendor: Vendor, device: u32) -> Self { 192 Self(bindings::pci_device_id { 193 vendor: vendor.as_raw() as u32, 194 device, 195 subvendor: DeviceId::PCI_ANY_ID, 196 subdevice: DeviceId::PCI_ANY_ID, 197 class: 0, 198 class_mask: 0, 199 driver_data: 0, 200 override_only: 0, 201 }) 202 } 203 204 /// Equivalent to C's `PCI_DEVICE_CLASS` macro. 205 /// 206 /// Create a new `pci::DeviceId` from a class number and mask. 207 #[inline] 208 pub const fn from_class(class: u32, class_mask: u32) -> Self { 209 Self(bindings::pci_device_id { 210 vendor: DeviceId::PCI_ANY_ID, 211 device: DeviceId::PCI_ANY_ID, 212 subvendor: DeviceId::PCI_ANY_ID, 213 subdevice: DeviceId::PCI_ANY_ID, 214 class, 215 class_mask, 216 driver_data: 0, 217 override_only: 0, 218 }) 219 } 220 221 /// Create a new [`DeviceId`] from a class number, mask, and specific vendor. 222 /// 223 /// This is more targeted than [`DeviceId::from_class`]: in addition to matching by [`Vendor`], 224 /// it also matches the PCI [`Class`] (up to the entire 24 bits, depending on the 225 /// [`ClassMask`]). 226 #[inline] 227 pub const fn from_class_and_vendor( 228 class: Class, 229 class_mask: ClassMask, 230 vendor: Vendor, 231 ) -> Self { 232 Self(bindings::pci_device_id { 233 vendor: vendor.as_raw() as u32, 234 device: DeviceId::PCI_ANY_ID, 235 subvendor: DeviceId::PCI_ANY_ID, 236 subdevice: DeviceId::PCI_ANY_ID, 237 class: class.as_raw(), 238 class_mask: class_mask.as_raw(), 239 driver_data: 0, 240 override_only: 0, 241 }) 242 } 243 } 244 245 // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `pci_device_id` and does not add 246 // additional invariants, so it's safe to transmute to `RawType`. 247 unsafe impl RawDeviceId for DeviceId { 248 type RawType = bindings::pci_device_id; 249 } 250 251 // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 252 unsafe impl RawDeviceIdIndex for DeviceId { 253 const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data); 254 255 fn index(&self) -> usize { 256 self.0.driver_data 257 } 258 } 259 260 /// `IdTable` type for PCI. 261 pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 262 263 /// Create a PCI `IdTable` with its alias for modpost. 264 #[macro_export] 265 macro_rules! pci_device_table { 266 ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 267 const $table_name: $crate::device_id::IdArray< 268 $crate::pci::DeviceId, 269 $id_info_type, 270 { $table_data.len() }, 271 > = $crate::device_id::IdArray::new($table_data); 272 273 $crate::module_device_table!("pci", $module_table_name, $table_name); 274 }; 275 } 276 277 /// The PCI driver trait. 278 /// 279 /// # Examples 280 /// 281 ///``` 282 /// # use kernel::{bindings, device::Core, pci}; 283 /// 284 /// struct MyDriver; 285 /// 286 /// kernel::pci_device_table!( 287 /// PCI_TABLE, 288 /// MODULE_PCI_TABLE, 289 /// <MyDriver as pci::Driver>::IdInfo, 290 /// [ 291 /// ( 292 /// pci::DeviceId::from_id(pci::Vendor::REDHAT, bindings::PCI_ANY_ID as u32), 293 /// (), 294 /// ) 295 /// ] 296 /// ); 297 /// 298 /// impl pci::Driver for MyDriver { 299 /// type IdInfo = (); 300 /// const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE; 301 /// 302 /// fn probe( 303 /// _pdev: &pci::Device<Core>, 304 /// _id_info: &Self::IdInfo, 305 /// ) -> Result<Pin<KBox<Self>>> { 306 /// Err(ENODEV) 307 /// } 308 /// } 309 ///``` 310 /// Drivers must implement this trait in order to get a PCI driver registered. Please refer to the 311 /// `Adapter` documentation for an example. 312 pub trait Driver: Send { 313 /// The type holding information about each device id supported by the driver. 314 // TODO: Use `associated_type_defaults` once stabilized: 315 // 316 // ``` 317 // type IdInfo: 'static = (); 318 // ``` 319 type IdInfo: 'static; 320 321 /// The table of device ids supported by the driver. 322 const ID_TABLE: IdTable<Self::IdInfo>; 323 324 /// PCI driver probe. 325 /// 326 /// Called when a new pci device is added or discovered. Implementers should 327 /// attempt to initialize the device here. 328 fn probe(dev: &Device<device::Core>, id_info: &Self::IdInfo) -> Result<Pin<KBox<Self>>>; 329 330 /// PCI driver unbind. 331 /// 332 /// Called when a [`Device`] is unbound from its bound [`Driver`]. Implementing this callback 333 /// is optional. 334 /// 335 /// This callback serves as a place for drivers to perform teardown operations that require a 336 /// `&Device<Core>` or `&Device<Bound>` reference. For instance, drivers may try to perform I/O 337 /// operations to gracefully tear down the device. 338 /// 339 /// Otherwise, release operations for driver resources should be performed in `Self::drop`. 340 fn unbind(dev: &Device<device::Core>, this: Pin<&Self>) { 341 let _ = (dev, this); 342 } 343 } 344 345 /// The PCI device representation. 346 /// 347 /// This structure represents the Rust abstraction for a C `struct pci_dev`. The implementation 348 /// abstracts the usage of an already existing C `struct pci_dev` within Rust code that we get 349 /// passed from the C side. 350 /// 351 /// # Invariants 352 /// 353 /// A [`Device`] instance represents a valid `struct pci_dev` created by the C portion of the 354 /// kernel. 355 #[repr(transparent)] 356 pub struct Device<Ctx: device::DeviceContext = device::Normal>( 357 Opaque<bindings::pci_dev>, 358 PhantomData<Ctx>, 359 ); 360 361 impl<Ctx: device::DeviceContext> Device<Ctx> { 362 #[inline] 363 fn as_raw(&self) -> *mut bindings::pci_dev { 364 self.0.get() 365 } 366 } 367 368 impl Device { 369 /// Returns the PCI vendor ID as [`Vendor`]. 370 /// 371 /// # Examples 372 /// 373 /// ``` 374 /// # use kernel::{device::Core, pci::{self, Vendor}, prelude::*}; 375 /// fn log_device_info(pdev: &pci::Device<Core>) -> Result { 376 /// // Get an instance of `Vendor`. 377 /// let vendor = pdev.vendor_id(); 378 /// dev_info!( 379 /// pdev.as_ref(), 380 /// "Device: Vendor={}, Device=0x{:x}\n", 381 /// vendor, 382 /// pdev.device_id() 383 /// ); 384 /// Ok(()) 385 /// } 386 /// ``` 387 #[inline] 388 pub fn vendor_id(&self) -> Vendor { 389 // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. 390 let vendor_id = unsafe { (*self.as_raw()).vendor }; 391 Vendor::from_raw(vendor_id) 392 } 393 394 /// Returns the PCI device ID. 395 #[inline] 396 pub fn device_id(&self) -> u16 { 397 // SAFETY: By its type invariant `self.as_raw` is always a valid pointer to a 398 // `struct pci_dev`. 399 unsafe { (*self.as_raw()).device } 400 } 401 402 /// Returns the PCI revision ID. 403 #[inline] 404 pub fn revision_id(&self) -> u8 { 405 // SAFETY: By its type invariant `self.as_raw` is always a valid pointer to a 406 // `struct pci_dev`. 407 unsafe { (*self.as_raw()).revision } 408 } 409 410 /// Returns the PCI bus device/function. 411 #[inline] 412 pub fn dev_id(&self) -> u16 { 413 // SAFETY: By its type invariant `self.as_raw` is always a valid pointer to a 414 // `struct pci_dev`. 415 unsafe { bindings::pci_dev_id(self.as_raw()) } 416 } 417 418 /// Returns the PCI subsystem vendor ID. 419 #[inline] 420 pub fn subsystem_vendor_id(&self) -> u16 { 421 // SAFETY: By its type invariant `self.as_raw` is always a valid pointer to a 422 // `struct pci_dev`. 423 unsafe { (*self.as_raw()).subsystem_vendor } 424 } 425 426 /// Returns the PCI subsystem device ID. 427 #[inline] 428 pub fn subsystem_device_id(&self) -> u16 { 429 // SAFETY: By its type invariant `self.as_raw` is always a valid pointer to a 430 // `struct pci_dev`. 431 unsafe { (*self.as_raw()).subsystem_device } 432 } 433 434 /// Returns the start of the given PCI bar resource. 435 pub fn resource_start(&self, bar: u32) -> Result<bindings::resource_size_t> { 436 if !Bar::index_is_valid(bar) { 437 return Err(EINVAL); 438 } 439 440 // SAFETY: 441 // - `bar` is a valid bar number, as guaranteed by the above call to `Bar::index_is_valid`, 442 // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. 443 Ok(unsafe { bindings::pci_resource_start(self.as_raw(), bar.try_into()?) }) 444 } 445 446 /// Returns the size of the given PCI bar resource. 447 pub fn resource_len(&self, bar: u32) -> Result<bindings::resource_size_t> { 448 if !Bar::index_is_valid(bar) { 449 return Err(EINVAL); 450 } 451 452 // SAFETY: 453 // - `bar` is a valid bar number, as guaranteed by the above call to `Bar::index_is_valid`, 454 // - by its type invariant `self.as_raw` is always a valid pointer to a `struct pci_dev`. 455 Ok(unsafe { bindings::pci_resource_len(self.as_raw(), bar.try_into()?) }) 456 } 457 458 /// Returns the PCI class as a `Class` struct. 459 #[inline] 460 pub fn pci_class(&self) -> Class { 461 // SAFETY: `self.as_raw` is a valid pointer to a `struct pci_dev`. 462 Class::from_raw(unsafe { (*self.as_raw()).class }) 463 } 464 } 465 466 /// Represents an allocated IRQ vector for a specific PCI device. 467 /// 468 /// This type ties an IRQ vector to the device it was allocated for, 469 /// ensuring the vector is only used with the correct device. 470 #[derive(Clone, Copy)] 471 pub struct IrqVector<'a> { 472 dev: &'a Device<Bound>, 473 index: u32, 474 } 475 476 impl<'a> IrqVector<'a> { 477 /// Creates a new [`IrqVector`] for the given device and index. 478 /// 479 /// # Safety 480 /// 481 /// - `index` must be a valid IRQ vector index for `dev`. 482 /// - `dev` must point to a [`Device`] that has successfully allocated IRQ vectors. 483 unsafe fn new(dev: &'a Device<Bound>, index: u32) -> Self { 484 Self { dev, index } 485 } 486 487 /// Returns the raw vector index. 488 fn index(&self) -> u32 { 489 self.index 490 } 491 } 492 493 impl<'a> TryInto<IrqRequest<'a>> for IrqVector<'a> { 494 type Error = Error; 495 496 fn try_into(self) -> Result<IrqRequest<'a>> { 497 // SAFETY: `self.as_raw` returns a valid pointer to a `struct pci_dev`. 498 let irq = unsafe { bindings::pci_irq_vector(self.dev.as_raw(), self.index()) }; 499 if irq < 0 { 500 return Err(crate::error::Error::from_errno(irq)); 501 } 502 // SAFETY: `irq` is guaranteed to be a valid IRQ number for `&self`. 503 Ok(unsafe { IrqRequest::new(self.dev.as_ref(), irq as u32) }) 504 } 505 } 506 507 /// Represents an IRQ vector allocation for a PCI device. 508 /// 509 /// This type ensures that IRQ vectors are properly allocated and freed by 510 /// tying the allocation to the lifetime of this registration object. 511 /// 512 /// # Invariants 513 /// 514 /// The [`Device`] has successfully allocated IRQ vectors. 515 struct IrqVectorRegistration { 516 dev: ARef<Device>, 517 } 518 519 impl IrqVectorRegistration { 520 /// Allocate and register IRQ vectors for the given PCI device. 521 /// 522 /// Allocates IRQ vectors and registers them with devres for automatic cleanup. 523 /// Returns a range of valid IRQ vectors. 524 fn register<'a>( 525 dev: &'a Device<Bound>, 526 min_vecs: u32, 527 max_vecs: u32, 528 irq_types: IrqTypes, 529 ) -> Result<RangeInclusive<IrqVector<'a>>> { 530 // SAFETY: 531 // - `dev.as_raw()` is guaranteed to be a valid pointer to a `struct pci_dev` 532 // by the type invariant of `Device`. 533 // - `pci_alloc_irq_vectors` internally validates all other parameters 534 // and returns error codes. 535 let ret = unsafe { 536 bindings::pci_alloc_irq_vectors(dev.as_raw(), min_vecs, max_vecs, irq_types.as_raw()) 537 }; 538 539 to_result(ret)?; 540 let count = ret as u32; 541 542 // SAFETY: 543 // - `pci_alloc_irq_vectors` returns the number of allocated vectors on success. 544 // - Vectors are 0-based, so valid indices are [0, count-1]. 545 // - `pci_alloc_irq_vectors` guarantees `count >= min_vecs > 0`, so both `0` and 546 // `count - 1` are valid IRQ vector indices for `dev`. 547 let range = unsafe { IrqVector::new(dev, 0)..=IrqVector::new(dev, count - 1) }; 548 549 // INVARIANT: The IRQ vector allocation for `dev` above was successful. 550 let irq_vecs = Self { dev: dev.into() }; 551 devres::register(dev.as_ref(), irq_vecs, GFP_KERNEL)?; 552 553 Ok(range) 554 } 555 } 556 557 impl Drop for IrqVectorRegistration { 558 fn drop(&mut self) { 559 // SAFETY: 560 // - By the type invariant, `self.dev.as_raw()` is a valid pointer to a `struct pci_dev`. 561 // - `self.dev` has successfully allocated IRQ vectors. 562 unsafe { bindings::pci_free_irq_vectors(self.dev.as_raw()) }; 563 } 564 } 565 566 impl Device<device::Bound> { 567 /// Returns a [`kernel::irq::Registration`] for the given IRQ vector. 568 pub fn request_irq<'a, T: crate::irq::Handler + 'static>( 569 &'a self, 570 vector: IrqVector<'a>, 571 flags: irq::Flags, 572 name: &'static CStr, 573 handler: impl PinInit<T, Error> + 'a, 574 ) -> Result<impl PinInit<irq::Registration<T>, Error> + 'a> { 575 let request = vector.try_into()?; 576 577 Ok(irq::Registration::<T>::new(request, flags, name, handler)) 578 } 579 580 /// Returns a [`kernel::irq::ThreadedRegistration`] for the given IRQ vector. 581 pub fn request_threaded_irq<'a, T: crate::irq::ThreadedHandler + 'static>( 582 &'a self, 583 vector: IrqVector<'a>, 584 flags: irq::Flags, 585 name: &'static CStr, 586 handler: impl PinInit<T, Error> + 'a, 587 ) -> Result<impl PinInit<irq::ThreadedRegistration<T>, Error> + 'a> { 588 let request = vector.try_into()?; 589 590 Ok(irq::ThreadedRegistration::<T>::new( 591 request, flags, name, handler, 592 )) 593 } 594 595 /// Allocate IRQ vectors for this PCI device with automatic cleanup. 596 /// 597 /// Allocates between `min_vecs` and `max_vecs` interrupt vectors for the device. 598 /// The allocation will use MSI-X, MSI, or legacy interrupts based on the `irq_types` 599 /// parameter and hardware capabilities. When multiple types are specified, the kernel 600 /// will try them in order of preference: MSI-X first, then MSI, then legacy interrupts. 601 /// 602 /// The allocated vectors are automatically freed when the device is unbound, using the 603 /// devres (device resource management) system. 604 /// 605 /// # Arguments 606 /// 607 /// * `min_vecs` - Minimum number of vectors required. 608 /// * `max_vecs` - Maximum number of vectors to allocate. 609 /// * `irq_types` - Types of interrupts that can be used. 610 /// 611 /// # Returns 612 /// 613 /// Returns a range of IRQ vectors that were successfully allocated, or an error if the 614 /// allocation fails or cannot meet the minimum requirement. 615 /// 616 /// # Examples 617 /// 618 /// ``` 619 /// # use kernel::{ device::Bound, pci}; 620 /// # fn no_run(dev: &pci::Device<Bound>) -> Result { 621 /// // Allocate using any available interrupt type in the order mentioned above. 622 /// let vectors = dev.alloc_irq_vectors(1, 32, pci::IrqTypes::all())?; 623 /// 624 /// // Allocate MSI or MSI-X only (no legacy interrupts). 625 /// let msi_only = pci::IrqTypes::default() 626 /// .with(pci::IrqType::Msi) 627 /// .with(pci::IrqType::MsiX); 628 /// let vectors = dev.alloc_irq_vectors(4, 16, msi_only)?; 629 /// # Ok(()) 630 /// # } 631 /// ``` 632 pub fn alloc_irq_vectors( 633 &self, 634 min_vecs: u32, 635 max_vecs: u32, 636 irq_types: IrqTypes, 637 ) -> Result<RangeInclusive<IrqVector<'_>>> { 638 IrqVectorRegistration::register(self, min_vecs, max_vecs, irq_types) 639 } 640 } 641 642 impl Device<device::Core> { 643 /// Enable memory resources for this device. 644 pub fn enable_device_mem(&self) -> Result { 645 // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. 646 to_result(unsafe { bindings::pci_enable_device_mem(self.as_raw()) }) 647 } 648 649 /// Enable bus-mastering for this device. 650 #[inline] 651 pub fn set_master(&self) { 652 // SAFETY: `self.as_raw` is guaranteed to be a pointer to a valid `struct pci_dev`. 653 unsafe { bindings::pci_set_master(self.as_raw()) }; 654 } 655 } 656 657 // SAFETY: `Device` is a transparent wrapper of a type that doesn't depend on `Device`'s generic 658 // argument. 659 kernel::impl_device_context_deref!(unsafe { Device }); 660 kernel::impl_device_context_into_aref!(Device); 661 662 impl crate::dma::Device for Device<device::Core> {} 663 664 // SAFETY: Instances of `Device` are always reference-counted. 665 unsafe impl crate::sync::aref::AlwaysRefCounted for Device { 666 fn inc_ref(&self) { 667 // SAFETY: The existence of a shared reference guarantees that the refcount is non-zero. 668 unsafe { bindings::pci_dev_get(self.as_raw()) }; 669 } 670 671 unsafe fn dec_ref(obj: NonNull<Self>) { 672 // SAFETY: The safety requirements guarantee that the refcount is non-zero. 673 unsafe { bindings::pci_dev_put(obj.cast().as_ptr()) } 674 } 675 } 676 677 impl<Ctx: device::DeviceContext> AsRef<device::Device<Ctx>> for Device<Ctx> { 678 fn as_ref(&self) -> &device::Device<Ctx> { 679 // SAFETY: By the type invariant of `Self`, `self.as_raw()` is a pointer to a valid 680 // `struct pci_dev`. 681 let dev = unsafe { addr_of_mut!((*self.as_raw()).dev) }; 682 683 // SAFETY: `dev` points to a valid `struct device`. 684 unsafe { device::Device::from_raw(dev) } 685 } 686 } 687 688 impl<Ctx: device::DeviceContext> TryFrom<&device::Device<Ctx>> for &Device<Ctx> { 689 type Error = kernel::error::Error; 690 691 fn try_from(dev: &device::Device<Ctx>) -> Result<Self, Self::Error> { 692 // SAFETY: By the type invariant of `Device`, `dev.as_raw()` is a valid pointer to a 693 // `struct device`. 694 if !unsafe { bindings::dev_is_pci(dev.as_raw()) } { 695 return Err(EINVAL); 696 } 697 698 // SAFETY: We've just verified that the bus type of `dev` equals `bindings::pci_bus_type`, 699 // hence `dev` must be embedded in a valid `struct pci_dev` as guaranteed by the 700 // corresponding C code. 701 let pdev = unsafe { container_of!(dev.as_raw(), bindings::pci_dev, dev) }; 702 703 // SAFETY: `pdev` is a valid pointer to a `struct pci_dev`. 704 Ok(unsafe { &*pdev.cast() }) 705 } 706 } 707 708 // SAFETY: A `Device` is always reference-counted and can be released from any thread. 709 unsafe impl Send for Device {} 710 711 // SAFETY: `Device` can be shared among threads because all methods of `Device` 712 // (i.e. `Device<Normal>) are thread safe. 713 unsafe impl Sync for Device {} 714