1a74931ebSIgor Korotin // SPDX-License-Identifier: GPL-2.0 2a74931ebSIgor Korotin 3a74931ebSIgor Korotin //! Advanced Configuration and Power Interface abstractions. 4a74931ebSIgor Korotin 5*8d84b320SFUJITA Tomonori use crate::{ 6*8d84b320SFUJITA Tomonori bindings, 7*8d84b320SFUJITA Tomonori device_id::{RawDeviceId, RawDeviceIdIndex}, 8*8d84b320SFUJITA Tomonori prelude::*, 9*8d84b320SFUJITA Tomonori }; 10a74931ebSIgor Korotin 11a74931ebSIgor Korotin /// IdTable type for ACPI drivers. 12a74931ebSIgor Korotin pub type IdTable<T> = &'static dyn kernel::device_id::IdTable<DeviceId, T>; 13a74931ebSIgor Korotin 14a74931ebSIgor Korotin /// An ACPI device id. 15a74931ebSIgor Korotin #[repr(transparent)] 16a74931ebSIgor Korotin #[derive(Clone, Copy)] 17a74931ebSIgor Korotin pub struct DeviceId(bindings::acpi_device_id); 18a74931ebSIgor Korotin 19*8d84b320SFUJITA Tomonori // SAFETY: `DeviceId` is a `#[repr(transparent)]` wrapper of `acpi_device_id` and does not add 20a74931ebSIgor Korotin // additional invariants, so it's safe to transmute to `RawType`. 21a74931ebSIgor Korotin unsafe impl RawDeviceId for DeviceId { 22a74931ebSIgor Korotin type RawType = bindings::acpi_device_id; 23*8d84b320SFUJITA Tomonori } 24a74931ebSIgor Korotin 25*8d84b320SFUJITA Tomonori // SAFETY: `DRIVER_DATA_OFFSET` is the offset to the `driver_data` field. 26*8d84b320SFUJITA Tomonori unsafe impl RawDeviceIdIndex for DeviceId { 27a74931ebSIgor Korotin const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::acpi_device_id, driver_data); 28a74931ebSIgor Korotin index(&self) -> usize29a74931ebSIgor Korotin fn index(&self) -> usize { 3097ba207aSMiguel Ojeda self.0.driver_data 31a74931ebSIgor Korotin } 32a74931ebSIgor Korotin } 33a74931ebSIgor Korotin 34a74931ebSIgor Korotin impl DeviceId { 35a74931ebSIgor Korotin const ACPI_ID_LEN: usize = 16; 36a74931ebSIgor Korotin 37a74931ebSIgor Korotin /// Create a new device id from an ACPI 'id' string. 38a74931ebSIgor Korotin #[inline(always)] new(id: &'static CStr) -> Self39a74931ebSIgor Korotin pub const fn new(id: &'static CStr) -> Self { 40a74931ebSIgor Korotin build_assert!( 41a74931ebSIgor Korotin id.len_with_nul() <= Self::ACPI_ID_LEN, 42a74931ebSIgor Korotin "ID exceeds 16 bytes" 43a74931ebSIgor Korotin ); 44a74931ebSIgor Korotin let src = id.as_bytes_with_nul(); 45a74931ebSIgor Korotin // Replace with `bindings::acpi_device_id::default()` once stabilized for `const`. 46a74931ebSIgor Korotin // SAFETY: FFI type is valid to be zero-initialized. 47a74931ebSIgor Korotin let mut acpi: bindings::acpi_device_id = unsafe { core::mem::zeroed() }; 48a74931ebSIgor Korotin let mut i = 0; 49a74931ebSIgor Korotin while i < src.len() { 50a74931ebSIgor Korotin acpi.id[i] = src[i]; 51a74931ebSIgor Korotin i += 1; 52a74931ebSIgor Korotin } 53a74931ebSIgor Korotin 54a74931ebSIgor Korotin Self(acpi) 55a74931ebSIgor Korotin } 56a74931ebSIgor Korotin } 57a74931ebSIgor Korotin 58a74931ebSIgor Korotin /// Create an ACPI `IdTable` with an "alias" for modpost. 59a74931ebSIgor Korotin #[macro_export] 60a74931ebSIgor Korotin macro_rules! acpi_device_table { 61a74931ebSIgor Korotin ($table_name:ident, $module_table_name:ident, $id_info_type: ty, $table_data: expr) => { 62a74931ebSIgor Korotin const $table_name: $crate::device_id::IdArray< 63a74931ebSIgor Korotin $crate::acpi::DeviceId, 64a74931ebSIgor Korotin $id_info_type, 65a74931ebSIgor Korotin { $table_data.len() }, 66a74931ebSIgor Korotin > = $crate::device_id::IdArray::new($table_data); 67a74931ebSIgor Korotin 68a74931ebSIgor Korotin $crate::module_device_table!("acpi", $module_table_name, $table_name); 69a74931ebSIgor Korotin }; 70a74931ebSIgor Korotin } 71