2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 #include <aros/asmcall.h>
7 #include <resources/acpi.h>
8 #include <proto/acpi.h>
9 #include <proto/exec.h>
14 #include "kernel_base.h"
15 #include "kernel_debug.h"
17 #include "apic_ia32.h"
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
))
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
;
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
))
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
));
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
))
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
;
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
;
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
))
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
))
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
)
117 reg
= APIC_LINT0_VEC
;
121 reg
= APIC_LINT1_VEC
;
125 /* Invalid LINT# value */
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
;
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
))
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
;
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
))
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,
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
))
189 D(bug("[APIC-ACPI] (HOOK) ACPI_hook_Table_NMI_Src_Parse()\n"));
191 /* FIXME: Uh... shouldn't we do something with this? */
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
);
245 struct ACPIBase
*ACPIBase
= data
->acpiBase
;
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
)
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
));
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
);
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();