1#include <acpi/madt.h>
2#include <log.h>
3#include <stdint.h>
4#include <uacpi/acpi.h>
5#include <uacpi/status.h>
6#include <uacpi/tables.h>
7
8static LOG_HANDLE_DECLARE_PRINT(madt);
9
10static struct madt_ioapic_info madt_ioapic = {0};
11static uint32_t isa_irq_to_gsi[MADT_MAX_ISO];
12static uint16_t isa_irq_flags[MADT_MAX_ISO];
13
14void madt_init(void) {
15 for (uint8_t i = 0; i < MADT_MAX_ISO; i++) {
16 isa_irq_to_gsi[i] = i;
17 isa_irq_flags[i] = 0;
18 }
19
20 struct uacpi_table apic_table;
21 if (uacpi_table_find_by_signature(signature: "APIC", out_table: &apic_table) != UACPI_STATUS_OK) {
22 log_warn_global(LOG_HANDLE(madt), "MADT table not found");
23 return;
24 }
25
26 struct acpi_madt *madt = (struct acpi_madt *) apic_table.ptr;
27 uint8_t *ptr = (uint8_t *) madt + sizeof(struct acpi_madt);
28 uint64_t remaining = madt->hdr.length - sizeof(struct acpi_madt);
29
30 while (remaining >= sizeof(struct acpi_entry_hdr)) {
31 struct acpi_entry_hdr *entry = (struct acpi_entry_hdr *) ptr;
32
33 if (entry->length == 0 || entry->length > remaining) {
34 log_warn_global(LOG_HANDLE(madt), "Corrupted MADT entry length %u",
35 entry->length);
36 break;
37 }
38
39 switch (entry->type) {
40 case ACPI_MADT_ENTRY_TYPE_IOAPIC: {
41 struct acpi_madt_ioapic *ioapic_entry =
42 (struct acpi_madt_ioapic *) entry;
43 madt_ioapic.id = ioapic_entry->id;
44 madt_ioapic.gsi_base = ioapic_entry->gsi_base;
45 madt_ioapic.address = ioapic_entry->address;
46 madt_ioapic.present = true;
47 log_info_global(LOG_HANDLE(madt),
48 "IOAPIC ID %u, GSI base %u, Address 0x%lx",
49 madt_ioapic.id, madt_ioapic.gsi_base,
50 (uintptr_t) madt_ioapic.address);
51 break;
52 }
53 case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
54 struct acpi_madt_interrupt_source_override *iso =
55 (struct acpi_madt_interrupt_source_override *) entry;
56 if (iso->source < MADT_MAX_ISO) {
57 isa_irq_to_gsi[iso->source] = iso->gsi;
58 isa_irq_flags[iso->source] = iso->flags;
59 log_info_global(LOG_HANDLE(madt),
60 "ISO: ISA IRQ %u -> GSI %u (flags 0x%04x)",
61 iso->source, iso->gsi, iso->flags);
62 }
63 break;
64 }
65 default: break;
66 }
67
68 ptr += entry->length;
69 remaining -= entry->length;
70 }
71}
72
73uint32_t madt_isa_to_gsi(uint8_t isa_irq) {
74 if (isa_irq < MADT_MAX_ISO)
75 return isa_irq_to_gsi[isa_irq];
76 return isa_irq;
77}
78
79uint16_t madt_isa_flags(uint8_t isa_irq) {
80 if (isa_irq < MADT_MAX_ISO)
81 return isa_irq_flags[isa_irq];
82 return 0;
83}
84
85struct madt_ioapic_info *madt_get_ioapic(void) {
86 return &madt_ioapic;
87}
88