• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! ACPI defines a Generic Address Structure (GAS), which provides a versatile way to describe register locations
2 //! in a wide range of address spaces.
3 
4 use crate::AcpiError;
5 use core::convert::TryFrom;
6 
7 /// This is the raw form of a Generic Address Structure, and follows the layout found in the ACPI tables. It does
8 /// not form part of the public API, and should be turned into a `GenericAddress` for most use-cases.
9 #[derive(Clone, Copy, Debug)]
10 #[repr(C, packed)]
11 pub(crate) struct RawGenericAddress {
12     pub address_space: u8,
13     pub bit_width: u8,
14     pub bit_offset: u8,
15     pub access_size: u8,
16     pub address: u64,
17 }
18 
19 impl RawGenericAddress {
is_empty(&self) -> bool20     pub(crate) const fn is_empty(&self) -> bool {
21         self.address_space == 0
22             && self.bit_width == 0
23             && self.bit_offset == 0
24             && self.access_size == 0
25             && self.address == 0
26     }
27 }
28 
29 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
30 pub enum AddressSpace {
31     SystemMemory,
32     SystemIo,
33     /// Describes a register in the configuration space of a PCI device in segment `0`, on bus `0`. The `address`
34     /// field is of the format:
35     /// ```ignore
36     /// 64              48              32              16               0
37     ///  +---------------+---------------+---------------+---------------+
38     ///  |  reserved (0) |    device     |   function    |    offset     |
39     ///  +---------------+---------------+---------------+---------------+
40     /// ```
41     PciConfigSpace,
42     EmbeddedController,
43     SMBus,
44     SystemCmos,
45     PciBarTarget,
46     Ipmi,
47     GeneralIo,
48     GenericSerialBus,
49     PlatformCommunicationsChannel,
50     FunctionalFixedHardware,
51     OemDefined(u8),
52 }
53 
54 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
55 pub enum AccessSize {
56     Undefined,
57     ByteAccess,
58     WordAccess,
59     DWordAccess,
60     QWordAccess,
61 }
62 
63 impl TryFrom<u8> for AccessSize {
64     type Error = AcpiError;
65 
try_from(size: u8) -> Result<Self, Self::Error>66     fn try_from(size: u8) -> Result<Self, Self::Error> {
67         match size {
68             0 => Ok(AccessSize::Undefined),
69             1 => Ok(AccessSize::ByteAccess),
70             2 => Ok(AccessSize::WordAccess),
71             3 => Ok(AccessSize::DWordAccess),
72             4 => Ok(AccessSize::QWordAccess),
73             _ => Err(AcpiError::InvalidGenericAddress),
74         }
75     }
76 }
77 
78 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
79 pub struct GenericAddress {
80     pub address_space: AddressSpace,
81     pub bit_width: u8,
82     pub bit_offset: u8,
83     pub access_size: AccessSize,
84     pub address: u64,
85 }
86 
87 impl GenericAddress {
from_raw(raw: RawGenericAddress) -> crate::AcpiResult<GenericAddress>88     pub(crate) fn from_raw(raw: RawGenericAddress) -> crate::AcpiResult<GenericAddress> {
89         let address_space = match raw.address_space {
90             0x00 => AddressSpace::SystemMemory,
91             0x01 => AddressSpace::SystemIo,
92             0x02 => AddressSpace::PciConfigSpace,
93             0x03 => AddressSpace::EmbeddedController,
94             0x04 => AddressSpace::SMBus,
95             0x05 => AddressSpace::SystemCmos,
96             0x06 => AddressSpace::PciBarTarget,
97             0x07 => AddressSpace::Ipmi,
98             0x08 => AddressSpace::GeneralIo,
99             0x09 => AddressSpace::GenericSerialBus,
100             0x0a => AddressSpace::PlatformCommunicationsChannel,
101             0x0b..=0x7e => return Err(AcpiError::InvalidGenericAddress),
102             0x7f => AddressSpace::FunctionalFixedHardware,
103             0x80..=0xbf => return Err(AcpiError::InvalidGenericAddress),
104             0xc0..=0xff => AddressSpace::OemDefined(raw.address_space),
105         };
106 
107         Ok(GenericAddress {
108             address_space,
109             bit_width: raw.bit_width,
110             bit_offset: raw.bit_offset,
111             access_size: AccessSize::try_from(raw.access_size)?,
112             address: raw.address,
113         })
114     }
115 }
116