make the linux-ppc packags be in synch with other platforms
[tangerine.git] / arch / x86_64-pc / kernel / acpi_tables.c
bloba1d29f0c0a91293f6c2201ef16f0c392806c79c0
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id: acpi_tables.c,v 1.7 2004/01/07 07:13:03 nicja Exp $
4 */
5 #include <inttypes.h>
7 #include "exec_intern.h"
8 #include "etask.h"
10 #include <exec/lists.h>
11 #include <exec/types.h>
12 #include <exec/tasks.h>
13 #include <exec/execbase.h>
14 #include <aros/libcall.h>
15 #include <asm/segments.h>
17 #include <proto/kernel.h>
19 #include "kernel_intern.h"
21 /************************************************************************************************/
23 struct KernelACPIData _Kern_ACPIData;
24 struct acpi_table_sdt KernACPISDTEntries[ACPI_MAX_TABLES];
25 char * KernACPISDTSigs[ACPI_TABLE_COUNT] =
27 "Unknown",
28 "APIC",
29 "BOOT",
30 "DBGP",
31 "DSDT",
32 "ECDT",
33 "ETDT",
34 "FADT",
35 "FACS",
36 "OEMX",
37 "PSDT",
38 "SBST",
39 "SLIT",
40 "SPCR",
41 "SRAT",
42 "SSDT",
43 "SPMI",
44 "HPET"
47 Everything that doesnt work MUST be put on the OEMBlacklist!!!
48 If the problem is critical - mark it as such
51 enum acpi_oemblacklist_revisionmatch
53 all_versions,
54 less_than_or_equal,
55 equal,
56 greater_than_or_equal,
59 struct acpi_oemblacklist_entry
61 char oem_id[7];
62 char oem_table_id[9];
63 unsigned int oem_revision;
64 unsigned int acpi_tableid;
65 enum acpi_oemblacklist_revisionmatch oem_revision_match;
66 char *blacklist_reason;
67 unsigned int blacklist_critical;
70 struct acpi_oemblacklist_entry _ACPI_OEMBlacklist[] =
72 /* ASUS K7M */
73 {"ASUS ", "K7M ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
75 /* ASUS P2B-S */
76 {"ASUS\0\0", "P2B-S ", 0, ACPI_DSDT, all_versions, "Bogus PCI routing", 1},
78 /* Seattle 2 - old BIOS rev. */
79 {"INTEL ", "440BX ", 0x00001000, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
81 /* Intel 810 Motherboard */
82 {"MNTRAL", "MO81010A", 0x00000012, ACPI_DSDT, less_than_or_equal, "Field beyond end of region", 0},
84 /* Compaq Presario 711FR */
85 {"COMAPQ", "EAGLES", 0x06040000, ACPI_DSDT, less_than_or_equal, "SCI issues (C2 disabled)", 0},
87 /* Compaq Presario 1700 */
88 {"PTLTD ", " DSDT ", 0x06040000, ACPI_DSDT, less_than_or_equal, "Multiple problems", 1},
90 /* Sony FX120, FX140, FX150? */
91 {"SONY ", "U0 ", 0x20010313, ACPI_DSDT, less_than_or_equal, "ACPI driver problem", 1},
93 /* Compaq Presario 800, Insyde BIOS */
94 {"INT440", "SYSFexxx", 0x00001001, ACPI_DSDT, less_than_or_equal, "Does not use _REG to protect EC OpRegions", 1},
96 /* IBM 600E - _ADR should return 7, but it returns 1 */
97 {"IBM ", "TP600E ", 0x00000105, ACPI_DSDT, less_than_or_equal, "Incorrect _ADR", 1},
99 /* Portege 7020, BIOS 8.10 */
100 {"TOSHIB", "7020CT ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
102 /* Portege 4030 */
103 {"TOSHIB", "4030 ", 0x19991112, ACPI_DSDT, all_versions, "Implicit Return", 0},
105 /* Portege 310/320, BIOS 7.1 */
106 {"TOSHIB", "310 ", 0x19990511, ACPI_DSDT, all_versions, "Implicit Return", 0},
108 {""}
111 /************************************************************************************************
112 ACPI RELATED FUNCTIONS
113 ************************************************************************************************/
115 /************************************************************************************************/
116 void core_ACPITableDump(IPTR dump_header, IPTR dump_table)
118 #warning "TODO: implement the table dump.."
119 return;
123 * core_ACPITableHeaderEarly() .... used by both core_ACPIIsBlacklisted() and core_ACPITableSDTGet()
125 int core_ACPITableHeaderEarly(int id, struct acpi_table_header ** header)
127 unsigned int i;
128 struct acpi_table_sdt *header_tmp;
129 enum acpi_table_id temp_id;
131 /* DSDT is different from the rest */
132 if (id == ACPI_DSDT) temp_id = ACPI_FADT;
133 else temp_id = id;
135 /* Locate the table. */
136 for (i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++)
138 header_tmp = _Kern_ACPIData.kb_ACPI_SDT_Entry[i];
139 if (header_tmp->id != temp_id)
140 continue;
142 *header = header_tmp->pa;
143 if (*header == NULL)
145 rkprintf("[Kernel] core_ACPITableHeaderEarly: ERROR - table %s has bad pointer\n", KernACPISDTSigs[id]);
146 return NULL;
148 break;
151 if (*header == NULL)
153 rkprintf("[Kernel] core_ACPITableHeaderEarly: WARNING - %s not present\n",
154 KernACPISDTSigs[id]);
155 return NULL;
158 if (id == ACPI_DSDT)
160 /* Map the DSDT header via the pointer in the FADT */
161 struct acpi_table_fadt *FADT = (struct acpi_table_fadt *)*header;
163 *header = FADT->dsdt_addr;
164 if (*header == NULL)
166 rkprintf("[Kernel] core_ACPITableHeaderEarly: ERROR - bad DSDT pointer\n");
167 return NULL;
171 return 0;
174 /**********************************************************/
175 int core_ACPITableMADTFamParse(int id, unsigned long madt_size, int entry_id, struct acpi_madt_entry_hook * entry_handler)
177 void *madt = NULL;
178 struct acpi_table_entry_header *entry = NULL;
179 unsigned long count = 0;
180 unsigned long madt_end = 0;
181 unsigned int i = 0;
182 struct acpi_table_sdt *header_tmp;
184 if ( !entry_handler ) return NULL;
186 /* Locate the MADT (if exists). There should only be one. */
187 for (i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++)
189 header_tmp = _Kern_ACPIData.kb_ACPI_SDT_Entry[i];
191 if ( header_tmp->id != id)
192 continue;
194 madt = header_tmp->pa;
195 if (madt == NULL)
197 rkprintf("[Kernel] core_ACPITableMADTFamParse: ERROR - table %s has bad pointer\n", KernACPISDTSigs[id]);
198 return NULL;
200 break;
203 if (madt == NULL)
205 rkprintf("[Kernel] core_ACPITableMADTFamParse: WARNING - %s not present\n", KernACPISDTSigs[id]);
206 return NULL;
209 madt_end = (unsigned long)madt + header_tmp->size;
211 entry = (struct acpi_table_entry_header *)((unsigned long) madt + madt_size);
213 /* Parse all entries looking for a match. */
214 while (((unsigned long)entry) < madt_end)
216 if (entry->type == entry_id)
218 count++;
220 entry_handler->header = entry;
221 AROS_UFC1(IPTR, entry_handler->h_Entry, AROS_UFCA(struct Hook *, entry_handler, A0));
223 entry = (struct acpi_table_entry_header *)((unsigned long)entry + entry->length);
226 return count;
229 /**********************************************************/
230 int core_ACPITableMADTParse(int id, struct acpi_madt_entry_hook * table_handler)
232 return core_ACPITableMADTFamParse(ACPI_APIC, sizeof(struct acpi_table_madt), id, table_handler);
235 /**********************************************************/
236 int core_ACPITableParse(int id, struct acpi_table_hook * header_handler)
238 int count = 0;
239 unsigned int i = 0;
240 struct acpi_table_sdt *header_tmp;
242 if ( !header_handler ) return NULL;
244 for ( i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++ )
246 header_tmp = _Kern_ACPIData.kb_ACPI_SDT_Entry[i];
248 if ( header_tmp->id != id ) continue;
250 header_handler->phys_addr = header_tmp->pa;
251 header_handler->size = header_tmp->size;
252 AROS_UFC1 ( IPTR, header_handler->h_Entry, AROS_UFCA(struct Hook *, header_handler, A0) );
254 count++;
257 return count;
260 /**********************************************************/
261 IPTR core_ACPITableSDTGet(struct acpi_table_rsdp * RSDP)
263 struct acpi_table_header *header = NULL;
264 unsigned int i, id = 0;
266 if (!RSDP) return NULL;
268 /* First check XSDT (but only on ACPI 2.0-compatible systems) */
269 if ((RSDP->revision >= 2) && (((struct acpi20_table_rsdp*)RSDP)->xsdt_address))
271 rkprintf("[Kernel] core_ACPITableSDTGet: Checking XSDT @ %p\n", RSDP->rsdt_address);
273 struct acpi_table_xsdt *XSDT = NULL;
275 _Kern_ACPIData.kb_ACPI_SDT_Phys = ((struct acpi20_table_rsdp *)RSDP)->xsdt_address;
277 XSDT = (struct acpi_table_xsdt *)_Kern_ACPIData.kb_ACPI_SDT_Phys;
278 if (!XSDT)
280 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - bad XSDT pointer\n");
281 return NULL;
283 header = &XSDT->header;
285 if (strncmp( header->signature, "XSDT", 4))
287 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - bad XSDT signature [header @ %p, sig='%4.4s']\n",header,header->signature);
288 return NULL;
291 if (core_ACPITableChecksum(header, header->length))
293 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - XSDT checksum invalid\n");
294 return NULL;
297 _Kern_ACPIData.kb_ACPI_SDT_Count = (header->length - sizeof(struct acpi_table_header)) >> 3;
298 if (_Kern_ACPIData.kb_ACPI_SDT_Count > ACPI_MAX_TABLES)
300 rkprintf("[Kernel] core_ACPITableSDTGet: WARNING - Truncated %lu XSDT entries\n", (_Kern_ACPIData.kb_ACPI_SDT_Count - ACPI_MAX_TABLES));
301 _Kern_ACPIData.kb_ACPI_SDT_Count = ACPI_MAX_TABLES;
304 for (i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++)
306 _Kern_ACPIData.kb_ACPI_SDT_Entry[i] = &KernACPISDTEntries[i];
307 ((struct acpi_table_sdt *)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->pa = (unsigned long)XSDT->entry[i];
310 else if (RSDP->rsdt_address)
312 /* If there is no XSDT, then check RSDT */
313 rkprintf("[Kernel] core_ACPITableSDTGet: Checking RSDT @ %p\n", RSDP->rsdt_address);
315 struct acpi_table_rsdt *RSDT = NULL;
317 _Kern_ACPIData.kb_ACPI_SDT_Phys = RSDP->rsdt_address;
319 RSDT = (struct acpi_table_rsdt *)_Kern_ACPIData.kb_ACPI_SDT_Phys;
320 if (!RSDT)
322 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - bad RSDT pointer\n");
323 return NULL;
325 header = &RSDT->header;
327 if (strncmp(header->signature, "RSDT", 4))
329 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - bad RSDT signature [header @ %p, sig='%4.4s']\n",header,header->signature);
330 return NULL;
333 if (core_ACPITableChecksum(header, header->length))
335 rkprintf("[Kernel] core_ACPITableSDTGet: ERROR - RSDT checksum invalid\n");
336 return NULL;
339 _Kern_ACPIData.kb_ACPI_SDT_Count = (header->length - sizeof(struct acpi_table_header)) >> 2;
340 if (_Kern_ACPIData.kb_ACPI_SDT_Count > ACPI_MAX_TABLES)
342 rkprintf("[Kernel] core_ACPITableSDTGet: WARNING - Truncated %lu RSDT entries\n", (_Kern_ACPIData.kb_ACPI_SDT_Count - ACPI_MAX_TABLES));
343 _Kern_ACPIData.kb_ACPI_SDT_Count = ACPI_MAX_TABLES;
346 for (i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++)
348 _Kern_ACPIData.kb_ACPI_SDT_Entry[i] = &KernACPISDTEntries[i];
349 ((struct acpi_table_sdt *)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->pa = (unsigned long)RSDT->entry[i];
352 else
354 rkprintf("[Kernel] core_ACPITableSDTGet: No System Description Table (RSDT/XSDT) specified in RSDP\n");
355 return NULL;
358 core_ACPITableDump(header, _Kern_ACPIData.kb_ACPI_SDT_Phys);
360 for (i = 0; i < _Kern_ACPIData.kb_ACPI_SDT_Count; i++)
362 header = (struct acpi_table_header *)(((struct acpi_table_sdt*)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->pa);
363 if (header == NULL)
364 continue;
366 core_ACPITableDump(header, ((struct acpi_table_sdt *)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->pa);
368 if (core_ACPITableChecksum(header, header->length))
370 rkprintf("[Kernel] core_ACPITableSDTGet: WARNING - SDT %d Checksum invalid\n", i);
371 continue;
374 ((struct acpi_table_sdt *)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->size = header->length;
376 /* Start at 1 to skip "unknown" */
377 for (id = 1; id < ACPI_TABLE_COUNT; id++)
379 if (!strncmp((char *)&header->signature, KernACPISDTSigs[id], sizeof(header->signature)))
381 ((struct acpi_table_sdt *)_Kern_ACPIData.kb_ACPI_SDT_Entry[i])->id = id;
386 /* We want to print the DSDT (because this is what people usually blacklist against),
387 but it is *not* in the RSDT. We don't know its phys_addr, so just print 0. */
388 header = NULL;
389 if (!(core_ACPITableHeaderEarly(ACPI_DSDT, &header)))
391 core_ACPITableDump(header, 0);
394 return _Kern_ACPIData.kb_ACPI_SDT_Phys;
397 /**********************************************************/
398 int core_ACPIIsBlacklisted()
400 int i = 0;
401 int blacklisted = 0;
402 struct acpi_table_header *table_header;
404 while (_ACPI_OEMBlacklist[i].oem_id[0] != '\0')
406 if (core_ACPITableHeaderEarly(_ACPI_OEMBlacklist[i].acpi_tableid, &table_header))
408 i++;
409 continue;
412 if (strncmp(_ACPI_OEMBlacklist[i].oem_id, table_header->oem_id, 6))
414 i++;
415 continue;
418 if (strncmp(_ACPI_OEMBlacklist[i].oem_table_id, table_header->oem_table_id, 8))
420 i++;
421 continue;
424 if ((_ACPI_OEMBlacklist[i].oem_revision_match == all_versions) ||
425 ((_ACPI_OEMBlacklist[i].oem_revision_match == less_than_or_equal) &&
426 (table_header->oem_revision <= _ACPI_OEMBlacklist[i].oem_revision)) ||
427 ((_ACPI_OEMBlacklist[i].oem_revision_match == greater_than_or_equal) &&
428 (table_header->oem_revision >= _ACPI_OEMBlacklist[i].oem_revision)) ||
429 ((_ACPI_OEMBlacklist[i].oem_revision_match == equal) &&
430 (table_header->oem_revision == _ACPI_OEMBlacklist[i].oem_revision)))
432 rkprintf("[Kernel] core_ACPIIsBlacklisted: ERROR - Vendor \"%6.6s\" System \"%8.8s\" Revision 0x%x has a known ACPI BIOS problem.\n",
433 _ACPI_OEMBlacklist[i].oem_id, _ACPI_OEMBlacklist[i].oem_table_id, _ACPI_OEMBlacklist[i].oem_revision);
434 rkprintf("[Kernel] core_ACPIIsBlacklisted: ERROR - Reason: %s. This is a %s error\n",
435 _ACPI_OEMBlacklist[i].blacklist_reason, ( _ACPI_OEMBlacklist[i].blacklist_critical ? "non-recoverable" : "recoverable" ));
437 blacklisted = _ACPI_OEMBlacklist[i].blacklist_critical;
438 break;
440 else i++;
443 return blacklisted;
446 ULONG core_ACPIInitialise()
448 int result = 0;
449 rkprintf("[Kernel] core_ACPIInitialise()\n");
451 struct acpi_table_hook ACPI_TableParse_MADT_hook = {
452 .h_Entry = (APTR)ACPI_hook_Table_MADT_Parse
455 struct acpi_table_hook ACPI_TableParse_LAPIC_Addr_Ovr_hook = {
456 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Addr_Ovr_Parse
459 struct acpi_table_hook ACPI_TableParse_LAPIC_hook = {
460 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_Parse
463 struct acpi_table_hook ACPI_TableParse_LAPIC_NMI_hook = {
464 .h_Entry = (APTR)ACPI_hook_Table_LAPIC_NMI_Parse
467 struct acpi_table_hook ACPI_TableParse_IOAPIC_hook = {
468 .h_Entry = (APTR)ACPI_hook_Table_IOAPIC_Parse
471 struct acpi_table_hook ACPI_TableParse_Int_Src_Ovr_hook = {
472 .h_Entry = (APTR)ACPI_hook_Table_Int_Src_Ovr_Parse
475 struct acpi_table_hook ACPI_TableParse_NMI_Src_hook = {
476 .h_Entry = (APTR)ACPI_hook_Table_NMI_Src_Parse
479 struct acpi_table_hook ACPI_TableParse_HPET_hook = {
480 .h_Entry = (APTR)ACPI_hook_Table_HPET_Parse
483 /* MADT : If it exists, parse the Multiple APIC Description Table "MADT",
484 This table provides platform SMP configuration information [the successor to MPS tables] */
485 result = core_ACPITableParse( ACPI_APIC, &ACPI_TableParse_MADT_hook);
486 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableParse(ACPI_APIC) returned %p\n", result);
487 if ( !result ) return NULL;
488 else if ( result < 0 )
490 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing MADT\n");
491 return result;
493 else if ( result > 1 )
495 rkprintf("[Kernel] core_ACPIInitialise: WARNING - Multiple MADT tables exist\n");
498 /* Local APIC : The LAPIC address is obtained from the MADT (32-bit value)
499 and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). */
500 result = core_ACPITableMADTParse( ACPI_MADT_LAPIC_ADDR_OVR, &ACPI_TableParse_LAPIC_Addr_Ovr_hook );
501 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_LAPIC_ADDR_OVR) returned %p\n", result);
502 if ( result < 0 )
504 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing LAPIC address override entry\n");
505 return result;
508 result = core_ACPITableMADTParse( ACPI_MADT_LAPIC, &ACPI_TableParse_LAPIC_hook);
509 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_LAPIC) returned %p\n", result);
510 if ( !result )
512 #warning "TODO: Cleanup to allow fallback to MPS.."
513 rkprintf("[Kernel] core_ACPIInitialise: ERROR - No LAPIC entries present\n");
514 return NULL;
516 else if (result < 0)
518 #warning "TODO: Cleanup to allow fallback to MPS.."
519 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing LAPIC entry\n");
520 return result;
523 result = core_ACPITableMADTParse( ACPI_MADT_LAPIC_NMI, &ACPI_TableParse_LAPIC_NMI_hook);
524 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_LAPIC_NMI) returned %p\n", result);
525 if ( result < 0 )
527 #warning "TODO: Cleanup to allow fallback to MPS.."
528 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing LAPIC NMI entry\n");
529 return result;
532 _Kern_ACPIData.kb_ACPI_LAPIC = 1;
534 /* I/O APIC : ACPI interpreter is required to complete interrupt setup,
535 so if it is off, don't enumerate the io-apics with ACPI.
536 If MPS is present, it will handle them, otherwise the system will stay in PIC mode */
537 if (_Kern_ACPIData.kb_ACPI_Disabled || !_Kern_ACPIData.kb_ACPI_IRQ) return 1;
539 result = core_ACPITableMADTParse(ACPI_MADT_IOAPIC, &ACPI_TableParse_IOAPIC_hook);
540 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_IOAPIC) returned %p\n", result);
541 if (!result)
543 rkprintf("[Kernel] core_ACPIInitialise: ERROR - No IOAPIC entries present\n");
544 return NULL;
546 else if (result < 0)
548 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing IOAPIC entry\n");
549 return result;
552 /* Build a default routing table for legacy (ISA) interrupts. */
553 #warning "TODO: implement legacy irq config.."
554 // mp_config_acpi_legacy_irqs();
556 result = core_ACPITableMADTParse(ACPI_MADT_INT_SRC_OVR, &ACPI_TableParse_Int_Src_Ovr_hook);
557 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_INT_SRC_OVR) returned %p\n", result);
558 if (result < 0)
560 #warning "TODO: Cleanup to allow fallback to MPS.."
561 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing interrupt source overrides entry\n");
562 return result;
565 result = core_ACPITableMADTParse(ACPI_MADT_NMI_SRC, &ACPI_TableParse_NMI_Src_hook);
566 rkprintf("[Kernel] core_ACPIInitialise: core_ACPITableMADTParse(ACPI_MADT_NMI_SRC) returned %p\n", result);
567 if (result < 0)
569 #warning "TODO: Cleanup to allow fallback to MPS.."
570 rkprintf("[Kernel] core_ACPIInitialise: ERROR - Error parsing NMI SRC entry\n");
571 return result;
574 _Kern_ACPIData.kb_APIC_IRQ_Model = ACPI_IRQ_MODEL_IOAPIC;
576 _Kern_ACPIData.kb_ACPI_IOAPIC = 1;
578 if ( _Kern_ACPIData.kb_ACPI_LAPIC && _Kern_ACPIData.kb_ACPI_IOAPIC )
580 _Kern_ACPIData.kb_SMP_Config = 1;
581 rkprintf("[Kernel] core_ACPIInitialise: SMP Configured by APIC\n");
582 #warning "TODO: implement check for clustered apic's.."
583 //core_APICClusteredCheck();
586 core_ACPITableParse( ACPI_HPET, &ACPI_TableParse_HPET_hook );
588 return NULL;
589 } /* core_ACPIInit */
592 /**********************************************************/
593 IPTR core_ACPIRootSystemDescriptionPointerScan(IPTR scan_start, IPTR scan_length)
595 unsigned long scan_offset;
596 char *scan_ptr;
598 /* Scan for the Root System Description Pointer signature
599 on 16-byte boundaries of the physical memory region */
600 for (scan_offset = 0; scan_offset < scan_length; scan_offset += 16)
602 scan_ptr = scan_start + scan_offset;
603 if ((scan_ptr[0] != 'R') ||
604 (scan_ptr[1] != 'S') ||
605 (scan_ptr[2] != 'D') ||
606 (scan_ptr[3] != ' ') ||
607 (scan_ptr[4] != 'P') ||
608 (scan_ptr[5] != 'T') ||
609 (scan_ptr[6] != 'R') ||
610 (scan_ptr[7] != ' '))
611 continue;
613 /* RSDP located, return its address */
614 return scan_ptr;
617 return NULL;
620 /* Attempt to locate the ACPI Root System Description Pointer */
621 IPTR core_ACPIRootSystemDescriptionPointerLocate()
623 IPTR RSDP_PhysAddr = 0;
625 /* Search the first Kilobyte of the Extended BIOS Data Area */
626 if ((RSDP_PhysAddr = core_ACPIRootSystemDescriptionPointerScan(0x00000000, 0x00000400)) == NULL)
628 /* Search in BIOS ROM address space */
629 if ((RSDP_PhysAddr = core_ACPIRootSystemDescriptionPointerScan(0x000E0000, 0x000FFFFF)) != NULL)
631 rkprintf("[Kernel] core_ACPIRootSystemDescriptionPointerLocate: RSDP found in BIOS ROM space @ %p\n", RSDP_PhysAddr);
634 else
636 rkprintf("[Kernel] core_ACPIRootSystemDescriptionPointerLocate: RSDP found in EBDA @ %p\n", RSDP_PhysAddr);
639 return RSDP_PhysAddr;
642 /**********************************************************/
643 int core_ACPITableChecksum(void * table_pointer, unsigned long table_length)
645 UBYTE *tmp_pointer = (UBYTE *)table_pointer;
646 unsigned long remains = table_length;
647 unsigned long sum = 0;
649 if (!tmp_pointer || !table_length) return NULL;
651 while (remains--) sum += *tmp_pointer++;
653 return (sum & 0xFF);
656 /**********************************************************/
657 IPTR core_ACPIProbe()
659 struct acpi_table_rsdp *RSDP;
660 IPTR *RSDP_PhysAddr;
661 int checksum = 0;
663 rkprintf("[Kernel] core_ACPIProbe()\n");
665 /* Locate the Root System Description Table (RSDP) */
666 RSDP_PhysAddr = core_ACPIRootSystemDescriptionPointerLocate();
667 if (RSDP_PhysAddr != NULL)
669 RSDP = RSDP_PhysAddr;
670 rkprintf("[Kernel] core_ACPIProbe: Root System Description Pointer @ %p\n", RSDP);
671 rkprintf("[Kernel] core_ACPIProbe: Root System Description Pointer [ v%3.3d '%6.6s' ]\n", RSDP->revision, RSDP->oem_id);
673 if (RSDP->revision >= 2) checksum = core_ACPITableChecksum(RSDP, ((struct acpi20_table_rsdp *)RSDP)->length);
674 else checksum = core_ACPITableChecksum(RSDP, sizeof(struct acpi_table_rsdp));
676 if (checksum)
678 rkprintf("[Kernel] core_ACPIProbe: ERROR: Invalid RSDP checksum (%d)\n", checksum);
679 return NULL;
682 /* Locate and map the System Description table (RSDT/XSDT) */
683 core_ACPITableSDTGet(RSDP);
685 if (core_ACPIIsBlacklisted())
687 rkprintf("[Kernel] core_ACPIProbe: WARNING - BIOS listed in blacklist, disabling ACPI support\n");
688 return NULL;
691 else
693 rkprintf("[Kernel] core_ACPIProbe: Unable to locate RSDP - no ACPI\n");
696 return RSDP;