; IBM/Microsoft Confidential
;
; Copyright (c) IBM Corporation 1987, 1989
; Copyright (c) Microsoft Corporation 1987, 1989
;
; All Rights Reserved

        page 78, 132
        title DHFIXUP, DosHlp Fixup Code

;****************************************************************************
;*                                                                          *
;* Source File: dhfixup.asm                                                 *
;*                                                                          *
;* Description:                                                             *
;*      This module has code for fixing up portions of the DosHlp code,     *
;*      that for performance reasons, need to be fixed up at initialization *
;*      time.                                                               *
;*                                                                          *
;* Entry points:                                                            *
;*      DHFixup -- fix up the code as per the fixup segment                 *
;*                                                                          *
;* External references:                                                     *
;*      none                                                                *
;*                                                                          *
;****************************************************************************

        include segments.inc            ; DosHlp segment definitions
        include dhfix.inc               ; Fixup macros
        include doshlp.inc              ; DosHlp macros
        include sysinvar.inc            ; Definition of DOSHLP_DATASEL

        .386p

        extrn   KAT:word
        extrn   IRQInfoBase:dword
        extrn   DosHlp_FLAT_Base:dword
        extrn   DiscDosHlp_FLAT_Base:dword
        extrn   _config_flags:word
        extrn   _bNWD:byte
        extrn   _IODelayCnt:word
        extrn   WDNMIEnabled:byte
        extrn   Flat_DSel:word

        extrn   DPResetWDNMI:near
        extrn   MCAResetWDNMI:near
        extrn   EISAResetWDNMI:near
        extrn   FakeResetWDNMI:near

DosHlpDisc32Code    segment
        assume cs:DGROUP
;** nearjmp_Kernel
;
;    This procedure performs the fixups for the Kjmp macro.  It replaces
;    the displacement of the near jump with the relative 32 address of the
;    kernel routine.
;
;    Entry
;       ES:EDI -> address to be fixed up
;       EBX = offset of next instruction
;
;    Exit
;       Normal: jmp fixed up, carry clear
;
;   USES    EAX, EBX, Flags

;   Procedure nearjmp_Kernel
;       set up relative addressing to KAT.KernelIRQRouter
;       patch up address
;       clear carry
;       exit

        public  nearjmp_Kernel
nearjmp_Kernel:
        push    ds
        push    fs
        mov     ax, DOSHLP_DATASEL  ; access doshlp data segment in prot mode
        mov     ds, ax
        assume  ds:DGROUP
        mov     ax, selSysInitData
        mov     fs, ax

        add     ebx, fs:DosHlp_FLAT_Base
        mov     eax, KAT.KernelIRQRouter
        sub     eax, ebx
        stosd                       ; fix address

        pop     fs
        pop     ds
        clc
        ret


;** loadbx_imm
;
;    This procedure performs the fixups for the ldirqi macro.   It replaces
;    the immediate operand in the mov ebx, imm with the value in ebx + the
;    offset of the IRQinfoTable.
;
;    Entry
;       ES:EDI -> operand to be fixed up
;       EBX = desired offset
;
;    Exit: carry clear
;
;   USES    EAX, EBX, Flags
;
;   Procedure loadbx_imm
;       add ebx to offset of IRQInfoTable
;       patch instruction
;       clear carry
;       exit

        public  loadbx_imm
loadbx_imm:
        push    ds
        mov     ax, selSysInitData
        mov     ds, ax
        assume  ds:DGROUP

        mov     eax, IRQInfoBase
        add     eax, ebx                    ; fix operrand
        stosd

        pop     ds
        clc
        ret

;** reset_nmi
;
;   This routine fixes up the resetnmi macro.  It replaces the destination
;   of the call with the linear offset of the appropriate routine.
;
;    Entry
;       ES:EDI -> opperand to be fixed up
;       EBX = offset of end of call instruction
;
;    Exit: carry clear
;
;   USES    EAX, EBX, Flags
;
;   procedure reset_nmi
;       if MCA
;               get offset of MCA reset nmi routine
;       elseif EISA
;               get offset of EISA reset nmi routine
;       elseif Compaq
;               get offset of DeskPro reset nmi routine
;       else /* we don't know how to support this machine, more machine
;               support here */
;               get address of fake routine
;       form offset for call
;       put offset into code


        public reset_nmi
reset_nmi:
        push    ds
        push    DOSHLP_DATASEL  ; access doshlp data segment in prot mode
        pop     ds
        assume  ds:DGROUP

        test    _config_flags, CFG_MCA
        jz      short rn20

        mov     eax, offset DGROUP:MCAResetWDNMI  ; PS/2
        jmp     short rn80

rn20:   test    _config_flags, CFG_EISA
        jz      short rn40

        mov     eax, offset DGROUP:EISAResetWDNMI ; EISA
        jmp     short rn80

rn40:   cmp     _bNWD, MACH_COMPAQ                ; running on Deskpro Compat?
        jne     short rn50

        mov     eax, offset DGROUP:DPResetWDNMI   ; deskpro
        jmp     short rn80

rn50:   mov     eax, offset DGROUP:FakeResetWDNMI ; unknow machine

rn80:   sub     eax, ebx                ; form relative displacement for call
        mov     es:[edi], eax

        clc
        pop     ds
        ret

;** clear_nmi
;
;   This routine fixes up the clearNMIcount macro.  It replaces the
;   the destination of the move immediate with the linear offset of the
;   system nmi count.
;
;    Entry
;       ES:EDI -> opperand to be fixed up
;
;    Exit: carry clear
;
;   USES    EAX

        public clear_nmi
clear_nmi:
        push    ds
        mov     ax, DOSHLP_DATASEL
        mov     ds, ax
        assume  ds:DGROUP

        mov     eax, KAT.KernelNMICount
        mov     es:[edi], eax
        pop     ds
        ret

;** test_WDNMI
;
;   This routine fixes up the testWDNMIEnabled macro.  It replaces the
;   the operand of the test immediate with the linear offset of the
;   WDNMIEnabled variable.
;
;    Entry
;       ES:EDI -> opperand to be fixed up
;
;    Exit: carry clear
;
;   USES    EAX, Flags

        public test_WDNMI
test_WDNMI:
        push    ds
        mov     ax, selSysInitData
        mov     ds, ax
        assume  ds:DGROUP

        mov     eax, offset DGROUP:WDNMIEnabled
        add     eax, DosHlp_FLAT_Base
        mov     es:[edi], eax
        pop     ds
        ret

;** push_flatds
;
;   This routine fixes up the pushflatds macro.  It replaces the
;   the operand of the push immediate with the flat data selector
;
;    Entry
;       ES:EDI -> opperand to be fixed up
;
;    Exit: carry clear
;
;   USES    EAX

        public push_flatds
push_flatds:
        push    ds
        mov     ax, selSysInitData
        mov     ds, ax
        assume  ds:DGROUP

        movzx   eax, Flat_DSel
        mov     es:[edi], eax
        pop     ds
        ret

;** cmp_flatds
;
;   This routine fixes up the cmpflatds macro.  It compares eax
;   with the flat data selector
;
;    Entry
;       ES:EDI -> opperand to be fixed up
;
;    Exit: carry clear
;
;   USES    EAX

        public cmp_flatds
cmp_flatds:
        push    ds
        mov     ax, selSysInitData
        mov     ds, ax
        assume  ds:DGROUP

        mov     ax, Flat_DSel
        mov     es:[edi], ax
        pop     ds
        ret

;** DHFixup
;
;   This routine is the driving routine for the DosHlp fixup code.  It sets
;   up for each of the fixups, and calls the appropriate routine through
;   the appropriate jump table.
;
;   Entry:
;       None
;
;   Exit
;       Normal: fixups performed, carry clear
;       Error: carry set
;
;   Uses: flags
;
;
;  Procedure DHFixup
;       convert fixup routine addresses to linear
;       get addressability of fixup segment
;       while more fixups to perform
;           get fixup info and address
;           get fixup type
;           call appropriate fixup routine
;           if error, set carry and exit
;       clear carry
;       exit

        public DHFixup
        assume ds:nothing, es:nothing, ss:nothing
BioFixUpTbl     label dword
        dd      offset DGROUP:nearjmp_Kernel
        dd      offset DGROUP:loadbx_imm
        dd      offset DGROUP:reset_nmi
        dd      offset DGROUP:clear_nmi
        dd      offset DGROUP:test_WDNMI
        dd      offset DGROUP:push_flatds
        dd      offset DGROUP:cmp_flatds
BioFixUpTblEnd  label dword

DHFixup proc    near

        push    ds
        pusha

        mov     ax, selSysInitData
        mov     ds, ax
        assume  ds:DGROUP

; Convert fixup routine addresses to linear

        mov     esi, offset BioFixUpTbl
dhfu5:  mov     eax, [esi]
        add     eax, DiscDosHlp_FLAT_Base
        mov     [esi], eax
        add     esi, 4
        cmp     esi, offset BioFixUpTblEnd
        jne     short dhfu5

        mov     esi, offset DGROUP:FIXUPBEGIN
dhfu10:
        cmp     esi, offset DGROUP:FIXUPEND ; while more fixups to do
        je      short dhfu60

;       set up for the call to the fixup routines
        mov     ebx, [esi].fusd             ; get fixup specific dword
        les     edi, [esi].fuaddr           ; get address
        mov     dl, [esi].fusb              ; get fixup specific byte

        push    esi

        movzx   esi, byte ptr [esi].futype  ; get fixup type
        shl     esi, 2                      ; make it a dword based index
        call    dword ptr BioFixUpTbl[esi]

        pop     esi
        jc      short dhfu70                ; error, exit
dhfu40:
        add     esi, size FixUpStruc
        jmp     short dhfu10                ; loop

dhfu60:
        clc
dhfu70:
        popa
        pop     ds
        ret
DHFixup endp

DosHlpDisc32Code    ends

_TEXT   segment

;** IODFixup
;
;   This routine is the driving routine for the IODelay fixup code.
;
;   Entry:
;       None
;
;   Exit
;       Normal: fixups performed, carry clear
;       Error: carry set
;
;   Uses: flags
;
;
;  Procedure IODFixup
;       get addressability of fixup segment
;       while more fixups to perform
;           get fixup info and address
;           get fixup type
;           perform fixup
;       clear carry
;       exit

        public IODFixup
        assume ds:nothing, es:nothing, ss:nothing

IODFixup proc   near

        push    ds
        push    es
        pusha

        mov     ax,cs
        mov     ds,ax
        mov     es,ax
        assume  ds:DGROUP

        mov     si, offset DGROUP:IODELAYFIXUPBEGIN
iofu10:
        cmp     si, offset DGROUP:IODELAYFIXUPEND ; while more fixups to do
        je      short iofu60

        mov     di, [si].iofuaddr           ; get address
        cmp     [si].iofusd,1               ; is 16-bit data needed
        jne     short iofu20                ; no

        mov     ax,_IODelayCnt      ; load iodelay count
        stosw                       ; fix instruciton
        jmp     short iofu50

iofu20:
        movzx   eax,_IODelayCnt     ; load iodelay count
        stosd                       ; fix instruction

iofu50:
        add     si, size IODelayFixUpStruc
        jmp     short iofu10                ; loop

iofu60:
        popa
        pop     es
        pop     ds
        ret

IODFixup endp

_TEXT   ends

        end
