revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-pc / kernel / acpi_ioapic.c
blob6cfd3ead63151c2aec9d11e60e1ba35a0eea737d
1 /*
2 Copyright � 1995-2018, The AROS Development Team. All rights reserved.
3 $Id$
5 http://download.intel.com/design/chipsets/datashts/29056601.pdf
6 */
8 #include <aros/macros.h>
9 #include <aros/asmcall.h>
10 #include <proto/exec.h>
11 #include <proto/arossupport.h>
12 #include <proto/acpica.h>
14 #define __KERNEL_NOLIBBASE__
15 #include <proto/kernel.h>
17 #include <inttypes.h>
18 #include <string.h>
20 #include "kernel_base.h"
21 #include "kernel_debug.h"
22 #include "kernel_intern.h"
23 #include "kernel_globals.h"
25 #include "acpi.h"
26 #include "apic.h"
27 #include "apic_ia32.h"
28 #include "ioapic.h"
30 #define D(x)
31 #define DINT(x)
32 #define DPARSE(x)
34 #define ACPI_MODPRIO_IOAPIC 50
36 /************************************************************************************************
37 ACPI IO-APIC RELATED FUNCTIONS
38 ************************************************************************************************/
40 const char *ACPI_TABLE_MADT_STR __attribute__((weak)) = "APIC";
42 #define IOREGSEL 0
43 #define IOREGWIN 0x10
45 /* descriptor for an ioapic routing table entry */
46 struct acpi_ioapic_route
48 uint32_t vect:8, dm:3, dstm:1, ds:1, pol:1, rirr:1, trig:1, mask:1, rsvd1:15;
49 uint32_t rsvd2:24, dst:8;
52 static ULONG acpi_IOAPIC_ReadReg(APTR apic_base, UBYTE offset)
54 *(ULONG volatile *)(apic_base + IOREGSEL) = offset;
55 return *(ULONG volatile *)(apic_base + IOREGWIN);
58 static void acpi_IOAPIC_WriteReg(APTR apic_base, UBYTE offset, ULONG val)
60 *(ULONG volatile *)(apic_base + IOREGSEL) = offset;
61 *(ULONG volatile *)(apic_base + IOREGWIN) = val;
64 /* IO-APIC Interrupt Functions ... ***************************/
66 struct IOAPICInt_Private
71 void ioapic_ParseTableEntry(UQUAD *tblData)
73 struct acpi_ioapic_route *tblEntry = (struct acpi_ioapic_route *)tblData;
75 bug("%08X%08X", ((*tblData >> 32) & 0xFFFFFFFF), (*tblData & 0xFFFFFFFF));
77 if (tblEntry->mask)
79 bug(" Disabled.");
81 else
83 if (tblEntry->pol)
85 bug(" Active LOW,");
87 else
89 bug(" Active HIGH,");
92 if (tblEntry->trig)
94 bug(" LEVEL");
96 else
98 bug(" EDGE");
101 bug(" ->");
103 if (tblEntry->dstm)
105 bug(" Logical %03u:%03u", ((tblEntry->dst >> 4) & 0xF), (tblEntry->dst & 0xF));
107 else
109 bug(" Physical %03u", (tblEntry->dst & 0xF));
114 icid_t IOAPICInt_Register(struct KernelBase *KernelBase)
116 ACPI_STATUS status;
117 ACPI_OBJECT arg = { ACPI_TYPE_INTEGER };
118 ACPI_OBJECT_LIST arg_list = { 1, &arg };
120 DINT(bug("[Kernel:IOAPIC] %s()\n", __func__));
122 /* if we have been disabled, fail to register */
123 if (IOAPICInt_IntrController.ic_Flags & ICF_DISABLED)
124 return (icid_t)-1;
127 * Inform ACPI/BIOS that we want to use IOAPIC mode...
128 * APIC IRQ model 0 = PIC (default)
129 * APIC IRQ model 1 = IOAPIC
130 * APIC IRQ model 2 = SIOAPIC
132 arg.Integer.Value = 1;
133 status = AcpiEvaluateObject(NULL,
134 (char *)"\\_PIC",
135 &arg_list,
136 NULL);
138 if (ACPI_FAILURE(status))
140 bug("[Kernel:IOAPIC] %s: Error evaluating _PIC: %s\n", __func__, AcpiFormatException(status));
141 return (icid_t)-1;
144 DINT(bug("[Kernel:IOAPIC] %s: IOAPIC Mode Enabled (status=%08X)\n", __func__, status));
146 return (icid_t)IOAPICInt_IntrController.ic_Node.ln_Type;
149 BOOL IOAPICInt_Init(struct KernelBase *KernelBase, icid_t instanceCount)
151 struct PlatformData *kernPlatD = (struct PlatformData *)KernelBase->kb_PlatformData;
152 struct IOAPICCfgData *ioapicData;
153 struct IOAPICData *ioapicPrivate = kernPlatD->kb_IOAPIC;
154 struct APICData *apicPrivate = kernPlatD->kb_APIC;
155 int instance, irq = 0, ioapic_irqbase;
156 struct IntrController *xtpicIC;
158 DINT(bug("[Kernel:IOAPIC] %s(%u)\n", __func__, instanceCount));
160 IOAPICInt_IntrController.ic_Private = ioapicPrivate;
162 for (
163 instance = 0;
164 ((instance < instanceCount) && (ioapicData = &ioapicPrivate->ioapics[instance]));
165 instance++
168 ULONG ioapicval;
170 ioapic_irqbase = ioapicData->ioapic_GSI;
172 DINT(
173 bug("[Kernel:IOAPIC] %s: Init IOAPIC #%u [ID=%03u] @ 0x%p\n", __func__, instance + 1, ioapicData->ioapic_ID, ioapicData->ioapic_Base);
177 * Skip controllers that report bogus version information
179 ioapicval = acpi_IOAPIC_ReadReg(
180 ioapicData->ioapic_Base,
181 IOAPICREG_VER);
182 if (ioapicval == 0xFFFFFFFF)
183 continue;
185 DINT(
186 bug("[Kernel:IOAPIC] %s: IOAPIC Version appears to be valid...\n", __func__);
189 * Make sure we are using the correct LocalID
191 ioapicval = acpi_IOAPIC_ReadReg(
192 ioapicData->ioapic_Base,
193 IOAPICREG_ID);
194 if (ioapicData->ioapic_ID != ((ioapicval >> 24) & 0xF))
196 ioapicval &= ~(0xF << 24);
197 ioapicval |= (ioapicData->ioapic_ID << 24);
199 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
200 IOAPICREG_ID,
201 ioapicval);
202 DINT(bug("[Kernel:IOAPIC] %s: IOAPIC LocalID configured\n", __func__);)
205 /* Check if the 8259A has been registered, and disable it */
206 if ((instance == 0) && ((xtpicIC = krnFindInterruptController(KernelBase, ICTYPE_I8259A)) != NULL))
208 DINT(bug("[Kernel:IOAPIC] %s: Disabling i8259A controller...\n", __func__);)
209 i8259a_Disable();
212 DINT(bug("[Kernel:IOAPIC] %s: Configuring IRQs & routing\n", __func__);)
214 if ((ioapicData->ioapic_RouteTable = AllocMem(ioapicData->ioapic_IRQCount * sizeof(UQUAD), MEMF_ANY)) != NULL)
216 DINT(bug("[Kernel:IOAPIC] %s: Routing Data @ 0x%p\n", __func__, ioapicData->ioapic_RouteTable));
217 for (irq = ioapic_irqbase; irq < (ioapic_irqbase + ioapicData->ioapic_IRQCount); irq++)
219 UBYTE ioapic_pin = irq - ioapic_irqbase;
220 struct acpi_ioapic_route *irqRoute = (struct acpi_ioapic_route *)&ioapicData->ioapic_RouteTable[ioapic_pin];
221 struct IntrMapping *intrMap = krnInterruptMapped(KernelBase, irq);
222 BOOL enabled = FALSE;
223 APTR ssp = NULL;
225 DINT(bug("[Kernel:IOAPIC] %s: Route Entry %u @ 0x%p\n", __func__, ioapic_pin, irqRoute));
227 ioapicval = acpi_IOAPIC_ReadReg(
228 ioapicData->ioapic_Base,
229 IOAPICREG_REDTBLBASE + (ioapic_pin << 1));
230 ioapicData->ioapic_RouteTable[ioapic_pin] = (UQUAD)ioapicval;
232 ioapicval = acpi_IOAPIC_ReadReg(
233 ioapicData->ioapic_Base,
234 IOAPICREG_REDTBLBASE + (ioapic_pin << 1) + 1);
235 ioapicData->ioapic_RouteTable[ioapic_pin] |= ((UQUAD)ioapicval << 32);
237 irqRoute->ds = 0;
238 irqRoute->rirr = 0;
239 if (ioapic_pin < I8259A_IRQCOUNT)
241 /* mark the ISA interrupts as active high, edge triggered... */
242 irqRoute->pol = 0;
243 irqRoute->trig = 0;
245 else
247 /* ...and PCI interrupts as active low, level triggered */
248 irqRoute->pol = 1;
249 irqRoute->trig = 1;
252 /* setup delivery to the boot processor */
253 if (intrMap)
255 irqRoute->vect = (UBYTE)intrMap->im_Node.ln_Pri + HW_IRQ_BASE;
256 if (ictl_is_irq_enabled(intrMap->im_Node.ln_Pri, KernelBase))
257 enabled = TRUE;
259 else
260 irqRoute->vect = irq + HW_IRQ_BASE;
261 D(bug("[Kernel:IOAPIC] %s: Routing HW IRQ to Vector #$%02X\n", __func__, irqRoute->vect);)
262 irqRoute->dm = 0; // fixed
263 irqRoute->dstm = 0; // physical
264 irqRoute->mask = 1;
265 if (apicPrivate)
266 irqRoute->dst = apicPrivate->cores[0].cpu_LocalID;
267 else
268 irqRoute->dst = 0;
270 if ((KrnIsSuper()) || ((ssp = SuperState()) != NULL))
272 if (!krnInitInterrupt(KernelBase, irq, IOAPICInt_IntrController.ic_Node.ln_Type, instance))
274 bug("[Kernel:IOAPIC] %s: Failed to acquire IRQ #$%02X\n", __func__, irq);
276 else
278 if (!core_SetIRQGate(apicPrivate->cores[0].cpu_IDT, irq, (uintptr_t)IntrDefaultGates[HW_IRQ_BASE + irq]))
280 bug("[Kernel:IOAPIC] %s: failed to set IRQ %d's gate\n", __func__, irq);
282 if ((!krnInterruptMapping(KernelBase, irq)) && (ictl_is_irq_enabled(irq, KernelBase)))
283 enabled = TRUE;
285 if (ssp)
286 UserState(ssp);
288 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
289 IOAPICREG_REDTBLBASE + (ioapic_pin << 1 ) + 1,
290 ((ioapicData->ioapic_RouteTable[ioapic_pin] >> 32) & 0xFFFFFFFF));
291 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
292 IOAPICREG_REDTBLBASE + (ioapic_pin << 1),
293 (ioapicData->ioapic_RouteTable[ioapic_pin] & 0xFFFFFFFF));
294 if (enabled)
296 irqRoute->mask = 0;
297 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
298 IOAPICREG_REDTBLBASE + (ioapic_pin << 1),
299 (ioapicData->ioapic_RouteTable[ioapic_pin] & 0xFFFFFFFF));
301 DINT(
302 bug("[Kernel:IOAPIC] %s: ", __func__);
303 ioapic_ParseTableEntry((UQUAD *)&ioapicData->ioapic_RouteTable[ioapic_pin]);
304 bug("\n");
308 ioapic_irqbase += ioapicData->ioapic_IRQCount;
311 return TRUE;
314 BOOL IOAPICInt_DisableIRQ(APTR icPrivate, icid_t icInstance, icid_t intNum)
316 struct IOAPICData *ioapicPrivate = (struct IOAPICData *)icPrivate;
317 struct IOAPICCfgData *ioapicData = &ioapicPrivate->ioapics[icInstance];
318 struct IntrMapping *intrMap = krnInterruptMapping(KernelBase, intNum);
319 struct acpi_ioapic_route *irqRoute;
320 UBYTE ioapic_pin;
322 DINT(bug("[Kernel:IOAPIC] %s(%02X)\n", __func__, intNum));
324 if (intrMap)
326 ioapic_pin = (intrMap->im_IRQ - ioapicData->ioapic_GSI);
328 else
329 ioapic_pin = intNum - ioapicData->ioapic_GSI;
331 DINT(bug("[Kernel:IOAPIC] %s: IOAPIC Pin %02X\n", __func__, ioapic_pin));
332 irqRoute = (struct acpi_ioapic_route *)&ioapicData->ioapic_RouteTable[ioapic_pin];
334 irqRoute->mask = 1;
336 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
337 IOAPICREG_REDTBLBASE + (ioapic_pin << 1),
338 (ioapicData->ioapic_RouteTable[ioapic_pin] & 0xFFFFFFFF));
339 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
340 IOAPICREG_REDTBLBASE + (ioapic_pin << 1 ) + 1,
341 ((ioapicData->ioapic_RouteTable[ioapic_pin] >> 32) & 0xFFFFFFFF));
343 return TRUE;
346 BOOL IOAPICInt_EnableIRQ(APTR icPrivate, icid_t icInstance, icid_t intNum)
348 struct PlatformData *kernPlatD = (struct PlatformData *)KernelBase->kb_PlatformData;
349 struct IOAPICData *ioapicPrivate = (struct IOAPICData *)icPrivate;
350 struct IOAPICCfgData *ioapicData = &ioapicPrivate->ioapics[icInstance];
351 struct IntrMapping *intrMap = krnInterruptMapping(KernelBase, intNum);
352 struct APICData *apicPrivate = kernPlatD->kb_APIC;
353 struct acpi_ioapic_route *irqRoute;
354 UBYTE ioapic_pin;
356 DINT(bug("[Kernel:IOAPIC] %s(%02X)\n", __func__, intNum));
358 if (intrMap)
360 ioapic_pin = (intrMap->im_IRQ - ioapicData->ioapic_GSI);
362 else
363 ioapic_pin = intNum - ioapicData->ioapic_GSI;
365 DINT(bug("[Kernel:IOAPIC] %s: IOAPIC Pin %02X\n", __func__, ioapic_pin));
366 irqRoute = (struct acpi_ioapic_route *)&ioapicData->ioapic_RouteTable[ioapic_pin];
369 * if we have APIC's get the ID from there
370 * otherwise use the pre-configured one. */
371 if (apicPrivate)
373 apicid_t cpuNo = KrnGetCPUNumber();
374 irqRoute->dst = apicPrivate->cores[cpuNo].cpu_LocalID;
377 irqRoute->vect = intNum + HW_IRQ_BASE;
378 irqRoute->mask = 0; // enable!!
380 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
381 IOAPICREG_REDTBLBASE + (ioapic_pin << 1 ) + 1,
382 ((ioapicData->ioapic_RouteTable[ioapic_pin] >> 32) & 0xFFFFFFFF));
383 acpi_IOAPIC_WriteReg(ioapicData->ioapic_Base,
384 IOAPICREG_REDTBLBASE + (ioapic_pin << 1),
385 (ioapicData->ioapic_RouteTable[ioapic_pin] & 0xFFFFFFFF));
387 return TRUE;
390 BOOL IOAPICInt_AckIntr(APTR icPrivate, icid_t icInstance, icid_t intNum)
392 IPTR apic_base;
394 DINT(bug("[Kernel:IOAPIC] %s()\n", __func__));
396 /* Write zero to EOI of APIC */
397 apic_base = core_APIC_GetBase();
399 APIC_REG(apic_base, APIC_EOI) = 0;
401 return TRUE;
404 struct IntrController IOAPICInt_IntrController =
407 .ln_Name = "82093AA IO-APIC",
408 .ln_Pri = 50
411 AROS_MAKE_ID('I','O','9','3'),
413 NULL,
414 IOAPICInt_Register,
415 IOAPICInt_Init,
416 IOAPICInt_EnableIRQ,
417 IOAPICInt_DisableIRQ,
418 IOAPICInt_AckIntr
421 /********************************************************************/
423 void acpi_IOAPIC_AllocPrivate(struct PlatformData *pdata)
425 if (!pdata->kb_IOAPIC)
427 pdata->kb_IOAPIC = AllocMem(sizeof(struct IOAPICData) + pdata->kb_ACPI->acpi_ioapicCnt * sizeof(struct IOAPICCfgData), MEMF_CLEAR);
428 D(bug("[Kernel:ACPI-IOAPIC] IO-APIC Private @ 0x%p, for %u IOAPIC's\n", pdata->kb_IOAPIC, pdata->kb_ACPI->acpi_ioapicCnt));
432 /* Process the 'Interrupt Source' MADT Table */
433 AROS_UFH2(IPTR, ACPI_hook_Table_Int_Src_Parse,
434 AROS_UFHA(struct Hook *, table_hook, A0),
435 AROS_UFHA(ACPI_MADT_INTERRUPT_SOURCE *, intsrc, A2))
437 AROS_USERFUNC_INIT
439 DPARSE(bug("[Kernel:ACPI-IOAPIC] ## %s()\n", __func__));
440 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: %u:%u, GSI %u, Flags 0x%x\n", __func__, intsrc->Id, intsrc->Eid,
441 intsrc->GlobalIrq, intsrc->IntiFlags));
442 DPARSE(
443 if (intsrc->Type == 1)
445 bug("[Kernel:ACPI-IOAPIC] %s: PMI, vector %d\n", __func__, intsrc->IoSapicVector);
447 else if(intsrc->Type == 2)
449 bug("[Kernel:ACPI-IOAPIC] %s: INIT\n", __func__);
451 else if(intsrc->Type == 3)
453 bug("[Kernel:ACPI-IOAPIC] %s: Corrected\n", __func__);
456 return TRUE;
458 AROS_USERFUNC_EXIT
461 /* Process the 'Interrupt Source Overide' MADT Table */
462 AROS_UFH2(IPTR, ACPI_hook_Table_Int_Src_Ovr_Parse,
463 AROS_UFHA(struct Hook *, table_hook, A0),
464 AROS_UFHA(ACPI_MADT_INTERRUPT_OVERRIDE *, intsrc, A2))
466 AROS_USERFUNC_INIT
468 struct IntrMapping *intrMap;
470 DPARSE(bug("[Kernel:ACPI-IOAPIC] ## %s()\n", __func__));
471 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: Bus %u, Source IRQ %u, GSI %u, Flags 0x%x\n", __func__, intsrc->Bus, intsrc->SourceIrq,
472 intsrc->GlobalIrq, intsrc->IntiFlags));
474 intrMap = AllocMem(sizeof(struct IntrMapping), MEMF_CLEAR);
475 intrMap->im_Node.ln_Pri = intsrc->SourceIrq;
476 //intrMap->im_Node.ln_Type = IOAPICInt_IntrController->;
477 intrMap->im_IRQ = intsrc->GlobalIrq;
478 Enqueue(&KernelBase->kb_InterruptMappings, &intrMap->im_Node);
480 return TRUE;
482 AROS_USERFUNC_EXIT
485 /* Process the 'Non-Maskable Interrupt Source' MADT Table */
486 AROS_UFH2(IPTR, ACPI_hook_Table_NMI_Src_Parse,
487 AROS_UFHA(struct Hook *, table_hook, A0),
488 AROS_UFHA(ACPI_MADT_NMI_SOURCE *, nmi_src, A2))
490 AROS_USERFUNC_INIT
492 DPARSE(bug("[Kernel:ACPI-IOAPIC] ## %s()\n", __func__));
493 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: GSI %u, Flags 0x%x\n", __func__, nmi_src->GlobalIrq, nmi_src->IntiFlags));
495 /* FIXME: Uh... shouldn't we do something with this? */
497 return TRUE;
499 AROS_USERFUNC_EXIT
502 /* Process the 'IO-APIC' MADT Table */
503 AROS_UFH3(IPTR, ACPI_hook_Table_IOAPIC_Parse,
504 AROS_UFHA(struct Hook *, table_hook, A0),
505 AROS_UFHA(ACPI_MADT_IO_APIC *, ioapic, A2),
506 AROS_UFHA(struct ACPI_TABLESCAN_DATA *, tsdata, A1))
508 AROS_USERFUNC_INIT
510 struct PlatformData *pdata = tsdata->acpits_UserData;
512 DPARSE(bug("[Kernel:ACPI-IOAPIC] ## %s()\n", __func__));
514 if (!pdata->kb_IOAPIC)
516 acpi_IOAPIC_AllocPrivate(pdata);
519 if (pdata->kb_IOAPIC)
521 icintrid_t ioapicICInstID;
522 ULONG ioapicval;
523 int i;
525 bug("[Kernel:ACPI-IOAPIC] Registering IO-APIC #%u [ID=%03u] @ %p [GSI = %u]\n",
526 pdata->kb_IOAPIC->ioapic_count + 1, ioapic->Id, ioapic->Address, ioapic->GlobalIrqBase);
528 if ((ioapicICInstID = krnAddInterruptController(KernelBase, &IOAPICInt_IntrController)) != (icintrid_t)-1)
530 struct IOAPICCfgData *ioapicData = (struct IOAPICCfgData *)&pdata->kb_IOAPIC->ioapics[pdata->kb_IOAPIC->ioapic_count];
532 DPARSE(bug("[Kernel:ACPI-IOAPIC] IO-APIC IC ID #%u:%u\n", ICINTR_ICID(ioapicICInstID), ICINTR_INST(ioapicICInstID)));
534 ioapicData->ioapic_Base = (APTR)((IPTR)ioapic->Address);
535 ioapicData->ioapic_GSI = ioapic->GlobalIrqBase;
537 ioapicval = acpi_IOAPIC_ReadReg(
538 ioapicData->ioapic_Base,
539 IOAPICREG_ID);
540 ioapicData->ioapic_ID = ioapic->Id; // we store the ACPI reported ID here, so we can check it during init.
542 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: #%u,",
543 __func__, ((ioapicval >> 24) & 0xF)));
545 ioapicval = acpi_IOAPIC_ReadReg(
546 ioapicData->ioapic_Base,
547 IOAPICREG_VER);
548 ioapicData->ioapic_IRQCount = ((ioapicval >> 16) & 0xFF) + 1;
549 ioapicData->ioapic_Ver = (ioapicval & 0xFF);
550 DPARSE(bug(" ver %u, max irqs = %u,",
551 ioapicData->ioapic_Ver, ioapicData->ioapic_IRQCount));
552 ioapicval = acpi_IOAPIC_ReadReg(
553 ioapicData->ioapic_Base,
554 IOAPICREG_ARB);
555 DPARSE(bug("arb %d\n", ((ioapicval >> 24) & 0xF)));
557 for (i = 0; i < (ioapicData->ioapic_IRQCount << 1); i += 2)
559 UQUAD tblraw = 0;
561 ioapicval = acpi_IOAPIC_ReadReg(
562 ioapicData->ioapic_Base,
563 IOAPICREG_REDTBLBASE + i);
564 tblraw = ((UQUAD)ioapicval << 32);
566 ioapicval = acpi_IOAPIC_ReadReg(
567 ioapicData->ioapic_Base,
568 IOAPICREG_REDTBLBASE + i + 1);
569 tblraw |= (UQUAD)ioapicval;
571 DPARSE(
572 bug("[Kernel:ACPI-IOAPIC] %s: ", __func__);
573 ioapic_ParseTableEntry(&tblraw);
574 bug("\n");
578 pdata->kb_IOAPIC->ioapic_count++;
581 return TRUE;
583 AROS_USERFUNC_EXIT
587 * Process the 'IO-APIC' MADT Table
588 * This function counts the available IO-APICs.
590 AROS_UFH3(static IPTR, ACPI_hook_Table_IOAPIC_Count,
591 AROS_UFHA(struct Hook *, table_hook, A0),
592 AROS_UFHA(ACPI_MADT_IO_APIC *, ioapic, A2),
593 AROS_UFHA(struct ACPI_TABLESCAN_DATA *, tsdata, A1))
595 AROS_USERFUNC_INIT
597 struct PlatformData *pdata = tsdata->acpits_UserData;
598 struct ACPI_TABLE_HOOK *scanHook;
600 DPARSE(bug("[Kernel:ACPI-IOAPIC] ## %s()\n", __func__));
602 if (pdata->kb_ACPI->acpi_ioapicCnt == 0)
604 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: Registering IO-APIC Table Parser...\n", __func__));
606 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
607 if (scanHook)
609 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
610 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_IOAPIC - 10; /* Queue 10 priority levels after the module parser */
611 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_IOAPIC_Parse;
612 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
613 scanHook->acpith_EntryType = ACPI_MADT_TYPE_IO_APIC;
614 scanHook->acpith_UserData = pdata;
615 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
618 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
619 if (scanHook)
621 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: Registering Interrupt Source Table Parser...\n", __func__));
623 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
624 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_IOAPIC - 20; /* Queue 20 priority levels after the module parser */
625 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_Int_Src_Parse;
626 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
627 scanHook->acpith_EntryType = ACPI_MADT_TYPE_INTERRUPT_SOURCE;
628 scanHook->acpith_UserData = pdata;
629 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
632 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
633 if (scanHook)
635 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: Registering Interrupt Override Table Parser...\n", __func__));
637 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
638 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_IOAPIC - 30; /* Queue 30 priority levels after the module parser */
639 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_Int_Src_Ovr_Parse;
640 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
641 scanHook->acpith_EntryType = ACPI_MADT_TYPE_INTERRUPT_OVERRIDE;
642 scanHook->acpith_UserData = pdata;
643 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
646 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
647 if (scanHook)
649 DPARSE(bug("[Kernel:ACPI-IOAPIC] %s: Registering NMI Source Table Parser...\n", __func__));
651 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
652 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_IOAPIC - 40; /* Queue 40 priority levels after the module parser */
653 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_NMI_Src_Parse;
654 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
655 scanHook->acpith_EntryType = ACPI_MADT_TYPE_NMI_SOURCE;
656 scanHook->acpith_UserData = pdata;
657 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
660 pdata->kb_ACPI->acpi_ioapicCnt++;
662 return TRUE;
664 AROS_USERFUNC_EXIT
668 void ACPI_IOAPIC_SUPPORT(struct PlatformData *pdata)
670 struct ACPI_TABLE_HOOK *scanHook;
671 struct TagItem *cmdTags = LibFindTagItem(KRN_CmdLine, BootMsg);
673 if (cmdTags && strstr((const char *)cmdTags->ti_Data, "noioapic"))
675 D(bug("[Kernel:ACPI-IOAPIC] %s: IOAPIC Support Disabled\n", __func__));
676 return;
679 scanHook = (struct ACPI_TABLE_HOOK *)AllocMem(sizeof(struct ACPI_TABLE_HOOK), MEMF_CLEAR);
680 if (scanHook)
682 D(bug("[Kernel:ACPI-IOAPIC] %s: Registering IOAPIC Table Parser...\n", __func__));
683 D(bug("[Kernel:ACPI-IOAPIC] %s: Table Hook @ 0x%p\n", __func__, scanHook));
684 scanHook->acpith_Node.ln_Name = (char *)ACPI_TABLE_MADT_STR;
685 scanHook->acpith_Node.ln_Pri = ACPI_MODPRIO_IOAPIC;
686 scanHook->acpith_Hook.h_Entry = (APTR)ACPI_hook_Table_IOAPIC_Count;
687 scanHook->acpith_HeaderLen = sizeof(ACPI_TABLE_MADT);
688 scanHook->acpith_EntryType = ACPI_MADT_TYPE_IO_APIC;
689 scanHook->acpith_UserData = pdata;
690 Enqueue(&pdata->kb_ACPI->acpi_tablehooks, &scanHook->acpith_Node);
692 D(bug("[Kernel:ACPI-IOAPIC] %s: Registering done\n", __func__));
695 DECLARESET(KERNEL__ACPISUPPORT)
696 ADD2SET(ACPI_IOAPIC_SUPPORT, KERNEL__ACPISUPPORT, 0)