Forgotten commit. Added automount.
[AROS.git] / arch / all-pc / kernel / apic_acpi.c
blob4aeed269f10eb1af864da9e59054e8bef6f318f5
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <aros/asmcall.h>
7 #include <resources/acpi.h>
8 #include <proto/acpi.h>
9 #include <proto/exec.h>
11 #include <inttypes.h>
12 #include <string.h>
14 #include "kernel_base.h"
15 #include "kernel_debug.h"
16 #include "apic.h"
17 #include "apic_ia32.h"
19 #define D(x) x
21 /************************************************************************************************
22 ACPI RELATED FUNCTIONS
23 ************************************************************************************************/
26 * Pre-process the 'Local APIC' MADT Table.
27 * This function simply counts enabled APICs in order to determine number of entries in APIC maps.
29 AROS_UFH2(static IPTR, ACPI_hook_Table_LAPIC_Count,
30 AROS_UFHA(struct Hook *, table_hook, A0),
31 AROS_UFHA(struct ACPI_TABLE_TYPE_LAPIC *, processor, A2))
33 AROS_USERFUNC_INIT
35 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_LAPIC_Count: Local APIC %d:%d [Flags=%08x]\n", processor->acpi_id, processor->id, processor->flags));
36 return processor->flags.enabled;
38 AROS_USERFUNC_EXIT
41 /* Process the 'Local APIC Address Overide' MADT Table */
42 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Addr_Ovr_Parse,
43 AROS_UFHA(struct Hook *, table_hook, A0),
44 AROS_UFHA(struct ACPI_TABLE_TYPE_LAPIC_ADDROVR *, lapic_addr_ovr, A2),
45 AROS_UFHA(struct APICData *, data, A2))
47 AROS_USERFUNC_INIT
49 data->lapicBase = lapic_addr_ovr->address;
50 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_LAPIC_Addr_Ovr_Parse: Local APIC address Override to 0x%p\n", data->lapicBase));
52 return TRUE;
54 AROS_USERFUNC_EXIT
58 * Process the 'Local APIC' MADT Table.
59 * This function collects APIC IDs into already allocated CPUData array.
61 AROS_UFH3(static IPTR, ACPI_hook_Table_LAPIC_Parse,
62 AROS_UFHA(struct Hook *, table_hook, A0),
63 AROS_UFHA(struct ACPI_TABLE_TYPE_LAPIC *, processor, A2),
64 AROS_UFHA(struct APICData *, data, A1))
66 AROS_USERFUNC_INIT
68 if (processor->flags.enabled)
70 if (data->cores[0].lapicID == processor->id)
72 /* This is the BSP, slot 0 is always reserved for it. */
73 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_LAPIC_Parse: Registering ACPI ID 0x%02X for BSP\n", processor->acpi_id));
75 data->cores[0].sysID = processor->acpi_id;
77 else
79 /* Add one more AP */
80 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_LAPIC_Parse: Registering APIC number %d [ID=0x%02X:0x%02X]\n", data->count, processor->id, processor->acpi_id));
82 data->cores[data->count].lapicID = processor->id;
83 data->cores[data->count].sysID = processor->acpi_id;
85 data->count++;
89 return TRUE;
92 return FALSE;
94 AROS_USERFUNC_EXIT
97 /* Process the 'Local APIC Non-Maskable Interrupt' MADT Table */
98 AROS_UFH3(IPTR, ACPI_hook_Table_LAPIC_NMI_Parse,
99 AROS_UFHA(struct Hook *, table_hook, A0),
100 AROS_UFHA(struct ACPI_TABLE_TYPE_LAPIC_NMI *, lapic_nmi, A2),
101 AROS_UFHA(struct APICData *, data, A1))
103 AROS_USERFUNC_INIT
105 IPTR cpu_num = (IPTR)table_hook->h_Data;
107 if ((lapic_nmi->acpi_id == data->cores[cpu_num].sysID) || (lapic_nmi->acpi_id == ACPI_ID_BROADCAST))
109 UWORD reg;
110 ULONG val = LVT_MT_NMI; /* This is the default (edge-triggered, active low) */
112 D(bug("[APIC-ACPI.%u] NMI LINT%u\n", cpu_num, lapic_nmi->lint));
114 switch (lapic_nmi->lint)
116 case 0:
117 reg = APIC_LINT0_VEC;
118 break;
120 case 1:
121 reg = APIC_LINT1_VEC;
122 break;
124 default:
125 /* Invalid LINT# value */
126 return FALSE;
129 if (lapic_nmi->flags.polarity == INTF_POLARITY_LOW)
131 D(bug("[APIC-ACPI.%u] NMI active low\n", cpu_num));
132 val |= LVT_ACTIVE_LOW;
135 if (lapic_nmi->flags.trigger == INTF_TRIGGER_LEVEL)
137 D(bug("[APIC-ACPI.%u] NMI level-triggered\n", cpu_num));
138 val |= LVT_TGM_LEVEL;
141 APIC_REG(data->lapicBase, reg) = val;
142 return TRUE;
145 return FALSE;
147 AROS_USERFUNC_EXIT
150 /* Process the 'IO-APIC' MADT Table */
151 AROS_UFH3(IPTR, ACPI_hook_Table_IOAPIC_Parse,
152 AROS_UFHA(struct Hook *, table_hook, A0),
153 AROS_UFHA(struct ACPI_TABLE_TYPE_IOAPIC *, ioapic, A2),
154 AROS_UFHA(struct APICData *, data, A1))
156 AROS_USERFUNC_INIT
158 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_IOAPIC_Parse: IOAPIC %d @ %p [irq base = %d]\n", ioapic->id, ioapic->address, ioapic->global_irq_base));
160 data->ioapicBase = ioapic->address;
161 return TRUE;
163 AROS_USERFUNC_EXIT
166 /* Process the 'Interrupt Source Overide' MADT Table */
167 AROS_UFH2(IPTR, ACPI_hook_Table_Int_Src_Ovr_Parse,
168 AROS_UFHA(struct Hook *, table_hook, A0),
169 AROS_UFHA(struct ACPI_TABLE_TYPE_INT_SRCOVR *, intsrc, A2))
171 AROS_USERFUNC_INIT
173 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_Int_Src_Ovr_Parse: BUS IRQ %d, Global IRQ %d, polarity ##, trigger ##\n", intsrc->bus_irq, intsrc->global_irq));
174 //intsrc->flags.polarity,
175 //intsrc->flags.trigger,
177 return TRUE;
179 AROS_USERFUNC_EXIT
182 /* Process the 'Non-Maskable Interrupt Source' MADT Table */
183 AROS_UFH2(IPTR, ACPI_hook_Table_NMI_Src_Parse,
184 AROS_UFHA(struct Hook *, table_hook, A0),
185 AROS_UFHA(struct ACPI_TABLE_TYPE_LAPIC_NMI_SRC *, nmi_src, A2))
187 AROS_USERFUNC_INIT
189 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_NMI_Src_Parse()\n"));
191 /* FIXME: Uh... shouldn't we do something with this? */
193 return TRUE;
195 AROS_USERFUNC_EXIT
198 static const struct Hook ACPI_TableParse_LAPIC_count_hook =
200 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Count,
203 static const struct Hook ACPI_TableParse_LAPIC_Addr_Ovr_hook =
205 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Addr_Ovr_Parse
208 static const struct Hook ACPI_TableParse_LAPIC_hook =
210 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Parse
213 static const struct Hook ACPI_TableParse_IOAPIC_hook =
215 .h_Entry = (APTR)ACPI_hook_Table_IOAPIC_Parse
218 static const struct Hook ACPI_TableParse_Int_Src_Ovr_hook =
220 .h_Entry = (APTR)ACPI_hook_Table_Int_Src_Ovr_Parse
223 static const struct Hook ACPI_TableParse_NMI_Src_hook =
225 .h_Entry = (APTR)ACPI_hook_Table_NMI_Src_Parse
228 /************************************************************************************************/
229 /************************************************************************************************
230 APIC Functions used by kernel.resource from outside this file ..
231 ************************************************************************************************/
232 /************************************************************************************************/
235 * Initialize APIC on a CPU core with specified number.
236 * This routine is ran by all cores.
238 void acpi_APIC_InitCPU(struct APICData *data, IPTR cpuNum)
240 /* Initialize APIC to the default configuration */
241 core_APIC_Init(data, cpuNum);
243 if (data->acpi_madt)
245 struct ACPIBase *ACPIBase = data->acpiBase;
246 struct Hook hook;
248 /* Set up NMI for ourselves */
249 hook.h_Entry = (APTR)ACPI_hook_Table_LAPIC_NMI_Parse;
250 hook.h_Data = (APTR)cpuNum;
251 ACPI_ScanEntries(data->acpi_madt, ACPI_MADT_LAPIC_NMI, &hook, data);
255 /* Initialize APIC from ACPI data */
256 struct APICData *acpi_APIC_Init(struct ACPIBase *ACPIBase)
258 ULONG result;
259 struct ACPI_TABLE_TYPE_MADT *madt;
260 struct APICData *data;
263 * MADT : If it exists, parse the Multiple APIC Description Table "MADT",
264 * This table provides platform SMP configuration information [the successor to MPS tables]
266 madt = ACPI_FindSDT(ACPI_MAKE_ID('A', 'P', 'I', 'C'));
267 D(bug("[APIC-ACPI] MADT at 0x%p\n", madt));
269 if (madt)
272 * We have MADT from ACPI.
273 * The first thing to do now is to count APICs and allocate struct APICData.
275 result = ACPI_ScanEntries(&madt->header, ACPI_MADT_LAPIC, &ACPI_TableParse_LAPIC_count_hook, NULL);
276 D(bug("[APIC-ACPI] Found %u enabled APICs\n", result));
278 data = AllocMem(sizeof(struct APICData) + result * sizeof(struct CPUData), MEMF_CLEAR);
279 if (!data)
280 return NULL;
282 data->lapicBase = madt->lapic_address;
283 data->acpiBase = ACPIBase; /* Cache ACPI data for secondary cores */
284 data->acpi_madt = madt;
285 data->count = 1; /* Only one CPU is running right now */
286 data->flags = madt->flags.pcat_compat ? APF_8259 : 0;
288 D(bug("[APIC-ACPI] Local APIC address 0x%08x; Flags 0x%04X\n", data->lapicBase, data->flags));
291 * The local APIC base address is obtained from the MADT (32-bit value) and
292 * (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
294 ACPI_ScanEntries(&madt->header, ACPI_MADT_LAPIC_ADDR_OVR, &ACPI_TableParse_LAPIC_Addr_Ovr_hook, data);
296 /* Remember ID of the bootstrap APIC, this is CPU #0 */
297 data->cores[0].lapicID = core_APIC_GetID(data->lapicBase);
298 D(bug("[APIC-ACPI] BSP ID: 0x%02X\n", data->cores[0].lapicID));
300 /* Now fill in IDs (both HW and ACPI) of the rest APICs */
301 ACPI_ScanEntries(&madt->header, ACPI_MADT_LAPIC, &ACPI_TableParse_LAPIC_hook, data);
302 D(bug("[APIC-ACPI] System Total APICs: %d\n", data->count));
304 /* Initialize LAPIC for ourselves (CPU #0) */
305 acpi_APIC_InitCPU(data, 0);
307 /* TODO: The following is actually not implemented yet. IOAPIC should be configured here. */
309 result = ACPI_ScanEntries(&madt->header, ACPI_MADT_IOAPIC, &ACPI_TableParse_IOAPIC_hook, data);
310 D(bug("[APIC-ACPI] ACPI_ScanEntries(ACPI_MADT_IOAPIC) returned %p\n", result));
312 ACPI_ScanEntries(&madt->header, ACPI_MADT_INT_SRC_OVR, &ACPI_TableParse_Int_Src_Ovr_hook, data);
314 result = ACPI_ScanEntries(&madt->header, ACPI_MADT_NMI_SRC, &ACPI_TableParse_NMI_Src_hook, data);
315 D(bug("[APIC-ACPI] ACPI_ScanEntries(ACPI_MADT_NMI_SRC) returned %p\n", result));
317 /* Build a default routing table for legacy (ISA) interrupts. */
318 /* TODO: implement legacy irq config.. */
319 D(bug("[APIC-ACPI] Configuring Legacy IRQs .. Skipped (UNIMPLEMENTED) ..\n"));
321 /* TODO: implement check for clustered apic's..
322 core_APICClusteredCheck();
324 return data;
327 return NULL;