Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenhalacpi.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS HAL 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: hal/halx86/generic/acpi/halacpi.c 00005 * PURPOSE: HAL ACPI Code 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <hal.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 LIST_ENTRY HalpAcpiTableCacheList; 00018 FAST_MUTEX HalpAcpiTableCacheLock; 00019 00020 BOOLEAN HalpProcessedACPIPhase0; 00021 BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB; 00022 00023 FADT HalpFixedAcpiDescTable; 00024 PDEBUG_PORT_TABLE HalpDebugPortTable; 00025 PACPI_SRAT HalpAcpiSrat; 00026 PBOOT_TABLE HalpSimpleBootFlagTable; 00027 00028 PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress; 00029 PHYSICAL_ADDRESS HalpLowStubPhysicalAddress; 00030 PHARDWARE_PTE HalpPteForFlush; 00031 PVOID HalpVirtAddrForFlush; 00032 PVOID HalpLowStub; 00033 00034 PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode; 00035 00036 LIST_ENTRY HalpAcpiTableMatchList; 00037 00038 ULONG HalpInvalidAcpiTable; 00039 00040 ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15}; 00041 00042 /* This determines the HAL type */ 00043 BOOLEAN HalDisableFirmwareMapper = TRUE; 00044 PWCHAR HalHardwareIdString = L"acpipic_up"; 00045 PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL"; 00046 00047 /* PRIVATE FUNCTIONS **********************************************************/ 00048 00049 PDESCRIPTION_HEADER 00050 NTAPI 00051 HalpAcpiGetCachedTable(IN ULONG Signature) 00052 { 00053 PLIST_ENTRY ListHead, NextEntry; 00054 PACPI_CACHED_TABLE CachedTable; 00055 00056 /* Loop cached tables */ 00057 ListHead = &HalpAcpiTableCacheList; 00058 NextEntry = ListHead->Flink; 00059 while (NextEntry != ListHead) 00060 { 00061 /* Get the table */ 00062 CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links); 00063 00064 /* Compare signatures */ 00065 if (CachedTable->Header.Signature == Signature) return &CachedTable->Header; 00066 00067 /* Keep going */ 00068 NextEntry = NextEntry->Flink; 00069 } 00070 00071 /* Nothing found */ 00072 return NULL; 00073 } 00074 00075 VOID 00076 NTAPI 00077 HalpAcpiCacheTable(IN PDESCRIPTION_HEADER TableHeader) 00078 { 00079 PACPI_CACHED_TABLE CachedTable; 00080 00081 /* Get the cached table and link it */ 00082 CachedTable = CONTAINING_RECORD(TableHeader, ACPI_CACHED_TABLE, Header); 00083 InsertTailList(&HalpAcpiTableCacheList, &CachedTable->Links); 00084 } 00085 00086 PVOID 00087 NTAPI 00088 HalpAcpiCopyBiosTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00089 IN PDESCRIPTION_HEADER TableHeader) 00090 { 00091 ULONG Size; 00092 PFN_COUNT PageCount; 00093 PHYSICAL_ADDRESS PhysAddress; 00094 PACPI_CACHED_TABLE CachedTable; 00095 PDESCRIPTION_HEADER CopiedTable; 00096 00097 /* Size we'll need for the cached table */ 00098 Size = TableHeader->Length + FIELD_OFFSET(ACPI_CACHED_TABLE, Header); 00099 if (LoaderBlock) 00100 { 00101 /* Phase 0: Convert to pages and use the HAL heap */ 00102 PageCount = BYTES_TO_PAGES(Size); 00103 PhysAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock, 00104 0x1000000, 00105 PageCount, 00106 FALSE); 00107 if (PhysAddress.QuadPart) 00108 { 00109 /* Map it */ 00110 CachedTable = HalpMapPhysicalMemory64(PhysAddress, PageCount); 00111 } 00112 else 00113 { 00114 /* No memory, so nothing to map */ 00115 CachedTable = NULL; 00116 } 00117 } 00118 else 00119 { 00120 /* Use Mm pool */ 00121 CachedTable = ExAllocatePoolWithTag(NonPagedPool, Size, ' laH'); 00122 } 00123 00124 /* Do we have the cached table? */ 00125 if (CachedTable) 00126 { 00127 /* Copy the data */ 00128 CopiedTable = &CachedTable->Header; 00129 RtlCopyMemory(CopiedTable, TableHeader, TableHeader->Length); 00130 } 00131 else 00132 { 00133 /* Nothing to return */ 00134 CopiedTable = NULL; 00135 } 00136 00137 /* Return the table */ 00138 return CopiedTable; 00139 } 00140 00141 PVOID 00142 NTAPI 00143 HalpAcpiGetTableFromBios(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00144 IN ULONG Signature) 00145 { 00146 PHYSICAL_ADDRESS PhysicalAddress; 00147 PXSDT Xsdt; 00148 PRSDT Rsdt; 00149 PFADT Fadt; 00150 PDESCRIPTION_HEADER Header = NULL; 00151 ULONG TableLength; 00152 CHAR CheckSum = 0; 00153 ULONG Offset; 00154 ULONG EntryCount, CurrentEntry; 00155 PCHAR CurrentByte; 00156 PFN_COUNT PageCount; 00157 00158 /* Should not query the RSDT/XSDT by itself */ 00159 if ((Signature == RSDT_SIGNATURE) || (Signature == XSDT_SIGNATURE)) return NULL; 00160 00161 /* Special case request for DSDT, because the FADT points to it */ 00162 if (Signature == DSDT_SIGNATURE) 00163 { 00164 /* Grab the FADT */ 00165 Fadt = HalpAcpiGetTable(LoaderBlock, FADT_SIGNATURE); 00166 if (Fadt) 00167 { 00168 /* Grab the DSDT address and assume 2 pages */ 00169 PhysicalAddress.HighPart = 0; 00170 PhysicalAddress.LowPart = Fadt->dsdt; 00171 TableLength = 2 * PAGE_SIZE; 00172 00173 /* Map it */ 00174 if (LoaderBlock) 00175 { 00176 /* Phase 0, use HAL heap */ 00177 Header = HalpMapPhysicalMemory64(PhysicalAddress, 2u); 00178 } 00179 else 00180 { 00181 /* Phase 1, use Mm */ 00182 Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, 0); 00183 } 00184 00185 /* Fail if we couldn't map it */ 00186 if (!Header) 00187 { 00188 DPRINT1("HAL: Failed to map ACPI table.\n"); 00189 return NULL; 00190 } 00191 00192 /* Validate the signature */ 00193 if (Header->Signature != DSDT_SIGNATURE) 00194 { 00195 /* Fail and unmap */ 00196 if (LoaderBlock) 00197 { 00198 /* Using HAL heap */ 00199 HalpUnmapVirtualAddress(Header, 2); 00200 } 00201 else 00202 { 00203 /* Using Mm */ 00204 MmUnmapIoSpace(Header, 2 * PAGE_SIZE); 00205 } 00206 00207 /* Didn't find anything */ 00208 return NULL; 00209 } 00210 } 00211 else 00212 { 00213 /* Couldn't find it */ 00214 return NULL; 00215 } 00216 } 00217 else 00218 { 00219 /* To find tables, we need the RSDT */ 00220 Rsdt = HalpAcpiGetTable(LoaderBlock, RSDT_SIGNATURE); 00221 if (Rsdt) 00222 { 00223 /* Won't be using the XSDT */ 00224 Xsdt = NULL; 00225 } 00226 else 00227 { 00228 /* Only other choice is to use the XSDT */ 00229 Xsdt = HalpAcpiGetTable(LoaderBlock, XSDT_SIGNATURE); 00230 if (!Xsdt) return NULL; 00231 00232 /* Won't be using the RSDT */ 00233 Rsdt = NULL; 00234 } 00235 00236 /* Smallest RSDT/XSDT is one without table entries */ 00237 Offset = FIELD_OFFSET(RSDT, Tables); 00238 if (Xsdt) 00239 { 00240 /* Figure out total size of table and the offset */ 00241 TableLength = Xsdt->Header.Length; 00242 if (TableLength < Offset) Offset = Xsdt->Header.Length; 00243 00244 /* The entries are each 64-bits, so count them */ 00245 EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS); 00246 } 00247 else 00248 { 00249 /* Figure out total size of table and the offset */ 00250 TableLength = Rsdt->Header.Length; 00251 if (TableLength < Offset) Offset = Rsdt->Header.Length; 00252 00253 /* The entries are each 32-bits, so count them */ 00254 EntryCount = (TableLength - Offset) / sizeof(ULONG); 00255 } 00256 00257 /* Start at the beginning of the array and loop it */ 00258 for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++) 00259 { 00260 /* Are we using the XSDT? */ 00261 if (!Xsdt) 00262 { 00263 /* Read the 32-bit physical address */ 00264 PhysicalAddress.LowPart = Rsdt->Tables[CurrentEntry]; 00265 PhysicalAddress.HighPart = 0; 00266 } 00267 else 00268 { 00269 /* Read the 64-bit physical address */ 00270 PhysicalAddress = Xsdt->Tables[CurrentEntry]; 00271 } 00272 00273 /* Had we already mapped a table? */ 00274 if (Header) 00275 { 00276 /* Yes, unmap it */ 00277 if (LoaderBlock) 00278 { 00279 /* Using HAL heap */ 00280 HalpUnmapVirtualAddress(Header, 2); 00281 } 00282 else 00283 { 00284 /* Using Mm */ 00285 MmUnmapIoSpace(Header, 2 * PAGE_SIZE); 00286 } 00287 } 00288 00289 /* Now map this table */ 00290 if (!LoaderBlock) 00291 { 00292 /* Phase 1: Use HAL heap */ 00293 Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, MmNonCached); 00294 } 00295 else 00296 { 00297 /* Phase 0: Use Mm */ 00298 Header = HalpMapPhysicalMemory64(PhysicalAddress, 2); 00299 } 00300 00301 /* Check if we mapped it */ 00302 if (!Header) 00303 { 00304 /* Game over */ 00305 DPRINT1("HAL: Failed to map ACPI table.\n"); 00306 return NULL; 00307 } 00308 00309 /* We found it, break out */ 00310 DPRINT("Found ACPI table %c%c%c%c at 0x%p\n", 00311 Header->Signature & 0xFF, 00312 (Header->Signature & 0xFF00) >> 8, 00313 (Header->Signature & 0xFF0000) >> 16, 00314 (Header->Signature & 0xFF000000) >> 24, 00315 Header); 00316 if (Header->Signature == Signature) break; 00317 } 00318 00319 /* Did we end up here back at the last entry? */ 00320 if (CurrentEntry == EntryCount) 00321 { 00322 /* Yes, unmap the last table we processed */ 00323 if (LoaderBlock) 00324 { 00325 /* Using HAL heap */ 00326 HalpUnmapVirtualAddress(Header, 2); 00327 } 00328 else 00329 { 00330 /* Using Mm */ 00331 MmUnmapIoSpace(Header, 2 * PAGE_SIZE); 00332 } 00333 00334 /* Didn't find anything */ 00335 return NULL; 00336 } 00337 } 00338 00339 /* Past this point, we assume something was found */ 00340 ASSERT(Header); 00341 00342 /* How many pages do we need? */ 00343 PageCount = BYTES_TO_PAGES(Header->Length); 00344 if (PageCount != 2) 00345 { 00346 /* We assumed two, but this is not the case, free the current mapping */ 00347 if (LoaderBlock) 00348 { 00349 /* Using HAL heap */ 00350 HalpUnmapVirtualAddress(Header, 2); 00351 } 00352 else 00353 { 00354 /* Using Mm */ 00355 MmUnmapIoSpace(Header, 2 * PAGE_SIZE); 00356 } 00357 00358 /* Now map this table using its correct size */ 00359 if (!LoaderBlock) 00360 { 00361 /* Phase 1: Use HAL heap */ 00362 Header = MmMapIoSpace(PhysicalAddress, PageCount << PAGE_SHIFT, MmNonCached); 00363 } 00364 else 00365 { 00366 /* Phase 0: Use Mm */ 00367 Header = HalpMapPhysicalMemory64(PhysicalAddress, PageCount); 00368 } 00369 } 00370 00371 /* Fail if the remapped failed */ 00372 if (!Header) return NULL; 00373 00374 /* All tables in ACPI 3.0 other than the FACP should have correct checksum */ 00375 if ((Header->Signature != FADT_SIGNATURE) || (Header->Revision > 2)) 00376 { 00377 /* Go to the end of the table */ 00378 CheckSum = 0; 00379 CurrentByte = (PCHAR)Header + Header->Length; 00380 while (CurrentByte-- != (PCHAR)Header) 00381 { 00382 /* Add this byte */ 00383 CheckSum += *CurrentByte; 00384 } 00385 00386 /* The correct checksum is always 0, anything else is illegal */ 00387 if (CheckSum) 00388 { 00389 HalpInvalidAcpiTable = Header->Signature; 00390 DPRINT1("Checksum failed on ACPI table %c%c%c%c\n", 00391 (Signature & 0xFF), 00392 (Signature & 0xFF00) >> 8, 00393 (Signature & 0xFF0000) >> 16, 00394 (Signature & 0xFF000000) >> 24); 00395 } 00396 } 00397 00398 /* Return the table */ 00399 return Header; 00400 } 00401 00402 PVOID 00403 NTAPI 00404 HalpAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00405 IN ULONG Signature) 00406 { 00407 PFN_COUNT PageCount; 00408 PDESCRIPTION_HEADER TableAddress, BiosCopy; 00409 00410 /* See if we have a cached table? */ 00411 TableAddress = HalpAcpiGetCachedTable(Signature); 00412 if (!TableAddress) 00413 { 00414 /* No cache, search the BIOS */ 00415 TableAddress = HalpAcpiGetTableFromBios(LoaderBlock, Signature); 00416 if (TableAddress) 00417 { 00418 /* Found it, copy it into our own memory */ 00419 BiosCopy = HalpAcpiCopyBiosTable(LoaderBlock, TableAddress); 00420 00421 /* Get the pages, and unmap the BIOS copy */ 00422 PageCount = BYTES_TO_PAGES(TableAddress->Length); 00423 if (LoaderBlock) 00424 { 00425 /* Phase 0, use the HAL heap */ 00426 HalpUnmapVirtualAddress(TableAddress, PageCount); 00427 } 00428 else 00429 { 00430 /* Phase 1, use Mm */ 00431 MmUnmapIoSpace(TableAddress, PageCount << PAGE_SHIFT); 00432 } 00433 00434 /* Cache the bios copy */ 00435 TableAddress = BiosCopy; 00436 if (BiosCopy) HalpAcpiCacheTable(BiosCopy); 00437 } 00438 } 00439 00440 /* Return the table */ 00441 return TableAddress; 00442 } 00443 00444 PVOID 00445 NTAPI 00446 HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00447 IN ULONG Signature) 00448 { 00449 PDESCRIPTION_HEADER TableHeader; 00450 00451 /* Is this phase0 */ 00452 if (LoaderBlock) 00453 { 00454 /* Initialize the cache first */ 00455 if (!NT_SUCCESS(HalpAcpiTableCacheInit(LoaderBlock))) return NULL; 00456 } 00457 else 00458 { 00459 /* Lock the cache */ 00460 ExAcquireFastMutex(&HalpAcpiTableCacheLock); 00461 } 00462 00463 /* Get the table */ 00464 TableHeader = HalpAcpiGetTable(LoaderBlock, Signature); 00465 00466 /* Release the lock in phase 1 */ 00467 if (!LoaderBlock) ExReleaseFastMutex(&HalpAcpiTableCacheLock); 00468 00469 /* Return the table */ 00470 return TableHeader; 00471 } 00472 00473 VOID 00474 NTAPI 00475 HalpNumaInitializeStaticConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00476 { 00477 PACPI_SRAT SratTable; 00478 00479 /* Get the SRAT, bail out if it doesn't exist */ 00480 SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE); 00481 HalpAcpiSrat = SratTable; 00482 if (!SratTable) return; 00483 } 00484 00485 VOID 00486 NTAPI 00487 HalpGetHotPlugMemoryInfo(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00488 { 00489 PACPI_SRAT SratTable; 00490 00491 /* Get the SRAT, bail out if it doesn't exist */ 00492 SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE); 00493 HalpAcpiSrat = SratTable; 00494 if (!SratTable) return; 00495 } 00496 00497 VOID 00498 NTAPI 00499 HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00500 { 00501 /* For this HAL, it means to get hot plug memory information */ 00502 HalpGetHotPlugMemoryInfo(LoaderBlock); 00503 } 00504 00505 VOID 00506 NTAPI 00507 HalpAcpiDetectMachineSpecificActions(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00508 IN PFADT DescriptionTable) 00509 { 00510 /* Does this HAL specify something? */ 00511 if (HalpAcpiTableMatchList.Flink) 00512 { 00513 /* Great, but we don't support it */ 00514 DPRINT1("WARNING: Your HAL has specific ACPI hacks to apply!\n"); 00515 } 00516 } 00517 00518 VOID 00519 NTAPI 00520 HalpInitBootTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00521 { 00522 PBOOT_TABLE BootTable; 00523 00524 /* Get the boot table */ 00525 BootTable = HalAcpiGetTable(LoaderBlock, BOOT_SIGNATURE); 00526 HalpSimpleBootFlagTable = BootTable; 00527 00528 /* Validate it */ 00529 if ((BootTable) && 00530 (BootTable->Header.Length >= sizeof(BOOT_TABLE)) && 00531 (BootTable->CMOSIndex >= 9)) 00532 { 00533 DPRINT1("ACPI Boot table found, but not supported!\n"); 00534 } 00535 else 00536 { 00537 /* Invalid or doesn't exist, ignore it */ 00538 HalpSimpleBootFlagTable = 0; 00539 } 00540 00541 /* Install the end of boot handler */ 00542 // HalEndOfBoot = HalpEndOfBoot; 00543 } 00544 00545 NTSTATUS 00546 NTAPI 00547 HalpAcpiFindRsdtPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock, 00548 OUT PACPI_BIOS_MULTI_NODE* AcpiMultiNode) 00549 { 00550 PCONFIGURATION_COMPONENT_DATA ComponentEntry; 00551 PCONFIGURATION_COMPONENT_DATA Next = NULL; 00552 PCM_PARTIAL_RESOURCE_LIST ResourceList; 00553 PACPI_BIOS_MULTI_NODE NodeData; 00554 SIZE_T NodeLength; 00555 PFN_COUNT PageCount; 00556 PVOID MappedAddress; 00557 PHYSICAL_ADDRESS PhysicalAddress; 00558 00559 /* Did we already do this once? */ 00560 if (HalpAcpiMultiNode) 00561 { 00562 /* Return what we know */ 00563 *AcpiMultiNode = HalpAcpiMultiNode; 00564 return STATUS_SUCCESS; 00565 } 00566 00567 /* Assume failure */ 00568 *AcpiMultiNode = NULL; 00569 00570 /* Find the multi function adapter key */ 00571 ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot, 00572 AdapterClass, 00573 MultiFunctionAdapter, 00574 0, 00575 &Next); 00576 while (ComponentEntry) 00577 { 00578 /* Find the ACPI BIOS key */ 00579 if (!_stricmp(ComponentEntry->ComponentEntry.Identifier, "ACPI BIOS")) 00580 { 00581 /* Found it */ 00582 break; 00583 } 00584 00585 /* Keep searching */ 00586 Next = ComponentEntry; 00587 ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot, 00588 AdapterClass, 00589 MultiFunctionAdapter, 00590 NULL, 00591 &Next); 00592 } 00593 00594 /* Make sure we found it */ 00595 if (!ComponentEntry) 00596 { 00597 DPRINT1("**** HalpAcpiFindRsdtPhase0: did NOT find RSDT\n"); 00598 return STATUS_NOT_FOUND; 00599 } 00600 00601 /* The configuration data is a resource list, and the BIOS node follows */ 00602 ResourceList = ComponentEntry->ConfigurationData; 00603 NodeData = (PACPI_BIOS_MULTI_NODE)(ResourceList + 1); 00604 00605 /* How many E820 memory entries are there? */ 00606 NodeLength = sizeof(ACPI_BIOS_MULTI_NODE) + 00607 (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY); 00608 00609 /* Convert to pages */ 00610 PageCount = (PFN_COUNT)BYTES_TO_PAGES(NodeLength); 00611 00612 /* Allocate the memory */ 00613 PhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock, 00614 0x1000000, 00615 PageCount, 00616 FALSE); 00617 if (PhysicalAddress.QuadPart) 00618 { 00619 /* Map it if the allocation worked */ 00620 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, PageCount); 00621 } 00622 else 00623 { 00624 /* Otherwise we'll have to fail */ 00625 MappedAddress = NULL; 00626 } 00627 00628 /* Save the multi node, bail out if we didn't find it */ 00629 HalpAcpiMultiNode = MappedAddress; 00630 if (!MappedAddress) return STATUS_INSUFFICIENT_RESOURCES; 00631 00632 /* Copy the multi-node data */ 00633 RtlCopyMemory(MappedAddress, NodeData, NodeLength); 00634 00635 /* Return the data */ 00636 *AcpiMultiNode = HalpAcpiMultiNode; 00637 return STATUS_SUCCESS; 00638 } 00639 00640 NTSTATUS 00641 NTAPI 00642 HalpAcpiTableCacheInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00643 { 00644 PACPI_BIOS_MULTI_NODE AcpiMultiNode; 00645 NTSTATUS Status = STATUS_SUCCESS; 00646 PHYSICAL_ADDRESS PhysicalAddress; 00647 PVOID MappedAddress; 00648 ULONG TableLength; 00649 PRSDT Rsdt; 00650 PLOADER_PARAMETER_EXTENSION LoaderExtension; 00651 00652 /* Only initialize once */ 00653 if (HalpAcpiTableCacheList.Flink) return Status; 00654 00655 /* Setup the lock and table */ 00656 ExInitializeFastMutex(&HalpAcpiTableCacheLock); 00657 InitializeListHead(&HalpAcpiTableCacheList); 00658 00659 /* Find the RSDT */ 00660 Status = HalpAcpiFindRsdtPhase0(LoaderBlock, &AcpiMultiNode); 00661 if (!NT_SUCCESS(Status)) return Status; 00662 00663 PhysicalAddress.QuadPart = AcpiMultiNode->RsdtAddress.QuadPart; 00664 00665 /* Map the RSDT */ 00666 if (LoaderBlock) 00667 { 00668 /* Phase0: Use HAL Heap to map the RSDT, we assume it's about 2 pages */ 00669 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, 2); 00670 } 00671 else 00672 { 00673 /* Use an I/O map */ 00674 MappedAddress = MmMapIoSpace(PhysicalAddress, PAGE_SIZE * 2, MmNonCached); 00675 } 00676 00677 /* Get the RSDT */ 00678 Rsdt = MappedAddress; 00679 if (!MappedAddress) 00680 { 00681 /* Fail, no memory */ 00682 DPRINT1("HAL: Failed to map RSDT\n"); 00683 return STATUS_INSUFFICIENT_RESOURCES; 00684 } 00685 00686 /* Validate it */ 00687 if ((Rsdt->Header.Signature != RSDT_SIGNATURE) && 00688 (Rsdt->Header.Signature != XSDT_SIGNATURE)) 00689 { 00690 /* Very bad: crash */ 00691 HalDisplayString("Bad RSDT pointer\n"); 00692 KeBugCheckEx(MISMATCHED_HAL, 4, __LINE__, 0, 0); 00693 } 00694 00695 /* We assumed two pages -- do we need less or more? */ 00696 TableLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart, 00697 Rsdt->Header.Length); 00698 if (TableLength != 2) 00699 { 00700 /* Are we in phase 0 or 1? */ 00701 if (!LoaderBlock) 00702 { 00703 /* Unmap the old table, remap the new one, using Mm I/O space */ 00704 MmUnmapIoSpace(MappedAddress, 2 * PAGE_SIZE); 00705 MappedAddress = MmMapIoSpace(PhysicalAddress, 00706 TableLength << PAGE_SHIFT, 00707 MmNonCached); 00708 } 00709 else 00710 { 00711 /* Unmap the old table, remap the new one, using HAL heap */ 00712 HalpUnmapVirtualAddress(MappedAddress, 2); 00713 MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, TableLength); 00714 } 00715 00716 /* Get the remapped table */ 00717 Rsdt = MappedAddress; 00718 if (!MappedAddress) 00719 { 00720 /* Fail, no memory */ 00721 DPRINT1("HAL: Couldn't remap RSDT\n"); 00722 return STATUS_INSUFFICIENT_RESOURCES; 00723 } 00724 } 00725 00726 /* Now take the BIOS copy and make our own local copy */ 00727 Rsdt = HalpAcpiCopyBiosTable(LoaderBlock, &Rsdt->Header); 00728 if (!Rsdt) 00729 { 00730 /* Fail, no memory */ 00731 DPRINT1("HAL: Couldn't remap RSDT\n"); 00732 return STATUS_INSUFFICIENT_RESOURCES; 00733 } 00734 00735 /* Get rid of the BIOS mapping */ 00736 if (LoaderBlock) 00737 { 00738 /* Use HAL heap */ 00739 HalpUnmapVirtualAddress(MappedAddress, TableLength); 00740 00741 LoaderExtension = LoaderBlock->Extension; 00742 } 00743 else 00744 { 00745 /* Use Mm */ 00746 MmUnmapIoSpace(MappedAddress, TableLength << PAGE_SHIFT); 00747 00748 LoaderExtension = NULL; 00749 } 00750 00751 /* Cache the RSDT */ 00752 HalpAcpiCacheTable(&Rsdt->Header); 00753 00754 /* Check for compatible loader block extension */ 00755 if (LoaderExtension && (LoaderExtension->Size >= 0x58)) 00756 { 00757 /* Compatible loader: did it provide an ACPI table override? */ 00758 if ((LoaderExtension->AcpiTable) && (LoaderExtension->AcpiTableSize)) 00759 { 00760 /* Great, because we don't support it! */ 00761 DPRINT1("ACPI Table Overrides Not Supported!\n"); 00762 } 00763 } 00764 00765 /* Done */ 00766 return Status; 00767 } 00768 00769 VOID 00770 NTAPI 00771 HaliAcpiTimerInit(IN ULONG TimerPort, 00772 IN ULONG TimerValExt) 00773 { 00774 PAGED_CODE(); 00775 00776 /* Is this in the init phase? */ 00777 if (!TimerPort) 00778 { 00779 /* Get the data from the FADT */ 00780 TimerPort = HalpFixedAcpiDescTable.pm_tmr_blk_io_port; 00781 TimerValExt = HalpFixedAcpiDescTable.flags & ACPI_TMR_VAL_EXT; 00782 DPRINT1("ACPI Timer at: %Xh (EXT: %d)\n", TimerPort, TimerValExt); 00783 } 00784 00785 /* FIXME: Now proceed to the timer initialization */ 00786 //HalaAcpiTimerInit(TimerPort, TimerValExt); 00787 } 00788 00789 NTSTATUS 00790 NTAPI 00791 HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00792 { 00793 NTSTATUS Status; 00794 PFADT Fadt; 00795 ULONG TableLength; 00796 PHYSICAL_ADDRESS PhysicalAddress; 00797 00798 /* Only do this once */ 00799 if (HalpProcessedACPIPhase0) return STATUS_SUCCESS; 00800 00801 /* Setup the ACPI table cache */ 00802 Status = HalpAcpiTableCacheInit(LoaderBlock); 00803 if (!NT_SUCCESS(Status)) return Status; 00804 00805 /* Grab the FADT */ 00806 Fadt = HalAcpiGetTable(LoaderBlock, FADT_SIGNATURE); 00807 if (!Fadt) 00808 { 00809 /* Fail */ 00810 DPRINT1("HAL: Didn't find the FACP\n"); 00811 return STATUS_NOT_FOUND; 00812 } 00813 00814 /* Assume typical size, otherwise whatever the descriptor table says */ 00815 TableLength = sizeof(FADT); 00816 if (Fadt->Header.Length < sizeof(FADT)) TableLength = Fadt->Header.Length; 00817 00818 /* Copy it in the HAL static buffer */ 00819 RtlCopyMemory(&HalpFixedAcpiDescTable, Fadt, TableLength); 00820 00821 /* Anything special this HAL needs to do? */ 00822 HalpAcpiDetectMachineSpecificActions(LoaderBlock, &HalpFixedAcpiDescTable); 00823 00824 /* Get the debug table for KD */ 00825 HalpDebugPortTable = HalAcpiGetTable(LoaderBlock, DBGP_SIGNATURE); 00826 00827 /* Initialize NUMA through the SRAT */ 00828 HalpNumaInitializeStaticConfiguration(LoaderBlock); 00829 00830 /* Initialize hotplug through the SRAT */ 00831 HalpDynamicSystemResourceConfiguration(LoaderBlock); 00832 if (HalpAcpiSrat) 00833 { 00834 DPRINT1("Your machine has a SRAT, but NUMA/HotPlug are not supported!\n"); 00835 } 00836 00837 /* Can there be memory higher than 4GB? */ 00838 if (HalpMaxHotPlugMemoryAddress.HighPart >= 1) 00839 { 00840 /* We'll need this for DMA later */ 00841 HalpPhysicalMemoryMayAppearAbove4GB = TRUE; 00842 } 00843 00844 /* Setup the ACPI timer */ 00845 HaliAcpiTimerInit(0, 0); 00846 00847 /* Do we have a low stub address yet? */ 00848 if (!HalpLowStubPhysicalAddress.QuadPart) 00849 { 00850 /* Allocate it */ 00851 HalpLowStubPhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock, 00852 0x100000, 00853 1, 00854 FALSE); 00855 if (HalpLowStubPhysicalAddress.QuadPart) 00856 { 00857 /* Map it */ 00858 HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, 1); 00859 } 00860 } 00861 00862 /* Grab a page for flushes */ 00863 PhysicalAddress.QuadPart = 0x100000; 00864 HalpVirtAddrForFlush = HalpMapPhysicalMemory64(PhysicalAddress, 1); 00865 HalpPteForFlush = HalAddressToPte(HalpVirtAddrForFlush); 00866 00867 /* Don't do this again */ 00868 HalpProcessedACPIPhase0 = TRUE; 00869 00870 /* Setup the boot table */ 00871 HalpInitBootTable(LoaderBlock); 00872 00873 /* Debugging code */ 00874 { 00875 PLIST_ENTRY ListHead, NextEntry; 00876 PACPI_CACHED_TABLE CachedTable; 00877 00878 /* Loop cached tables */ 00879 ListHead = &HalpAcpiTableCacheList; 00880 NextEntry = ListHead->Flink; 00881 while (NextEntry != ListHead) 00882 { 00883 /* Get the table */ 00884 CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links); 00885 00886 /* Compare signatures */ 00887 if ((CachedTable->Header.Signature == RSDT_SIGNATURE) || 00888 (CachedTable->Header.Signature == XSDT_SIGNATURE)) 00889 { 00890 DPRINT1("ACPI %d.0 Detected. Tables: ", (CachedTable->Header.Revision + 1)); 00891 } 00892 00893 DbgPrint("[%c%c%c%c] ", 00894 (CachedTable->Header.Signature & 0xFF), 00895 (CachedTable->Header.Signature & 0xFF00) >> 8, 00896 (CachedTable->Header.Signature & 0xFF0000) >> 16, 00897 (CachedTable->Header.Signature & 0xFF000000) >> 24); 00898 00899 /* Keep going */ 00900 NextEntry = NextEntry->Flink; 00901 } 00902 DbgPrint("\n"); 00903 } 00904 00905 /* Return success */ 00906 return STATUS_SUCCESS; 00907 } 00908 00909 VOID 00910 NTAPI 00911 HalpInitializePciBus(VOID) 00912 { 00913 /* Setup the PCI stub support */ 00914 HalpInitializePciStubs(); 00915 00916 /* Set the NMI crash flag */ 00917 HalpGetNMICrashFlag(); 00918 } 00919 00920 VOID 00921 NTAPI 00922 HalpInitNonBusHandler(VOID) 00923 { 00924 /* These should be written by the PCI driver later, but we give defaults */ 00925 HalPciTranslateBusAddress = HalpTranslateBusAddress; 00926 HalPciAssignSlotResources = HalpAssignSlotResources; 00927 HalFindBusAddressTranslation = HalpFindBusAddressTranslation; 00928 } 00929 00930 VOID 00931 NTAPI 00932 HalpInitBusHandlers(VOID) 00933 { 00934 /* On ACPI, we only have a fake PCI bus to worry about */ 00935 HalpInitNonBusHandler(); 00936 } 00937 00938 VOID 00939 NTAPI 00940 HalpBuildAddressMap(VOID) 00941 { 00942 /* ACPI is magic baby */ 00943 } 00944 00945 BOOLEAN 00946 NTAPI 00947 HalpGetDebugPortTable(VOID) 00948 { 00949 return ((HalpDebugPortTable) && 00950 (HalpDebugPortTable->BaseAddress.AddressSpaceID == 1)); 00951 } 00952 00953 ULONG 00954 NTAPI 00955 HalpIs16BitPortDecodeSupported(VOID) 00956 { 00957 /* All ACPI systems are at least "EISA" so they support this */ 00958 return CM_RESOURCE_PORT_16_BIT_DECODE; 00959 } 00960 00961 VOID 00962 NTAPI 00963 HalpAcpiDetectResourceListSize(OUT PULONG ListSize) 00964 { 00965 PAGED_CODE(); 00966 00967 /* One element if there is a SCI */ 00968 *ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0; 00969 } 00970 00971 NTSTATUS 00972 NTAPI 00973 HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList) 00974 { 00975 ULONG Interrupt; 00976 PAGED_CODE(); 00977 ASSERT(ResourceList != NULL); 00978 00979 /* Initialize the list */ 00980 ResourceList->BusNumber = -1; 00981 ResourceList->AlternativeLists = 1; 00982 ResourceList->InterfaceType = PNPBus; 00983 ResourceList->List[0].Version = 1; 00984 ResourceList->List[0].Revision = 1; 00985 ResourceList->List[0].Count = 0; 00986 00987 /* Is there a SCI? */ 00988 if (HalpFixedAcpiDescTable.sci_int_vector) 00989 { 00990 /* Fill out the entry for it */ 00991 ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; 00992 ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt; 00993 ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared; 00994 00995 /* Get the interrupt number */ 00996 Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector]; 00997 ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt; 00998 ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt; 00999 01000 /* One more */ 01001 ++ResourceList->List[0].Count; 01002 } 01003 01004 /* All good */ 01005 return STATUS_SUCCESS; 01006 } 01007 01008 NTSTATUS 01009 NTAPI 01010 HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements) 01011 { 01012 PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList; 01013 ULONG Count = 0, ListSize; 01014 NTSTATUS Status; 01015 PAGED_CODE(); 01016 01017 /* Get ACPI resources */ 01018 HalpAcpiDetectResourceListSize(&Count); 01019 DPRINT("Resource count: %d\n", Count); 01020 01021 /* Compute size of the list and allocate it */ 01022 ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) + 01023 (Count * sizeof(IO_RESOURCE_DESCRIPTOR)); 01024 DPRINT("Resource list size: %d\n", ListSize); 01025 RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, ' laH'); 01026 if (RequirementsList) 01027 { 01028 /* Initialize it */ 01029 RtlZeroMemory(RequirementsList, ListSize); 01030 RequirementsList->ListSize = ListSize; 01031 01032 /* Build it */ 01033 Status = HalpBuildAcpiResourceList(RequirementsList); 01034 if (NT_SUCCESS(Status)) 01035 { 01036 /* It worked, return it */ 01037 *Requirements = RequirementsList; 01038 01039 /* Validate the list */ 01040 ASSERT(RequirementsList->List[0].Count == Count); 01041 } 01042 else 01043 { 01044 /* Fail */ 01045 ExFreePoolWithTag(RequirementsList, ' laH'); 01046 Status = STATUS_NO_SUCH_DEVICE; 01047 } 01048 } 01049 else 01050 { 01051 /* Not enough memory */ 01052 Status = STATUS_INSUFFICIENT_RESOURCES; 01053 } 01054 01055 /* Return the status */ 01056 return Status; 01057 } 01058 01059 /* 01060 * @implemented 01061 */ 01062 VOID 01063 NTAPI 01064 HalReportResourceUsage(VOID) 01065 { 01066 INTERFACE_TYPE InterfaceType; 01067 UNICODE_STRING HalString; 01068 01069 /* FIXME: Initialize DMA 64-bit support */ 01070 01071 /* FIXME: Initialize MCA bus */ 01072 01073 /* Initialize PCI bus. */ 01074 HalpInitializePciBus(); 01075 01076 /* What kind of bus is this? */ 01077 switch (HalpBusType) 01078 { 01079 /* ISA Machine */ 01080 case MACHINE_TYPE_ISA: 01081 InterfaceType = Isa; 01082 break; 01083 01084 /* EISA Machine */ 01085 case MACHINE_TYPE_EISA: 01086 InterfaceType = Eisa; 01087 break; 01088 01089 /* MCA Machine */ 01090 case MACHINE_TYPE_MCA: 01091 InterfaceType = MicroChannel; 01092 break; 01093 01094 /* Unknown */ 01095 default: 01096 InterfaceType = Internal; 01097 break; 01098 } 01099 01100 /* Build HAL usage */ 01101 RtlInitUnicodeString(&HalString, HalName); 01102 HalpReportResourceUsage(&HalString, InterfaceType); 01103 01104 /* Setup PCI debugging and Hibernation */ 01105 HalpRegisterPciDebuggingDeviceInfo(); 01106 } 01107 01108 /* EOF */ Generated on Tue May 22 2012 04:32:42 for ReactOS by
1.7.6.1
|