|
|
/*++ 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 "hal.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))
VOID RtlMoveMemory ( PVOID Destination, CONST VOID *Source, ULONG Length );
// 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 PROCESSOR_FENCE HalpProcessorFence()
//
// On AMD64, HalpGetProcessorFlags() must reside in it's own asm
// function. It cannot be done inline because there is no intrinsic, and
// there is no intrinsic because getting the value of EFLAGS involves stack
// manipulation outside of the prolog, which is not permitted.
//
ULONG HalpGetProcessorFlags( VOID );
//
// 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 );
#if !defined(PICACPI)
//
// 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;
#endif
#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
#endif
__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 );
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[];
//
// 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) >> 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)) >> 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)) >> 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 );
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 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; }
VOID 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 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
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
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)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_
|