863 lines
20 KiB
PHP
863 lines
20 KiB
PHP
;/*++
|
|
;
|
|
;Module Name:
|
|
;
|
|
; ntapic.inc
|
|
;
|
|
;Abstract:
|
|
;
|
|
; This header file is intended to be included by any HAL
|
|
; that uses APICs.
|
|
;
|
|
;Author:
|
|
;
|
|
; Ron Mosgrove (Intel)
|
|
;
|
|
;Environment:
|
|
;
|
|
; Kernel mode only.
|
|
;
|
|
;Revision History:
|
|
;
|
|
; Separated out from pcmp_nt.inc -- 6-2-98 (jakeo)
|
|
;
|
|
;
|
|
if 0 ; Begin C only code */
|
|
|
|
#if !defined(_NTAPIC_INC_)
|
|
|
|
#define _NTAPIC_INC_ 1
|
|
|
|
//#define DEBUGGING 1
|
|
|
|
#ifndef DBGMSG
|
|
#ifdef DEBUGGING
|
|
extern CHAR Cbuf[];
|
|
#define DBGMSG(x) DbgPrint(x);
|
|
#else
|
|
#define DBGMSG(x)
|
|
#endif
|
|
#endif
|
|
|
|
//
|
|
// To allow the user to specify command line options to the HAL.
|
|
//
|
|
#define USER_SETABLE_OPTIONS
|
|
// #define BUILD_FOR_OLD_IDW
|
|
|
|
//
|
|
// Default BusType
|
|
//
|
|
|
|
#ifndef MCA
|
|
#define DEFAULT_PC_BUS Eisa
|
|
#else
|
|
#define DEFAULT_PC_BUS MicroChannel
|
|
#endif
|
|
|
|
|
|
//
|
|
// Well known virtual address of local processor apic
|
|
//
|
|
|
|
#if defined(_WIN64)
|
|
#define LOCALAPIC 0xfffffffffffe0000
|
|
#else
|
|
#define LOCALAPIC 0xfffe0000
|
|
#endif
|
|
|
|
#define pLocalApic ((ULONG volatile *) LOCALAPIC)
|
|
#define LOCAL_APIC(x) (*((ULONG volatile *)&pLocalApic[(x)/sizeof(ULONG)]))
|
|
|
|
//
|
|
// Additional CpuFlags Bits used by NT in PC+MP Table
|
|
//
|
|
#define CPU_NT_STARTED 0x40 // CPU Has Been Started
|
|
#define CPU_NT_RUNNING 0x80 // CPU is Runing NT
|
|
#define MAX_PROCESSORS 32
|
|
#define MAX_CLUSTERS 15
|
|
#define MAX_IOAPICS 64
|
|
|
|
//
|
|
// This OS specific structure holds useful MP information. This information
|
|
// is obtained from the PC+MP table and stored here for convenience.
|
|
//
|
|
typedef struct HalpMpInfo {
|
|
ULONG ApicVersion; // 82489Dx or Not
|
|
ULONG ProcessorCount; // Number of Enabled Processors
|
|
ULONG NtProcessors; // Number of Running Processors
|
|
ULONG BusCount; // Number of buses in system
|
|
ULONG IOApicCount; // Number of Io Apics in system
|
|
ULONG IntiCount; // Number of Io Apic interrupt input entries
|
|
ULONG LintiCount; // Number of Local Apic interrupt input entries
|
|
ULONG IMCRPresent; // Indicates if the IMCR is present
|
|
ULONG LocalApicBase; // Base of local APIC
|
|
PULONG IoApicBase[MAX_IOAPICS]; // The virtual addresses of the IoApics
|
|
ULONG IoApicPhys[MAX_IOAPICS]; // The physical addresses of the IoApics
|
|
#ifdef ACPI_HAL
|
|
ULONG IoApicIntiBase[MAX_IOAPICS]; // The 'number' of the first INTI -- only used for ACPI
|
|
#else
|
|
PPCMPPROCESSOR ProcessorEntryPtr; // Ptr to 1st PC+MP processor entry
|
|
PPCMPBUS BusEntryPtr; // Ptr to 1st PC+MP bus entry
|
|
PPCMPIOAPIC IoApicEntryPtr; // Ptr to 1st PC+MP IoApic entry
|
|
PPCMPINTI IntiEntryPtr; // Ptr to 1st PC+MP Inti entry
|
|
PPCMPLINTI LintiEntryPtr; // Ptr to 1st PC+MP Linti entry
|
|
PMPS_EXTENTRY ExtensionTable; // Ptr to 1st extension table entry
|
|
PMPS_EXTENTRY EndOfExtensionTable;
|
|
#endif
|
|
} MP_INFO, *PMP_INFO;
|
|
|
|
typedef struct {
|
|
PUCHAR PcMpType;
|
|
BOOLEAN PhysicalInstance;
|
|
UCHAR Level;
|
|
INTERFACE_TYPE NtType;
|
|
PINSTALL_BUS_HANDLER NewInstance;
|
|
BUS_DATA_TYPE NtConfig;
|
|
ULONG BusExtensionSize;
|
|
} PCMPBUSTRANS, *PPCMPBUSTRANS;
|
|
|
|
#define CFG_MUST_BE 0x02
|
|
#define CFG_ERROR 0x80
|
|
|
|
#define CFG_HIGH 0x01
|
|
#define CFG_LOW 0x00
|
|
|
|
#define CFG_EDGE 0x00
|
|
#define CFG_LEVEL 0x01
|
|
#define CFG_MB_EDGE (CFG_MUST_BE | CFG_EDGE)
|
|
#define CFG_MB_LEVEL (CFG_MUST_BE | CFG_LEVEL)
|
|
#define CFG_ERR_EDGE (CFG_ERROR | CFG_EDGE)
|
|
#define CFG_ERR_LEVEL (CFG_ERROR | CFG_LEVEL)
|
|
#define CFG_ERR_MB_EDGE (CFG_ERROR | CFG_MUST_BE | CFG_EDGE)
|
|
#define CFG_ERR_MB_LEVEL (CFG_ERROR | CFG_MUST_BE | CFG_LEVEL)
|
|
|
|
#define CFG_TYPE(a) (a & 1)
|
|
|
|
typedef union _INTERRUPT_DEST {
|
|
union _Cluster {
|
|
struct _Hw {
|
|
UCHAR DestId:4;
|
|
UCHAR ClusterId:4;
|
|
} Hw;
|
|
UCHAR AsUchar;
|
|
} Cluster;
|
|
UCHAR LogicalId;
|
|
} INTERRUPT_DEST, *PINTERRUPT_DEST;
|
|
|
|
|
|
#if defined(_X86_)
|
|
|
|
//
|
|
// The kernel leaves some space (64 byte) of the PCR for the HAL to use
|
|
// as it needs. Currently this space is used for some efficiency in
|
|
// some of the MP specific code and is highly implementation-dependent.
|
|
//
|
|
typedef struct _HALPCR {
|
|
UCHAR PcrNumber; // Processor's number
|
|
UCHAR ShortDpc; // Short circut dpc interrupt
|
|
UCHAR DpcPending; // Dpc interrupt pending
|
|
UCHAR Reserved; // force dword alignment
|
|
|
|
//
|
|
// The next three dwords are used to manipulate the APIC counter
|
|
//
|
|
ULONG ApicClockFreqHz; // Counter Freq in Hertz
|
|
ULONG ApicClockFreqKhz; // Counter Freq in Khertz (rounded)
|
|
ULONG ProfileCountDown; // Current Countdown Interval
|
|
|
|
ULONGLONG TSCHz; // Time stamp counter hertz
|
|
|
|
ULONG PerfCounterLow; // PerProcessor Counter
|
|
ULONG PerfCounterHigh;
|
|
} HALPCR, *PHALPCR;
|
|
|
|
#elif defined(_AMD64_)
|
|
|
|
typedef struct _HALPCR {
|
|
ULONG64 PerfCounter;
|
|
ULONG64 TSCHz; // time stamp counter frequency
|
|
ULONG ProfileCountDown; // current profile countdown interval
|
|
ULONG ApicClockFreqHz; // counter frequency
|
|
ULONG StallScaleFactor;
|
|
ULONG ApicId; // APIC Id assigned this processor
|
|
} HALPCR, *PHALPCR;
|
|
|
|
C_ASSERT(sizeof(HALPCR) <= RTL_FIELD_SIZE(KPCR,HalReserved));
|
|
|
|
#else
|
|
|
|
#error "Platform not supported"
|
|
|
|
#endif
|
|
|
|
//
|
|
// The kernel leaves some space (64 byte) of the PCRB for the HAL to use
|
|
// as it needs. Currently this space is used for some efficiency in
|
|
// some of the MP specific code and is highly implementation-dependent.
|
|
//
|
|
|
|
typedef struct {
|
|
UCHAR PCMPApicID;
|
|
UCHAR na[3];
|
|
} HALPRCB, *PHALPRCB;
|
|
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
#define ZERO_VECTOR 0x00 // IRQL 0 placeholder
|
|
#define APC_VECTOR 0x1f // IRQL 1 APC
|
|
#define DPC_VECTOR 0x2f // IRQL 2 DPC
|
|
|
|
#define APIC_SPURIOUS_VECTOR 0x3f // IRQL 3 Spurious handler
|
|
|
|
#define APIC_REBOOT_VECTOR 0x50 // IRQL 5 Vector used to reboot
|
|
#define APIC_GENERIC_VECTOR 0xC1 // IRQL 12 broadcast function call
|
|
#define APIC_CLOCK_VECTOR 0xD1 // IRQL 13 APIC INTI0 - CLOCK2_LEVEL
|
|
#define APIC_SYNCH_VECTOR 0xD1 // IRQL 13 IPI_LEVEL-1
|
|
#define APIC_IPI_VECTOR 0xE1 // IRQL 14 APIC IPI
|
|
|
|
#define APIC_FAULT_VECTOR 0xE3 // IRQL 14
|
|
#define POWERFAIL_VECTOR 0xEF // IRQL 14 reserved. not used
|
|
|
|
#define APIC_PROFILE_VECTOR 0xFD // IRQL 15
|
|
#define APIC_PERF_VECTOR 0xFE // IRQL 15
|
|
#define NMI_VECTOR 0xFF // IRQL 15
|
|
|
|
//
|
|
// The APIC hard-wires the four low-order bits of the spurious interrupt
|
|
// vector to 1.
|
|
//
|
|
|
|
C_ASSERT((APIC_SPURIOUS_VECTOR & 0x0f) == 0x0f);
|
|
|
|
|
|
#else
|
|
|
|
//
|
|
// interrupt vector definitions for C
|
|
//
|
|
|
|
#define ZERO_VECTOR 0x00 // IRQL 00 placeholder
|
|
#define APIC_SPURIOUS_VECTOR 0x1f // IRQL Spurious handler
|
|
#define APC_VECTOR 0x3D // IRQL 01 APC
|
|
#define DPC_VECTOR 0x41 // IRQL 02 DPC
|
|
#define APIC_REBOOT_VECTOR 0x50 // IRQL Vector used to reboot
|
|
#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27 broadcast function call
|
|
#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28 APIC INTI0 - CLOCK2_LEVEL
|
|
|
|
//
|
|
// If MP, define APIC_SYNCH_LEVEL as SYNCH_LEVEL, otherwise define
|
|
// to be the same as DPC_LEVEL.
|
|
//
|
|
|
|
#if (SYNCH_LEVEL != DISPATCH_LEVEL)
|
|
|
|
#define APIC_SYNCH_VECTOR 0xC1 // IRQL 28 IPI_LEVEL-1
|
|
|
|
#else
|
|
|
|
#define APIC_SYNCH_VECTOR DPC_VECTOR // IRQL 02 if UNIPROCESSOR
|
|
|
|
#endif
|
|
|
|
#define APIC_IPI_VECTOR 0xE1 // IRQL 29 APIC IPI
|
|
|
|
#define APIC_FAULT_VECTOR 0xE3 //
|
|
#define POWERFAIL_VECTOR 0xEF // IRQL 30 reserved. not used
|
|
|
|
#define APIC_PROFILE_VECTOR 0xFD // IRQL 31
|
|
#define APIC_PERF_VECTOR 0xFE // IRQL 31
|
|
#define NMI_VECTOR 0xFF // IRQL 31
|
|
|
|
#endif
|
|
|
|
//
|
|
// 8259/ISP interrupt controller register addresses
|
|
//
|
|
|
|
#define PIC1_PORT0 0x20
|
|
#define PIC1_PORT1 0x21
|
|
#define PIC2_PORT0 0xA0
|
|
#define PIC2_PORT1 0xA1
|
|
|
|
#define PIC_SLAVE_IRQ 2
|
|
#define RTC_IRQ 8
|
|
|
|
#define PIC1_ELCR_PORT 0x04D0 // ISP edge/level control registers
|
|
#define PIC2_ELCR_PORT 0x04D1
|
|
|
|
#define PIC1_SPURIOUS_VECTOR 0x37
|
|
|
|
//
|
|
// Defines for HalpFeatureBits
|
|
//
|
|
|
|
extern ULONG HalpFeatureBits;
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
#if defined(_AMD64_) && defined(NT_UP)
|
|
|
|
#define HalpAcquireHighLevelLock(lock) HalpDisableInterrupts()
|
|
#define HalpReleaseHighLevelLock(lock,irql) HalpRestoreInterrupts(irql)
|
|
|
|
#else
|
|
|
|
ULONG FASTCALL HalpAcquireHighLevelLock(PKSPIN_LOCK);
|
|
VOID FASTCALL HalpReleaseHighLevelLock(PKSPIN_LOCK, ULONG);
|
|
|
|
#endif
|
|
|
|
extern KSPIN_LOCK HalpAccountingLock;
|
|
extern KAFFINITY HalpActiveProcessors;
|
|
|
|
//
|
|
// Prototypes
|
|
//
|
|
|
|
#define MAX_INTI (MAX_IOAPICS*32) // Max interrupt inputs from APICs
|
|
#define MAX_SOURCE_IRQS MAX_INTI // Max different interrupts supported
|
|
|
|
//
|
|
// HalVectorToIDTEntry(vector) is defined in i386.h, because the kernel needs
|
|
// it.
|
|
#define MAX_NODES MAX_PROCESSORS
|
|
#define HalpVectorToNode(vector) ((vector)>>8)
|
|
#define HalpVector(node, idtentry) ((node)<<8|(idtentry))
|
|
|
|
extern struct HalpMpInfo HalpMpInfoTable;
|
|
extern UCHAR HalpMaxProcsPerCluster;
|
|
|
|
extern BOOLEAN HalpELCRChecked;
|
|
extern USHORT HalpGlobal8259Mask;
|
|
extern USHORT HalpVectorToINTI[];
|
|
extern UCHAR HalpInitLevel[4][4];
|
|
extern UCHAR HalpDevPolarity[4][2];
|
|
extern UCHAR HalpDevLevel[2][4];
|
|
|
|
//
|
|
// Initialized from MPS table
|
|
//
|
|
|
|
typedef struct _INTI_INFO {
|
|
UCHAR Type:4;
|
|
UCHAR Level:2;
|
|
UCHAR Polarity:2;
|
|
UCHAR Destinations;
|
|
USHORT Entry;
|
|
} INTI_INFO, *PINTI_INFO;
|
|
|
|
extern INTI_INFO HalpIntiInfo[];
|
|
extern USHORT HalpMaxApicInti[];
|
|
extern PCMPBUSTRANS HalpTypeTranslation[];
|
|
|
|
extern ULONG HalpIpiClock;
|
|
|
|
#define BusIrq2Id(bus,no,irq) \
|
|
((bus << 16) | (no << 8) | irq)
|
|
|
|
#define Id2BusIrq(id) \
|
|
(id & 0xff)
|
|
|
|
VOID
|
|
HalpInitIntiInfo (
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
HalpGetIoApicId(
|
|
ULONG ApicNo
|
|
);
|
|
|
|
VOID
|
|
HalpSet8259Mask(
|
|
IN USHORT Mask
|
|
);
|
|
|
|
VOID
|
|
HalpInitializeLocalUnit (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpInitializeIOUnits (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpRestoreIoApicRedirTable (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpEnableNMI (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpEnableLocalNmiSources(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpSet8259Mask(
|
|
IN USHORT Mask
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpGetApicInterruptDesc (
|
|
IN INTERFACE_TYPE BusType,
|
|
IN ULONG BusNumber,
|
|
IN ULONG BusInterruptLevel,
|
|
OUT PUSHORT PcMpInti
|
|
);
|
|
|
|
VOID
|
|
HalpCheckELCR (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpGenericCall (
|
|
VOID (*Fnc)(ULONG_PTR),
|
|
ULONG Context,
|
|
KAFFINITY Processors
|
|
);
|
|
|
|
VOID
|
|
HalpPollForBroadcast (
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
FASTCALL
|
|
HalpWaitForPending (
|
|
IN ULONG Count,
|
|
IN volatile ULONG *LuICR
|
|
);
|
|
|
|
//
|
|
// Warning 4131 is "uses old-style declarator"
|
|
//
|
|
|
|
#pragma warning(disable:4131)
|
|
|
|
//
|
|
// Warning 4218 is "nonstandard extension used"
|
|
//
|
|
|
|
#pragma warning(disable:4218)
|
|
|
|
HAL_INTERRUPT_SERVICE_PROTOTYPE(HalpPerfInterrupt);
|
|
|
|
VOID
|
|
HalpEnablePerfInterupt (
|
|
ULONG_PTR Context
|
|
);
|
|
|
|
VOID
|
|
HalpEnableNMI (
|
|
VOID
|
|
);
|
|
|
|
NTSTATUS
|
|
HalpSetSystemInformation (
|
|
IN HAL_SET_INFORMATION_CLASS InformationClass,
|
|
IN ULONG BufferSize,
|
|
IN PVOID Buffer
|
|
);
|
|
|
|
ULONG
|
|
HalpInti2BusInterruptLevel(
|
|
ULONG Inti
|
|
);
|
|
|
|
VOID
|
|
HalpUnMapIOApics(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpInitializeIOUnits (
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
HalpPostSleepMP(
|
|
IN LONG NumberProcessors,
|
|
IN volatile PLONG Number
|
|
);
|
|
|
|
VOID
|
|
HalpSetRedirEntry (
|
|
IN USHORT InterruptInput,
|
|
IN ULONG Entry,
|
|
IN ULONG Destination
|
|
);
|
|
|
|
VOID
|
|
HalpGetRedirEntry (
|
|
IN USHORT InterruptInput,
|
|
IN PULONG Entry,
|
|
IN PULONG Destination
|
|
);
|
|
|
|
/*++
|
|
|
|
HalpStallWhileApicBusy (
|
|
VOID
|
|
)
|
|
|
|
Routine Description:
|
|
|
|
This routine waits until the local apic has completed sending
|
|
an IPI.
|
|
|
|
Parameters:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
#define HalpStallWhileApicBusy() \
|
|
while ((LOCAL_APIC(LU_INT_CMD_LOW) & DELIVERY_PENDING) != 0) { }
|
|
|
|
|
|
#if defined(_AMD64_)
|
|
|
|
#define HalpGetHalPcr(pcr) ((PHALPCR)(pcr->HalReserved))
|
|
#define HalpGetCurrentHalPcr() HalpGetHalPcr(KeGetPcr())
|
|
|
|
#endif
|
|
|
|
#endif // _NTAPIC_INC_
|
|
|
|
|
|
/*
|
|
endif
|
|
;
|
|
; Begin assembly part of the definitions
|
|
;
|
|
|
|
;
|
|
; Well known virtual address of local processor apic
|
|
;
|
|
|
|
LOCALAPIC equ 0fffe0000h
|
|
APIC equ ds:[LOCALAPIC]
|
|
|
|
DEBUGGING equ 0
|
|
|
|
|
|
if DEBUGGING
|
|
IRQL_METRICS equ 0
|
|
endif
|
|
;
|
|
; To allow the user to specify command line options to the HAL.
|
|
;
|
|
USER_SETABLE_OPTIONS equ 1
|
|
|
|
MAX_PROCESSORS equ 32
|
|
MAX_NODES equ MAX_PROCESSORS
|
|
MAX_IOAPICS equ 64
|
|
;
|
|
; This OS specific structure holds useful MP information. This information
|
|
; is obtained from the PC+MP table and stored here for convenience.
|
|
;
|
|
|
|
HalpMpInfo struc
|
|
ApicVersion dd 0 ; 82489Dx or Not
|
|
ProcessorCount dd 0 ; Number of Enabled Processors
|
|
NtProcessors dd 0 ; Number of Running Processors
|
|
BusCount dd 0 ; Number of buses in system
|
|
IOApicCount dd 0 ; Number of Io Apics in system
|
|
IntiCount dd 0 ; Num of Io Apic interrupt inputs
|
|
LintiCount dd 0 ; Num of Local Apic interrupt inputs
|
|
IMCRPresent dd 0 ; Indicates if the IMCR is present
|
|
LocalApicBase dd 0 ; Base of local apic
|
|
IoApicBase dd MAX_IOAPICS dup (0) ; Virtual addresses of IoApics
|
|
IoApicPhys dd MAX_IOAPICS dup (0) ; Physical addresses of IoApics
|
|
ifdef ACPI_HAL
|
|
IoApicIntiBase dd MAX_IOAPICS dup (0) ; ACPI only. First GSIV.
|
|
else
|
|
ProcessorEntryPtr dd 0 ; Ptr to 1st PC+MP processor entry
|
|
BusEntryPtr dd 0 ; Ptr to 1st PC+MP bus entry
|
|
IoApicEntryPtr dd 0 ; Ptr to 1st PC+MP IoApic entry
|
|
IntiEntryPtr dd 0 ; Ptr to 1st PC+MP Inti entry
|
|
LintiEntryPtr dd 0 ; Ptr to 1st PC+MP Linti entry
|
|
ExtensionTable dd 0 ; Ptr to 1st extension table entry
|
|
EndExtensionTable dd 0 ; Ptr to 1st extension table entry
|
|
endif
|
|
HalpMpInfo ends
|
|
|
|
|
|
;
|
|
; interrupt vector definitions for assembler
|
|
;
|
|
|
|
ZERO_VECTOR equ 000h ; IRQL 00 placeholder
|
|
APIC_SPURIOUS_VECTOR equ 01fh ; Vector used for spurious handler
|
|
APC_VECTOR equ 03Dh ; IRQL 01 APC
|
|
DPC_VECTOR equ 041h ; IRQL 02 DPC
|
|
APIC_REBOOT_VECTOR equ 050h ; Vector used to reboot
|
|
DEVICE_LEVEL1 equ 051h
|
|
DEVICE_LEVEL2 equ 061h
|
|
DEVICE_LEVEL3 equ 071h
|
|
DEVICE_LEVEL4 equ 081h
|
|
DEVICE_LEVEL5 equ 091h
|
|
DEVICE_LEVEL6 equ 0A1h
|
|
DEVICE_LEVEL7 equ 0B1h
|
|
APIC_GENERIC_VECTOR equ 0C1h ; IRQL 27 broadcast function call
|
|
APIC_CLOCK_VECTOR equ 0D1h ; IRQL 28 APIC INTI0 - CLOCK2_LEVEL
|
|
|
|
if SYNCH_LEVEL-DISPATCH_LEVEL
|
|
|
|
APIC_SYNCH_VECTOR equ 0C1h ; IRQL 28 IPI_LEVEL-1
|
|
|
|
else
|
|
|
|
APIC_SYNCH_VECTOR equ DPC_VECTOR
|
|
|
|
endif
|
|
|
|
APIC_IPI_VECTOR equ 0E1h ; IRQL 29 APIC IPI
|
|
|
|
APIC_FAULT_VECTOR equ 0E3h ;
|
|
POWERFAIL_VECTOR equ 0EFh ; IRQL 30 reserved
|
|
|
|
APIC_PROFILE_VECTOR equ 0FDh ; IRQL 27
|
|
APIC_PERF_VECTOR equ 0FEh ; IRQL 27
|
|
NMI_VECTOR equ 0FFh ; IRQL 31
|
|
|
|
HAL_PROFILE_LEVEL equ HIGH_LEVEL
|
|
|
|
;
|
|
; 8259/ISP interrupt controller register addresses
|
|
;
|
|
|
|
PIC1_PORT0 equ 020H
|
|
PIC1_PORT1 equ 021H
|
|
PIC2_PORT0 equ 0A0H
|
|
PIC2_PORT1 equ 0A1H
|
|
|
|
PIC1_ELCR_PORT equ 04D0H ; ISP edge/level control registers
|
|
PIC2_ELCR_PORT equ 04D1H
|
|
|
|
;
|
|
; Initialization control words for the PICs
|
|
;
|
|
|
|
ICW1_ICW4_NEEDED equ 01H
|
|
ICW1_CASCADE equ 00H
|
|
ICW1_INTERVAL8 equ 00H
|
|
ICW1_LEVEL_TRIG equ 08H
|
|
ICW1_EDGE_TRIG equ 00H
|
|
ICW1_ICW equ 10H
|
|
|
|
ICW4_8086_MODE equ 001H
|
|
ICW4_AUTO_EOI equ 002H
|
|
ICW4_NORM_EOI equ 000H
|
|
ICW4_NON_BUF_MODE equ 000H
|
|
ICW4_SPEC_FULLY_NESTED equ 010H
|
|
ICW4_NOT_SPEC_FULLY_NESTED equ 000H
|
|
|
|
PIC_SLAVE_IRQ equ 2
|
|
|
|
PIC1_BASE equ 30H
|
|
PIC2_BASE equ 38H
|
|
PIC_CLOCK_VECTOR equ 30H
|
|
PIC_DMA_VECTOR equ 3DH
|
|
PIC1_SPURIOUS_VECTOR equ 37H
|
|
PIC2_SPURIOUS_VECTOR equ 3FH
|
|
|
|
;
|
|
; Operation control words for the PICs
|
|
;
|
|
|
|
OCW2_NON_SPECIFIC_EOI equ 020H
|
|
OCW2_SPECIFIC_EOI equ 060H
|
|
OCW3_READ_ISR equ 0BH
|
|
OCW3_READ_IRR equ 0AH
|
|
OCW3_READ_POLLED equ 0CH
|
|
|
|
;
|
|
; A couple of definitions that shouldn't change on a Compatible
|
|
;
|
|
|
|
TimerPicInti equ 0
|
|
DmaPic2Inti equ 5
|
|
SlavePicInti equ 2
|
|
DmaPicInti equ 13 ; DMA input relative to 0
|
|
|
|
cr equ 0ah
|
|
lf equ 0dh
|
|
|
|
;
|
|
; The kernel leaves some space (64 byte) of the PCR for the HAL to use
|
|
; as it needs. Currently this space is used for some efficiency in
|
|
; some of the MP specific code and is highly implementation-dependent.
|
|
;
|
|
|
|
|
|
PcrE struc
|
|
PcrNumber db 0 ; Processor's number
|
|
ShortDpc db 0 ; Short circut dpc interrupt
|
|
DpcPending db 0 ; Dpc interrupt pending
|
|
|
|
db 0 ; force dword alignment
|
|
;
|
|
; The next three dwords are used to manipulate the APIC counter
|
|
;
|
|
|
|
ApicClockFreqHz dd 0 ; Counter Freq in Hertz
|
|
ApicClockFreqKhz dd 0 ; Counter Freq in Khertz (rounded)
|
|
ProfileCountDown dd 0 ; Current Countdown Interval
|
|
|
|
TSCHz dq 0 ; Time stamp counter hertz
|
|
|
|
|
|
PerfCounterLow dd 0 ; PerProcessor Counter
|
|
PerfCounterHigh dd 0 ;
|
|
; ProfileCountLast dd 0
|
|
|
|
OEMPcr db size OEMPcr dup(?)
|
|
|
|
PcrE ends
|
|
|
|
PrcbE struc
|
|
PrcbPCMPApicID db 0 ; Processor's PCMP ApicID
|
|
db 3 dup (0) ; force dword alignment
|
|
PrcbE ends
|
|
|
|
|
|
MsrTSC equ 10h
|
|
|
|
;++
|
|
;
|
|
; STALL_WHILE_APIC_BUSY
|
|
;
|
|
; Wait for the APIC DELIVERY_PENDING bit to be clear
|
|
;
|
|
;--
|
|
|
|
STALL_WHILE_APIC_BUSY macro
|
|
local a, b
|
|
if 0
|
|
|
|
push eax
|
|
mov eax, 5000h
|
|
|
|
a: test dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
|
|
jz short b
|
|
|
|
dec eax
|
|
jnz short a
|
|
|
|
int 3
|
|
jmp short a
|
|
|
|
b: pop eax
|
|
|
|
else
|
|
|
|
a: test dword ptr APIC[LU_INT_CMD_LOW],DELIVERY_PENDING
|
|
jnz short a
|
|
|
|
endif
|
|
endm
|
|
|
|
;++
|
|
;
|
|
; APICFIX
|
|
;
|
|
; Macro Description:
|
|
;
|
|
; For internal testing use
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None
|
|
;
|
|
;--
|
|
|
|
APICFIX macro reg1
|
|
; inc dword ptr PCR[PcKernel] ; Count # of times patched
|
|
endm
|
|
|
|
;++
|
|
;
|
|
; CHECKTPR
|
|
;
|
|
; Macro Description:
|
|
;
|
|
; For internal testing use
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None
|
|
;
|
|
;--
|
|
|
|
CHECKTPR macro reg1, reg2
|
|
if DBG
|
|
cmp reg1, reg2
|
|
je short @f
|
|
int 3
|
|
@@:
|
|
endif
|
|
endm
|
|
|
|
;++
|
|
;
|
|
; IODELAY
|
|
;
|
|
; Macro Description:
|
|
;
|
|
; This macro delays the CPU just a little so the PIC has time to settle
|
|
; between IO port accesses. Current mechanism is to read an APIC local
|
|
; unit register (eax is saved). Note that PUSHF/POPF is worth 10 clocks.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; None
|
|
;
|
|
;--
|
|
|
|
IODELAY macro
|
|
pushf
|
|
popf
|
|
jmp $+2
|
|
endm
|
|
|
|
;++
|
|
;
|
|
; SET_8259_MASK
|
|
;
|
|
; Macro Description:
|
|
;
|
|
; This macro sets the 8259 PIC interrupt mask register with the mask
|
|
; passed from eax register. Bits 7:0 are the mask for the master PIC
|
|
; and bits 15:8 are the mask for the slave PIC.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; (eax) = mask for setting 8259 PIC interrupt mask register
|
|
;
|
|
;--
|
|
|
|
SET_8259_MASK macro
|
|
|
|
out PIC1_PORT1, al ; set master 8259 mask
|
|
shr eax, 8 ; shift slave 8259 mask to al
|
|
out PIC2_PORT1, al ; set slave 8259 mask
|
|
endm
|
|
|
|
;*/
|