windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/pmsapic.c

909 lines
24 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
pmsapic.c
Abstract:
Implements various SAPIC-ACPI functions.
Author:
Todd Kjos (Hewlett-Packard) 20-Apr-1998
Based on I386 version of pmapic.c:
Jake Oshins (jakeo) 19-May-1997
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
#include "acpitabl.h"
#include "iosapic.h"
#include "xxacpi.h"
#include "ixsleep.h"
PMAPIC HalpApicTable;
struct _IOAPIC_DEBUG_TABLE
{
PIO_INTR_CONTROL IoIntrControl;
PIO_SAPIC_REGS IoSapicRegs;
} *HalpApicDebugAddresses;
ULONG
DetectAcpiMP(
OUT PBOOLEAN IsConfiguredMp,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
VOID
HalpInitMPInfo(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PMAPIC ApicTable
);
BOOLEAN
HalpVerifyIoSapic(
IN PUCHAR BaseAddress
);
VOID
HalpSaveInterruptControllerState(
VOID
);
VOID
HalpRestoreInterruptControllerState(
VOID
);
VOID
HalpSetInterruptControllerWakeupState(
ULONG Context
);
VOID
HalpSetCPEVectorState(
IN ULONG GlobalInterrupt,
IN UCHAR SapicVector,
IN USHORT DestinationCPU,
IN ULONG Flags
);
VOID
HalpProcessLocalSapic(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PPROCLOCALSAPIC ProcLocalSapic
);
VOID
HalpProcessIoSapic(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PIOSAPIC IoSapic
);
VOID
HalpProcessIsaVector(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PISA_VECTOR IsaVector
);
VOID
HalpProcessPlatformInt(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PPLATFORM_INTERRUPT PlatformInt
);
extern UCHAR rgzNoApicTable[];
extern UCHAR rgzNoApic[];
extern UCHAR rgzApicNotVerified[];
extern ULONG HalpPicVectorRedirect[];
struct _MPINFO HalpMpInfo;
extern ULONG HalpPicVectorFlags[];
extern ULONG HalpIpiClock;
extern BOOLEAN HalpHiberInProgress;
// from pmdata.c: CPE related.
extern ULONG HalpCPEIntIn[];
extern USHORT HalpCPEDestination[];
extern ULONG HalpCPEVectorFlags[];
extern UCHAR HalpCPEIoSapicVector[];
extern ULONG HalpMaxCPEImplemented;
BOOLEAN HalpPicStateIntact = TRUE;
PIO_INTR_CONTROL HalpIoSapicList = NULL;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DetectAcpiMP)
#pragma alloc_text(INIT, HalpInitMPInfo)
#pragma alloc_text(INIT, HalpProcessLocalSapic)
#pragma alloc_text(INIT, HalpProcessIoSapic)
#pragma alloc_text(INIT, HalpProcessIsaVector)
#pragma alloc_text(INIT, HalpProcessPlatformInt)
#pragma alloc_text(PAGELK, HalpVerifyIoSapic)
#pragma alloc_text(PAGELK, HalpSaveInterruptControllerState)
#pragma alloc_text(PAGELK, HalpRestoreInterruptControllerState)
#pragma alloc_text(PAGELK, HalpSetInterruptControllerWakeupState)
#pragma alloc_text(PAGELK, HalpAcpiPicStateIntact)
#endif
ULONG
DetectAcpiMP(
OUT PBOOLEAN IsConfiguredMp,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
{
UCHAR ApicVersion, index, processorNumber;
PUCHAR LocalApic;
NTSTATUS status;
//
// Make sure there is an SAPIC Table
//
HalpApicTable = HalpGetAcpiTablePhase0(LoaderBlock, APIC_SIGNATURE);
if (HalpApicTable == NULL) {
HalDisplayString(rgzNoApicTable);
KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 10, 0, 0);
return(FALSE);
}
HalDebugPrint(( HAL_INFO, "HAL: Found a MADT table at %p\n", HalpApicTable ));
HalDebugPrint(( HAL_INFO, "HAL: Signature: %x Length: %x\n",
HalpApicTable->Header.Signature,
HalpApicTable->Header.Length ));
HalDebugPrint(( HAL_INFO, "HAL: OEMID: %s\n", HalpApicTable->Header.OEMID ));
// We have a SAPIC table. Initialize the interrupt info structure
HalpInitMPInfo(LoaderBlock, HalpApicTable);
if (HalpMpInfo.IoSapicCount == 0) {
//
// There are no IO Sapics.
//
// Should we allow this case on the theory that
// that all the interrupts are connected to LINTx pins on the CPU?
//
HalDebugPrint(( HAL_ERROR, rgzNoApic ));
return (FALSE);
}
if (HalpMpInfo.ProcessorCount == 0) {
KeBugCheckEx(ACPI_BIOS_ERROR, 0x11, 11, 0, 0);
}
//
// Initialize NtProcessorNumber in the order that we are going to process
// them in HalStartNextProcessor. The BSP is 0 and the rest are numbered
// in the order the Local SAPICs appear in the MADT starting at 1.
//
processorNumber = 1;
for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
if (HalpProcessorInfo[index].LocalApicID == (USHORT)PCR->HalReserved[PROCESSOR_ID_INDEX]) {
HalpProcessorInfo[index].NtProcessorNumber = 0;
} else {
HalpProcessorInfo[index].NtProcessorNumber = processorNumber++;
}
}
*IsConfiguredMp = (HalpMpInfo.ProcessorCount > 1 ? TRUE : FALSE);
return TRUE;
}
#define IO_SAPIC_REGS_SIZE 4096
VOID
HalpInitMPInfo(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PMAPIC ApicTable
)
/*++
Routine Description:
This routine initializes a HAL specific data structure that is
used by the HAL to simplify access to MP information.
Arguments:
SapicTable Pointer to the SAPIC table.
Return Value:
None
*/
{
PAPICTABLE TablePtr;
ULONG i;
HalpMpInfo.ProcessorCount = 0;
HalpMpInfo.IoSapicCount = 0;
// Walk the Multiple Apic table...
TablePtr = (PAPICTABLE) ApicTable->APICTables;
// Loop ends when TraversePtr is off the end of the table...
while ((UINT_PTR)TablePtr <
((UINT_PTR)ApicTable + ApicTable->Header.Length)) {
if (TablePtr->Type == LOCAL_SAPIC) {
HalpProcessLocalSapic(LoaderBlock, (PPROCLOCALSAPIC)TablePtr);
} else if (TablePtr->Type == IO_SAPIC) {
HalpProcessIoSapic(LoaderBlock, (PIOSAPIC)TablePtr);
} else if (TablePtr->Type == ISA_VECTOR_OVERRIDE) {
HalpProcessIsaVector(LoaderBlock, (PISA_VECTOR)TablePtr);
} else if (TablePtr->Type == PLATFORM_INTERRUPT_SOURCE) {
HalpProcessPlatformInt(LoaderBlock, (PPLATFORM_INTERRUPT)TablePtr);
} else {
HalDebugPrint(( HAL_ERROR, "HAL: Processing MADT - Skip Table %p: Type = %d, Length = %d\n", TablePtr, TablePtr->Type, TablePtr->Length ));
}
(UINT_PTR)TablePtr += TablePtr->Length;
}
//
// Check if there is Interrupt Source Override entry. If there is, force the
// new flags into the SAPIC state. This is done now because of the possibility
// the firmware can place the ISO Vector Override entry ahead of IOSAPIC entry.
//
for (i = 0; i < PIC_VECTORS; i++) {
if (HalpPicVectorFlags[i]) {
HaliSetVectorState( HalpPicVectorRedirect[i],
HalpPicVectorFlags[i]
);
}
}
}
VOID
HalpProcessLocalSapic(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PPROCLOCALSAPIC ProcLocalSapic
)
{
USHORT LID;
ULONG ProcessorNum;
if (ProcLocalSapic->Length != PROCESSOR_LOCAL_SAPIC_LENGTH) {
HalDebugPrint(( HAL_ERROR,
"HAL: HalpProcessLocalSapic - Invalid Length %p: Expected %d, Found %d\n",
ProcLocalSapic,
PROCESSOR_LOCAL_SAPIC_LENGTH,
ProcLocalSapic->Length ));
return;
}
// Make sure processor is enabled...
if (!(ProcLocalSapic->Flags & PLAF_ENABLED)) {
return;
}
// It is. Bump the count and store the LID value for IPIs
LID = (ProcLocalSapic->APICID << 8) | ProcLocalSapic->APICEID;
HalpProcessorInfo[HalpMpInfo.ProcessorCount].AcpiProcessorID = ProcLocalSapic->ACPIProcessorID;
HalpProcessorInfo[HalpMpInfo.ProcessorCount].LocalApicID = LID;
HalpMpInfo.ProcessorCount++;
HalDebugPrint(( HAL_INFO,
"HAL: Found a processor-local SAPIC: %p LID=%x\n",
ProcLocalSapic,
LID ));
}
VOID
HalpProcessIoSapic(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PIOSAPIC IoSapic
)
{
ULONG IntiBase,RedirEntries;
PHYSICAL_ADDRESS IoSapicPhys;
PVOID IoSapicBase;
UINT_PTR IoSapicPhysBase;
PIO_SAPIC_REGS SapicRegs;
PIO_INTR_CONTROL IoIntrControl;
ULONG i;
union {
ULONG raw;
SAPIC_VERSION version;
} versionUnion;
if (IoSapic->Length != IO_SAPIC_LENGTH) {
HalDebugPrint(( HAL_ERROR,
"HAL: HalpProcessIoSapic - Invalid Length %p: Expected %d, Found %d\n",
IoSapic,
IO_SAPIC_LENGTH,
IoSapic->Length ));
return;
}
HalDebugPrint(( HAL_INFO, "HAL: Found an IO SAPIC: %p\n", IoSapic ));
// Map IO Sapic Registers...
IntiBase = IoSapic->SystemVectorBase;
IoSapicPhysBase = IoSapic->IOSAPICAddress;
IoSapicPhys.QuadPart = (UINT_PTR)IoSapicPhysBase;
IoSapicBase = HalpMapPhysicalMemory( IoSapicPhys,
ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicPhys.LowPart, IO_SAPIC_REGS_SIZE),
MmNonCached);
ASSERT(IoSapicBase);
SapicRegs = (PIO_SAPIC_REGS)IoSapicBase;
if (!SapicRegs) {
HalDebugPrint(( HAL_ERROR, "HAL: Couldn't map the I/O Sapic\n" ));
return;
}
// Read the IO Sapic version and extract the number of redirection table entries
SapicRegs->RegisterSelect = IO_VERS_REGISTER;
SapicRegs->RegisterWindow = 0;
versionUnion.raw = SapicRegs->RegisterWindow;
//
// CPQMOD_JL001 - Incorrect count - hw provide max rte index not
// count.
//
//RedirEntries = versionUnion.version.MaxRedirEntries;
RedirEntries = versionUnion.version.MaxRedirEntries + 1;
if (HalpVerifyIoSapic((PUCHAR)SapicRegs)) {
// Allocate and fill out a IO Sapic structure
PHYSICAL_ADDRESS physicalAddress;
physicalAddress.QuadPart = (LONGLONG)HalpAllocPhysicalMemory(
LoaderBlock,
~0,
BYTES_TO_PAGES(sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
FALSE );
if (physicalAddress.QuadPart == 0) {
HalDebugPrint(( HAL_ERROR, "HAL: Couldn't allocate memory for the IO Sapic structures\n" ));
return;
}
IoIntrControl = (PIO_INTR_CONTROL)HalpMapPhysicalMemory(
physicalAddress,
ADDRESS_AND_SIZE_TO_SPAN_PAGES(physicalAddress.LowPart, sizeof(IO_INTR_CONTROL) + (RedirEntries*sizeof(IOSAPICINTI))),
MmCached );
ASSERT(IoIntrControl);
IoIntrControl->IntiBase = IntiBase;
IoIntrControl->IntiMax = IntiBase + RedirEntries - 1;
IoIntrControl->RegBaseVirtual = IoSapicBase;
IoIntrControl->RegBasePhysical = IoSapicPhys;
IoIntrControl->IntrMethods = &HalpIoSapicMethods;
IoIntrControl->InterruptAffinity = 0xffffffff;
IoIntrControl->NextCpu = 0;
IoIntrControl->flink = NULL;
for (i = 0; i < RedirEntries; i++) {
IoIntrControl->Inti[i].Vector =
DELIVER_FIXED | ACTIVE_LOW | LEVEL_TRIGGERED;
IoIntrControl->Inti[i].Destination = 0;
IoIntrControl->Inti[i].GlobalVector = 0;
//
// CPQMOD_JL002 - Fix for using the rte and not the
// SystemVector.
//
//IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,IntiBase+i);
IoIntrControl->IntrMethods->MaskEntry(IoIntrControl,i);
}
// Insert structure into list. Since we are running on P0 at
// Phase0 initialization, we can assume that no one else is
// modifying this list therefore no synchronization is needed.
if (HalpIoSapicList == NULL) {
HalpIoSapicList = IoIntrControl;
} else {
PIO_INTR_CONTROL *LastLink;
PIO_INTR_CONTROL IoSapicListEntry;
LastLink = &HalpIoSapicList;
IoSapicListEntry = HalpIoSapicList;
while (IoSapicListEntry != NULL) {
if (IoSapicListEntry->IntiBase > IoIntrControl->IntiMax) {
// Insert new entry before current entry
IoIntrControl->flink = *LastLink;
*LastLink = IoIntrControl;
break;
} else {
LastLink = &IoSapicListEntry->flink;
IoSapicListEntry = IoSapicListEntry->flink;
}
}
if (IoSapicListEntry == NULL) {
// We got to the end of the list. The new entry goes
// after the last entry...
*LastLink = IoIntrControl;
}
}
HalpMpInfo.IoSapicCount++;
} else {
// The Io Sapic is not there, ignore this entry in the table
HalDebugPrint(( HAL_ERROR, rgzApicNotVerified ));
HalpUnmapVirtualAddress(IoSapicBase, ADDRESS_AND_SIZE_TO_SPAN_PAGES(IoSapicBase, IO_SAPIC_REGS_SIZE));
}
}
VOID
HalpProcessIsaVector(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PISA_VECTOR IsaVector
)
{
if (IsaVector->Length != ISA_VECTOR_OVERRIDE_LENGTH) {
HalDebugPrint(( HAL_ERROR,
"HAL: HalpProcessIsaVector - Invalid Length %p: Expected %d, Found %d\n",
IsaVector,
ISA_VECTOR_OVERRIDE_LENGTH,
IsaVector->Length ));
return;
}
//
// Found an ISA vector redirection entry.
//
HalpPicVectorRedirect[IsaVector->Source] =
IsaVector->GlobalSystemInterruptVector;
HalpPicVectorFlags[IsaVector->Source] = IsaVector->Flags;
HalDebugPrint(( HAL_INFO, "HAL: Found an ISA VECTOR: %p, %x -> %x, flags: %x\n",
IsaVector,
IsaVector->Source,
IsaVector->GlobalSystemInterruptVector,
IsaVector->Flags ));
}
VOID
HalpProcessPlatformInt(
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
IN PPLATFORM_INTERRUPT PlatformInt
)
{
static ULONG currentCPECount = 0;
if (PlatformInt->Length != PLATFORM_INTERRUPT_SOURCE_LENGTH) {
HalDebugPrint(( HAL_ERROR,
"HAL: HalpProcessPlatformInt - Invalid Length %p: Expected %d, Found %d\n",
PlatformInt,
PLATFORM_INTERRUPT_SOURCE_LENGTH,
PlatformInt->Length ));
return;
}
//
// Process a Corrected Platform Error Interrupt Source structure.
//
if (PlatformInt->InterruptType == PLATFORM_INT_CPE) {
//
// Does this platform has more (than what we expected) number of CPE sources?
//
if ( currentCPECount >= HALP_CPE_MAX_INTERRUPT_SOURCES ) {
HalDebugPrint(( HAL_ERROR,
"HAL: Platform Interrupt Source %p skipped due to overflow: %ld >= HALP_CPE_MAX_INTERRUPT_SOURCES\n", PlatformInt, currentCPECount ));
return;
}
//
// Save the input pin number of SAPIC for this CPE source
//
HalpCPEIntIn[currentCPECount] = (ULONG)PlatformInt->GlobalVector;
//
// Save the Flags for this CPE source
//
HalpCPEVectorFlags[currentCPECount] = (ULONG)PlatformInt->Flags;
//
// Save the IO Sapic Vector (that BIOS expects OS to use) for this platform CMC source
//
HalpCPEIoSapicVector[currentCPECount] = (UCHAR)PlatformInt->IOSAPICVector;
// Thierry - WARNING - 09/19/2000
// NT HAL ignores the IO SAPIC vector field for the platform interrupt sources.
// NT imposes the CPEI_VECTOR value for Corrected Machine Errors interrupt vector, for all
// the destination processors. Actually, the current default is to attach all the processors
// IDT[CPEI_VECTOR] with the HAL default ISR - HalpCPEIHandler for the CPE interrupt model.
// We will connect the ISR only for the destination processors after testing if judged valid.
// The rationales are:
// - IOSAPICVector was mostly added in the specs by Intel for IA64 PMI interrupt sources.
// These PMI interrupts are not visible by NT.
// - NT has no infrastructure at this time to support vector registration for FW/chipset
// generated external interrupts visible to NT.
// - Having the FW specifying the vector requires the HAL to control the specified
// value with its current IDT[] related resources usage and defines actions in case
// of conficts.
//
HalDebugPrint(( HAL_INFO, "HAL: CPE source VECTOR: %x. HAL imposes VECTOR: %x\n",
HalpCPEIoSapicVector[currentCPECount],
CPEI_VECTOR ));
HalpCPEIoSapicVector[currentCPECount] = (UCHAR)(CPEI_VECTOR);
//
// Save the Destination Processor (that BIOS expects OS to use) for this CPE source)
//
HalpCPEDestination[currentCPECount] = (USHORT)(
(PlatformInt->APICID << 8) | PlatformInt->ACPIEID);
//
// Force the flags into the SAPIC state
//
HalpSetCPEVectorState( HalpCPEIntIn[currentCPECount],
HalpCPEIoSapicVector[currentCPECount],
HalpCPEDestination[currentCPECount],
HalpCPEVectorFlags[currentCPECount]
);
HalDebugPrint(( HAL_INFO, "HAL: Found an Platform Interrupt VECTOR: %p, %x -> %x, flags: %x\n",
PlatformInt,
PlatformInt->IOSAPICVector,
PlatformInt->GlobalVector,
PlatformInt->Flags ));
//
// Keep track of how many CPE sources are implemented in the platform.
//
HalpMaxCPEImplemented = ++currentCPECount;
}
else if ( ( PlatformInt->InterruptType == PLATFORM_INT_PMI ) ||
( PlatformInt->InterruptType == PLATFORM_INT_INIT ) ) {
HalpWriteRedirEntry( PlatformInt->GlobalVector,
PlatformInt->IOSAPICVector,
(USHORT)((PlatformInt->APICID <<8) | PlatformInt->ACPIEID),
PlatformInt->Flags,
PlatformInt->InterruptType
);
}
return;
}
BOOLEAN
HalpVerifyIoSapic(
IN PUCHAR BaseAddress
)
/*++
Routine Description:
Verify that an IO Sapic Unit exists at the specified address
Arguments:
BaseAddress - Virtual address of the IO Unit to test.
Return Value:
BOOLEAN - TRUE if a IO Unit was found at the passed address
- FALSE otherwise
--*/
{
union SapicUnion {
ULONG Raw;
struct SapicVersion Ver;
} Temp1, Temp2;
PIO_SAPIC_REGS IoUnitPtr = (PIO_SAPIC_REGS) BaseAddress;
//
// The documented detection mechanism is to write all zeros to
// the Version register. Then read it back. The IO Unit exists if the
// same result is read both times and the Version is valid.
//
IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
IoUnitPtr->RegisterWindow = 0;
IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
Temp1.Raw = IoUnitPtr->RegisterWindow;
IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
IoUnitPtr->RegisterWindow = 0;
IoUnitPtr->RegisterSelect = IO_VERS_REGISTER;
Temp2.Raw = IoUnitPtr->RegisterWindow;
if ( Temp1.Raw == 0 ||
(Temp1.Ver.Version != Temp2.Ver.Version) ||
(Temp1.Ver.MaxRedirEntries != Temp2.Ver.MaxRedirEntries)) {
//
// No IO Unit There
//
HalDebugPrint(( HAL_ERROR, "HAL: No IoSapic at %I64x\n", BaseAddress ));
return (FALSE);
}
HalDebugPrint(( HAL_INFO, "HAL: IoSapic found at %I64x, Max Entries = %d\n", BaseAddress, Temp1.Ver.MaxRedirEntries ));
return (TRUE);
}
VOID
HalpInitApicDebugMappings(
VOID
)
/*++
Routine Description:
This routine is called at the very beginning of phase 1 initialization.
It creates mappings for the APICs using MmMapIoSpace. This will allow
us to access their registers from the debugger.
A much better solution would be to allow us to describe our memory usage to
MM but ....
Arguments:
Return Value:
--*/
{
PHYSICAL_ADDRESS physicalAddress;
PIO_INTR_CONTROL IoIntrControl;
ULONG index;
if (HalpMpInfo.IoSapicCount == 0) {
//
// I doubt this machine is going to get very far without IOAPICs
// but there is certainly nothing for this routine to do.
return;
}
ASSERT(HalpApicDebugAddresses == NULL);
HalpApicDebugAddresses = ExAllocatePool(NonPagedPool,
HalpMpInfo.IoSapicCount * sizeof(*HalpApicDebugAddresses));
if (HalpApicDebugAddresses == NULL) {
return;
}
IoIntrControl = HalpIoSapicList;
for (index = 0; index < HalpMpInfo.IoSapicCount; index++) {
if (IoIntrControl != NULL) {
if (HalpVirtualToPhysical((ULONG_PTR)IoIntrControl, &physicalAddress)) {
HalpApicDebugAddresses[index].IoIntrControl =
MmMapIoSpace(physicalAddress,
sizeof(IO_INTR_CONTROL) +
(IoIntrControl->IntiMax - IoIntrControl->IntiBase + 1) * sizeof(IOSAPICINTI),
MmCached
);
}
HalpApicDebugAddresses[index].IoSapicRegs =
MmMapIoSpace(IoIntrControl->RegBasePhysical,
IO_SAPIC_REGS_SIZE,
MmNonCached
);
IoIntrControl = IoIntrControl->flink;
} else {
HalpApicDebugAddresses[index].IoIntrControl = NULL;
HalpApicDebugAddresses[index].IoSapicRegs = NULL;
}
}
}
VOID
HalpSaveInterruptControllerState(
VOID
)
{
HalDebugPrint(( HAL_ERROR, "HAL: HalpSaveInterruptControllerState - not yet implemented\n"));
HalpHiberInProgress = TRUE;
}
VOID
HalpRestoreInterruptControllerState(
VOID
)
{
//
// Restore the IO APIC state
//
HalDebugPrint(( HAL_ERROR, "HAL: HalpRestoreInterruptControllerState - not yet implemented\n"));
HalpPicStateIntact = TRUE;
}
VOID
HalpSetInterruptControllerWakeupState(
ULONG Context
)
{
HalDebugPrint(( HAL_FATAL_ERROR, "HAL: HalpSetInterruptControllerWakeupState - not yet implemented\n"));
KeBugCheckEx(HAL_INITIALIZATION_FAILED, 0, 0, 0 , 0);
}
BOOLEAN
HalpAcpiPicStateIntact(
VOID
)
{
return HalpPicStateIntact;
}
ULONG
HalpAcpiNumProcessors(
VOID
)
{
return HalpMpInfo.ProcessorCount;
}
VOID
HalpMaskAcpiInterrupt(
VOID
)
{
ULONG inti;
KAFFINITY affinity;
ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
if (sciVector < PIC_VECTORS) {
sciVector = HalpPicVectorRedirect[sciVector];
}
HalpGetSapicInterruptDesc(
Internal,
0,
sciVector,
&inti,
&affinity
);
HalpDisableRedirEntry(inti);
}
VOID
HalpUnmaskAcpiInterrupt(
VOID
)
{
ULONG inti;
KAFFINITY affinity;
ULONG sciVector = HalpFixedAcpiDescTable.sci_int_vector;
if (sciVector < PIC_VECTORS) {
sciVector = HalpPicVectorRedirect[sciVector];
}
HalpGetSapicInterruptDesc(
Internal,
0,
sciVector,
&inti,
&affinity
);
HalpEnableRedirEntry(inti);
}
NTSTATUS
HalpGetApicIdByProcessorNumber(
IN UCHAR Processor,
IN OUT USHORT *ApicId
)
/*++
Routine Description:
This function returns an APIC ID for a given processor.
Arguments:
Processor - The logical processor number that is
associated with this APIC ID.
ApicId - pointer to a value to fill in with the APIC ID.
Return Value:
Status.
--*/
{
ULONG index;
for (index = 0; index < HalpMpInfo.ProcessorCount; index++) {
if (HalpProcessorInfo[index].NtProcessorNumber == Processor) {
//
// Return the APIC ID, Extended APIC ID for this
// processor.
//
*ApicId = HalpProcessorInfo[index].LocalApicID;
return STATUS_SUCCESS;
}
}
return STATUS_NOT_FOUND;
}