windows-nt/Source/XPSP1/NT/base/hals/halia64/ia64/ixinfo.c
2020-09-26 16:20:57 +08:00

350 lines
10 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ixinfo.c
Abstract:
Author:
Ken Reneris (kenr) 08-Aug-1994
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,HaliQuerySystemInformation)
#pragma alloc_text(PAGE,HaliSetSystemInformation)
#pragma alloc_text(INIT,HalInitSystemPhase2)
#endif
//
// NUMA Information.
//
extern PVOID HalpAcpiSrat;
NTSTATUS
HalpGetAcpiStaticNumaTopology(
HAL_NUMA_TOPOLOGY_INTERFACE * NumaInfo
);
NTSTATUS
HaliQuerySystemInformation(
IN HAL_QUERY_INFORMATION_CLASS InformationClass,
IN ULONG BufferSize,
OUT PVOID Buffer,
OUT PULONG ReturnedLength
)
{
NTSTATUS Status;
PVOID InternalBuffer;
ULONG Length, PlatformProperties;
union {
HAL_POWER_INFORMATION PowerInf;
HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
HAL_ERROR_INFO ErrorInfo;
HAL_DISPLAY_BIOS_INFORMATION DisplayBiosInf;
HAL_PLATFORM_INFORMATION PlatformInfo;
} U;
BOOLEAN bUseFrameBufferCaching;
PAGED_CODE();
Status = STATUS_SUCCESS;
*ReturnedLength = 0;
Length = 0;
switch (InformationClass) {
case HalFrameBufferCachingInformation:
Status = HalpGetPlatformProperties(&PlatformProperties);
if (NT_SUCCESS(Status) &&
(PlatformProperties & IPPT_DISABLE_WRITE_COMBINING)) {
bUseFrameBufferCaching = FALSE;
} else {
//
// Note - we want to return TRUE here to enable USWC in all
// cases except in a "Shared Memory Cluster" machine.
//
Status = STATUS_SUCCESS;
bUseFrameBufferCaching = TRUE;
}
InternalBuffer = &bUseFrameBufferCaching;
Length = sizeof (BOOLEAN);
break;
case HalMcaLogInformation:
Status = HalpGetMcaLog( Buffer, BufferSize, ReturnedLength );
break;
case HalCmcLogInformation:
Status = HalpGetCmcLog( Buffer, BufferSize, ReturnedLength );
break;
case HalCpeLogInformation:
Status = HalpGetCpeLog( Buffer, BufferSize, ReturnedLength );
break;
case HalErrorInformation:
InternalBuffer = &U.ErrorInfo;
if ( Buffer && (BufferSize > sizeof(U.ErrorInfo.Version)) ) {
U.ErrorInfo.Version = ((PHAL_ERROR_INFO)Buffer)->Version;
Status = HalpGetMceInformation(&U.ErrorInfo, &Length);
}
else {
Status = STATUS_INVALID_PARAMETER;
}
break;
case HalDisplayBiosInformation:
InternalBuffer = &U.DisplayBiosInf;
Length = sizeof(U.DisplayBiosInf);
U.DisplayBiosInf = HalpGetDisplayBiosInformation ();
break;
case HalProcessorSpeedInformation:
RtlZeroMemory (&U.ProcessorInf, sizeof(HAL_PROCESSOR_SPEED_INFORMATION));
// U.ProcessorInf.MaximumProcessorSpeed = HalpCPUMHz;
// U.ProcessorInf.CurrentAvailableSpeed = HalpCPUMHz;
// U.ProcessorInf.ConfiguredSpeedLimit = HalpCPUMHz;
U.ProcessorInf.ProcessorSpeed = HalpCPUMHz;
InternalBuffer = &U.ProcessorInf;
Length = sizeof (HAL_PROCESSOR_SPEED_INFORMATION);
break;
case HalProfileSourceInformation:
Status = HalpProfileSourceInformation (
Buffer,
BufferSize,
ReturnedLength);
return Status;
break;
case HalNumaTopologyInterface:
if (BufferSize == sizeof(HAL_NUMA_TOPOLOGY_INTERFACE)) {
Status = STATUS_INVALID_LEVEL;
if (HalpAcpiSrat) {
Status = HalpGetAcpiStaticNumaTopology(Buffer);
if (NT_SUCCESS(Status)) {
*ReturnedLength = sizeof(HAL_NUMA_TOPOLOGY_INTERFACE);
}
break;
}
} else {
//
// Buffer size is wrong, we could return valid data
// if the buffer is too big,.... but instead we will
// use this as an indication that we're not compatible
// with the kernel.
//
Status = STATUS_INFO_LENGTH_MISMATCH;
}
break;
case HalPartitionIpiInterface:
//
// Some platforms generate interrupts in remote partitions
// as part of their shared memory implementation. This is
// accomplished by targetting an IPI at a processor/vector
// in that remote partition. Provide interfaces to enable
// this but make them conditional on presence of IPPT
// table and appropriate bit explicitly enabling this
// functionality. OEM is responsible for ensuring that an
// interrupt isn't sent to a logical processor that isn't
// present.
//
if (BufferSize >= sizeof(HAL_CROSS_PARTITION_IPI_INTERFACE)) {
Status = HalpGetPlatformProperties(&PlatformProperties);
if (NT_SUCCESS(Status) &&
(PlatformProperties & IPPT_ENABLE_CROSS_PARTITION_IPI)) {
Status = HalpGetCrossPartitionIpiInterface(Buffer);
if (NT_SUCCESS(Status)) {
*ReturnedLength = sizeof(HAL_CROSS_PARTITION_IPI_INTERFACE);
}
} else {
Status = STATUS_UNSUCCESSFUL;
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
break;
case HalPlatformInformation:
//
// Any platform information that must be exposed to the kernel.
//
if (BufferSize >= sizeof(HAL_PLATFORM_INFORMATION)) {
Status = HalpGetPlatformProperties(&PlatformProperties);
if (NT_SUCCESS(Status)) {
InternalBuffer = &U.PlatformInfo;
Length = sizeof(U.PlatformInfo);
U.PlatformInfo.PlatformFlags = PlatformProperties;
}
} else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
break;
default:
Status = STATUS_INVALID_LEVEL;
break;
}
//
// If non-zero Length copy data to callers buffer
//
if (Length) {
if (BufferSize < Length) {
Length = BufferSize;
}
*ReturnedLength = Length;
RtlCopyMemory (Buffer, InternalBuffer, Length);
}
return Status;
} // HaliQuerySystemInformation()
#if !defined(MmIsFunctionPointerValid)
#define MmIsFunctionPointerValid( _Va ) ( MmIsAddressValid((PVOID)(_Va)) && MmIsAddressValid((PVOID)(*((PULONG_PTR)(_Va)))) )
#endif // !MmIsFunctionPointerValid
NTSTATUS
HaliSetSystemInformation (
IN HAL_SET_INFORMATION_CLASS InformationClass,
IN ULONG BufferSize,
IN PVOID Buffer
)
/*++
Routine Description:
The function allows setting of various fields return by
HalQuerySystemInformation.
Arguments:
InformationClass - Information class of the request.
BufferSize - Size of buffer supplied by the caller.
Buffer - Supplies the data to be set.
Return Value:
STATUS_SUCCESS or error.
--*/
{
NTSTATUS Status;
PAGED_CODE();
Status = STATUS_SUCCESS;
switch (InformationClass) {
case HalProfileSourceInterval:
if (BufferSize == sizeof(HAL_PROFILE_SOURCE_INTERVAL)) {
PHAL_PROFILE_SOURCE_INTERVAL sourceInterval =
(PHAL_PROFILE_SOURCE_INTERVAL)Buffer;
Status = HalSetProfileSourceInterval( sourceInterval->Source,
&sourceInterval->Interval
);
}
else {
Status = STATUS_INFO_LENGTH_MISMATCH;
}
break;
case HalProfileSourceInterruptHandler:
//
// Register an Profiling Interrupt Handler.
//
Status = STATUS_INFO_LENGTH_MISMATCH;
if (BufferSize == sizeof(ULONG_PTR)) {
if ( !(HalpFeatureBits & HAL_PERF_EVENTS) ) {
Status = STATUS_NO_SUCH_DEVICE;
}
else if ( !MmIsFunctionPointerValid(Buffer) ) {
Status = STATUS_INVALID_ADDRESS;
}
else {
Status = (NTSTATUS)KiIpiGenericCall( HalpSetProfileInterruptHandler, *(PULONG_PTR)Buffer );
}
}
break;
case HalKernelErrorHandler:
Status = HalpMceRegisterKernelDriver( (PKERNEL_ERROR_HANDLER_INFO) Buffer, BufferSize );
break;
case HalMcaRegisterDriver:
Status = HalpMcaRegisterDriver(
(PMCA_DRIVER_INFO) Buffer // Info about registering driver
);
break;
case HalCmcRegisterDriver:
Status = HalpCmcRegisterDriver(
(PCMC_DRIVER_INFO) Buffer // Info about registering driver
);
break;
case HalCpeRegisterDriver:
Status = HalpCpeRegisterDriver(
(PCPE_DRIVER_INFO) Buffer // Info about registering driver
);
break;
case HalMcaLog: // Class requested by MS Machine Check Event Test Team.
Status = HalpSetMcaLog( (PMCA_EXCEPTION) Buffer, BufferSize );
break;
case HalCmcLog: // Class requested by MS Machine Check Event Test Team.
Status = HalpSetCmcLog( (PCMC_EXCEPTION) Buffer, BufferSize );
break;
case HalCpeLog: // Class requested by MS Machine Check Event Test Team.
Status = HalpSetCpeLog( (PCPE_EXCEPTION) Buffer, BufferSize );
break;
default:
Status = STATUS_INVALID_LEVEL;
break;
}
return Status;
} // HaliSetSystemInformation()