PatchworkOS  2ca1c69
A non-POSIX operating system.
Loading...
Searching...
No Matches
resources.h
Go to the documentation of this file.
1#pragma once
2
3#include <kernel/defs.h>
5#include <stdint.h>
6
7/**
8 * @brief ACPI resource settings.
9 * @defgroup modules_acpi_resources Resources
10 * @ingroup modules_acpi
11 *
12 * In the AML namespace heirarchy each device uses a buffer object, usually returned by their `_CRS` method, to describe
13 * the resources they require, for example IO ports, IRQs, DMA channels, etc.
14 *
15 * For the vast majority of use cases, its recommended to use the device abstraction layer provided by the `devices.h`
16 * file or @ref modules_acpi_devices instead of directly parsing these overcomplicated structures.
17 *
18 * ## Example
19 *
20 * So, lets take a PS2 keyboard as an example. The PS2 keyboard device will have `_CRS` method that when evaluated will
21 * return a buffer object. This buffer object will contain data in the format outlined by the structures within this
22 * section, which describe the IO ports and the IRQ that the keyboard expects to use, most likely IO ports `0x60` and
23 * `0x64` and IRQ `1`. Much more could be described, like IRQ trigger modes, polarity, DMA channels, etc. but this is a
24 * simple example.
25 *
26 * ## Resource Data Format
27 *
28 * The resource data is made up of a series of resource descriptors of varying formats and lengths. All descriptor types
29 * are either "small" or "large", depending on the value of the first byte of the descriptor, which decides the header
30 * used by the descriptor. After the header comes the actual data for the descriptor, which is descriptor specific,
31 * finally either another descriptor follows or the end of the resource data is reached, indicated by the "End Tag"
32 * descriptor.
33 *
34 * ## Helpers
35 *
36 * Since the resource descriptor format is kinda messy, a abstraction layer is provided in the form of helper macros
37 * which should always be used instead of directly parsing the resource data.
38 *
39 * @see Section 6.4 of the ACPI specification for more details.
40 *
41 * @{
42 */
43
44/**
45 * @brief ACPI small resource header.
46 * @struct acpi_resource_small_t
47 *
48 * Note that the `isLarge` field is in the same position as the `isLarge` field in the large resource header.
49 */
50typedef struct PACKED
51{
52 uint8_t length : 3; ///< Does not include the header byte.
53 uint8_t itemName : 4; ///< acpi_item_name_small_t
54 uint8_t isLarge : 1; ///< Always 0 for small resource types.
56
57/**
58 * @brief ACPI large resource header.
59 * @struct acpi_resource_large_t
60 *
61 * Note that the `isLarge` field is in the same position as the `isLarge` field in the small resource header.
62 */
63typedef struct PACKED
64{
65 uint8_t itemName : 7; ///< acpi_item_name_large_t
66 uint8_t isLarge : 1; ///< Always 1 for large resource types.
67 uint16_t length; ///< Does not include the header bytes.
69
70/**
71 * @brief ACPI IRQ resource descriptor.
72 * @struct acpi_irq_descriptor_t
73 *
74 * @note The actual IRQ resource descriptor may contain an additional byte at the end depending on if the `length` field
75 * in the header is `2` or `3`. To maintain type safety we do not include this byte in the structure. Instead use the
76 * `ACPI_IRQ_DESCRIPTOR_INFO()` macro to access it if needed.
77 */
78typedef struct PACKED
79{
81 uint16_t mask; ///< Mask of IRQs used by the device, bit 0 = IRQ 0, bit 1 = IRQ 1, etc..
83
84/**
85 * @brief ACPI IRQ descriptor info flags.
86 * @enum acpi_irq_descriptor_info_t
87 *
88 * Stored in the optional third byte of the IRQ resource descriptor, if the third byte is not present then assume "edge
89 * sensitive, high true interrupts", as in all zeroes.
90 */
91typedef enum
92{
93 ACPI_IRQ_LEVEL_TRIGGERED = 0 << 0, ///< Interrupt is triggered in response to signal in a low state.
95 1 << 0, ///< Interrupt is triggered in response to a change in signal state from low to high.
96 ACPI_IRQ_ACTIVE_HIGH = 0 << 3, ///< This interrupt is sampled with the signal is high, or true.
97 ACPI_IRQ_ACTIVE_LOW = 1 << 3, ///< This interrupt is sampled with the signal is low, or false.
98 ACPI_IRQ_SHARED = 0 << 4, ///< This interrupt is shared with other devices.
99 ACPI_IRQ_EXCLUSIVE = 1 << 4, ///< This interrupt is not shared with other devices.
100 ACPI_IRQ_NOT_WAKE_CAPABLE = 0 << 5, ///< This interrupt is not capable of waking the system.
102 1 << 5, ///< This interrupt is capable of waking the system from a low-power idle state or a system sleep state.
106
107/**
108 * @brief Retrieves the IRQ descriptor info flags from an IRQ resource descriptor.
109 *
110 * Will assume all zeroes if the optional third byte is not present.
111 *
112 * @param descriptor Pointer to an `acpi_irq_descriptor_t` structure.
113 * @return The IRQ descriptor info flags as an `acpi_irq_descriptor_info_t` value.
114 */
115#define ACPI_IRQ_DESCRIPTOR_INFO(descriptor) \
116 ((acpi_irq_descriptor_info_t)((descriptor)->header.length >= 3 \
117 ? *((((uint8_t*)(descriptor)) + sizeof(acpi_irq_descriptor_t))) \
118 : 0))
119
120/**
121 * @brief ACPI IO port resource descriptor.
122 * @struct acpi_io_port_descriptor_t
123 *
124 * Used by a device to request IO port resources with some constraints, like alignment and address range.
125 *
126 * ## Port Reservation Rules
127 *
128 * The `minBase` and `maxBase` fields defines the min and maximum starting address of the IO port range, not the entire
129 * range. For example, if a device requires 8 IO ports and has `minBase = 0x10` and `maxBase = 0x20` then allocating
130 * ports `0x20` to `0x27` would be valid.
131 *
132 * The `alignment` field defines the alignment of the starting address of the IO port range. For example, if a device
133 * requires 8 IO ports and has `alignment = 0x08`, then valid starting addresses would be `0x00`, `0x08`, `0x10`,
134 * `0x18`, etc.
135 *
136 * The `length` field defines the number of contiguous IO ports required by the device.
137 *
138 * Finally, the `decode16` field defines whether the device uses 10-bit or 16-bit IO port decoding. As in, if it will
139 * only consider the lower 10 bits of the IO port address, or all 16 bits.
140 *
141 * @note Certain legacy devices, like the PS/2 controller, will have fixed IO port addresses and will set the `minBase`
142 * and `maxBase` fields set to the same value.
143 */
144typedef struct PACKED
145{
147 uint8_t decode16 : 1; ///< 0 = 10-bit decoding, 1 = 16-bit decoding.
149 uint16_t minBase; ///< Minimum base IO port address that may be used for the device.
150 uint16_t maxBase; ///< Maximum base IO port address that may be used for the device.
151 uint8_t alignment; ///< Alignment of the IO port(s) to utilize within the min and max range.
152 uint8_t length; ///< The amount of contiguous IO ports required by the device.
154
155/**
156 * @brief ACPI end tag resource descriptor.
157 * @struct acpi_end_tag_t
158 *
159 * Found at the end of a resource settings buffer.
160 */
161typedef struct PACKED
162{
164 uint8_t checksum; ///< Checksum to ensure that the sum of all bytes in the resource data is zero.
166
167/**
168 * @brief Small ACPI resource item names.
169 * @enum acpi_item_name_small_t
170 *
171 * This enum stores the values that will be found in the actual small resource descriptor headers.
172 */
179
180/**
181 * @brief Large ACPI resource item names.
182 * @enum acpi_item_name_large_t
183 *
184 * This enum stores the values that will be found in the actual large resource descriptor headers.
185 */
190
191/**
192 * @brief ACPI resources structure.
193 * @struct acpi_resources_t
194 *
195 * Buffer to store all the resource descriptors for a device.
196 */
202
203/**
204 * @brief Generic ACPI resource descriptor.
205 * @struct acpi_resource_t
206 *
207 * Used as a intermediate structure to determine if a resource descriptor is small or large.
208 */
209typedef struct PACKED
210{
212 uint8_t isLarge : 1; ///< Same position in both small and large resource headers.
214
215/**
216 * @brief Generic ACPI resource item names.
217 * @enum acpi_item_name_t
218 *
219 * This enum stores the values returned by `ACPI_RESOURCE_ITEM_NAME()` macro, NOT the actual values found in the
220 * resource descriptor headers.
221 *
222 * Used to simplify checking the type of a resource descriptor.
223 */
233
234/**
235 * @brief Helper macro to get the generic item name of a resource descriptor.
236 *
237 * Abstracts away the difference between small and large resource descriptors, after this any resource can be type cast
238 * to the expected structure based on the returned item name.
239 *
240 * @param resource Pointer to an `acpi_resource_t` structure.
241 * @return The item name of the resource descriptor as an `acpi_item_name_t` value.
242 */
243#define ACPI_RESOURCE_ITEM_NAME(resource) \
244 (((resource)->isLarge) \
245 ? (acpi_item_name_t)(ACPI_ITEM_NAME_LARGE_BASE + ((acpi_resource_large_t*)(resource))->itemName) \
246 : (acpi_item_name_t)((acpi_resource_small_t*)(resource))->itemName)
247
248/**
249 * @brief Helper macro to get the size of a resource descriptor.
250 *
251 * @param resource Pointer to an `acpi_resource_t` structure.
252 * @return The size of the entire resource descriptor, including the header.
253 */
254#define ACPI_RESOURCE_SIZE(resource) \
255 (((resource)->isLarge) ? ((acpi_resource_large_t*)(resource))->length + sizeof(acpi_resource_large_t) \
256 : ((acpi_resource_small_t*)(resource))->length + sizeof(acpi_resource_small_t))
257
258/**
259 * @brief Helper macro to iterate over all resource descriptors in an ACPI resources structure.
260 *
261 * Works by initializing a pointer to the start of the resource data and then iterating over each descriptor by checking
262 * if its a small or large descriptor, retreving its size, and moving the pointer forward by that size.
263 *
264 * @param resource Pointer to an `acpi_resource_t` structure that will be set to each resource descriptor in the
265 * iteration.
266 * @param resources The `acpi_resources_t` structure to iterate over.
267 */
268#define ACPI_RESOURCES_FOR_EACH(resource, resources) \
269 for (uint8_t* __ptr = (resources)->data; \
270 (__ptr < (resources)->data + (resources)->length) && ((resource) = (acpi_resource_t*)__ptr) && \
271 (__ptr + ACPI_RESOURCE_SIZE(resource) <= (resources)->data + (resources)->length); \
272 __ptr += ACPI_RESOURCE_SIZE(resource))
273
274/**
275 * @brief Get the current ACPI resource settings for a device.
276 *
277 * Will ensure the data return by the device's `_CRS` method is valid, no need for the caller to do so.
278 *
279 * @param device The device object in the AML namespace.
280 * @return On success, a allocated resources structure. On failure, `NULL` and `errno` is set to:
281 * - `EINVAL`: Invalid parameters.
282 * - `ENOENT`: The device has no `_CRS` method.
283 * - `EILSEQ`: Unexpected data from the `_CRS` method.
284 * - `ENOMEM`: Out of memory.
285 * - Other values from `aml_evaluate()`.
286 */
288
289/**
290 * @brief Free an ACPI resources structure.
291 *
292 * @param resources Pointer to the resources structure to free.
293 */
295
296/** @} */
static fd_t data
Definition dwm.c:21
#define PACKED
GCC packed attribute.
Definition defs.h:32
void acpi_resources_free(acpi_resources_t *resources)
Free an ACPI resources structure.
Definition resources.c:116
acpi_irq_descriptor_info_t
ACPI IRQ descriptor info flags.
Definition resources.h:92
acpi_resources_t * acpi_resources_current(aml_object_t *device)
Get the current ACPI resource settings for a device.
Definition resources.c:25
acpi_item_name_large_t
Large ACPI resource item names.
Definition resources.h:187
acpi_item_name_small_t
Small ACPI resource item names.
Definition resources.h:174
acpi_item_name_t
Generic ACPI resource item names.
Definition resources.h:225
@ ACPI_IRQ_EDGE_TRIGGERED
Interrupt is triggered in response to a change in signal state from low to high.
Definition resources.h:94
@ ACPI_IRQ_RESERVED2
Definition resources.h:104
@ ACPI_IRQ_ACTIVE_HIGH
This interrupt is sampled with the signal is high, or true.
Definition resources.h:96
@ ACPI_IRQ_EXCLUSIVE
This interrupt is not shared with other devices.
Definition resources.h:99
@ ACPI_IRQ_WAKE_CAPABLE
This interrupt is capable of waking the system from a low-power idle state or a system sleep state.
Definition resources.h:101
@ ACPI_IRQ_NOT_WAKE_CAPABLE
This interrupt is not capable of waking the system.
Definition resources.h:100
@ ACPI_IRQ_ACTIVE_LOW
This interrupt is sampled with the signal is low, or false.
Definition resources.h:97
@ ACPI_IRQ_LEVEL_TRIGGERED
Interrupt is triggered in response to signal in a low state.
Definition resources.h:93
@ ACPI_IRQ_RESERVED1
Definition resources.h:103
@ ACPI_IRQ_SHARED
This interrupt is shared with other devices.
Definition resources.h:98
@ ACPI_LARGE_ITEM_24_MEM_RANGE
Definition resources.h:188
@ ACPI_ITEM_SMALL_END_TAG
Definition resources.h:177
@ ACPI_ITEM_SMALL_IO_PORT
Definition resources.h:176
@ ACPI_ITEM_SMALL_IRQ
Definition resources.h:175
@ ACPI_ITEM_NAME_IRQ
Definition resources.h:226
@ ACPI_ITEM_NAME_END_TAG
Definition resources.h:228
@ ACPI_ITEM_NAME_24_MEM_RANGE
Definition resources.h:231
@ ACPI_ITEM_NAME_LARGE_BASE
Definition resources.h:230
@ ACPI_ITEM_NAME_IO_PORT
Definition resources.h:227
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
__UINT16_TYPE__ uint16_t
Definition stdint.h:13
ACPI end tag resource descriptor.
Definition resources.h:162
uint8_t checksum
Checksum to ensure that the sum of all bytes in the resource data is zero.
Definition resources.h:164
acpi_resource_small_t header
Definition resources.h:163
ACPI IO port resource descriptor.
Definition resources.h:145
uint8_t alignment
Alignment of the IO port(s) to utilize within the min and max range.
Definition resources.h:151
uint16_t minBase
Minimum base IO port address that may be used for the device.
Definition resources.h:149
acpi_resource_small_t header
Definition resources.h:146
uint8_t decode16
0 = 10-bit decoding, 1 = 16-bit decoding.
Definition resources.h:147
uint16_t maxBase
Maximum base IO port address that may be used for the device.
Definition resources.h:150
uint8_t length
The amount of contiguous IO ports required by the device.
Definition resources.h:152
ACPI IRQ resource descriptor.
Definition resources.h:79
acpi_resource_small_t header
Definition resources.h:80
uint16_t mask
Mask of IRQs used by the device, bit 0 = IRQ 0, bit 1 = IRQ 1, etc..
Definition resources.h:81
ACPI large resource header.
Definition resources.h:64
uint16_t length
Does not include the header bytes.
Definition resources.h:67
uint8_t itemName
acpi_item_name_large_t
Definition resources.h:65
uint8_t isLarge
Always 1 for large resource types.
Definition resources.h:66
ACPI small resource header.
Definition resources.h:51
uint8_t isLarge
Always 0 for small resource types.
Definition resources.h:54
uint8_t itemName
acpi_item_name_small_t
Definition resources.h:53
uint8_t length
Does not include the header byte.
Definition resources.h:52
Generic ACPI resource descriptor.
Definition resources.h:210
uint8_t reserved
Definition resources.h:211
uint8_t isLarge
Same position in both small and large resource headers.
Definition resources.h:212
ACPI resources structure.
Definition resources.h:198
uint64_t length
Definition resources.h:199
ACPI object.
Definition object.h:447