; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
;
        page    78, 132
        title   DHINTR2, DosHlp real mode redirectors

;******************************************************************************
;*                                                                            *
;* Source File: Dhintr2                                                       *
;*                                                                            *
;* Description:                                                               *
;*      This file contains the real mode redirectors and protect mode routers *
;*      to be installed be DosHlpInit.  All of the functions will be directly *
;*      entered upon receiving the cooresponding interrupt in real mode.      *
;*                                                                            *
;* Entry Points:                                                              *
;*      DHIRQnRMVector - Real mode vector redirectors                         *
;*      DHIRQnRouter - Protect mode routers                                   *
;*                                                                            *
;* External References:                                                       *
;*                                                                            *
;******************************************************************************

        .286                            ; Realmode only

        .xlist
        include basemaca.inc            ; Base macros
        include segments.inc            ; DosHlp segment definitions
        include doshlp.inc              ; DosHlp macros
        include dhintr2.inc
        include int.inc                 ; Interrupt manager structures
        include dhfix.inc               ; fixup macros
        include sysinvar.inc            ; Definition of DOSHLP_DATASEL
        include eisa.inc
        .list

        extrn   GetISR:near
        extrn   DHSendEOI:near

DosHlpCode  SEGMENT
        public      IRQ_RM_VECTOR_SIZE
        public      IRQ_ROUTER_SIZE
        public      IRQ_7_SIZE
        public      IRQ_8_SIZE

;***LT  DHIRQnRMVector - Real mode vector redirectors
;
;       Redirects vectors 50-57 to 8 - F.
;
;       ENTRY   CS = 0
;
;       EXIT    jumps to old vector
;
;       USES    NONE
;

        assume  cs:DGROUP
IRPC    x,01234567

ALIGN 4

Procedure DHIRQ&x&RMVector,near
        jmp     dword ptr cs:[(&x + PIC1_OLD_BASE) * 4]
EndProc   DHIRQ&x&RMVector

ENDM

IRQ_RM_VECTOR_SIZE equ  (DHIRQ1RMVector - DHIRQ0RMVector)
DosHlpCode  ENDS

        .386p
DosHlp32Code    SEGMENT

;***LP  DHIRQnRouter - IRQ routers
;
;       These routines are entered directly by the hardware when
;       an interrupt is received.  The address of these handlers
;       are in the protected mode IDT.  They setup a pointer to
;       the per-IRQ information and jump to a command handler.
;
;       ENTRY   NONE
;
;       EXIT    Jumps to KernelIRQRouter,
;                       EBX = offset of irqi entry
;
;       USES    NONE
;
;       CONTEXT Interrupt
;
;       PSEUDO-CODE
;
;       save all general registers
;       setup pointer to irqi entry
;       jump to intIRQRouter
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

IRP     x,<0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F>

ALIGN 4
Procedure DHIRQ&x&Router,near

        SaveReg <eax>
        mov     ax,ss
        cmpflatds                               ; get access to kernel data
        RestoreReg <eax>
        je   short ixx&x&
        movzx   esp,sp                          ; clear high word of ESP
ixx&x&:
        sub     esp,ISF_STACK_PAD               ; pad ISF stack for v86 mode
        .errnz  isf_pad - 52
        pushad                                  ;; save registers
        .errnz  isf_eax - 48
        .errnz  isf_ecx - 44
        .errnz  isf_edx - 40
        .errnz  isf_ebx - 36
        .errnz  isf_ebp - 28
        .errnz  isf_esi - 24
        .errnz  isf_edi - 20

if (0&x&h mod 8) eq 7

;       This is the last IRQ level for this PIC - make sure this is not a
;       spurious interrupt

        call    GetISR                          ; read the 8259 in service registers
        test    eax,ISR_IRQ&x                   ; is the IRQ in service?
        jnz     iir&x&
if 0&x&h gt 7
        mov   al,PIC_SLAVE_IRQ                  ; if this is IRQ > 7, then..
        call    DHSendEOI                       ; ..must reset master PIC
endif
        popad                                   ; no, this is a spurious interrupt -
        add     esp,ISF_STACK_PAD               ;   ignore it
        iretd
iir&x&:
endif

if 0&x&h eq 8
        push    ds
        pushflatds                              ; get access to kernel data
        pop     ds
        resetNMI                                ; restart the watchdog timer
        clearNMIcount                           ; clear count of nmi's
        pop     ds
endif
        ldirqi  0&x&h
        Kjmp    KernelIRQRouter                 ; go to common routine
EndProc   DHIRQ&x&Router

ENDM

IRQ_ROUTER_SIZE equ     (DHIRQ1Router - DHIRQ0Router)
IRQ_7_SIZE      equ     (DHIRQ8Router - DHIRQ7Router)
IRQ_8_SIZE      equ     (DHIRQ9Router - DHIRQ8Router)

.errnz  IRQ_ROUTER_SIZE - (DHIRQ2Router - DHIRQ1Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQ3Router - DHIRQ2Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQ4Router - DHIRQ3Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQ5Router - DHIRQ4Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQ6Router - DHIRQ5Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQ7Router - DHIRQ6Router)
.errnz  IRQ_7_SIZE      - (DHIRQ8Router - DHIRQ7Router)
.errnz  IRQ_8_SIZE      - (DHIRQ9Router - DHIRQ8Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQARouter - DHIRQ9Router)
.errnz  IRQ_ROUTER_SIZE - (DHIRQBRouter - DHIRQARouter)
.errnz  IRQ_ROUTER_SIZE - (DHIRQCRouter - DHIRQBRouter)
.errnz  IRQ_ROUTER_SIZE - (DHIRQDRouter - DHIRQCRouter)
.errnz  IRQ_ROUTER_SIZE - (DHIRQERouter - DHIRQDRouter)
.errnz  IRQ_ROUTER_SIZE - (DHIRQFRouter - DHIRQERouter)

DosHlp32Code    ENDS

_TEXT   segment

;***LP  DHHWIRET - IRQ routers
;
;       This is the IRET handler.  It is used to field interrupts
;       before paging is enabled, and the interrupt manager is initialized.
;       It simply performs an IRET.
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
;       USES    NONE
;
;       CONTEXT Interrupt
;
;       NOTE:
;               This will work all all machines (including those with
;               level triggered interrupts) because it is only in use
;               when all IRQs are masked at the PIC.  It is necessary
;               to have these handlers, because one of the work arounds
;               for a 486 bug involved something called an "interrupt
;               stretcher".  The stretcher sometimes resulted in an
;               interrupt being pending at the INTR pin of the 486,
;               after all IRQs had been masked.  This resulted in a
;               spurious interrupt the next time an STI was executed.
;
;               The solution of just doing an IRET only works for
;               spurious interrupts (which do not set any bit in the
;               ISR).  This should not be a problem, since the hardware
;               would have to be really broken to generate a real
;               interrupt with all IRQs masked.  If it ever turns out
;               that this problem must be fixed, the fix must be guarenteed
;               to never drop an interrupt, or RIPL will be broken.
;
;               We install this handler for all hardware IRQs, so that
;               we can be sure that in the event that an interrupt
;               does occur, it will be handled, rather than faulting.
;
;               The code that installs this handler depends on this routine
;               being in the _TEXT segment.
;
        ASSUME  DS:NOTHING, ES:NOTHING, SS:NOTHING, FS:NOTHING, GS:NOTHING

DHHWIRET proc far
        public DHHWIRET
        iretd
DHHWIRET endp

_TEXT ends
        end
