You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2256 lines
46 KiB
2256 lines
46 KiB
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
halp.h
|
|
|
|
Abstract:
|
|
|
|
This header file defines the private Hardware Architecture Layer (HAL)
|
|
interfaces, defines and structures.
|
|
|
|
Author:
|
|
|
|
John Vert (jvert) 11-Feb-92
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _HALP_H_
|
|
#define _HALP_H_
|
|
#include "nthal.h"
|
|
#include "halnls.h"
|
|
|
|
//
|
|
//Pickup the pnp guid definitions.
|
|
//
|
|
#include "wdmguid.h"
|
|
|
|
|
|
#if defined(NEC_98)
|
|
#include "nec98.h"
|
|
#else
|
|
#if MCA
|
|
#include "mca.h"
|
|
#else
|
|
#include "eisa.h"
|
|
#endif
|
|
#endif // NEC_98
|
|
|
|
#ifndef _HALI_
|
|
#include "hali.h"
|
|
#endif
|
|
|
|
#ifdef RtlMoveMemory
|
|
#undef RtlMoveMemory
|
|
|
|
// #undef RtlCopyMemory
|
|
// #undef RtlFillMemory
|
|
// #undef RtlZeroMemory
|
|
|
|
//#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length))
|
|
|
|
#if defined(_WIN64)
|
|
|
|
__inline
|
|
VOID
|
|
RtlMoveMemory (
|
|
PVOID Destination,
|
|
CONST VOID *Source,
|
|
SIZE_T Length
|
|
)
|
|
{
|
|
memmove(Destination,Source,Length);
|
|
}
|
|
|
|
#else
|
|
|
|
VOID
|
|
RtlMoveMemory (
|
|
PVOID Destination,
|
|
CONST VOID *Source,
|
|
SIZE_T Length
|
|
);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// VOID
|
|
// RtlFillMemory (
|
|
// PVOID Destination,
|
|
// ULONG Length,
|
|
// UCHAR Fill
|
|
// );
|
|
//
|
|
// VOID
|
|
// RtlZeroMemory (
|
|
// PVOID Destination,
|
|
// ULONG Length
|
|
// );
|
|
//
|
|
|
|
#endif
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
//
|
|
// A temporary macro used to indicate that a particular piece of code
|
|
// has never been executed on AMD64 before, and should be examined
|
|
// carefully for correct operation.
|
|
//
|
|
|
|
#define AMD64_COVERAGE_TRAP() DbgBreakPoint()
|
|
|
|
//
|
|
// The following prototypes are not available from the standard HAL headers
|
|
// due to the fact that NO_LEGACY_DRIVERS is defined while compiling the
|
|
// HAL... however, they are used internally.
|
|
//
|
|
|
|
NTSTATUS
|
|
HalAssignSlotResources (
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN INTERFACE_TYPE BusType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
|
);
|
|
|
|
ULONG
|
|
HalGetInterruptVector(
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG BusInterruptLevel,
|
|
IN ULONG BusInterruptVector,
|
|
OUT PKIRQL Irql,
|
|
OUT PKAFFINITY Affinity
|
|
);
|
|
|
|
ULONG
|
|
HalGetBusData(
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
);
|
|
|
|
ULONG
|
|
HalSetBusData(
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Length
|
|
);
|
|
|
|
//
|
|
// We are sharing code that was written for the x86. There are some
|
|
// macros with identical meanings but different names in AMD64. Following
|
|
// are some definitions to abstract those differences.
|
|
//
|
|
|
|
//
|
|
// CLOCK2_LEVEL on x86 is CLOCK_LEVEL on AMD64.
|
|
//
|
|
|
|
#define CLOCK2_LEVEL CLOCK_LEVEL
|
|
|
|
//
|
|
// X86 EFLAGS_INTERRUPT_MASK == AMD64 EFLAGS_IF_MASK
|
|
//
|
|
|
|
#define EFLAGS_INTERRUPT_MASK EFLAGS_IF_MASK
|
|
|
|
//
|
|
// The PCR's pointer to the current prcb is named Prcb, while on AMD64
|
|
// it is named CurrentPrcb.
|
|
//
|
|
// The CurrentPrcb() macro is used to abstract this difference.
|
|
//
|
|
|
|
#define CurrentPrcb(x) (x)->CurrentPrcb
|
|
|
|
//
|
|
// The x86 KiReturnHandlerAddressFromIDT() is the equivalent of the AMD64's
|
|
// KeGetIdtHandlerAddress()
|
|
//
|
|
|
|
#define KiReturnHandlerAddressFromIDT(v) (ULONG_PTR)KeGetIdtHandlerAddress(v)
|
|
|
|
//
|
|
// More macro and structure name differences
|
|
//
|
|
|
|
#define RDMSR(m) ReadMSR(m)
|
|
#define WRMSR(m,d) WriteMSR(m,d)
|
|
#define KGDTENTRY KGDTENTRY64
|
|
#define PKGDTENTRY PKGDTENTRY64
|
|
|
|
#define PIOPM_SIZE (sizeof(KIO_ACCESS_MAP) + sizeof(ULONG))
|
|
|
|
//
|
|
// The AMD64 in long mode uses 8-byte PTE entries, which have the same format
|
|
// as Pentium PAE page tables.
|
|
//
|
|
|
|
#if !defined(_HALPAE_)
|
|
#define _HALPAE_ 1
|
|
#endif
|
|
|
|
#define HARDWARE_PTE_X86PAE HARDWARE_PTE
|
|
#define HARDWARE_PTE_X86 HARDWARE_PTE
|
|
|
|
#define PHARDWARE_PTE_X86PAE PHARDWARE_PTE
|
|
#define PHARDWARE_PTE_X86 PHARDWARE_PTE
|
|
|
|
#define PDE_BASE_X86PAE PDE_BASE
|
|
#define PDE_BASE_X86 PDE_BASE
|
|
|
|
#define PDI_SHIFT_X86PAE PDI_SHIFT
|
|
#define PDI_SHIFT_X86 PDI_SHIFT
|
|
|
|
//
|
|
// Fence instruction.
|
|
//
|
|
|
|
__forceinline
|
|
VOID
|
|
HalpProcessorFence (
|
|
VOID
|
|
)
|
|
{
|
|
CPU_INFO cpuInfo;
|
|
KiCpuId (0,&cpuInfo);
|
|
}
|
|
|
|
#define HalpGetProcessorFlags() __getcallerseflags()
|
|
|
|
//
|
|
// While _enable() and _disable() are intrinsics in both the AMD64 and X86
|
|
// compilers, they are disabled on X86. HalpDisableInterruptsNoFlags and
|
|
// HalpEnableInterrupts are macros used to abstract this difference.
|
|
//
|
|
|
|
#define HalpDisableInterruptsNoFlags _disable
|
|
#define HalpEnableInterrupts _enable
|
|
|
|
//
|
|
// There is no intrinsic for the hlt instruction on AMD64. HalpHalt()
|
|
// is a function call on AMD64, and inline asm on X86.
|
|
//
|
|
|
|
VOID
|
|
HalpHalt (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// On x86, the variables HalpClockSetMSRate, HalpClockMcaQueueDpc and
|
|
// HalpClockWork are defined in an .asm module such that HalpClockWork
|
|
// is defined as a DWORD that overlapps HalpClockSetMSRate and
|
|
// HalpClockMcaQueueDpc.
|
|
//
|
|
// This is not directly representable in C, so instead HALP_CLOCKWORK_UNION
|
|
// is defined and the above variable names are instead redefined to reference
|
|
// elements of this union.
|
|
//
|
|
|
|
#define HalpClockSetMSRate HalpClockWorkUnion.ClockSetMSRate
|
|
#define HalpClockMcaQueueDpc HalpClockWorkUnion.ClockMcaQueueDpc
|
|
#define HalpClockWork HalpClockWorkUnion.ClockWork
|
|
|
|
typedef union {
|
|
struct {
|
|
UCHAR ClockMcaQueueDpc;
|
|
UCHAR ClockSetMSRate;
|
|
UCHAR bReserved1;
|
|
UCHAR bReserved2;
|
|
};
|
|
ULONG ClockWork;
|
|
} HALP_CLOCKWORK_UNION;
|
|
|
|
extern HALP_CLOCKWORK_UNION HalpClockWorkUnion;
|
|
|
|
#else
|
|
|
|
//
|
|
// Following are X86 definitions that are used to help abstract differences
|
|
// between X86 and AMD64 platforms.
|
|
//
|
|
|
|
#define AMD64_COVERAGE_TRAP()
|
|
|
|
//
|
|
// We are sharing code that was written for the x86. There are some
|
|
// macros with identical meanings but different names in AMD64. Following
|
|
// are some definitions to abstract those differences.
|
|
//
|
|
|
|
//
|
|
// The following _KPCR fields have different names but identical purposes.
|
|
//
|
|
|
|
#define IdtBase IDT
|
|
#define GdtBase GDT
|
|
#define TssBase TSS
|
|
|
|
//
|
|
// The PCR's pointer to the current prcb is named Prcb, while on AMD64
|
|
// it is named CurrentPrcb.
|
|
//
|
|
// The CurrentPrcb() macro is used to abstract this difference.
|
|
//
|
|
|
|
#define CurrentPrcb(x) (x)->Prcb
|
|
|
|
//
|
|
// On X86, HalpGetProcessorFlags() can be implemented inline.
|
|
//
|
|
|
|
__forceinline
|
|
ULONG
|
|
HalpGetProcessorFlags (
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This procedure retrieves the contents of the EFLAGS register.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The 32-bit contents of the EFLAGS register.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG flags;
|
|
|
|
_asm {
|
|
pushfd
|
|
pop eax
|
|
mov flags, eax
|
|
}
|
|
|
|
return flags;
|
|
}
|
|
|
|
//
|
|
// While _enable() and _disable() are intrinsics in both the AMD64 and X86
|
|
// compilers, they are disabled in the HAL on X86.
|
|
//
|
|
// HalpDisableInterruptsNoFlags and HalpEnableInterrupts are macros used
|
|
// to abstract this difference.
|
|
//
|
|
|
|
#define HalpDisableInterruptsNoFlags() _asm cli
|
|
#define HalpEnableInterrupts() _asm sti
|
|
|
|
//
|
|
// There is no intrinsic for the hlt instruction on AMD64. HalpHalt()
|
|
// is a function call on AMD64, and inline asm on X86.
|
|
//
|
|
|
|
#define HalpHalt() _asm hlt
|
|
|
|
//
|
|
// Fence instruction
|
|
//
|
|
|
|
__forceinline
|
|
VOID
|
|
HalpProcessorFence (
|
|
VOID
|
|
)
|
|
{
|
|
_asm {
|
|
xor eax, eax
|
|
cpuid
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
#define PROCESSOR_FENCE HalpProcessorFence()
|
|
|
|
__forceinline
|
|
ULONG
|
|
HalpDisableInterrupts(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function saves the state of the processor flag register, clears the
|
|
state of the interrupt flag (disables interrupts), and returns the
|
|
previous contents of the processor flag register.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The previous contents of the processor flag register.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG flags;
|
|
|
|
flags = HalpGetProcessorFlags();
|
|
HalpDisableInterruptsNoFlags();
|
|
|
|
return flags;
|
|
}
|
|
|
|
__forceinline
|
|
VOID
|
|
HalpRestoreInterrupts(
|
|
IN ULONG Flags
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This procedure restores the state of the interrupt flag based on a
|
|
value returned by a previous call to HalpDisableInterrupts.
|
|
|
|
Arguments:
|
|
|
|
Flags - Supplies the value returned by a previous call to
|
|
HalpDisableInterrupts
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
if ((Flags & EFLAGS_INTERRUPT_MASK) != 0) {
|
|
HalpEnableInterrupts();
|
|
}
|
|
}
|
|
|
|
#if defined(_WIN64)
|
|
|
|
//
|
|
// For AMD64 (and, ideally, all subsequent WIN64 platforms), interrupt
|
|
// service routines are C callable.
|
|
//
|
|
|
|
typedef PKSERVICE_ROUTINE PHAL_INTERRUPT_SERVICE_ROUTINE;
|
|
|
|
#define HAL_INTERRUPT_SERVICE_PROTOTYPE(RoutineName) \
|
|
BOOLEAN \
|
|
RoutineName ( \
|
|
IN PKINTERRUPT Interrupt, \
|
|
IN PVOID ServiceContext \
|
|
)
|
|
|
|
#define PROCESSOR_CURRENT ((UCHAR)-1)
|
|
|
|
VOID
|
|
HalpSetHandlerAddressToIDTIrql (
|
|
IN ULONG Vector,
|
|
IN PHAL_INTERRUPT_SERVICE_ROUTINE ServiceRoutine,
|
|
IN PVOID Context,
|
|
IN KIRQL Irql
|
|
);
|
|
|
|
#define KiSetHandlerAddressToIDT Dont_Use_KiSetHandlerAddressToIdt
|
|
|
|
//
|
|
// On AMD64, the HAL does not connect directly to the IDT, rather the
|
|
// kernel handles the interrupt and calls a C-callable interrupt routine.
|
|
//
|
|
// Therefore, HalpSetHandlerAddressToIDT() must supply a context and an
|
|
// IRQL in addition to the vector number and interrupt routine.
|
|
//
|
|
// On X86, the context and IRQL are ignored, as the vector is inserted
|
|
// directly into the IDT, such that the service routine is responsible for
|
|
// raising IRQL.
|
|
//
|
|
|
|
#define KiSetHandlerAddressToIDTIrql(v,a,c,i) \
|
|
HalpSetHandlerAddressToIDTIrql (v,a,c,i);
|
|
|
|
#else
|
|
|
|
//
|
|
// On X86, the last two parameters of KiSetHandlerAddressToIDTIrql()
|
|
// (Context and Irql) are ignored. The interrupt handlers themselves
|
|
// are responsible for raising IRQL.
|
|
//
|
|
|
|
#define KiSetHandlerAddressToIDTIrql(v,a,c,i) KiSetHandlerAddressToIDT(v,a)
|
|
|
|
//
|
|
// For X86, interrupt service routines must be written in assembler because
|
|
// they are referenced directly in the IDT and trasferred to directly by
|
|
// the processor with a convention that is not C callable.
|
|
//
|
|
// For purposes of C code that references ISRs, then, the prototype is
|
|
// very simple.
|
|
//
|
|
|
|
typedef
|
|
VOID
|
|
(*PHAL_INTERRUPT_SERVICE_ROUTINE)(
|
|
VOID
|
|
);
|
|
|
|
#define HAL_INTERRUPT_SERVICE_PROTOTYPE(RoutineName) \
|
|
VOID \
|
|
RoutineName ( \
|
|
VOID \
|
|
)
|
|
|
|
#endif
|
|
|
|
typedef
|
|
VOID
|
|
(*HALP_MOVE_MEMORY_ROUTINE)(
|
|
PVOID Destination,
|
|
CONST VOID *Source,
|
|
SIZE_T Length
|
|
);
|
|
|
|
VOID
|
|
HalpMovntiCopyBuffer(
|
|
PVOID Destination,
|
|
CONST VOID *Source,
|
|
ULONG Length
|
|
);
|
|
|
|
VOID
|
|
HalpSetInternalVector (
|
|
IN ULONG InternalVector,
|
|
IN PHAL_INTERRUPT_SERVICE_ROUTINE HalInterruptSerivceRoutine,
|
|
IN PVOID Context,
|
|
IN KIRQL Irql
|
|
);
|
|
|
|
extern HALP_MOVE_MEMORY_ROUTINE HalpMoveMemory;
|
|
|
|
#if MCA
|
|
|
|
#include "ixmca.h"
|
|
|
|
#else
|
|
|
|
#include "ixisa.h"
|
|
|
|
#endif
|
|
|
|
#include "ix8259.inc"
|
|
|
|
#if DBG
|
|
extern ULONG HalDebug;
|
|
|
|
#define HalPrint(x) \
|
|
if (HalDebug) { \
|
|
DbgPrint("HAL: "); \
|
|
DbgPrint x; \
|
|
DbgPrint("\n"); \
|
|
}
|
|
#else
|
|
#define HalPrint(x)
|
|
#endif
|
|
|
|
//
|
|
// Define map register translation entry structure.
|
|
//
|
|
|
|
typedef struct _TRANSLATION_ENTRY {
|
|
PVOID VirtualAddress;
|
|
ULONG PhysicalAddress;
|
|
ULONG Index;
|
|
} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
|
|
|
|
//
|
|
// Some devices require a phyicially contiguous data buffers for DMA transfers.
|
|
// Map registers are used give the appearance that all data buffers are
|
|
// contiguous. In order to pool all of the map registers a master
|
|
// adapter object is used. This object is allocated and saved internal to this
|
|
// file. It contains a bit map for allocation of the registers and a queue
|
|
// for requests which are waiting for more map registers. This object is
|
|
// allocated during the first request to allocate an adapter which requires
|
|
// map registers.
|
|
//
|
|
// In this system, the map registers are translation entries which point to
|
|
// map buffers. Map buffers are physically contiguous and have physical memory
|
|
// addresses less than 0x01000000. All of the map registers are allocated
|
|
// initialially; however, the map buffers are allocated base in the number of
|
|
// adapters which are allocated.
|
|
//
|
|
// If the master adapter is NULL in the adapter object then device does not
|
|
// require any map registers.
|
|
//
|
|
|
|
extern POBJECT_TYPE *IoAdapterObjectType;
|
|
|
|
extern BOOLEAN LessThan16Mb;
|
|
|
|
extern BOOLEAN HalpEisaDma;
|
|
|
|
VOID
|
|
HalpGrowMapBufferWorker(
|
|
IN PVOID Context
|
|
);
|
|
|
|
//
|
|
// Work item to grow map buffers
|
|
//
|
|
typedef struct _BUFFER_GROW_WORK_ITEM {
|
|
WORK_QUEUE_ITEM WorkItem;
|
|
PADAPTER_OBJECT AdapterObject;
|
|
ULONG MapRegisterCount;
|
|
} BUFFER_GROW_WORK_ITEM, *PBUFFER_GROW_WORK_ITEM;
|
|
|
|
//
|
|
// Map buffer prameters. These are initialized in HalInitSystem
|
|
//
|
|
|
|
//
|
|
// PAE note:
|
|
//
|
|
// Previously, there was only one class of adapter that we had to double-buffer
|
|
// for: adapters with only 24 address lines that could access memory up to
|
|
// 16MB.
|
|
//
|
|
// The HAL tracked these map buffers with a single, global master adapter.
|
|
// Associated with this master adapter were three global variables:
|
|
//
|
|
// - MasterAdapterObject
|
|
// - HalpMapBufferSize
|
|
// - HalpMapBufferPhysicalAddress
|
|
//
|
|
// With PAE, we have another class of adapters that require double-buffering:
|
|
// specifically, adapters with only 32 address lines that can access memory
|
|
// up to 4G.
|
|
//
|
|
// This meant the introduction of another master adapter along with an
|
|
// associated set of variables. For PAE-capable hals, this data has been
|
|
// reorganized into a MASTER_ADAPTER_OBJECT (see ixisa.h).
|
|
//
|
|
// So now we have two global MASTER_ADAPTER_OBJECT structures:
|
|
//
|
|
// MasterAdapter24
|
|
// MasterAdapter32
|
|
//
|
|
// The following macros are used in code that is included in PAE-capable
|
|
// hals. It is important to note that in a non-PAE-capable HAL (i.e. one
|
|
// that does not have _HALPAE_ defined), the macros must resolve to the
|
|
// values that they replaced.
|
|
//
|
|
|
|
#if defined(_HALPAE_)
|
|
|
|
PADAPTER_OBJECT
|
|
HalpAllocateAdapterEx(
|
|
IN ULONG MapRegistersPerChannel,
|
|
IN PVOID AdapterBaseVa,
|
|
IN PVOID ChannelNumber,
|
|
IN BOOLEAN Dma32Bit
|
|
);
|
|
|
|
extern MASTER_ADAPTER_OBJECT MasterAdapter24;
|
|
extern MASTER_ADAPTER_OBJECT MasterAdapter32;
|
|
|
|
#define HalpMasterAdapterStruc( Dma32Bit ) \
|
|
((HalPaeEnabled() && (Dma32Bit)) ? &MasterAdapter32 : &MasterAdapter24)
|
|
|
|
#define HalpMaximumMapBufferRegisters( Dma32Bit ) \
|
|
(HalpMasterAdapterStruc( Dma32Bit )->MaxBufferPages)
|
|
|
|
#define HalpMaximumMapRegisters( Dma32Bit ) \
|
|
(Dma32Bit ? MAXIMUM_PCI_MAP_REGISTER : MAXIMUM_ISA_MAP_REGISTER)
|
|
|
|
#define HalpMapBufferSize( Dma32Bit ) \
|
|
(HalpMasterAdapterStruc( Dma32Bit )->MapBufferSize)
|
|
|
|
#define HalpMapBufferPhysicalAddress( Dma32Bit ) \
|
|
(HalpMasterAdapterStruc( Dma32Bit )->MapBufferPhysicalAddress)
|
|
|
|
#define HalpMasterAdapter( Dma32Bit ) \
|
|
HalpMasterAdapterStruc( Dma32Bit )->AdapterObject
|
|
|
|
#else
|
|
|
|
extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
|
|
extern ULONG HalpMapBufferSize;
|
|
extern PADAPTER_OBJECT MasterAdapterObject;
|
|
|
|
#define HalpAllocateAdapterEx( _m, _a, _c, _d ) \
|
|
HalpAllocateAdapter( _m, _a, _c )
|
|
|
|
#define HalpMaximumMapBufferRegisters( Dma32Bit ) \
|
|
(MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE)
|
|
|
|
#define HalpMaximumMapRegisters( Dma32Bit ) \
|
|
(MAXIMUM_ISA_MAP_REGISTER)
|
|
|
|
#define HalpMapBufferSize( Dma32Bit ) HalpMapBufferSize
|
|
|
|
#define HalpMapBufferPhysicalAddress( Dma32Bit ) \
|
|
(HalpMapBufferPhysicalAddress)
|
|
|
|
#define HalpMasterAdapter( Dma32Bit ) MasterAdapterObject
|
|
|
|
#endif
|
|
|
|
extern ULONG HalpBusType;
|
|
extern ULONG HalpCpuType;
|
|
extern UCHAR HalpSerialLen;
|
|
extern UCHAR HalpSerialNumber[];
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
//
|
|
// Amd64 decodes 48 bits of virtual address space.
|
|
//
|
|
|
|
#define MI_DECODE_MASK (((ULONG64)1 << 48) - 1)
|
|
#define VA_TRUNC(x) ((ULONG64)(x) & MI_DECODE_MASK)
|
|
|
|
#else
|
|
|
|
#define VA_TRUNC(x) (x)
|
|
|
|
#endif
|
|
|
|
|
|
//
|
|
// The following macros are taken from mm\i386\mi386.h. We need them here
|
|
// so the HAL can map its own memory before memory-management has been
|
|
// initialized, or during a BugCheck.
|
|
//
|
|
// MiGetPdeAddress returns the address of the PDE which maps the
|
|
// given virtual address.
|
|
//
|
|
|
|
#define MiGetPdeAddressX86(va) ((PHARDWARE_PTE)(((((ULONG_PTR)(va)) >> 22) << 2) + PDE_BASE))
|
|
|
|
//
|
|
// MiGetPteAddress returns the address of the PTE which maps the
|
|
// given virtual address.
|
|
//
|
|
|
|
#define MiGetPteAddressX86(va) ((PHARDWARE_PTE)(((((ULONG_PTR)(va)) >> 12) << 2) + PTE_BASE))
|
|
|
|
//
|
|
// MiGetPteIndex returns the index within a page table of the PTE for the
|
|
// given virtual address
|
|
//
|
|
|
|
#define MiGetPteIndexX86(va) (((ULONG_PTR)(va) >> PAGE_SHIFT) & 0x3FF)
|
|
#define MiGetPteIndexPae(va) (((ULONG_PTR)(VA_TRUNC(va)) >> PAGE_SHIFT) & 0x1FF)
|
|
|
|
//
|
|
// The following macros are taken from mm\i386\mipae.h. We need them here
|
|
// so the HAL can map its own memory before memory-management has been
|
|
// initialized, or during a BugCheck.
|
|
//
|
|
// MiGetPdeAddressPae returns the address of the PDE which maps the
|
|
// given virtual address.
|
|
//
|
|
|
|
#define MiGetPdeAddressPae(va) ((PHARDWARE_PTE_X86PAE)(PDE_BASE_X86PAE + ((((ULONG_PTR)(VA_TRUNC(va))) >> 21) << 3)))
|
|
|
|
//
|
|
// MiGetPteAddressPae returns the address of the PTE which maps the
|
|
// given virtual address.
|
|
//
|
|
|
|
#define MiGetPteAddressPae(va) ((PHARDWARE_PTE_X86PAE)(PTE_BASE + ((((ULONG_PTR)(VA_TRUNC(va))) >> 12) << 3)))
|
|
|
|
//
|
|
// Resource usage information
|
|
//
|
|
|
|
#pragma pack(1)
|
|
typedef struct {
|
|
UCHAR Flags;
|
|
} IDTUsageFlags;
|
|
|
|
typedef struct {
|
|
KIRQL Irql;
|
|
UCHAR BusReleativeVector;
|
|
} IDTUsage;
|
|
|
|
typedef struct _HalAddressUsage{
|
|
struct _HalAddressUsage *Next;
|
|
CM_RESOURCE_TYPE Type; // Port or Memory
|
|
UCHAR Flags; // same as IDTUsage.Flags
|
|
struct {
|
|
ULONG Start;
|
|
ULONG Length;
|
|
} Element[];
|
|
} ADDRESS_USAGE;
|
|
#pragma pack()
|
|
|
|
#define IDTOwned 0x01 // IDT is not available for others
|
|
#define InterruptLatched 0x02 // Level or Latched
|
|
#define RomResource 0x04 // ROM
|
|
#define InternalUsage 0x11 // Report usage on internal bus
|
|
#define DeviceUsage 0x21 // Report usage on device bus
|
|
|
|
extern IDTUsageFlags HalpIDTUsageFlags[];
|
|
extern IDTUsage HalpIDTUsage[];
|
|
extern ADDRESS_USAGE *HalpAddressUsageList;
|
|
|
|
#define HalpRegisterAddressUsage(a) \
|
|
(a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
|
|
|
|
//
|
|
// Temp definitions to thunk into supporting new bus extension format
|
|
//
|
|
|
|
VOID
|
|
HalpRegisterInternalBusHandlers (
|
|
VOID
|
|
);
|
|
|
|
PBUS_HANDLER
|
|
HalpAllocateBusHandler (
|
|
IN INTERFACE_TYPE InterfaceType,
|
|
IN BUS_DATA_TYPE BusDataType,
|
|
IN ULONG BusNumber,
|
|
IN INTERFACE_TYPE ParentBusDataType,
|
|
IN ULONG ParentBusNumber,
|
|
IN ULONG BusSpecificData
|
|
);
|
|
|
|
#define HalpHandlerForBus HaliHandlerForBus
|
|
#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
|
|
|
|
//
|
|
// Define function prototypes.
|
|
//
|
|
|
|
VOID
|
|
HalInitSystemPhase2(
|
|
VOID
|
|
);
|
|
|
|
KIRQL
|
|
HaliRaiseIrqlToDpcLevel (
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpGrowMapBuffers(
|
|
PADAPTER_OBJECT AdapterObject,
|
|
ULONG Amount
|
|
);
|
|
|
|
PADAPTER_OBJECT
|
|
HalpAllocateAdapter(
|
|
IN ULONG MapRegistersPerChannel,
|
|
IN PVOID AdapterBaseVa,
|
|
IN PVOID MapRegisterBase
|
|
);
|
|
|
|
HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpClockInterrupt);
|
|
|
|
KIRQL
|
|
HalpDisableAllInterrupts (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpReenableInterrupts (
|
|
KIRQL NewIrql
|
|
);
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
VOID
|
|
HalpInitializeProfiling (
|
|
ULONG Number
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpSetProfileSourceInterval(
|
|
IN KPROFILE_SOURCE ProfileSource,
|
|
IN OUT ULONG_PTR *Interval
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpQueryProfileInformation(
|
|
IN HAL_QUERY_INFORMATION_CLASS InformationClass,
|
|
IN ULONG BufferSize,
|
|
OUT PVOID Buffer,
|
|
OUT PULONG ReturnedLength
|
|
);
|
|
|
|
#endif
|
|
|
|
HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpProfileInterrupt);
|
|
|
|
VOID
|
|
HalpInitializeClock(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpInitializeStallExecution(
|
|
IN CCHAR ProcessorNumber
|
|
);
|
|
|
|
VOID
|
|
HalpRemoveFences (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpInitializePICs(
|
|
BOOLEAN EnableInterrupts
|
|
);
|
|
|
|
VOID
|
|
HalpIrq13Handler (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpFlushTLB (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSerialize (
|
|
VOID
|
|
);
|
|
|
|
PVOID
|
|
HalpMapPhysicalMemory64(
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN ULONG NumberPages
|
|
);
|
|
|
|
PVOID
|
|
HalpMapPhysicalMemoryWriteThrough64(
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN ULONG NumberPages
|
|
);
|
|
|
|
ULONG
|
|
HalpAllocPhysicalMemory(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock,
|
|
IN ULONG MaxPhysicalAddress,
|
|
IN ULONG NoPages,
|
|
IN BOOLEAN bAlignOn64k
|
|
);
|
|
|
|
VOID
|
|
HalpUnmapVirtualAddress(
|
|
IN PVOID VirtualAddress,
|
|
IN ULONG NumberPages
|
|
);
|
|
|
|
PVOID
|
|
HalpRemapVirtualAddress64 (
|
|
IN PVOID VirtualAddress,
|
|
IN PHYSICAL_ADDRESS PhysicalAddress,
|
|
IN BOOLEAN WriteThrough
|
|
);
|
|
|
|
PHYSICAL_ADDRESS
|
|
__inline
|
|
HalpPtrToPhysicalAddress(
|
|
IN PVOID Address
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine converts a physical address expressed as a PVOID into
|
|
a physical address expresses as PHYSICAL_ADDRESS.
|
|
|
|
Arguments:
|
|
|
|
Address - PVOID representation of the physical address.
|
|
|
|
Return Value:
|
|
|
|
PHYSICAL_ADDRESS representation of the physical address.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
|
|
physicalAddress.QuadPart = (ULONG_PTR)Address;
|
|
|
|
return physicalAddress;
|
|
}
|
|
|
|
#if defined(_HALPAE_)
|
|
|
|
//
|
|
// This hal is to be PAE compatible. Therefore, physical addresses must
|
|
// be treated as 64-bit entitites instead of PVOID.
|
|
//
|
|
|
|
#define _PHYS64_
|
|
#endif
|
|
|
|
#if defined(_PHYS64_)
|
|
|
|
//
|
|
// HALs with _PHYS64_ defined pass physical addresses as PHYSICAL_ADDRESS,
|
|
// so call the 64-bit versions of these routines directly.
|
|
//
|
|
|
|
#define HalpMapPhysicalMemory HalpMapPhysicalMemory64
|
|
#define HalpMapPhysicalMemoryWriteThrough HalpMapPhysicalMemoryWriteThrough64
|
|
#define HalpRemapVirtualAddress HalpRemapVirtualAddress64
|
|
|
|
#define HalpMapPhysicalRange(_addr_,_len_) \
|
|
HalpMapPhysicalMemory((_addr_), \
|
|
HalpRangePages((_addr_).QuadPart,(_len_)))
|
|
|
|
#define HalpUnMapPhysicalRange(_addr_,_len_) \
|
|
HalpUnmapVirtualAddress((_addr_), \
|
|
HalpRangePages((ULONG_PTR)(_addr_),(_len_)))
|
|
|
|
#else
|
|
|
|
//
|
|
// HALs without _PHYS64_ defined pass physical addresses as PVOIDs. Convert
|
|
// such parameters to PHYSICAL_ADDRESS before passing to the 64-bit routines.
|
|
//
|
|
|
|
PVOID
|
|
__inline
|
|
HalpMapPhysicalMemory(
|
|
IN PVOID PhysicalAddress,
|
|
IN ULONG NumberPages
|
|
)
|
|
{
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
|
|
physicalAddress = HalpPtrToPhysicalAddress( PhysicalAddress );
|
|
return HalpMapPhysicalMemory64( physicalAddress, NumberPages );
|
|
}
|
|
|
|
PVOID
|
|
__inline
|
|
HalpMapPhysicalMemoryWriteThrough(
|
|
IN PVOID PhysicalAddress,
|
|
IN ULONG NumberPages
|
|
)
|
|
{
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
|
|
physicalAddress = HalpPtrToPhysicalAddress( PhysicalAddress );
|
|
return HalpMapPhysicalMemoryWriteThrough64( physicalAddress, NumberPages );
|
|
}
|
|
|
|
PVOID
|
|
__inline
|
|
HalpRemapVirtualAddress(
|
|
IN PVOID VirtualAddress,
|
|
IN PVOID PhysicalAddress,
|
|
IN BOOLEAN WriteThrough
|
|
)
|
|
{
|
|
PHYSICAL_ADDRESS physicalAddress;
|
|
|
|
physicalAddress = HalpPtrToPhysicalAddress( PhysicalAddress );
|
|
return HalpRemapVirtualAddress64( VirtualAddress,
|
|
physicalAddress,
|
|
WriteThrough );
|
|
}
|
|
|
|
#define HalpMapPhysicalRangeWriteThrough(_addr_,_len_) \
|
|
HalpMapPhysicalMemoryWriteThrough((_addr_), \
|
|
HalpRangePages((ULONG_PTR)(_addr_),(_len_)))
|
|
|
|
#define HalpMapPhysicalRange(_addr_,_len_) \
|
|
HalpMapPhysicalMemory((_addr_), \
|
|
HalpRangePages((ULONG_PTR)(_addr_),(_len_)))
|
|
|
|
#define HalpUnMapPhysicalRange(_addr_,_len_) \
|
|
HalpUnmapVirtualAddress((_addr_), \
|
|
HalpRangePages((ULONG_PTR)(_addr_),(_len_)))
|
|
|
|
|
|
#endif
|
|
|
|
ULONG
|
|
__inline
|
|
HalpRangePages(
|
|
IN ULONGLONG Address,
|
|
IN ULONG Length
|
|
)
|
|
{
|
|
ULONG startPage;
|
|
ULONG endPage;
|
|
|
|
startPage = (ULONG)(Address / PAGE_SIZE);
|
|
endPage = (ULONG)((Address + Length + PAGE_SIZE - 1) / PAGE_SIZE);
|
|
|
|
return endPage - startPage;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
HalpBiosDisplayReset(
|
|
IN VOID
|
|
);
|
|
|
|
HAL_DISPLAY_BIOS_INFORMATION
|
|
HalpGetDisplayBiosInformation (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpInitializeCmos (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpReadCmosTime (
|
|
PTIME_FIELDS TimeFields
|
|
);
|
|
|
|
VOID
|
|
HalpWriteCmosTime (
|
|
PTIME_FIELDS TimeFields
|
|
);
|
|
|
|
VOID
|
|
HalpAcquireCmosSpinLock (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpReleaseCmosSpinLock (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpResetAllProcessors (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpWriteResetCommand (
|
|
VOID
|
|
);
|
|
|
|
|
|
VOID
|
|
HalpCpuID (
|
|
ULONG InEax,
|
|
PULONG OutEax,
|
|
PULONG OutEbx,
|
|
PULONG OutEcx,
|
|
PULONG OutEdx
|
|
);
|
|
|
|
#if defined(_WIN64)
|
|
#define HalpYieldProcessor()
|
|
|
|
#else
|
|
|
|
VOID
|
|
HalpYieldProcessor (
|
|
VOID
|
|
);
|
|
#endif
|
|
|
|
ULONGLONG
|
|
FASTCALL
|
|
RDMSR (
|
|
IN ULONG MsrAddress
|
|
);
|
|
|
|
VOID
|
|
WRMSR (
|
|
IN ULONG MsrAddress,
|
|
IN ULONGLONG MsrValue
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
HalpEnableInterruptHandler (
|
|
IN UCHAR ReportFlags,
|
|
IN ULONG BusInterruptVector,
|
|
IN ULONG SystemInterruptVector,
|
|
IN KIRQL SystemIrql,
|
|
IN PHAL_INTERRUPT_SERVICE_ROUTINE HalInterruptServiceRoutine,
|
|
IN KINTERRUPT_MODE InterruptMode
|
|
);
|
|
|
|
VOID
|
|
HalpRegisterVector (
|
|
IN UCHAR ReportFlags,
|
|
IN ULONG BusInterruptVector,
|
|
IN ULONG SystemInterruptVector,
|
|
IN KIRQL SystemIrql
|
|
);
|
|
|
|
VOID
|
|
HalpReportResourceUsage (
|
|
IN PUNICODE_STRING HalName,
|
|
IN INTERFACE_TYPE DeviceInterfaceToUse
|
|
);
|
|
|
|
VOID
|
|
HalpYearIs(
|
|
IN ULONG Year
|
|
);
|
|
|
|
VOID
|
|
HalpRecordEisaInterruptVectors(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpMcaCurrentProcessorSetConfig(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpGetNextProcessorApicId(
|
|
IN ULONG ProcessorNumber,
|
|
IN OUT UCHAR *ApicId
|
|
);
|
|
|
|
VOID
|
|
FASTCALL
|
|
HalpIoDelay (
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Defines for HalpFeatureBits
|
|
//
|
|
|
|
#define HAL_PERF_EVENTS 0x00000001
|
|
#define HAL_NO_SPECULATION 0x00000002
|
|
#define HAL_MCA_PRESENT 0x00000004 // Intel MCA Available
|
|
#define HAL_MCE_PRESENT 0x00000008 // ONLY Pentium style MCE available
|
|
#define HAL_CR4_PRESENT 0x00000010
|
|
#define HAL_WNI_PRESENT 0x00000020
|
|
#define HAL_NX_PRESENT 0x00000040 // from extended processor features
|
|
|
|
extern ULONG HalpFeatureBits;
|
|
|
|
extern USHORT HalpPciIrqMask;
|
|
|
|
//
|
|
// Defines for Processor Features returned from CPUID instruction
|
|
//
|
|
|
|
#define CPUID_MCA_MASK 0x4000
|
|
#define CPUID_MCE_MASK 0x0080
|
|
#define CPUID_VME_MASK 0x0002
|
|
#define CPUID_WNI_MASK 0x04000000
|
|
#define CPUID_NX_MASK 0x00100000
|
|
|
|
|
|
NTSTATUS
|
|
HalpGetMceInformation(
|
|
IN PHAL_ERROR_INFO ErrorInfo,
|
|
OUT PULONG ErrorInfoLength
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpMceRegisterKernelDriver(
|
|
IN PKERNEL_ERROR_HANDLER_INFO KernelErrorHandler,
|
|
IN ULONG InfoSize
|
|
);
|
|
|
|
//
|
|
// Token passed in by WMI to distinguish it from the MCA logging driver.
|
|
//
|
|
#define HALP_KERNEL_TOKEN 0x59364117
|
|
|
|
NTSTATUS
|
|
HalpGetMcaLog(
|
|
OUT PMCA_EXCEPTION Exception,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG ReturnedLength
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpMcaRegisterDriver(
|
|
IN PMCA_DRIVER_INFO pMcaDriverInfo // Info about registering driver
|
|
);
|
|
|
|
VOID
|
|
HalpMcaInit(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Disable the Local APIC on UP (PIC 8259) PentiumPro systems to work around
|
|
// spurious interrupt errata.
|
|
//
|
|
#define APIC_BASE_MSR 0x1B
|
|
#define APIC_ENABLED 0x0000000000000800
|
|
|
|
//
|
|
// PnP stuff
|
|
//
|
|
|
|
#define HAL_BUS_INTERFACE_STD_VERSION 1
|
|
#define HAL_IRQ_TRANSLATOR_VERSION 0
|
|
#define HAL_MEMIO_TRANSLATOR_VERSION 1
|
|
|
|
VOID
|
|
HalTranslatorReference(
|
|
PVOID Context
|
|
);
|
|
|
|
VOID
|
|
HalTranslatorDereference(
|
|
PVOID Context
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResources(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourcesRoot(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourceRequirementsRoot(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourceRequirementsIsa(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourcesIsa(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpTransMemIoResourceRequirement(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpTransMemIoResource(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateRequirementsPciBridge(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalIrqTranslateResourcesPciBridge(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpIrqTranslateRequirementsPci(
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpIrqTranslateResourcesPci(
|
|
IN PVOID Context,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|
IN ULONG AlternativesCount, OPTIONAL
|
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpTranslateSystemBusAddress(
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN PHYSICAL_ADDRESS BusAddress,
|
|
IN OUT PULONG AddressSpace,
|
|
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
|
);
|
|
|
|
ULONG
|
|
HalpGetSystemInterruptVector(
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN ULONG InterruptLevel,
|
|
IN ULONG InterruptVector,
|
|
OUT PKIRQL Irql,
|
|
OUT PKAFFINITY Affinity
|
|
);
|
|
|
|
ULONG
|
|
HalpGetIsaIrqState(
|
|
ULONG Vector
|
|
);
|
|
|
|
extern INT_ROUTE_INTERFACE_STANDARD PciIrqRoutingInterface;
|
|
|
|
#if defined(_WIN64)
|
|
#define MM_HAL_RESERVED ((PVOID)HAL_VA_START)
|
|
#else
|
|
#define MM_HAL_RESERVED ((PVOID)0xffc00000)
|
|
#endif
|
|
|
|
#if defined(_HALPAE_)
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
//
|
|
// For the purposes of the AMD64 HAL, "PAE" mode is always enabled, therefore
|
|
// no run-time PAE checks are necessary.
|
|
//
|
|
|
|
#define HalPaeEnabled() TRUE
|
|
|
|
#else // _AMD64_
|
|
|
|
//
|
|
// This hal supports PAE mode. Therefore checks need to be made at run-time
|
|
// to determine whether PAE is enabled or not.
|
|
//
|
|
|
|
BOOLEAN
|
|
__inline
|
|
HalPaeEnabled(
|
|
VOID
|
|
)
|
|
{
|
|
return SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] != FALSE;
|
|
}
|
|
|
|
#endif // _AMD64_
|
|
|
|
#else
|
|
|
|
//
|
|
// This hal does not support PAE mode. Therefore no run-time PAE checks
|
|
// are necessary.
|
|
//
|
|
|
|
#define HalPaeEnabled() FALSE
|
|
|
|
#endif
|
|
|
|
//
|
|
// The following inline functions and macros are used so that PHARDWARE_PTE
|
|
// can be used as a pointer to a four-byte legacy PTE or an eight-byte
|
|
// PAE PTE.
|
|
//
|
|
// With the exception of the PageFrameNumber field, all fields in these two
|
|
// different PTE formats are identical. Therefore access to these fields
|
|
// can be made directly.
|
|
//
|
|
// However, code in a PAE-enabled HAL may not access the PageFrameNumber
|
|
// of a PTE directly, nor may it make any assumptions about the size of a
|
|
// PTE or the number of address bits decoded by the page directory pointer
|
|
// table, the page directory or the page table. Instead, the following
|
|
// inline functions should be used.
|
|
//
|
|
|
|
ULONG
|
|
__inline
|
|
HalPteSize(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the size, in bytes, of a PTE.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The size, in bytes, of a PTE.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (HalPaeEnabled() != FALSE) {
|
|
return sizeof(HARDWARE_PTE_X86PAE);
|
|
} else {
|
|
return sizeof(HARDWARE_PTE_X86);
|
|
}
|
|
}
|
|
|
|
PHARDWARE_PTE
|
|
__inline
|
|
HalpIndexPteArray(
|
|
IN PHARDWARE_PTE BasePte,
|
|
IN ULONG Index
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine returns the address of a PTE within an array of PTEs.
|
|
|
|
Arguments:
|
|
|
|
BasePte - Pointer to the PTE array.
|
|
|
|
Index - Index within the PTE array.
|
|
|
|
Return Value:
|
|
|
|
Address of BasePte[ Index ]
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_PTE pointerPte;
|
|
|
|
pointerPte = (PHARDWARE_PTE)((ULONG_PTR)BasePte + Index * HalPteSize());
|
|
return pointerPte;
|
|
}
|
|
|
|
VOID
|
|
__inline
|
|
HalpAdvancePte(
|
|
IN OUT PHARDWARE_PTE *PointerPte,
|
|
IN ULONG Count
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine advances the value of a PTE pointer by the specified number
|
|
of PTEs.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE pointer to increment.
|
|
|
|
Count - Number of PTEs to advance the PTE pointer.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
*PointerPte = HalpIndexPteArray( *PointerPte, Count );
|
|
}
|
|
|
|
VOID
|
|
__inline
|
|
HalpIncrementPte(
|
|
IN PHARDWARE_PTE *PointerPte
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine increments the value of a PTE pointer by one PTE.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE pointer to increment.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
HalpAdvancePte( PointerPte, 1 );
|
|
}
|
|
|
|
VOID
|
|
__inline
|
|
HalpSetPageFrameNumber(
|
|
IN OUT PHARDWARE_PTE PointerPte,
|
|
IN ULONGLONG PageFrameNumber
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets the PageFrameNumber within a PTE.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE to modify.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_PTE_X86PAE pointerPtePae;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
|
|
pointerPtePae = (PHARDWARE_PTE_X86PAE)PointerPte;
|
|
pointerPtePae->PageFrameNumber = PageFrameNumber;
|
|
|
|
} else {
|
|
|
|
PointerPte->PageFrameNumber = (ULONG_PTR)PageFrameNumber;
|
|
}
|
|
}
|
|
|
|
ULONGLONG
|
|
__inline
|
|
HalpGetPageFrameNumber(
|
|
IN PHARDWARE_PTE PointerPte
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine retrieves PageFrameNumber from within a PTE.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE to read.
|
|
|
|
Return Value:
|
|
|
|
The page frame number within the PTE.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_PTE_X86PAE pointerPtePae;
|
|
ULONGLONG pageFrameNumber;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
|
|
pointerPtePae = (PHARDWARE_PTE_X86PAE)PointerPte;
|
|
pageFrameNumber = pointerPtePae->PageFrameNumber;
|
|
|
|
} else {
|
|
|
|
pageFrameNumber = PointerPte->PageFrameNumber;
|
|
}
|
|
|
|
return pageFrameNumber;
|
|
}
|
|
|
|
VOID
|
|
__inline
|
|
HalpCopyPageFrameNumber(
|
|
OUT PHARDWARE_PTE DestinationPte,
|
|
IN PHARDWARE_PTE SourcePte
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine copies the page frame number from one PTE to another PTE.
|
|
|
|
Arguments:
|
|
|
|
DestinationPte - Pointer to the PTE in which the new page frame number
|
|
will be stored.
|
|
|
|
PointerPte - Pointer to the PTE from which the page frame number will be
|
|
read.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONGLONG pageFrameNumber;
|
|
|
|
pageFrameNumber = HalpGetPageFrameNumber( SourcePte );
|
|
HalpSetPageFrameNumber( DestinationPte, pageFrameNumber );
|
|
}
|
|
|
|
BOOLEAN
|
|
__inline
|
|
HalpIsPteFree(
|
|
IN PHARDWARE_PTE PointerPte
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines whether a PTE is free or not. A free PTE is defined
|
|
here as one containing all zeros.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE for which the detmination is desired.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The PTE is free.
|
|
|
|
FALSE - The PTE is not free.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONGLONG pteContents;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
pteContents = *(PULONGLONG)PointerPte;
|
|
} else {
|
|
pteContents = *(PULONG)PointerPte;
|
|
}
|
|
|
|
if (pteContents == 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
__inline
|
|
HalpFreePte(
|
|
IN PHARDWARE_PTE PointerPte
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine sets a PTE to the free state. It does this by setting the
|
|
entire PTE to zero.
|
|
|
|
Arguments:
|
|
|
|
PointerPte - Pointer to the PTE to free.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
if (HalPaeEnabled() != FALSE) {
|
|
|
|
*((PULONGLONG)PointerPte) = 0;
|
|
|
|
} else {
|
|
|
|
*((PULONG)PointerPte) = 0;
|
|
}
|
|
}
|
|
|
|
|
|
PHARDWARE_PTE
|
|
__inline
|
|
MiGetPteAddress(
|
|
IN PVOID Va
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a virtual address, this routine returns a pointer to the mapping PTE.
|
|
|
|
Arguments:
|
|
|
|
Va - Virtual Address for which a PTE pointer is desired.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_PTE pointerPte;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
pointerPte = (PHARDWARE_PTE)MiGetPteAddressPae( Va );
|
|
} else {
|
|
pointerPte = MiGetPteAddressX86( Va );
|
|
}
|
|
|
|
return pointerPte;
|
|
}
|
|
|
|
PHARDWARE_PTE
|
|
__inline
|
|
MiGetPdeAddress(
|
|
IN PVOID Va
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a virtual address, this routine returns a pointer to the mapping PDE.
|
|
|
|
Arguments:
|
|
|
|
Va - Virtual Address for which a PDE pointer is desired.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PHARDWARE_PTE pointerPte;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
pointerPte = (PHARDWARE_PTE)MiGetPdeAddressPae( Va );
|
|
} else {
|
|
pointerPte = MiGetPdeAddressX86( Va );
|
|
}
|
|
|
|
return pointerPte;
|
|
}
|
|
|
|
ULONG
|
|
__inline
|
|
MiGetPteIndex(
|
|
IN PVOID Va
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a virtual address, this routine returns the index of the mapping
|
|
PTE within its page table.
|
|
|
|
Arguments:
|
|
|
|
Va - Virtual Address for which the PTE index is desired.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG_PTR index;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
index = MiGetPteIndexPae( Va );
|
|
} else {
|
|
index = MiGetPteIndexX86( Va );
|
|
}
|
|
|
|
return (ULONG)index;
|
|
}
|
|
|
|
ULONG
|
|
__inline
|
|
MiGetPdiShift(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns the number of bits that an address should be shifted right in order
|
|
to right-justify the portion of the address mapped by a page directory
|
|
entry.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The number of bits to shift right.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG shift;
|
|
|
|
if (HalPaeEnabled() != FALSE) {
|
|
shift = PDI_SHIFT_X86PAE;
|
|
} else {
|
|
shift = PDI_SHIFT_X86;
|
|
}
|
|
|
|
return shift;
|
|
}
|
|
|
|
//
|
|
// ACPI specific stuff
|
|
//
|
|
|
|
NTSTATUS
|
|
HalpSetupAcpiPhase0(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpAcpiFindRsdtPhase0(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
VOID
|
|
HaliHaltSystem(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpCheckPowerButton(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRegisterHibernate(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FASTCALL
|
|
HalProcessorThrottle (
|
|
IN UCHAR Throttle
|
|
);
|
|
|
|
VOID
|
|
HalpSaveInterruptControllerState(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSaveDmaControllerState(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSaveTimerState(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRestoreInterruptControllerState(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSetInterruptControllerWakeupState(
|
|
ULONG Context
|
|
);
|
|
|
|
VOID
|
|
HalpRestorePicEdgeLevelRegister(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSetAcpiEdgeLevelRegister(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRestoreDmaControllerState(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRestoreTimerState(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
HalacpiGetInterruptTranslator(
|
|
IN INTERFACE_TYPE ParentInterfaceType,
|
|
IN ULONG ParentBusNumber,
|
|
IN INTERFACE_TYPE BridgeInterfaceType,
|
|
IN USHORT Size,
|
|
IN USHORT Version,
|
|
OUT PTRANSLATOR_INTERFACE Translator,
|
|
OUT PULONG BridgeBusNumber
|
|
);
|
|
|
|
VOID
|
|
HalpInitNonBusHandler (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpMapNvsArea(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpPreserveNvsArea(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRestoreNvsArea(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpFreeNvsBuffers(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpPowerStateCallback(
|
|
IN PVOID CallbackContext,
|
|
IN PVOID Argument1,
|
|
IN PVOID Argument2
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpBuildResumeStructures(
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpFreeResumeStructures(
|
|
VOID
|
|
);
|
|
|
|
typedef struct {
|
|
UCHAR MasterMask;
|
|
UCHAR SlaveMask;
|
|
UCHAR MasterEdgeLevelControl;
|
|
UCHAR SlaveEdgeLevelControl;
|
|
} PIC_CONTEXT, *PPIC_CONTEXT;
|
|
|
|
#define EISA_DMA_CHANNELS 8
|
|
|
|
typedef struct {
|
|
UCHAR Dma1ExtendedModePort;
|
|
UCHAR Dma2ExtendedModePort;
|
|
DMA1_CONTROL Dma1Control;
|
|
DMA2_CONTROL Dma2Control;
|
|
} DMA_CONTEXT, *PDMA_CONTEXT;
|
|
|
|
typedef struct {
|
|
UCHAR nothing;
|
|
} TIMER_CONTEXT, *PTIMER_CONTEXT;
|
|
|
|
typedef struct {
|
|
PIC_CONTEXT PicState;
|
|
DMA_CONTEXT DmaState;
|
|
} MOTHERBOARD_CONTEXT, *PMOTHERBOARD_CONTEXT;
|
|
|
|
typedef struct {
|
|
UCHAR ChannelMode;
|
|
UCHAR ChannelExtendedMode;
|
|
UCHAR ChannelMask;
|
|
BOOLEAN ChannelProgrammed; // Adapter created, mode set
|
|
#if DBG
|
|
BOOLEAN ChannelBusy;
|
|
#endif
|
|
} DMA_CHANNEL_CONTEXT;
|
|
|
|
extern MOTHERBOARD_CONTEXT HalpMotherboardState;
|
|
extern PVOID HalpSleepPageLock;
|
|
extern PVOID HalpSleepPage16Lock;
|
|
extern DMA_CHANNEL_CONTEXT HalpDmaChannelState[];
|
|
|
|
ULONG
|
|
HalpcGetCmosDataByType(
|
|
IN CMOS_DEVICE_TYPE CmosType,
|
|
IN ULONG SourceAddress,
|
|
IN PUCHAR DataBuffer,
|
|
IN ULONG ByteCount
|
|
);
|
|
|
|
ULONG
|
|
HalpcSetCmosDataByType(
|
|
IN CMOS_DEVICE_TYPE CmosType,
|
|
IN ULONG SourceAddress,
|
|
IN PUCHAR DataBuffer,
|
|
IN ULONG ByteCount
|
|
);
|
|
|
|
|
|
NTSTATUS
|
|
HalpOpenRegistryKey(
|
|
OUT PHANDLE Handle,
|
|
IN HANDLE BaseHandle OPTIONAL,
|
|
IN PUNICODE_STRING KeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
IN BOOLEAN Create
|
|
);
|
|
|
|
#ifdef WANT_IRQ_ROUTING
|
|
|
|
NTSTATUS
|
|
HalpInitIrqArbiter (
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpFillInIrqArbiter (
|
|
IN PDEVICE_OBJECT HalFdo,
|
|
IN LPCGUID InterfaceType,
|
|
IN USHORT Version,
|
|
IN PVOID InterfaceSpecificData,
|
|
IN ULONG InterfaceBufferSize,
|
|
IN OUT PINTERFACE Interface,
|
|
IN OUT PULONG Length
|
|
);
|
|
|
|
VOID
|
|
HalpIrqArbiterInterfaceReference(
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
HalpIrqArbiterInterfaceDereference(
|
|
IN PVOID Context
|
|
);
|
|
|
|
#endif
|
|
|
|
//
|
|
// PnPBIOS specific stuff
|
|
//
|
|
VOID
|
|
HalpMarkChipsetDecode(
|
|
BOOLEAN FullDecodeChipset
|
|
);
|
|
|
|
ULONG
|
|
HalpPhase0SetPciDataByOffset (
|
|
ULONG BusNumber,
|
|
ULONG SlotNumber,
|
|
PVOID Buffer,
|
|
ULONG Offset,
|
|
ULONG Length
|
|
);
|
|
|
|
ULONG
|
|
HalpPhase0GetPciDataByOffset (
|
|
ULONG BusNumber,
|
|
ULONG SlotNumber,
|
|
PVOID Buffer,
|
|
ULONG Offset,
|
|
ULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpSetupPciDeviceForDebugging(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock, OPTIONAL
|
|
IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpReleasePciDeviceForDebugging(
|
|
IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice
|
|
);
|
|
|
|
VOID
|
|
HalpRegisterKdSupportFunctions(
|
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|
);
|
|
|
|
VOID
|
|
HalpRegisterPciDebuggingDeviceInfo(
|
|
VOID
|
|
);
|
|
|
|
#endif // _HALP_H_
|