reactos/hal/halx86/acpi/halacpi.c

1109 lines
31 KiB
C

/*
* PROJECT: ReactOS HAL
* LICENSE: BSD - See COPYING.ARM in the top level directory
* FILE: hal/halx86/acpi/halacpi.c
* PURPOSE: HAL ACPI Code
* PROGRAMMERS: ReactOS Portable Systems Group
*/
/* INCLUDES *******************************************************************/
#include <hal.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS ********************************************************************/
LIST_ENTRY HalpAcpiTableCacheList;
FAST_MUTEX HalpAcpiTableCacheLock;
BOOLEAN HalpProcessedACPIPhase0;
BOOLEAN HalpPhysicalMemoryMayAppearAbove4GB;
FADT HalpFixedAcpiDescTable;
PDEBUG_PORT_TABLE HalpDebugPortTable;
PACPI_SRAT HalpAcpiSrat;
PBOOT_TABLE HalpSimpleBootFlagTable;
PHYSICAL_ADDRESS HalpMaxHotPlugMemoryAddress;
PHYSICAL_ADDRESS HalpLowStubPhysicalAddress;
PHARDWARE_PTE HalpPteForFlush;
PVOID HalpVirtAddrForFlush;
PVOID HalpLowStub;
PACPI_BIOS_MULTI_NODE HalpAcpiMultiNode;
LIST_ENTRY HalpAcpiTableMatchList;
ULONG HalpInvalidAcpiTable;
ULONG HalpPicVectorRedirect[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15};
/* This determines the HAL type */
BOOLEAN HalDisableFirmwareMapper = TRUE;
PWCHAR HalHardwareIdString = L"acpipic_up";
PWCHAR HalName = L"ACPI Compatible Eisa/Isa HAL";
/* PRIVATE FUNCTIONS **********************************************************/
PDESCRIPTION_HEADER
NTAPI
HalpAcpiGetCachedTable(IN ULONG Signature)
{
PLIST_ENTRY ListHead, NextEntry;
PACPI_CACHED_TABLE CachedTable;
/* Loop cached tables */
ListHead = &HalpAcpiTableCacheList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the table */
CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
/* Compare signatures */
if (CachedTable->Header.Signature == Signature) return &CachedTable->Header;
/* Keep going */
NextEntry = NextEntry->Flink;
}
/* Nothing found */
return NULL;
}
VOID
NTAPI
HalpAcpiCacheTable(IN PDESCRIPTION_HEADER TableHeader)
{
PACPI_CACHED_TABLE CachedTable;
/* Get the cached table and link it */
CachedTable = CONTAINING_RECORD(TableHeader, ACPI_CACHED_TABLE, Header);
InsertTailList(&HalpAcpiTableCacheList, &CachedTable->Links);
}
PVOID
NTAPI
HalpAcpiCopyBiosTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PDESCRIPTION_HEADER TableHeader)
{
ULONG Size;
PFN_COUNT PageCount;
PHYSICAL_ADDRESS PhysAddress;
PACPI_CACHED_TABLE CachedTable;
PDESCRIPTION_HEADER CopiedTable;
/* Size we'll need for the cached table */
Size = TableHeader->Length + FIELD_OFFSET(ACPI_CACHED_TABLE, Header);
if (LoaderBlock)
{
/* Phase 0: Convert to pages and use the HAL heap */
PageCount = BYTES_TO_PAGES(Size);
PhysAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
0x1000000,
PageCount,
FALSE);
if (PhysAddress.QuadPart)
{
/* Map it */
CachedTable = HalpMapPhysicalMemory64(PhysAddress, PageCount);
}
else
{
/* No memory, so nothing to map */
CachedTable = NULL;
}
}
else
{
/* Use Mm pool */
CachedTable = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_HAL);
}
/* Do we have the cached table? */
if (CachedTable)
{
/* Copy the data */
CopiedTable = &CachedTable->Header;
RtlCopyMemory(CopiedTable, TableHeader, TableHeader->Length);
}
else
{
/* Nothing to return */
CopiedTable = NULL;
}
/* Return the table */
return CopiedTable;
}
PVOID
NTAPI
HalpAcpiGetTableFromBios(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN ULONG Signature)
{
PHYSICAL_ADDRESS PhysicalAddress;
PXSDT Xsdt;
PRSDT Rsdt;
PFADT Fadt;
PDESCRIPTION_HEADER Header = NULL;
ULONG TableLength;
CHAR CheckSum = 0;
ULONG Offset;
ULONG EntryCount, CurrentEntry;
PCHAR CurrentByte;
PFN_COUNT PageCount;
/* Should not query the RSDT/XSDT by itself */
if ((Signature == RSDT_SIGNATURE) || (Signature == XSDT_SIGNATURE)) return NULL;
/* Special case request for DSDT, because the FADT points to it */
if (Signature == DSDT_SIGNATURE)
{
/* Grab the FADT */
Fadt = HalpAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
if (Fadt)
{
/* Grab the DSDT address and assume 2 pages */
PhysicalAddress.HighPart = 0;
PhysicalAddress.LowPart = Fadt->dsdt;
TableLength = 2 * PAGE_SIZE;
/* Map it */
if (LoaderBlock)
{
/* Phase 0, use HAL heap */
Header = HalpMapPhysicalMemory64(PhysicalAddress, 2u);
}
else
{
/* Phase 1, use Mm */
Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, 0);
}
/* Fail if we couldn't map it */
if (!Header)
{
DPRINT1("HAL: Failed to map ACPI table.\n");
return NULL;
}
/* Validate the signature */
if (Header->Signature != DSDT_SIGNATURE)
{
/* Fail and unmap */
if (LoaderBlock)
{
/* Using HAL heap */
HalpUnmapVirtualAddress(Header, 2);
}
else
{
/* Using Mm */
MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
}
/* Didn't find anything */
return NULL;
}
}
else
{
/* Couldn't find it */
return NULL;
}
}
else
{
/* To find tables, we need the RSDT */
Rsdt = HalpAcpiGetTable(LoaderBlock, RSDT_SIGNATURE);
if (Rsdt)
{
/* Won't be using the XSDT */
Xsdt = NULL;
}
else
{
/* Only other choice is to use the XSDT */
Xsdt = HalpAcpiGetTable(LoaderBlock, XSDT_SIGNATURE);
if (!Xsdt) return NULL;
/* Won't be using the RSDT */
Rsdt = NULL;
}
/* Smallest RSDT/XSDT is one without table entries */
Offset = FIELD_OFFSET(RSDT, Tables);
if (Xsdt)
{
/* Figure out total size of table and the offset */
TableLength = Xsdt->Header.Length;
if (TableLength < Offset) Offset = Xsdt->Header.Length;
/* The entries are each 64-bits, so count them */
EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS);
}
else
{
/* Figure out total size of table and the offset */
TableLength = Rsdt->Header.Length;
if (TableLength < Offset) Offset = Rsdt->Header.Length;
/* The entries are each 32-bits, so count them */
EntryCount = (TableLength - Offset) / sizeof(ULONG);
}
/* Start at the beginning of the array and loop it */
for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++)
{
/* Are we using the XSDT? */
if (!Xsdt)
{
/* Read the 32-bit physical address */
PhysicalAddress.LowPart = Rsdt->Tables[CurrentEntry];
PhysicalAddress.HighPart = 0;
}
else
{
/* Read the 64-bit physical address */
PhysicalAddress = Xsdt->Tables[CurrentEntry];
}
/* Had we already mapped a table? */
if (Header)
{
/* Yes, unmap it */
if (LoaderBlock)
{
/* Using HAL heap */
HalpUnmapVirtualAddress(Header, 2);
}
else
{
/* Using Mm */
MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
}
}
/* Now map this table */
if (!LoaderBlock)
{
/* Phase 1: Use HAL heap */
Header = MmMapIoSpace(PhysicalAddress, 2 * PAGE_SIZE, MmNonCached);
}
else
{
/* Phase 0: Use Mm */
Header = HalpMapPhysicalMemory64(PhysicalAddress, 2);
}
/* Check if we mapped it */
if (!Header)
{
/* Game over */
DPRINT1("HAL: Failed to map ACPI table.\n");
return NULL;
}
/* We found it, break out */
DPRINT("Found ACPI table %c%c%c%c at 0x%p\n",
Header->Signature & 0xFF,
(Header->Signature & 0xFF00) >> 8,
(Header->Signature & 0xFF0000) >> 16,
(Header->Signature & 0xFF000000) >> 24,
Header);
if (Header->Signature == Signature) break;
}
/* Did we end up here back at the last entry? */
if (CurrentEntry == EntryCount)
{
/* Yes, unmap the last table we processed */
if (LoaderBlock)
{
/* Using HAL heap */
HalpUnmapVirtualAddress(Header, 2);
}
else
{
/* Using Mm */
MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
}
/* Didn't find anything */
return NULL;
}
}
/* Past this point, we assume something was found */
ASSERT(Header);
/* How many pages do we need? */
PageCount = BYTES_TO_PAGES(Header->Length);
if (PageCount != 2)
{
/* We assumed two, but this is not the case, free the current mapping */
if (LoaderBlock)
{
/* Using HAL heap */
HalpUnmapVirtualAddress(Header, 2);
}
else
{
/* Using Mm */
MmUnmapIoSpace(Header, 2 * PAGE_SIZE);
}
/* Now map this table using its correct size */
if (!LoaderBlock)
{
/* Phase 1: Use HAL heap */
Header = MmMapIoSpace(PhysicalAddress, PageCount << PAGE_SHIFT, MmNonCached);
}
else
{
/* Phase 0: Use Mm */
Header = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
}
}
/* Fail if the remapped failed */
if (!Header) return NULL;
/* All tables in ACPI 3.0 other than the FACP should have correct checksum */
if ((Header->Signature != FADT_SIGNATURE) || (Header->Revision > 2))
{
/* Go to the end of the table */
CheckSum = 0;
CurrentByte = (PCHAR)Header + Header->Length;
while (CurrentByte-- != (PCHAR)Header)
{
/* Add this byte */
CheckSum += *CurrentByte;
}
/* The correct checksum is always 0, anything else is illegal */
if (CheckSum)
{
HalpInvalidAcpiTable = Header->Signature;
DPRINT1("Checksum failed on ACPI table %c%c%c%c\n",
(Signature & 0xFF),
(Signature & 0xFF00) >> 8,
(Signature & 0xFF0000) >> 16,
(Signature & 0xFF000000) >> 24);
}
}
/* Return the table */
return Header;
}
PVOID
NTAPI
HalpAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN ULONG Signature)
{
PFN_COUNT PageCount;
PDESCRIPTION_HEADER TableAddress, BiosCopy;
/* See if we have a cached table? */
TableAddress = HalpAcpiGetCachedTable(Signature);
if (!TableAddress)
{
/* No cache, search the BIOS */
TableAddress = HalpAcpiGetTableFromBios(LoaderBlock, Signature);
if (TableAddress)
{
/* Found it, copy it into our own memory */
BiosCopy = HalpAcpiCopyBiosTable(LoaderBlock, TableAddress);
/* Get the pages, and unmap the BIOS copy */
PageCount = BYTES_TO_PAGES(TableAddress->Length);
if (LoaderBlock)
{
/* Phase 0, use the HAL heap */
HalpUnmapVirtualAddress(TableAddress, PageCount);
}
else
{
/* Phase 1, use Mm */
MmUnmapIoSpace(TableAddress, PageCount << PAGE_SHIFT);
}
/* Cache the bios copy */
TableAddress = BiosCopy;
if (BiosCopy) HalpAcpiCacheTable(BiosCopy);
}
}
/* Return the table */
return TableAddress;
}
PVOID
NTAPI
HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN ULONG Signature)
{
PDESCRIPTION_HEADER TableHeader;
/* Is this phase0 */
if (LoaderBlock)
{
/* Initialize the cache first */
if (!NT_SUCCESS(HalpAcpiTableCacheInit(LoaderBlock))) return NULL;
}
else
{
/* Lock the cache */
ExAcquireFastMutex(&HalpAcpiTableCacheLock);
}
/* Get the table */
TableHeader = HalpAcpiGetTable(LoaderBlock, Signature);
/* Release the lock in phase 1 */
if (!LoaderBlock) ExReleaseFastMutex(&HalpAcpiTableCacheLock);
/* Return the table */
return TableHeader;
}
VOID
NTAPI
HalpNumaInitializeStaticConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PACPI_SRAT SratTable;
/* Get the SRAT, bail out if it doesn't exist */
SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
HalpAcpiSrat = SratTable;
if (!SratTable) return;
}
VOID
NTAPI
HalpGetHotPlugMemoryInfo(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PACPI_SRAT SratTable;
/* Get the SRAT, bail out if it doesn't exist */
SratTable = HalAcpiGetTable(LoaderBlock, SRAT_SIGNATURE);
HalpAcpiSrat = SratTable;
if (!SratTable) return;
}
VOID
NTAPI
HalpDynamicSystemResourceConfiguration(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
/* For this HAL, it means to get hot plug memory information */
HalpGetHotPlugMemoryInfo(LoaderBlock);
}
VOID
NTAPI
HalpAcpiDetectMachineSpecificActions(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PFADT DescriptionTable)
{
/* Does this HAL specify something? */
if (HalpAcpiTableMatchList.Flink)
{
/* Great, but we don't support it */
DPRINT1("WARNING: Your HAL has specific ACPI hacks to apply!\n");
}
}
VOID
NTAPI
HalpInitBootTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PBOOT_TABLE BootTable;
/* Get the boot table */
BootTable = HalAcpiGetTable(LoaderBlock, BOOT_SIGNATURE);
HalpSimpleBootFlagTable = BootTable;
/* Validate it */
if ((BootTable) &&
(BootTable->Header.Length >= sizeof(BOOT_TABLE)) &&
(BootTable->CMOSIndex >= 9))
{
DPRINT1("ACPI Boot table found, but not supported!\n");
}
else
{
/* Invalid or doesn't exist, ignore it */
HalpSimpleBootFlagTable = 0;
}
/* Install the end of boot handler */
// HalEndOfBoot = HalpEndOfBoot;
}
NTSTATUS
NTAPI
HalpAcpiFindRsdtPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
OUT PACPI_BIOS_MULTI_NODE* AcpiMultiNode)
{
PCONFIGURATION_COMPONENT_DATA ComponentEntry;
PCONFIGURATION_COMPONENT_DATA Next = NULL;
PCM_PARTIAL_RESOURCE_LIST ResourceList;
PACPI_BIOS_MULTI_NODE NodeData;
SIZE_T NodeLength;
PFN_COUNT PageCount;
PVOID MappedAddress;
PHYSICAL_ADDRESS PhysicalAddress;
/* Did we already do this once? */
if (HalpAcpiMultiNode)
{
/* Return what we know */
*AcpiMultiNode = HalpAcpiMultiNode;
return STATUS_SUCCESS;
}
/* Assume failure */
*AcpiMultiNode = NULL;
/* Find the multi function adapter key */
ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
AdapterClass,
MultiFunctionAdapter,
0,
&Next);
while (ComponentEntry)
{
/* Find the ACPI BIOS key */
if (!_stricmp(ComponentEntry->ComponentEntry.Identifier, "ACPI BIOS"))
{
/* Found it */
break;
}
/* Keep searching */
Next = ComponentEntry;
ComponentEntry = KeFindConfigurationNextEntry(LoaderBlock->ConfigurationRoot,
AdapterClass,
MultiFunctionAdapter,
NULL,
&Next);
}
/* Make sure we found it */
if (!ComponentEntry)
{
DPRINT1("**** HalpAcpiFindRsdtPhase0: did NOT find RSDT\n");
return STATUS_NOT_FOUND;
}
/* The configuration data is a resource list, and the BIOS node follows */
ResourceList = ComponentEntry->ConfigurationData;
NodeData = (PACPI_BIOS_MULTI_NODE)(ResourceList + 1);
/* How many E820 memory entries are there? */
NodeLength = sizeof(ACPI_BIOS_MULTI_NODE) +
(NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
/* Convert to pages */
PageCount = (PFN_COUNT)BYTES_TO_PAGES(NodeLength);
/* Allocate the memory */
PhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
0x1000000,
PageCount,
FALSE);
if (PhysicalAddress.QuadPart)
{
/* Map it if the allocation worked */
MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, PageCount);
}
else
{
/* Otherwise we'll have to fail */
MappedAddress = NULL;
}
/* Save the multi node, bail out if we didn't find it */
HalpAcpiMultiNode = MappedAddress;
if (!MappedAddress) return STATUS_INSUFFICIENT_RESOURCES;
/* Copy the multi-node data */
RtlCopyMemory(MappedAddress, NodeData, NodeLength);
/* Return the data */
*AcpiMultiNode = HalpAcpiMultiNode;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
HalpAcpiTableCacheInit(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PACPI_BIOS_MULTI_NODE AcpiMultiNode;
NTSTATUS Status = STATUS_SUCCESS;
PHYSICAL_ADDRESS PhysicalAddress;
PVOID MappedAddress;
ULONG TableLength;
PRSDT Rsdt;
PLOADER_PARAMETER_EXTENSION LoaderExtension;
/* Only initialize once */
if (HalpAcpiTableCacheList.Flink) return Status;
/* Setup the lock and table */
ExInitializeFastMutex(&HalpAcpiTableCacheLock);
InitializeListHead(&HalpAcpiTableCacheList);
/* Find the RSDT */
Status = HalpAcpiFindRsdtPhase0(LoaderBlock, &AcpiMultiNode);
if (!NT_SUCCESS(Status)) return Status;
PhysicalAddress.QuadPart = AcpiMultiNode->RsdtAddress.QuadPart;
/* Map the RSDT */
if (LoaderBlock)
{
/* Phase0: Use HAL Heap to map the RSDT, we assume it's about 2 pages */
MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, 2);
}
else
{
/* Use an I/O map */
MappedAddress = MmMapIoSpace(PhysicalAddress, PAGE_SIZE * 2, MmNonCached);
}
/* Get the RSDT */
Rsdt = MappedAddress;
if (!MappedAddress)
{
/* Fail, no memory */
DPRINT1("HAL: Failed to map RSDT\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Validate it */
if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
(Rsdt->Header.Signature != XSDT_SIGNATURE))
{
/* Very bad: crash */
HalDisplayString("Bad RSDT pointer\r\n");
KeBugCheckEx(MISMATCHED_HAL, 4, __LINE__, 0, 0);
}
/* We assumed two pages -- do we need less or more? */
TableLength = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
Rsdt->Header.Length);
if (TableLength != 2)
{
/* Are we in phase 0 or 1? */
if (!LoaderBlock)
{
/* Unmap the old table, remap the new one, using Mm I/O space */
MmUnmapIoSpace(MappedAddress, 2 * PAGE_SIZE);
MappedAddress = MmMapIoSpace(PhysicalAddress,
TableLength << PAGE_SHIFT,
MmNonCached);
}
else
{
/* Unmap the old table, remap the new one, using HAL heap */
HalpUnmapVirtualAddress(MappedAddress, 2);
MappedAddress = HalpMapPhysicalMemory64(PhysicalAddress, TableLength);
}
/* Get the remapped table */
Rsdt = MappedAddress;
if (!MappedAddress)
{
/* Fail, no memory */
DPRINT1("HAL: Couldn't remap RSDT\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
}
/* Now take the BIOS copy and make our own local copy */
Rsdt = HalpAcpiCopyBiosTable(LoaderBlock, &Rsdt->Header);
if (!Rsdt)
{
/* Fail, no memory */
DPRINT1("HAL: Couldn't remap RSDT\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Get rid of the BIOS mapping */
if (LoaderBlock)
{
/* Use HAL heap */
HalpUnmapVirtualAddress(MappedAddress, TableLength);
LoaderExtension = LoaderBlock->Extension;
}
else
{
/* Use Mm */
MmUnmapIoSpace(MappedAddress, TableLength << PAGE_SHIFT);
LoaderExtension = NULL;
}
/* Cache the RSDT */
HalpAcpiCacheTable(&Rsdt->Header);
/* Check for compatible loader block extension */
if (LoaderExtension && (LoaderExtension->Size >= 0x58))
{
/* Compatible loader: did it provide an ACPI table override? */
if ((LoaderExtension->AcpiTable) && (LoaderExtension->AcpiTableSize))
{
/* Great, because we don't support it! */
DPRINT1("ACPI Table Overrides Not Supported!\n");
}
}
/* Done */
return Status;
}
VOID
NTAPI
HaliAcpiTimerInit(IN ULONG TimerPort,
IN ULONG TimerValExt)
{
PAGED_CODE();
/* Is this in the init phase? */
if (!TimerPort)
{
/* Get the data from the FADT */
TimerPort = HalpFixedAcpiDescTable.pm_tmr_blk_io_port;
TimerValExt = HalpFixedAcpiDescTable.flags & ACPI_TMR_VAL_EXT;
DPRINT1("ACPI Timer at: %Xh (EXT: %d)\n", TimerPort, TimerValExt);
}
/* FIXME: Now proceed to the timer initialization */
//HalaAcpiTimerInit(TimerPort, TimerValExt);
}
NTSTATUS
NTAPI
HalpSetupAcpiPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
NTSTATUS Status;
PFADT Fadt;
ULONG TableLength;
PHYSICAL_ADDRESS PhysicalAddress;
/* Only do this once */
if (HalpProcessedACPIPhase0) return STATUS_SUCCESS;
/* Setup the ACPI table cache */
Status = HalpAcpiTableCacheInit(LoaderBlock);
if (!NT_SUCCESS(Status)) return Status;
/* Grab the FADT */
Fadt = HalAcpiGetTable(LoaderBlock, FADT_SIGNATURE);
if (!Fadt)
{
/* Fail */
DPRINT1("HAL: Didn't find the FACP\n");
return STATUS_NOT_FOUND;
}
/* Assume typical size, otherwise whatever the descriptor table says */
TableLength = sizeof(FADT);
if (Fadt->Header.Length < sizeof(FADT)) TableLength = Fadt->Header.Length;
/* Copy it in the HAL static buffer */
RtlCopyMemory(&HalpFixedAcpiDescTable, Fadt, TableLength);
/* Anything special this HAL needs to do? */
HalpAcpiDetectMachineSpecificActions(LoaderBlock, &HalpFixedAcpiDescTable);
/* Get the debug table for KD */
HalpDebugPortTable = HalAcpiGetTable(LoaderBlock, DBGP_SIGNATURE);
/* Initialize NUMA through the SRAT */
HalpNumaInitializeStaticConfiguration(LoaderBlock);
/* Initialize hotplug through the SRAT */
HalpDynamicSystemResourceConfiguration(LoaderBlock);
if (HalpAcpiSrat)
{
DPRINT1("Your machine has a SRAT, but NUMA/HotPlug are not supported!\n");
}
/* Can there be memory higher than 4GB? */
if (HalpMaxHotPlugMemoryAddress.HighPart >= 1)
{
/* We'll need this for DMA later */
HalpPhysicalMemoryMayAppearAbove4GB = TRUE;
}
/* Setup the ACPI timer */
HaliAcpiTimerInit(0, 0);
/* Do we have a low stub address yet? */
if (!HalpLowStubPhysicalAddress.QuadPart)
{
/* Allocate it */
HalpLowStubPhysicalAddress.QuadPart = HalpAllocPhysicalMemory(LoaderBlock,
0x100000,
1,
FALSE);
if (HalpLowStubPhysicalAddress.QuadPart)
{
/* Map it */
HalpLowStub = HalpMapPhysicalMemory64(HalpLowStubPhysicalAddress, 1);
}
}
/* Grab a page for flushes */
PhysicalAddress.QuadPart = 0x100000;
HalpVirtAddrForFlush = HalpMapPhysicalMemory64(PhysicalAddress, 1);
HalpPteForFlush = HalAddressToPte(HalpVirtAddrForFlush);
/* Don't do this again */
HalpProcessedACPIPhase0 = TRUE;
/* Setup the boot table */
HalpInitBootTable(LoaderBlock);
/* Debugging code */
{
PLIST_ENTRY ListHead, NextEntry;
PACPI_CACHED_TABLE CachedTable;
/* Loop cached tables */
ListHead = &HalpAcpiTableCacheList;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the table */
CachedTable = CONTAINING_RECORD(NextEntry, ACPI_CACHED_TABLE, Links);
/* Compare signatures */
if ((CachedTable->Header.Signature == RSDT_SIGNATURE) ||
(CachedTable->Header.Signature == XSDT_SIGNATURE))
{
DPRINT1("ACPI %d.0 Detected. Tables: ", (CachedTable->Header.Revision + 1));
}
DbgPrint("[%c%c%c%c] ",
(CachedTable->Header.Signature & 0xFF),
(CachedTable->Header.Signature & 0xFF00) >> 8,
(CachedTable->Header.Signature & 0xFF0000) >> 16,
(CachedTable->Header.Signature & 0xFF000000) >> 24);
/* Keep going */
NextEntry = NextEntry->Flink;
}
DbgPrint("\n");
}
/* Return success */
return STATUS_SUCCESS;
}
VOID
NTAPI
HalpInitializePciBus(VOID)
{
/* Setup the PCI stub support */
HalpInitializePciStubs();
/* Set the NMI crash flag */
HalpGetNMICrashFlag();
}
VOID
NTAPI
HalpInitNonBusHandler(VOID)
{
/* These should be written by the PCI driver later, but we give defaults */
HalPciTranslateBusAddress = HalpTranslateBusAddress;
HalPciAssignSlotResources = HalpAssignSlotResources;
HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
}
VOID
NTAPI
HalpInitBusHandlers(VOID)
{
/* On ACPI, we only have a fake PCI bus to worry about */
HalpInitNonBusHandler();
}
VOID
NTAPI
HalpBuildAddressMap(VOID)
{
/* ACPI is magic baby */
}
BOOLEAN
NTAPI
HalpGetDebugPortTable(VOID)
{
return ((HalpDebugPortTable) &&
(HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
}
ULONG
NTAPI
HalpIs16BitPortDecodeSupported(VOID)
{
/* All ACPI systems are at least "EISA" so they support this */
return CM_RESOURCE_PORT_16_BIT_DECODE;
}
VOID
NTAPI
HalpAcpiDetectResourceListSize(OUT PULONG ListSize)
{
PAGED_CODE();
/* One element if there is a SCI */
*ListSize = HalpFixedAcpiDescTable.sci_int_vector ? 1: 0;
}
NTSTATUS
NTAPI
HalpBuildAcpiResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceList)
{
ULONG Interrupt;
PAGED_CODE();
ASSERT(ResourceList != NULL);
/* Initialize the list */
ResourceList->BusNumber = -1;
ResourceList->AlternativeLists = 1;
ResourceList->InterfaceType = PNPBus;
ResourceList->List[0].Version = 1;
ResourceList->List[0].Revision = 1;
ResourceList->List[0].Count = 0;
/* Is there a SCI? */
if (HalpFixedAcpiDescTable.sci_int_vector)
{
/* Fill out the entry for it */
ResourceList->List[0].Descriptors[0].Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
ResourceList->List[0].Descriptors[0].Type = CmResourceTypeInterrupt;
ResourceList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared;
/* Get the interrupt number */
Interrupt = HalpPicVectorRedirect[HalpFixedAcpiDescTable.sci_int_vector];
ResourceList->List[0].Descriptors[0].u.Interrupt.MinimumVector = Interrupt;
ResourceList->List[0].Descriptors[0].u.Interrupt.MaximumVector = Interrupt;
/* One more */
++ResourceList->List[0].Count;
}
/* All good */
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
HalpQueryAcpiResourceRequirements(OUT PIO_RESOURCE_REQUIREMENTS_LIST *Requirements)
{
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
ULONG Count = 0, ListSize;
NTSTATUS Status;
PAGED_CODE();
/* Get ACPI resources */
HalpAcpiDetectResourceListSize(&Count);
DPRINT("Resource count: %d\n", Count);
/* Compute size of the list and allocate it */
ListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List[0].Descriptors) +
(Count * sizeof(IO_RESOURCE_DESCRIPTOR));
DPRINT("Resource list size: %d\n", ListSize);
RequirementsList = ExAllocatePoolWithTag(PagedPool, ListSize, TAG_HAL);
if (RequirementsList)
{
/* Initialize it */
RtlZeroMemory(RequirementsList, ListSize);
RequirementsList->ListSize = ListSize;
/* Build it */
Status = HalpBuildAcpiResourceList(RequirementsList);
if (NT_SUCCESS(Status))
{
/* It worked, return it */
*Requirements = RequirementsList;
/* Validate the list */
ASSERT(RequirementsList->List[0].Count == Count);
}
else
{
/* Fail */
ExFreePoolWithTag(RequirementsList, TAG_HAL);
Status = STATUS_NO_SUCH_DEVICE;
}
}
else
{
/* Not enough memory */
Status = STATUS_INSUFFICIENT_RESOURCES;
}
/* Return the status */
return Status;
}
/*
* @implemented
*/
VOID
NTAPI
HalReportResourceUsage(VOID)
{
INTERFACE_TYPE InterfaceType;
UNICODE_STRING HalString;
/* FIXME: Initialize DMA 64-bit support */
/* FIXME: Initialize MCA bus */
/* Initialize PCI bus. */
HalpInitializePciBus();
/* What kind of bus is this? */
switch (HalpBusType)
{
/* ISA Machine */
case MACHINE_TYPE_ISA:
InterfaceType = Isa;
break;
/* EISA Machine */
case MACHINE_TYPE_EISA:
InterfaceType = Eisa;
break;
/* MCA Machine */
case MACHINE_TYPE_MCA:
InterfaceType = MicroChannel;
break;
/* Unknown */
default:
InterfaceType = Internal;
break;
}
/* Build HAL usage */
RtlInitUnicodeString(&HalString, HalName);
HalpReportResourceUsage(&HalString, InterfaceType);
/* Setup PCI debugging and Hibernation */
HalpRegisterPciDebuggingDeviceInfo();
}
/* EOF */