|
1 | 1 | /** |
2 | 2 | * @file acpi.h |
3 | 3 | * @author Craig Edwards (craigedwards@brainbox.cc) |
4 | | - * @copyright Copyright (c) 2012-2025 |
| 4 | + * @brief ACPI detection and enumeration header. Provides low-level interfaces |
| 5 | + * to extract CPU topology, IOAPIC mappings, and PCI IRQ routing from |
| 6 | + * ACPI tables such as RSDP, XSDT, MADT, and others. |
| 7 | + * @copyright Copyright (c) 2012–2025 |
5 | 8 | */ |
6 | 9 | #pragma once |
7 | 10 |
|
8 | 11 | #include <kernel.h> |
9 | 12 |
|
10 | 13 | /** |
11 | 14 | * @brief ACPI Root System Description Pointer (RSDP) |
| 15 | + * |
| 16 | + * This structure serves as the entry point to the ACPI system description tables. |
| 17 | + * Its location is typically found by scanning the BIOS memory range. It may point |
| 18 | + * to either the RSDT (ACPI 1.0) or XSDT (ACPI 2.0+). |
12 | 19 | */ |
13 | 20 | typedef struct rsdp_t { |
14 | | - char signature[8]; // "RSD PTR " |
15 | | - uint8_t checksum; |
16 | | - char oem_id[6]; // OEM identifier string |
17 | | - uint8_t revision; // 0 for ACPI 1.0, >0 for ACPI 2.0 or later |
18 | | - uint32_t rsdt_address; // Root System Description Table Address |
19 | | - uint32_t length; // Length of Root System Description Table |
20 | | - uint64_t xsdt_address; // Extended System Description Table Address |
21 | | - uint8_t extended_checksum; // Extended System Description Table Checksum |
22 | | - uint8_t reserved[3]; // Reserved |
| 21 | + char signature[8]; ///< Should contain "RSD PTR " |
| 22 | + uint8_t checksum; ///< Checksum of first 20 bytes |
| 23 | + char oem_id[6]; ///< OEM identifier string |
| 24 | + uint8_t revision; ///< Revision: 0 = ACPI 1.0, 2+ = ACPI 2.0+ |
| 25 | + uint32_t rsdt_address; ///< 32-bit physical address of RSDT |
| 26 | + uint32_t length; ///< Total length of the RSDP (ACPI 2.0+) |
| 27 | + uint64_t xsdt_address; ///< 64-bit physical address of XSDT (ACPI 2.0+) |
| 28 | + uint8_t extended_checksum; ///< Checksum of entire RSDP (ACPI 2.0+) |
| 29 | + uint8_t reserved[3]; ///< Reserved bytes (must be zero) |
23 | 30 | } __attribute__((packed)) rsdp_t; |
24 | 31 |
|
25 | 32 | /** |
26 | | - * @brief System Description Table Header |
| 33 | + * @brief Generic ACPI System Description Table Header |
| 34 | + * |
| 35 | + * All ACPI tables begin with this header. It is used to identify table type, |
| 36 | + * length, version, and source information. |
27 | 37 | */ |
28 | 38 | typedef struct sdt_header_t { |
29 | | - char signature[4]; |
30 | | - uint32_t length; |
31 | | - uint8_t revision; |
32 | | - uint8_t checksum; |
33 | | - char oem_id[6]; |
34 | | - char oem_table_id[8]; |
35 | | - uint32_t oem_revision; |
36 | | - uint32_t creator_id; |
37 | | - uint32_t creator_revision; |
| 39 | + char signature[4]; ///< Table identifier (e.g. "APIC", "DSDT", etc.) |
| 40 | + uint32_t length; ///< Total length of the table, including this header |
| 41 | + uint8_t revision; ///< Table version |
| 42 | + uint8_t checksum; ///< Entire table checksum |
| 43 | + char oem_id[6]; ///< OEM identifier string |
| 44 | + char oem_table_id[8]; ///< OEM-defined table identifier |
| 45 | + uint32_t oem_revision; ///< OEM table revision |
| 46 | + uint32_t creator_id; ///< Vendor ID of utility that created the table |
| 47 | + uint32_t creator_revision; ///< Version of utility that created the table |
38 | 48 | } __attribute__((packed)) sdt_header_t; |
39 | 49 |
|
40 | 50 | /** |
41 | | - * @brief Root System Description Table |
| 51 | + * @brief Root System Description Table (RSDT) |
| 52 | + * |
| 53 | + * Points to other system description tables using 32-bit addresses. |
| 54 | + * Superseded by XSDT in ACPI 2.0+ which uses 64-bit addresses. |
42 | 55 | */ |
43 | 56 | typedef struct rsdt_t { |
44 | | - sdt_header_t header; // System Description Table header |
45 | | - uint32_t pointer_to_other_sdt[]; // 32-Bit Pointer to other table |
46 | | - |
| 57 | + sdt_header_t header; ///< Standard ACPI header |
| 58 | + uint32_t pointer_to_other_sdt[]; ///< Array of 32-bit physical addresses to other tables |
47 | 59 | } __attribute__((packed)) rsdt_t; |
48 | 60 |
|
49 | 61 | /** |
50 | | - * @brief Definition of an IOAPIC |
| 62 | + * @brief Describes a detected IOAPIC from the MADT table. |
51 | 63 | */ |
52 | 64 | typedef struct ioapic_t { |
53 | | - uint8_t id; // The IO APIC id. |
54 | | - uint64_t paddr; // The physical address of the MMIO region. |
55 | | - uint32_t gsi_base; // The GSI base. |
56 | | - uint8_t gsi_count; // The interrupt count. |
| 65 | + uint8_t id; ///< IOAPIC ID as reported by MADT |
| 66 | + uint64_t paddr; ///< Physical address of the IOAPIC's MMIO region |
| 67 | + uint32_t gsi_base; ///< Global System Interrupt (GSI) base for this IOAPIC |
| 68 | + uint8_t gsi_count; ///< Number of GSIs this IOAPIC handles |
57 | 69 | } ioapic_t; |
58 | 70 |
|
| 71 | +/** |
| 72 | + * @brief Describes an IRQ override from the MADT table. |
| 73 | + * |
| 74 | + * Used to override the default IRQ to GSI mapping, and specify trigger mode and polarity. |
| 75 | + */ |
59 | 76 | typedef struct { |
60 | | - uint8_t type; |
61 | | - uint8_t length; |
62 | | - uint8_t bus_source; |
63 | | - uint8_t irq_source; |
64 | | - uint32_t gsi; |
65 | | - uint16_t flags; |
| 77 | + uint8_t type; ///< Entry type (always 2 for overrides) |
| 78 | + uint8_t length; ///< Length of this entry |
| 79 | + uint8_t bus_source; ///< Typically 0 (ISA bus) |
| 80 | + uint8_t irq_source; ///< Original IRQ number |
| 81 | + uint32_t gsi; ///< New GSI mapping |
| 82 | + uint16_t flags; ///< Bitmask defining polarity and trigger mode |
66 | 83 | } __attribute__((packed)) madt_override_t; |
67 | 84 |
|
68 | | -#define IRQ_DEFAULT_POLARITY 0 // active high |
69 | | -#define IRQ_DEFAULT_TRIGGER 0 // edge |
| 85 | +/** |
| 86 | + * @brief Default polarity: active high |
| 87 | + */ |
| 88 | +#define IRQ_DEFAULT_POLARITY 0 |
| 89 | + |
| 90 | +/** |
| 91 | + * @brief Default trigger mode: edge-triggered |
| 92 | + */ |
| 93 | +#define IRQ_DEFAULT_TRIGGER 0 |
70 | 94 |
|
| 95 | +/** |
| 96 | + * @brief Indicates the source of a PCI IRQ route. |
| 97 | + */ |
71 | 98 | typedef enum detected_from { |
72 | | - FROM_MADT, |
73 | | - FROM_PRT, |
74 | | - FROM_FALLBACK, |
| 99 | + FROM_MADT, ///< IRQ derived from MADT (ACPI interrupt overrides) |
| 100 | + FROM_PRT, ///< IRQ derived from PCI Routing Table (_PRT) |
| 101 | + FROM_FALLBACK, ///< No override detected, fallback to default IRQ mapping |
75 | 102 | } detected_from_t; |
76 | 103 |
|
| 104 | +/** |
| 105 | + * @brief A mapping of PCI interrupt pin to global system interrupt (GSI). |
| 106 | + * |
| 107 | + * Used for routing PCI IRQs through ACPI, based on _PRT or MADT. |
| 108 | + */ |
77 | 109 | typedef struct pci_irq_route { |
78 | | - bool exists; |
79 | | - uint8_t int_pin; |
80 | | - uint32_t gsi; |
81 | | - int polarity; // 0 = high, 1 = low |
82 | | - int trigger; // 0 = edge, 1 = level |
83 | | - detected_from_t detected_from; |
| 110 | + bool exists; ///< True if this route is defined |
| 111 | + uint8_t int_pin; ///< PCI interrupt pin (INTA–INTD) |
| 112 | + uint32_t gsi; ///< Global System Interrupt (GSI) to which the pin maps |
| 113 | + int polarity; ///< Interrupt polarity (0 = high, 1 = low) |
| 114 | + int trigger; ///< Trigger mode (0 = edge, 1 = level) |
| 115 | + detected_from_t detected_from; ///< Source of route (MADT, PRT, or fallback) |
84 | 116 | } pci_irq_route_t; |
85 | 117 |
|
86 | | -#define MAX_PCI_ROUTES 256 |
| 118 | +#define MAX_PCI_ROUTES 256 ///< Maximum number of PCI IRQ routes supported |
87 | 119 |
|
88 | 120 | /** |
89 | | - * @brief Detect SMP cores, IOAPICs, Local APICs |
| 121 | + * @brief Detect SMP CPU cores and APICs (Local and IOAPIC). |
| 122 | + * |
| 123 | + * This function parses the MADT (APIC table) and sets up CPU topology and IOAPIC data. |
90 | 124 | */ |
91 | 125 | void init_cores(); |
92 | 126 |
|
93 | 127 | /** |
94 | | - * @brief Get the local apic ids |
95 | | - * |
96 | | - * @return uint8_t* |
| 128 | + * @brief Get an array of Local APIC IDs. |
| 129 | + * |
| 130 | + * @return Pointer to array of LAPIC IDs (size = get_cpu_count()). |
97 | 131 | */ |
98 | 132 | uint8_t* get_lapic_ids(); |
99 | 133 |
|
100 | 134 | /** |
101 | | - * @brief Get the cpu count |
102 | | - * |
103 | | - * @return uint16_t |
| 135 | + * @brief Get total number of CPUs detected via ACPI. |
| 136 | + * |
| 137 | + * @return Number of CPUs detected. |
104 | 138 | */ |
105 | 139 | uint16_t get_cpu_count(); |
106 | 140 |
|
107 | 141 | /** |
108 | | - * @brief Get the local apic |
109 | | - * |
110 | | - * @return uint64_t |
| 142 | + * @brief Retrieve the physical address of the Local APIC MMIO. |
| 143 | + * |
| 144 | + * @return 64-bit physical address of LAPIC base. |
111 | 145 | */ |
112 | 146 | uint64_t get_local_apic(); |
113 | 147 |
|
114 | 148 | /** |
115 | | - * @brief Get the ioapic |
116 | | - * |
117 | | - * @param index IOAPIC index |
118 | | - * @return ioapic_t |
| 149 | + * @brief Retrieve the IOAPIC structure by index. |
| 150 | + * |
| 151 | + * @param index IOAPIC index in internal array |
| 152 | + * @return ioapic_t structure containing details of the IOAPIC |
119 | 153 | */ |
120 | 154 | ioapic_t get_ioapic(uint16_t index); |
121 | 155 |
|
122 | 156 | /** |
123 | | - * @brief Get the ioapic count |
124 | | - * |
125 | | - * @return uint16_t total number of IOAPICs |
| 157 | + * @brief Get the total number of IOAPICs detected in the system. |
| 158 | + * |
| 159 | + * @return Number of IOAPICs. |
126 | 160 | */ |
127 | 161 | uint16_t get_ioapic_count(); |
128 | 162 |
|
| 163 | +/** |
| 164 | + * @brief Translate a legacy IRQ number (0–15) into a GSI using overrides. |
| 165 | + * |
| 166 | + * @param irq Legacy IRQ number |
| 167 | + * @return Global System Interrupt (GSI) for the IRQ |
| 168 | + */ |
129 | 169 | uint32_t irq_to_gsi(uint8_t irq); |
130 | 170 |
|
| 171 | +/** |
| 172 | + * @brief Determine the interrupt polarity of a given IRQ. |
| 173 | + * |
| 174 | + * @param irq IRQ number |
| 175 | + * @return 0 for active high, 1 for active low |
| 176 | + */ |
131 | 177 | uint8_t get_irq_polarity(uint8_t irq); |
132 | 178 |
|
| 179 | +/** |
| 180 | + * @brief Determine the trigger mode of a given IRQ. |
| 181 | + * |
| 182 | + * @param irq IRQ number |
| 183 | + * @return 0 for edge-triggered, 1 for level-triggered |
| 184 | + */ |
133 | 185 | uint8_t get_irq_trigger_mode(uint8_t irq); |
134 | 186 |
|
| 187 | +/** |
| 188 | + * @brief Return human-readable string for trigger mode. |
| 189 | + * |
| 190 | + * @param trig Trigger mode value |
| 191 | + * @return "edge" or "level" |
| 192 | + */ |
135 | 193 | const char *triggering_str(uint8_t trig); |
136 | 194 |
|
| 195 | +/** |
| 196 | + * @brief Return human-readable string for polarity. |
| 197 | + * |
| 198 | + * @param pol Polarity value |
| 199 | + * @return "high" or "low" |
| 200 | + */ |
137 | 201 | const char *polarity_str(uint8_t pol); |
138 | 202 |
|
| 203 | +/** |
| 204 | + * @brief Return human-readable string for IRQ sharing model. |
| 205 | + * |
| 206 | + * @param share Sharing type |
| 207 | + * @return Descriptive string of the IRQ sharing status |
| 208 | + */ |
139 | 209 | const char *sharing_str(uint8_t share); |
0 commit comments