[PERF]: Optimize nested interrupt cases (where a pending interrupt exists at the...
[reactos.git] / reactos / hal / halx86 / include / halp.h
index 61e9260..ab7e016 100644 (file)
@@ -1,10 +1,40 @@
 /*
- * 
+ *
  */
 
 #ifndef __INTERNAL_HAL_HAL_H
 #define __INTERNAL_HAL_HAL_H
 
+typedef struct _HAL_BIOS_FRAME
+{
+    ULONG SegSs;
+    ULONG Esp;
+    ULONG EFlags;
+    ULONG SegCs;
+    ULONG Eip;
+    PKTRAP_FRAME TrapFrame;
+    ULONG CsLimit;
+    ULONG CsBase;
+    ULONG CsFlags;
+    ULONG SsLimit;
+    ULONG SsBase;
+    ULONG SsFlags;
+    ULONG Prefix;
+} HAL_BIOS_FRAME, *PHAL_BIOS_FRAME;
+
+typedef
+VOID
+(*PHAL_SW_INTERRUPT_HANDLER)(
+    VOID
+);
+
+typedef
+FASTCALL
+VOID
+(*PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)(
+    IN PKTRAP_FRAME TrapFrame
+);
+
 #define HAL_APC_REQUEST         0
 #define HAL_DPC_REQUEST         1
 
 #define RTC_REG_A_UIP           0x80
 #define RTC_REGISTER_CENTURY    0x32
 
-/* Timer Registers and Ports */
-#define TIMER_CONTROL_PORT      0x43
-#define TIMER_DATA_PORT0        0x40
-#define TIMER_SC0               0
-#define TIMER_BOTH              0x30
-#define TIMER_MD2               0x4
+/* Usage flags */
+#define IDT_REGISTERED          0x01
+#define IDT_LATCHED             0x02
+#define IDT_INTERNAL            0x11
+#define IDT_DEVICE              0x21
 
 /* Conversion functions */
 #define BCD_INT(bcd)            \
 #define INT_BCD(int)            \
     (UCHAR)(((int / 10) << 4) + (int % 10))
 
+//
+// BIOS Interrupts
+//
+#define VIDEO_SERVICES   0x10
+
+//
+// Operations for INT 10h (in AH)
+//
+#define SET_VIDEO_MODE   0x00
+
+//
+// Video Modes for INT10h AH=00 (in AL)
+//
+#define GRAPHICS_MODE_12 0x12           /* 80x30        8x16  640x480   16/256K */
+
+//
+// Generates a 16-bit (real-mode or Virtual 8086) BIOS interrupt with a given AX */
+//
+VOID
+FORCEINLINE
+HalpCallBiosInterrupt(IN ULONG Interrupt,
+                      IN ULONG Ax)
+{
+    __asm__ __volatile__
+    (
+        ".byte 0x66\n"
+        "movl $%c[v], %%eax\n"
+        "int $%c[i]\n"
+        :
+        : [v] "i"(Ax),
+          [i] "i"(Interrupt)
+    );
+}
+
+//
+// Constructs a stack of the given size and alignment in the real-mode .text region */
+//
+VOID
+FORCEINLINE
+HalpRealModeStack(IN ULONG Alignment,
+                  IN ULONG Size)
+{
+    __asm__ __volatile__
+    (
+        ".align %c[v]\n"
+        ".space %c[i]\n"
+        ".globl _HalpRealModeEnd\n_HalpRealModeEnd:\n"
+        :
+        : [v] "i"(Alignment),
+          [i] "i"(Size)
+    );
+}
+
+//
+// Nested Trap Trampoline
+//
+VOID
+DECLSPEC_NORETURN
+FORCEINLINE
+HalpNestedTrap(IN KIRQL PendingIrql)
+{
+    /* Use the second interrupt handler table */
+    extern PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3];
+    __asm__ __volatile__
+    (
+        "movl %c[t], %%ecx\n"
+        "jmp *%0\n"
+        :
+        : "im"(SWInterruptHandlerTable2[PendingIrql]),
+          [t] "i"(&PCR->VdmAlert)
+        : "%esp"
+    );
+    UNREACHABLE;
+}
+
+//
+// Commonly stated as being 1.19318MHz
+//
+// See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
+// P. 471
+//
+// However, the true value is closer to 1.19318181[...]81MHz since this is 1/3rd
+// of the NTSC color subcarrier frequency which runs at 3.57954545[...]45MHz.
+//
+// Note that Windows uses 1.193167MHz which seems to have no basis. However, if
+// one takes the NTSC color subcarrier frequency as being 3.579545 (trimming the
+// infinite series) and divides it by three, one obtains 1.19318167.
+//
+// It may be that the original NT HAL source code introduced a typo and turned
+// 119318167 into 1193167 by ommitting the "18". This is very plausible as the
+// number is quite long.
+//
+#define PIT_FREQUENCY 1193182
+
+//
+// These ports are controlled by the i8254 Programmable Interrupt Timer (PIT)
+//
+#define TIMER_CHANNEL0_DATA_PORT 0x40
+#define TIMER_CHANNEL1_DATA_PORT 0x41
+#define TIMER_CHANNEL2_DATA_PORT 0x42
+#define TIMER_CONTROL_PORT       0x43
+
+//
+// Mode 0 - Interrupt On Terminal Count
+// Mode 1 - Hardware Re-triggerable One-Shot
+// Mode 2 - Rate Generator
+// Mode 3 - Square Wave Generator
+// Mode 4 - Software Triggered Strobe
+// Mode 5 - Hardware Triggered Strobe
+//
+typedef enum _TIMER_OPERATING_MODES
+{
+    PitOperatingMode0,
+    PitOperatingMode1,
+    PitOperatingMode2,
+    PitOperatingMode3,
+    PitOperatingMode4,
+    PitOperatingMode5,
+    PitOperatingMode2Reserved,
+    PitOperatingMode5Reserved
+} TIMER_OPERATING_MODES;
+
+typedef enum _TIMER_ACCESS_MODES
+{
+    PitAccessModeCounterLatch,
+    PitAccessModeLow,
+    PitAccessModeHigh,
+    PitAccessModeLowHigh
+} TIMER_ACCESS_MODES;
+
+typedef enum _TIMER_CHANNELS
+{
+    PitChannel0,
+    PitChannel1,
+    PitChannel2,
+    PitReadBack
+} TIMER_CHANNELS;
+
+typedef union _TIMER_CONTROL_PORT_REGISTER
+{
+    struct 
+    {
+        UCHAR BcdMode:1;
+        TIMER_OPERATING_MODES OperatingMode:3;
+        TIMER_ACCESS_MODES AccessMode:2;
+        TIMER_CHANNELS Channel:2;
+    };
+    UCHAR Bits;
+} TIMER_CONTROL_PORT_REGISTER, *PTIMER_CONTROL_PORT_REGISTER;
+
+//
+// See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
+// P. 400
+//
+// This port is controled by the i8255 Programmable Peripheral Interface (PPI)
+//
+#define SYSTEM_CONTROL_PORT_A   0x92
+#define SYSTEM_CONTROL_PORT_B   0x61
+typedef union _SYSTEM_CONTROL_PORT_B_REGISTER
+{
+    struct 
+    {
+        UCHAR Timer2GateToSpeaker:1;
+        UCHAR SpeakerDataEnable:1;
+        UCHAR ParityCheckEnable:1;
+        UCHAR ChannelCheckEnable:1;
+        UCHAR RefreshRequest:1;
+        UCHAR Timer2Output:1;
+        UCHAR ChannelCheck:1;
+        UCHAR ParityCheck:1;
+    };
+    UCHAR Bits;
+} SYSTEM_CONTROL_PORT_B_REGISTER, *PSYSTEM_CONTROL_PORT_B_REGISTER;
+
+//
+// See ISA System Architecture 3rd Edition (Tom Shanley, Don Anderson, John Swindle)
+// P. 396, 397
+//
+// These ports are controlled by the i8259 Programmable Interrupt Controller (PIC)
+//
+#define PIC1_CONTROL_PORT      0x20
+#define PIC1_DATA_PORT         0x21
+#define PIC2_CONTROL_PORT      0xA0
+#define PIC2_DATA_PORT         0xA1
+
+//
+// Definitions for ICW/OCW Bits
+//
+typedef enum _I8259_ICW1_OPERATING_MODE
+{
+    Cascade,
+    Single
+} I8259_ICW1_OPERATING_MODE;
+
+typedef enum _I8259_ICW1_INTERRUPT_MODE
+{
+    EdgeTriggered,
+    LevelTriggered
+} I8259_ICW1_INTERRUPT_MODE;
+
+typedef enum _I8259_ICW1_INTERVAL
+{
+    Interval8,
+    Interval4
+} I8259_ICW1_INTERVAL;
+
+typedef enum _I8259_ICW4_SYSTEM_MODE
+{
+    Mcs8085Mode,
+    New8086Mode
+} I8259_ICW4_SYSTEM_MODE;
+
+typedef enum _I8259_ICW4_EOI_MODE
+{
+    NormalEoi,
+    AutomaticEoi
+} I8259_ICW4_EOI_MODE;
+
+typedef enum _I8259_ICW4_BUFFERED_MODE
+{
+    NonBuffered,
+    NonBuffered2,
+    BufferedSlave,
+    BufferedMaster
+} I8259_ICW4_BUFFERED_MODE;
+
+typedef enum _I8259_READ_REQUEST
+{
+    InvalidRequest,
+    InvalidRequest2,
+    ReadIdr,
+    ReadIsr
+} I8259_READ_REQUEST;
+
+typedef enum _I8259_EOI_MODE
+{
+    RotateAutoEoiClear,
+    NonSpecificEoi,
+    InvalidEoiMode,
+    SpecificEoi,
+    RotateAutoEoiSet,
+    RotateNonSpecific,
+    SetPriority,
+    RotateSpecific
+} I8259_EOI_MODE;
+
+//
+// Definitions for ICW Registers
+//
+typedef union _I8259_ICW1
+{
+    struct 
+    {
+        UCHAR NeedIcw4:1;
+        I8259_ICW1_OPERATING_MODE OperatingMode:1;
+        I8259_ICW1_INTERVAL Interval:1;
+        I8259_ICW1_INTERRUPT_MODE InterruptMode:1;
+        UCHAR Init:1;
+        UCHAR InterruptVectorAddress:3;
+    };
+    UCHAR Bits;
+} I8259_ICW1, *PI8259_ICW1;
+
+typedef union _I8259_ICW2
+{
+    struct 
+    {
+        UCHAR Sbz:3;
+        UCHAR InterruptVector:5;
+    };
+    UCHAR Bits;
+} I8259_ICW2, *PI8259_ICW2;
+
+typedef union _I8259_ICW3
+{
+    union
+    {
+        struct 
+        {
+            UCHAR SlaveIrq0:1;
+            UCHAR SlaveIrq1:1;
+            UCHAR SlaveIrq2:1;
+            UCHAR SlaveIrq3:1;
+            UCHAR SlaveIrq4:1;
+            UCHAR SlaveIrq5:1;
+            UCHAR SlaveIrq6:1;
+            UCHAR SlaveIrq7:1;
+        };
+        struct 
+        {
+            UCHAR SlaveId:3;
+            UCHAR Reserved:5;
+        };
+    };
+    UCHAR Bits;
+} I8259_ICW3, *PI8259_ICW3;
+
+typedef union _I8259_ICW4
+{
+    struct 
+    {
+        I8259_ICW4_SYSTEM_MODE SystemMode:1;
+        I8259_ICW4_EOI_MODE EoiMode:1;
+        I8259_ICW4_BUFFERED_MODE BufferedMode:2;
+        UCHAR SpecialFullyNestedMode:1;
+        UCHAR Reserved:3;
+    };
+    UCHAR Bits;
+} I8259_ICW4, *PI8259_ICW4;
+
+typedef union _I8259_OCW2
+{
+    struct
+    {
+        UCHAR IrqNumber:3;
+        UCHAR Sbz:2;
+        I8259_EOI_MODE EoiMode:3;
+    };
+    UCHAR Bits;
+} I8259_OCW2, *PI8259_OCW2;
+
+typedef union _I8259_OCW3
+{
+    struct
+    {
+        I8259_READ_REQUEST ReadRequest:2;
+        UCHAR PollCommand:1;
+        UCHAR Sbo:1;
+        UCHAR Sbz:1;
+        UCHAR SpecialMaskMode:2;
+        UCHAR Reserved:1;
+    };
+    UCHAR Bits;
+} I8259_OCW3, *PI8259_OCW3;
+
+typedef union _I8259_ISR
+{
+    union
+    {
+        struct
+        {
+            UCHAR Irq0:1;
+            UCHAR Irq1:1;
+            UCHAR Irq2:1;
+            UCHAR Irq3:1;
+            UCHAR Irq4:1;
+            UCHAR Irq5:1;
+            UCHAR Irq6:1;
+            UCHAR Irq7:1;
+        };
+    };
+    UCHAR Bits;
+} I8259_ISR, *PI8259_ISR;
+
+typedef I8259_ISR I8259_IDR, *PI8259_IDR;
+
+//
+// See EISA System Architecture 2nd Edition (Tom Shanley, Don Anderson, John Swindle)
+// P. 34, 35
+//
+// These ports are controlled by the i8259A Programmable Interrupt Controller (PIC)
+//
+#define EISA_ELCR_MASTER       0x4D0
+#define EISA_ELCR_SLAVE        0x4D1
+
+typedef union _EISA_ELCR
+{
+    struct
+    {
+        struct
+        {
+            UCHAR Irq0Level:1;
+            UCHAR Irq1Level:1;
+            UCHAR Irq2Level:1;
+            UCHAR Irq3Level:1;
+            UCHAR Irq4Level:1;
+            UCHAR Irq5Level:1;
+            UCHAR Irq6Level:1;
+            UCHAR Irq7Level:1;
+        } Master;
+        struct
+        {
+            UCHAR Irq8Level:1;
+            UCHAR Irq9Level:1;
+            UCHAR Irq10Level:1;
+            UCHAR Irq11Level:1;
+            UCHAR Irq12Level:1;
+            UCHAR Irq13Level:1;
+            UCHAR Irq14Level:1;
+            UCHAR Irq15Level:1;
+        } Slave;
+    };
+    USHORT Bits;
+} EISA_ELCR, *PEISA_ELCR;
+
+typedef struct _PIC_MASK
+{
+    union
+    {
+        struct
+        {
+            UCHAR Master;
+            UCHAR Slave;
+        };
+        USHORT Both;
+    };    
+} PIC_MASK, *PPIC_MASK;
+
+typedef
+BOOLEAN
+__attribute__((regparm(3)))
+(*PHAL_DISMISS_INTERRUPT)(
+    IN KIRQL Irql,
+    IN ULONG Irq,
+    OUT PKIRQL OldIrql
+);
+
+BOOLEAN
+__attribute__((regparm(3)))
+HalpDismissIrqGeneric(
+    IN KIRQL Irql,
+    IN ULONG Irq,
+    OUT PKIRQL OldIrql
+);
+
+BOOLEAN
+__attribute__((regparm(3)))
+HalpDismissIrq15(
+    IN KIRQL Irql,
+    IN ULONG Irq,
+    OUT PKIRQL OldIrql
+);
+
+BOOLEAN
+__attribute__((regparm(3)))
+HalpDismissIrq13(
+    IN KIRQL Irql,
+    IN ULONG Irq,
+    OUT PKIRQL OldIrql
+);
+
+BOOLEAN
+__attribute__((regparm(3)))
+HalpDismissIrq07(
+    IN KIRQL Irql,
+    IN ULONG Irq,
+    OUT PKIRQL OldIrql
+);
+
+//
+// Mm PTE/PDE to Hal PTE/PDE
+//
+#define HalAddressToPde(x) (PHARDWARE_PTE)MiAddressToPde(x)
+#define HalAddressToPte(x) (PHARDWARE_PTE)MiAddressToPte(x)
+    
+typedef struct _IDTUsageFlags
+{
+    UCHAR Flags;
+} IDTUsageFlags;
+
+typedef struct
+{
+    KIRQL Irql;
+    UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage
+{
+    struct _HalAddressUsage *Next;
+    CM_RESOURCE_TYPE Type;
+    UCHAR Flags;
+    struct
+    {
+        ULONG Start;
+        ULONG Length;
+    } Element[];
+} ADDRESS_USAGE, *PADDRESS_USAGE;
+
 /* adapter.c */
-PADAPTER_OBJECT STDCALL HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses);
-  
-/* bus.c */
-VOID NTAPI HalpInitNonBusHandler (VOID);
+PADAPTER_OBJECT NTAPI HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses);
+
+/* sysinfo.c */
+VOID
+NTAPI
+HalpRegisterVector(IN UCHAR Flags,
+                   IN ULONG BusVector,
+                   IN ULONG SystemVector,
+                   IN KIRQL Irql);
 
-/* irql.c */
-VOID NTAPI HalpInitPICs(VOID);
+VOID
+NTAPI
+HalpEnableInterruptHandler(IN UCHAR Flags,
+                           IN ULONG BusVector,
+                           IN ULONG SystemVector,
+                           IN KIRQL Irql,
+                           IN PVOID Handler,
+                           IN KINTERRUPT_MODE Mode);
 
-/* udelay.c */
+/* pic.c */
+VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts);
+VOID HalpApcInterrupt(VOID);
+VOID HalpDispatchInterrupt(VOID);
+VOID FASTCALL HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame);
+
+/* timer.c */
 VOID NTAPI HalpInitializeClock(VOID);
+VOID HalpClockInterrupt(VOID);
+VOID HalpProfileInterrupt(VOID);
+
+VOID
+NTAPI
+HalpCalibrateStallExecution(VOID);
 
 /* pci.c */
 VOID HalpInitPciBus (VOID);
@@ -50,7 +581,10 @@ VOID HalpInitDma (VOID);
 /* Non-generic initialization */
 VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock);
 VOID HalpInitPhase1(VOID);
-VOID NTAPI HalpClockInterrupt(VOID);
+
+VOID
+NTAPI
+HalpFlushTLB(VOID);
 
 //
 // KD Support
@@ -115,12 +649,170 @@ HaliSetSystemInformation(
     IN OUT PVOID Buffer
 );
 
-typedef struct tagHALP_HOOKS
+//
+// BIOS Routines
+//
+BOOLEAN
+NTAPI
+HalpBiosDisplayReset(
+    VOID
+);
+
+//
+// Processor Halt Routine
+//
+VOID
+NTAPI
+HaliHaltSystem(
+    VOID
+);
+
+//
+// CMOS initialization
+//
+VOID
+NTAPI
+HalpInitializeCmos(
+    VOID
+);
+
+//
+// Spinlock for protecting CMOS access
+//
+VOID
+NTAPI
+HalpAcquireSystemHardwareSpinLock(
+    VOID
+);
+
+VOID
+NTAPI
+HalpReleaseCmosSpinLock(
+    VOID
+);
+
+//
+// This is duplicated from ke_x.h
+//
+#ifdef CONFIG_SMP
+//
+// Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
+//
+FORCEINLINE
+VOID
+KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
+{
+    /* Make sure that we don't own the lock already */
+    if (((KSPIN_LOCK)KeGetCurrentThread() | 1) == *SpinLock)
+    {
+        /* We do, bugcheck! */
+        KeBugCheckEx(SPIN_LOCK_ALREADY_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
+    }
+
+    for (;;)
+    {
+        /* Try to acquire it */
+        if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
+        {
+            /* Value changed... wait until it's locked */
+            while (*(volatile KSPIN_LOCK *)SpinLock == 1)
+            {
+#ifdef DBG
+                /* On debug builds, we use a much slower but useful routine */
+                //Kii386SpinOnSpinLock(SpinLock, 5);
+
+                /* FIXME: Do normal yield for now */
+                YieldProcessor();
+#else
+                /* Otherwise, just yield and keep looping */
+                YieldProcessor();
+#endif
+            }
+        }
+        else
+        {
+#ifdef DBG
+            /* On debug builds, we OR in the KTHREAD */
+            *SpinLock = (KSPIN_LOCK)KeGetCurrentThread() | 1;
+#endif
+            /* All is well, break out */
+            break;
+        }
+    }
+}
+
+//
+// Spinlock Release at IRQL >= DISPATCH_LEVEL
+//
+FORCEINLINE
+VOID
+KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
 {
-  void (*InitPciBus)(ULONG BusNumber, PBUS_HANDLER BusHandler);
-} HALP_HOOKS, *PHALP_HOOKS;
+#ifdef DBG
+    /* Make sure that the threads match */
+    if (((KSPIN_LOCK)KeGetCurrentThread() | 1) != *SpinLock)
+    {
+        /* They don't, bugcheck */
+        KeBugCheckEx(SPIN_LOCK_NOT_OWNED, (ULONG_PTR)SpinLock, 0, 0, 0);
+    }
+#endif
+    /* Clear the lock */
+    InterlockedAnd((PLONG)SpinLock, 0);
+}
+
+#else
+
+//
+// Spinlock Acquire at IRQL >= DISPATCH_LEVEL
+//
+FORCEINLINE
+VOID
+KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
+{
+    /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
+    UNREFERENCED_PARAMETER(SpinLock);
+}
+
+//
+// Spinlock Release at IRQL >= DISPATCH_LEVEL
+//
+FORCEINLINE
+VOID
+KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
+{
+    /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
+    UNREFERENCED_PARAMETER(SpinLock);
+}
+
+#endif
+
+VOID
+FASTCALL
+KeUpdateSystemTime(
+    IN PKTRAP_FRAME TrapFrame,
+    IN ULONG Increment,
+    IN KIRQL OldIrql
+);
+
+#ifdef _M_AMD64
+#define KfLowerIrql KeLowerIrql
+#ifndef CONFIG_SMP
+/* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
+#define KiAcquireSpinLock(SpinLock)
+#define KiReleaseSpinLock(SpinLock)
+#define KfAcquireSpinLock(SpinLock) KfRaiseIrql(DISPATCH_LEVEL);
+#define KfReleaseSpinLock(SpinLock, OldIrql) KeLowerIrql(OldIrql);
+#endif // !CONFIG_SMP
+#endif // _M_AMD64
+
+extern BOOLEAN HalpNMIInProgress;
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
 
-extern HALP_HOOKS HalpHooks;
 extern KSPIN_LOCK HalpSystemHardwareLock;
 
+extern PADDRESS_USAGE HalpAddressUsageList;
+
+extern LARGE_INTEGER HalpPerfCounter;
+
 #endif /* __INTERNAL_HAL_HAL_H */