reactos/hal/halx86/acpi/halacpi.c

1116 lines
31 KiB
C
Raw Normal View History

/*
* 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);
}
INIT_FUNCTION
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;
}
INIT_FUNCTION
VOID
NTAPI
HalpInitializePciBus(VOID)
{
/* Setup the PCI stub support */
HalpInitializePciStubs();
/* Set the NMI crash flag */
HalpGetNMICrashFlag();
}
[HAL]: Bus support in the HAL actually creates a further wedge between the different x86 HALs: There are actually two dinstinct implementations. On the ACPI HAL, the system is assumed not to have things like special ISA, MCA, EISA buses, and a PCI driver is used in combination with the ACPI Interface for PCI Bus support. On non-ACPI systems, the legacy "Bus Handler" library is used, and the HAL provides a core set of CMOS, EISA, ISA, MCA and PCI bus handlers, each with their own routines and specific code. Additionally, PCI IRQ Routing and other PCI bus internals are handled directly by the HAL -- on the ACPI HAL, the PCI Bus support is implemented through a "Fake"/static bus handler, just to keep the functions shared. On ReactOS, both the ACPI and non-ACPI HAL were currently using a mix of both HAL bus handling types, mostly implemented the "ACPI way" (with a fake PCI bus handler and such). As a result, none of the Hal*Bus HALDISPATCH routines were implemented, which bus drivers expect to find when they're not on ACPI systems (ReactOS today). eVb's new PCI driver was crashing, for example. Furthermore, legacy systems suffer, because the ACPI HAL Bus routines (that we currently have) expect perfect ACPI-style-compliant systems, not the legacy crap from the early 90ies. This works fine in VMs and new hardware, but old hardware is left behind. This patch basically corrects the first part of the problem, by making the bus handling support separate between ACPI and non-ACPI HALs. For now, the code remains 100% the same in functionality between both. However, I have started adding the first few elements: [HAL]: Implement HalRegisterBusHandler HALDISPATCH routine. [HAL]: On legacy HALs, register the CMOS, ISA, SYSTEM handlers. [HAL]: Add cmosbus.c. Stub all bus-specific bus handler routines in the xxxbus.c files. No real functionality change occurs with this patch, yet. svn path=/trunk/; revision=47649
2010-06-07 01:09:41 +00:00
VOID
NTAPI
HalpInitNonBusHandler(VOID)
{
/* These should be written by the PCI driver later, but we give defaults */
HalPciTranslateBusAddress = HalpTranslateBusAddress;
HalPciAssignSlotResources = HalpAssignSlotResources;
HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
}
INIT_FUNCTION
[HAL]: Bus support in the HAL actually creates a further wedge between the different x86 HALs: There are actually two dinstinct implementations. On the ACPI HAL, the system is assumed not to have things like special ISA, MCA, EISA buses, and a PCI driver is used in combination with the ACPI Interface for PCI Bus support. On non-ACPI systems, the legacy "Bus Handler" library is used, and the HAL provides a core set of CMOS, EISA, ISA, MCA and PCI bus handlers, each with their own routines and specific code. Additionally, PCI IRQ Routing and other PCI bus internals are handled directly by the HAL -- on the ACPI HAL, the PCI Bus support is implemented through a "Fake"/static bus handler, just to keep the functions shared. On ReactOS, both the ACPI and non-ACPI HAL were currently using a mix of both HAL bus handling types, mostly implemented the "ACPI way" (with a fake PCI bus handler and such). As a result, none of the Hal*Bus HALDISPATCH routines were implemented, which bus drivers expect to find when they're not on ACPI systems (ReactOS today). eVb's new PCI driver was crashing, for example. Furthermore, legacy systems suffer, because the ACPI HAL Bus routines (that we currently have) expect perfect ACPI-style-compliant systems, not the legacy crap from the early 90ies. This works fine in VMs and new hardware, but old hardware is left behind. This patch basically corrects the first part of the problem, by making the bus handling support separate between ACPI and non-ACPI HALs. For now, the code remains 100% the same in functionality between both. However, I have started adding the first few elements: [HAL]: Implement HalRegisterBusHandler HALDISPATCH routine. [HAL]: On legacy HALs, register the CMOS, ISA, SYSTEM handlers. [HAL]: Add cmosbus.c. Stub all bus-specific bus handler routines in the xxxbus.c files. No real functionality change occurs with this patch, yet. svn path=/trunk/; revision=47649
2010-06-07 01:09:41 +00:00
VOID
NTAPI
HalpInitBusHandlers(VOID)
{
/* On ACPI, we only have a fake PCI bus to worry about */
HalpInitNonBusHandler();
}
INIT_FUNCTION
VOID
NTAPI
HalpBuildAddressMap(VOID)
{
/* ACPI is magic baby */
}
INIT_FUNCTION
BOOLEAN
NTAPI
HalpGetDebugPortTable(VOID)
{
return ((HalpDebugPortTable) &&
(HalpDebugPortTable->BaseAddress.AddressSpaceID == 1));
}
INIT_FUNCTION
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
*/
INIT_FUNCTION
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 */