|
|
;/*++ ; ;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 */
//#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
//
#define LOCALAPIC 0xfffe0000 #define pLocalApic ((volatile PULONG) LOCALAPIC)
//
// 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;
//
// 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
ULONG TSCHz; // Time stamp counter hertz low
ULONG PerfCounterLow; // PerProcessor Counter
ULONG PerfCounterHigh; } HALPCR, *PHALPCR;
//
// 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;
//
// 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 0xD1 // 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
//
// 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;
//
//
//
ULONG FASTCALL HalpAcquireHighLevelLock(PKSPIN_LOCK); VOID FASTCALL HalpReleaseHighLevelLock(PKSPIN_LOCK, ULONG); 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 HalpSetInternalVector ( IN ULONG InternalVector, IN VOID (*HalInterruptSerivceRoutine)(VOID) );
VOID HalpGenericCall ( VOID (*Fnc)(ULONG), ULONG Context, KAFFINITY Processors );
VOID HalpPollForBroadcast ( VOID );
ULONG FASTCALL HalpWaitForPending ( IN ULONG Count, IN volatile ULONG *LuICR );
VOID HalpPerfInterrupt( VOID );
VOID HalpEnablePerfInterupt ( ULONG 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 );
/* 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 0D1h ; 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 dd 0 ; Time stamp counter hertz low
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
;*/
|