kernel.resource(all-pc): Compiler delint
[AROS.git] / arch / all-pc / kernel / apic_acpi.c
blob7b8ced413ff3ced23b7b325cae6a8cdd252ce929
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/asmcall.h>
7 #include <proto/acpica.h>
8 #include <proto/exec.h>
10 #include <utility/hooks.h>
12 #include <inttypes.h>
13 #include <string.h>
15 #include "kernel_base.h"
16 #include "kernel_debug.h"
18 #include "apic.h"
19 #include "apic_ia32.h"
21 #define D(x)
23 /************************************************************************************************
24 ACPI RELATED FUNCTIONS
25 ************************************************************************************************/
27 /* Process the 'Local APIC Address Overide' MADT Table */
28 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Addr_Ovr_Parse,
29 AROS_UFHA(struct Hook *, table_hook, A0),
30 AROS_UFHA(ACPI_MADT_LOCAL_APIC_OVERRIDE *, lapic_addr_ovr, A2),
31 AROS_UFHA(struct APICData *, data, A2))
33 AROS_USERFUNC_INIT
35 data->lapicBase = lapic_addr_ovr->Address;
36 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_LAPIC_Addr_Ovr_Parse: Local APIC address Override to 0x%p\n", data->lapicBase));
38 return TRUE;
40 AROS_USERFUNC_EXIT
44 * Process the 'Local APIC' MADT Table.
45 * This function collects APIC IDs into already allocated CPUData array.
47 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Parse,
48 AROS_UFHA(struct Hook *, table_hook, A0),
49 AROS_UFHA(ACPI_MADT_LOCAL_APIC *, processor, A2),
50 AROS_UFHA(struct APICData *, data, A1))
52 AROS_USERFUNC_INIT
54 if (processor->LapicFlags & ACPI_MADT_ENABLED)
56 if (data->cores[0].lapicID == processor->Id)
58 /* This is the BSP, slot 0 is always reserved for it. */
59 bug("[APIC-ACPI] Registering APIC [ID=0x%02X] for BSP\n", processor->Id);
61 data->cores[0].sysID = processor->ProcessorId;
63 else
65 /* Add one more AP */
66 bug("[APIC-ACPI] Registering APIC [ID=0x%02X:0x%02X]\n", processor->Id, processor->ProcessorId);
68 data->cores[data->count].lapicID = processor->Id;
69 data->cores[data->count].sysID = processor->ProcessorId;
71 data->count++;
75 return TRUE;
78 return FALSE;
80 AROS_USERFUNC_EXIT
83 /* Process the 'Local APIC Non-Maskable Interrupt' MADT Table */
84 AROS_UFH3(IPTR, ACPI_hook_Table_LAPIC_NMI_Parse,
85 AROS_UFHA(struct Hook *, table_hook, A0),
86 AROS_UFHA(ACPI_MADT_LOCAL_APIC_NMI *, lapic_nmi, A2),
87 AROS_UFHA(struct APICData *, data, A1))
89 AROS_USERFUNC_INIT
91 IPTR cpu_num = (IPTR)table_hook->h_Data;
93 if ((lapic_nmi->ProcessorId == data->cores[cpu_num].sysID) || (lapic_nmi->ProcessorId == 0xff))
95 UWORD reg;
96 ULONG val = LVT_MT_NMI; /* This is the default (edge-triggered, active low) */
98 D(bug("[APIC-ACPI.%u] NMI LINT%u\n", cpu_num, lapic_nmi->Lint));
100 switch (lapic_nmi->Lint)
102 case 0:
103 reg = APIC_LINT0_VEC;
104 break;
106 case 1:
107 reg = APIC_LINT1_VEC;
108 break;
110 default:
111 /* Invalid LINT# value */
112 return FALSE;
115 if ((lapic_nmi->IntiFlags & ACPI_MADT_POLARITY_MASK) == ACPI_MADT_POLARITY_ACTIVE_LOW)
117 D(bug("[APIC-ACPI.%u] NMI active low\n", cpu_num));
118 val |= LVT_ACTIVE_LOW;
121 if ((lapic_nmi->IntiFlags & ACPI_MADT_TRIGGER_MASK) == ACPI_MADT_TRIGGER_LEVEL)
123 D(bug("[APIC-ACPI.%u] NMI level-triggered\n", cpu_num));
124 val |= LVT_TGM_LEVEL;
127 APIC_REG(data->lapicBase, reg) = val;
128 return TRUE;
131 return FALSE;
133 AROS_USERFUNC_EXIT
136 /* Process the 'IO-APIC' MADT Table */
137 AROS_UFH3(IPTR, ACPI_hook_Table_IOAPIC_Parse,
138 AROS_UFHA(struct Hook *, table_hook, A0),
139 AROS_UFHA(ACPI_MADT_IO_APIC *, ioapic, A2),
140 AROS_UFHA(struct APICData *, data, A1))
142 AROS_USERFUNC_INIT
144 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_IOAPIC_Parse: IOAPIC %d @ %p [irq base = %d]\n", ioapic->Id, ioapic->Address, ioapic->GlobalIrqBase));
146 data->ioapicBase = ioapic->Address;
147 return TRUE;
149 AROS_USERFUNC_EXIT
152 /* Process the 'Interrupt Source Overide' MADT Table */
153 AROS_UFH2(IPTR, ACPI_hook_Table_Int_Src_Ovr_Parse,
154 AROS_UFHA(struct Hook *, table_hook, A0),
155 AROS_UFHA(ACPI_MADT_INTERRUPT_OVERRIDE *, intsrc, A2))
157 AROS_USERFUNC_INIT
159 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_Int_Src_Ovr_Parse: Bus %d, Source IRQ %d, Global IRQ %d, Flags 0x%x\n", intsrc->Bus, intsrc->SourceIrq,
160 intsrc->GlobalIrq, intsrc->IntiFlags));
162 return TRUE;
164 AROS_USERFUNC_EXIT
167 /* Process the 'Non-Maskable Interrupt Source' MADT Table */
168 AROS_UFH2(IPTR, ACPI_hook_Table_NMI_Src_Parse,
169 AROS_UFHA(struct Hook *, table_hook, A0),
170 AROS_UFHA(ACPI_MADT_NMI_SOURCE *, nmi_src, A2))
172 AROS_USERFUNC_INIT
174 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_NMI_Src_Parse()\n"));
176 /* FIXME: Uh... shouldn't we do something with this? */
178 return TRUE;
180 AROS_USERFUNC_EXIT
183 static const struct Hook ACPI_TableParse_LAPIC_Addr_Ovr_hook =
185 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Addr_Ovr_Parse
188 static const struct Hook ACPI_TableParse_LAPIC_hook =
190 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Parse
193 static const struct Hook ACPI_TableParse_IOAPIC_hook =
195 .h_Entry = (APTR)ACPI_hook_Table_IOAPIC_Parse
198 static const struct Hook ACPI_TableParse_Int_Src_Ovr_hook =
200 .h_Entry = (APTR)ACPI_hook_Table_Int_Src_Ovr_Parse
203 static const struct Hook ACPI_TableParse_NMI_Src_hook =
205 .h_Entry = (APTR)ACPI_hook_Table_NMI_Src_Parse
208 /************************************************************************************************/
209 /************************************************************************************************
210 APIC Functions used by kernel.resource from outside this file ..
211 ************************************************************************************************/
212 /************************************************************************************************/
214 static int MADT_ScanEntries(ACPI_TABLE_MADT *madt, enum AcpiMadtType type, const struct Hook *hook, APTR userdata)
216 UINT8 *madt_entry = (UINT8 *)&madt[1];
217 UINT8 *madt_end = (UINT8 *)madt + madt->Header.Length;
218 int count;
220 for (count = 0; madt_entry < madt_end; madt_entry += ((ACPI_SUBTABLE_HEADER *)madt_entry)->Length) {
221 ACPI_SUBTABLE_HEADER *sh = (ACPI_SUBTABLE_HEADER *)madt_entry;
222 if (sh->Type == (UINT8)type) {
223 BOOL res;
224 if (hook == NULL)
225 res = TRUE;
226 else
227 res = CALLHOOKPKT((struct Hook *)hook, (APTR)sh, userdata);
228 if (res)
229 count++;
233 return count;
238 * Initialize APIC on a CPU core with specified number.
239 * This routine is ran by all cores.
241 void acpi_APIC_InitCPU(struct APICData *data, IPTR cpuNum)
243 /* Initialize APIC to the default configuration */
244 core_APIC_Init(data, cpuNum);
246 if (data->acpi_madt)
248 struct Hook hook;
250 /* Set up NMI for ourselves */
251 hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_NMI_Parse;
252 hook.h_Data = (APTR)cpuNum;
253 MADT_ScanEntries(data->acpi_madt, ACPI_MADT_TYPE_LOCAL_APIC_NMI, &hook, data);
257 /* Initialize APIC from ACPI data */
258 struct APICData *acpi_APIC_Init(struct Library *ACPICABase)
260 ULONG result;
261 ACPI_STATUS err;
262 const ACPI_TABLE_MADT *madt;
263 struct APICData *data;
266 * MADT : If it exists, parse the Multiple APIC Description Table "MADT",
267 * This table provides platform SMP configuration information [the successor to MPS tables]
269 err = AcpiGetTable("MADT", 1, (ACPI_TABLE_HEADER **)&madt);
270 if (err != AE_OK) {
271 D(bug("[APCI-ACPI] No MADT table found, err = %d\n", err));
272 return NULL;
275 if (madt)
278 * We have MADT from ACPI.
279 * The first thing to do now is to count APICs and allocate struct APICData.
281 result = MADT_ScanEntries(madt, ACPI_MADT_TYPE_LOCAL_APIC, NULL, NULL);
282 D(bug("[APIC-ACPI] Found %u enabled APICs\n", result));
284 data = AllocMem(sizeof(struct APICData) + result * sizeof(struct CPUData), MEMF_CLEAR);
285 if (!data)
286 return NULL;
288 data->lapicBase = madt->Address;
289 data->acpicaBase = ACPICABase; /* Cache ACPI data for secondary cores */
290 data->acpi_madt = madt;
291 data->count = 1; /* Only one CPU is running right now */
292 data->flags = ((madt->Flags & ACPI_MADT_PCAT_COMPAT) == ACPI_MADT_MULTIPLE_APIC) ? APF_8259 : 0;
294 bug("[APIC-ACPI] Local APIC address 0x%08x; Flags 0x%04X\n", data->lapicBase, data->flags);
297 * The local APIC base address is obtained from the MADT (32-bit value) and
298 * (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
300 MADT_ScanEntries(madt, ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, &ACPI_TableParse_LAPIC_Addr_Ovr_hook, data);
302 /* Remember ID of the bootstrap APIC, this is CPU #0 */
303 data->cores[0].lapicID = core_APIC_GetID(data->lapicBase);
304 D(bug("[APIC-ACPI] BSP ID: 0x%02X\n", data->cores[0].lapicID));
306 /* Now fill in IDs (both HW and ACPI) of the rest APICs */
307 MADT_ScanEntries(madt, ACPI_MADT_TYPE_LOCAL_APIC, &ACPI_TableParse_LAPIC_hook, data);
308 bug("[APIC-ACPI] System Total APICs: %d\n", data->count);
310 /* Initialize LAPIC for ourselves (CPU #0) */
311 acpi_APIC_InitCPU(data, 0);
313 /* TODO: The following is actually not implemented yet. IOAPIC should be configured here. */
315 result = MADT_ScanEntries(madt, ACPI_MADT_TYPE_IO_APIC, &ACPI_TableParse_IOAPIC_hook, data);
316 D(bug("[APIC-ACPI] ACPI_ScanEntries(ACPI_MADT_IOAPIC) returned %p\n", result));
318 MADT_ScanEntries(madt, ACPI_MADT_TYPE_INTERRUPT_OVERRIDE, &ACPI_TableParse_Int_Src_Ovr_hook, data);
320 result = MADT_ScanEntries(madt, ACPI_MADT_TYPE_NMI_SOURCE, &ACPI_TableParse_NMI_Src_hook, data);
321 D(bug("[APIC-ACPI] ACPI_ScanEntries(ACPI_MADT_NMI_SRC) returned %p\n", result));
323 /* Build a default routing table for legacy (ISA) interrupts. */
324 /* TODO: implement legacy irq config.. */
325 D(bug("[APIC-ACPI] Configuring Legacy IRQs .. Skipped (UNIMPLEMENTED) ..\n"));
327 /* TODO: implement check for clustered apic's..
328 core_APICClusteredCheck();
330 return data;
333 return NULL;