.386p
page    58,132
;******************************************************************************
        title   InitDeb - initialize debugger
;******************************************************************************
;
;   (C) Copyright MICROSOFT Corp. 1986-1991
;   (C) Copyright COMPAQ Computer Corp. 1986-1991
;
;   Title:    EMM386.EXE - MICROSOFT Expanded Memory Manager 386 Driver
;
;   Module:   InitDeb - initialize debugger
;
;   Version:  2.00
;
;   Date:     June 16,1986
;
;   Author:   Steve Preston
;
;******************************************************************************
;
;   Change log:
;
;     DATE    REVISION                  DESCRIPTION
;   --------  --------  -------------------------------------------------------
;   06/16/86  Original  from VDM MAIN.ASM module
;   06/28/86  0.02      Name changed from CEMM386 to CEMM (SBP).
;   07/06/86  0.04      Changed assume to _DATA (SBP).
;   05/18/87  2.00      Changed GDT_Seg to R_CODE (SBP).
;   03/19/93  909  ELM  Changes to messages for usability.
;
;******************************************************************************
;
;   Functional Description:
;
;       This routine is linked in when linking with the kernel debugger.
;    InitDeb calls the debugger initialization routine.
;
;******************************************************************************
.lfcond                                 ; list false conditionals
;******************************************************************************
;       P U B L I C S
;******************************************************************************

        public  InitDeb
        public  ReInitDeb

;******************************************************************************
;       D E F I N E S
;******************************************************************************
        include vdmseg.inc
        include vdmsel.inc
        include desc.inc
        include emmfunct.inc
        include emm386.inc
;
; Definition of the packet used in debug initialization. A pointer to
; this structure is passed to Debug_Entry.
;
DebugInit       struc
        CSseg           dw      ?               ;Real mode code segment
        DSseg           dw      ?               ;Real mode data segment
        CSsel           dw      ?               ;Prot mode code selector
        DSsel           dw      ?               ;Prot mode data selector
        SpareSel1       dw      ?               ;Prot mode alias selector 1
        SpareSel2       dw      ?               ;Prot mode alias selector 2
        GDTalias        dw      ?               ;Prot mode GDT r/w alias
        ProtIDTaddr     dq      ?               ;Prot mode IDT base & limit
        RealIDTaddr     dq      ?               ;Real mode IDT base & limit
        BrkFlag         db      ?               ;TRUE if break to debugger
        ComFlag         db      ?               ;TRUE if com1, FALSE if com2
DebugInit       ends


;******************************************************************************
;       E X T E R N A L   R E F E R E N C E S
;******************************************************************************
ifdef   BugMode
dcode   segment
extrn   _Debug_Entry:far        ; (debinit.asm)
dcode   ends
endif

R_CODE  SEGMENT
extrn   GDT_Seg:word
extrn   IDT_Seg:word
extrn   GenFlags:dword
R_CODE ENDS

;******************************************************************************
;       S E G M E N T   D E F I N I T I O N S
;******************************************************************************

ifdef   BugMode
_DATA   SEGMENT
InitData        DebugInit       <>
_DATA ENDS
endif

R_CODE  segment
        public  DebugEntry
DebugEntry      dd      R_CODE:NoDebugEntry

        public  DebBreakStr
DebBreakStr     label   byte
ifdef DEBUG
                db      'EMM386 initialization',13,10  ;909 ELM;
endif
                db      0
R_CODE  ends

LAST SEGMENT

ifndef BugMode

MyDebugEntry    dd      0

debugddname     db      '$debugdd',0
emm386name      db      'emm386',0

debsegtable     label   word
        dw      R_CODE,         R_CODE,         RCODE_GSEL,     5040h
        dw      R_STACK,        R_STACK,        RMS_GSEL,       5041h
        dw      R1_CODE,        R1_CODE,        R1CODE_GSEL,    5040h
        dw      STACK,          VDMS_GSEL,      0,              5001h
        dw      GDT,            GDT,            GDTD_GSEL,      5041h
        dw      LDT,            LDT,            LDTD_GSEL,      5041h
        dw      IDT,            IDT,            IDTD_GSEL,      5041h
        dw      SGDT,           SGDT,           0,              5011h
        dw      SIDT,           SIDT,           0,              5011h
        dw      _DATA,          VDMD_GSEL,      0,              5001h
        dw      _TEXT,          VDMC_GSEL,      0,              5000h
        dw      LAST,           LAST,           0,              5011h
        dw      L_STACK,        L_STACK,        0,              5011h
debsegtablelen  equ     ($ - offset LAST:debsegtable)/8
endif
        assume cs:LAST, ds:_DATA, es:_DATA

;******************************************************************************
;       InitDeb - initialize kernel debugger
;
;
;    ENTRY:     Real Mode
;               DS = _DATA
;               AL = 00h => dont't break on debug init
;               AL = FFh => break on debug init
;
;    EXIT:      Real Mode
;               Kernel debugger initialized
;
;    USED:      none
;
;       NOTE:  this routine assumes that the GDT is addressible in real mode
;
;******************************************************************************
InitDeb proc    near
;
ifdef   BugMode
        pusha
        push    ds
        push    es
;
        push    ds
        pop     es              ; ES = data
;
        mov     di, offset _DATA:InitData

        mov     bx, dcode
        mov     [di].CSseg, bx
        mov     bx, ddata
        mov     [di].DSseg, bx
        mov     [di].CSsel, DEBC_GSEL
        mov     [di].DSsel, DEBD_GSEL
        mov     [di].SpareSel1, DEBW1_GSEL
        mov     [di].SpareSel2, DEBW2_GSEL
        mov     [di].GDTalias, GDTD_GSEL
        mov     [di].BrkFlag, al                ; ? break on entry ?
        mov     [di].ComFlag, FALSE             ; com2

        sidt    fword ptr [di].RealIDTaddr

        push    ds
        push    di
        mov     ax, seg R_CODE
        mov     ds,ax                   ; DS -> R_CODE
        ASSUME  DS:R_CODE

        mov     ax, [GDT_Seg]
        mov     ds, ax                  ; DS -> GDT

        db      66h
        lgdt    fword ptr ds:[GDTD_GSEL]

        mov     si, IDTD_GSEL
        mov     cx, 6
        lea     di, [di].ProtIDTaddr
        cld
        rep movsb
        pop     di
        pop     ds
        ASSUME  DS:_DATA

        call    _Debug_Entry
;
; and return
;
        pop     es
        pop     ds
        popa

else

    ASSUME   DS:NOTHING, ES:NOTHING, SS:NOTHING, GS:NOTHING, FS:NOTHING

; Initialize DEBX_GSEL GDT Selector and Deb386

        pusha
        push    ds
        push    es

        mov     ax,cs
        mov     ds,ax
    ASSUME   DS:LAST
        mov     dx,offset LAST:debugddname      ; ds:dx->db '$DebugDD',0
        mov     ax,3D00h
        int     21h
        jc      no_debdd

        mov     bx,ax
        mov     ax,R_CODE
        mov     ds,ax                           ; DS -> R_CODE
    ASSUME   DS:R_CODE
        mov     dx,offset R_CODE:DebugEntry     ; ds:dx->dd ?
        mov     cx,3001h
        mov     ax,440Ch
        int     21h

        mov     ah,3Eh
        int     21h
        jmp     short deb_init

no_debdd:
        mov     ax,R_CODE
        mov     ds, ax
    ASSUME   DS:R_CODE
        mov     ax,3568h                        ; get debugger int vector (68h)
        int     21h
        mov     ax,es
        or      ax,bx                           ; Q: non-zero vector?
        jz      deb_done                        ;  N: exit

        mov     ah,43h                          ; identify
        int     68h
        cmp     ax,0f386h                       ; Q: debugger exists?
        jne     short deb_done                  ;  N: exit

        mov     word ptr [DebugEntry],offset R_CODE:Int68DebugEntry

deb_init:
    ASSUME   DS:R_CODE

        bts     [GenFlags], fDebugActiveBit
        mov     ax, word ptr [DebugEntry]
        mov     word ptr [MyDebugEntry], ax
        mov     ax, word ptr [DebugEntry+2]
        mov     word ptr [MyDebugEntry+2], ax

        mov     es,[IDT_Seg]
        xor     di,di                           ; ES:DI <-- IDT

        mov     ds,[GDT_Seg]
    ASSUME   DS:NOTHING
        xor     si,si                           ; DS:SI <-- GDT

        mov     bx,DEBX_GSEL
        and     bl,SEL_LOW_MASK
        mov     word ptr [bx],0ffffh            ; Low Limit = 0ffffh
        mov     word ptr [bx + 2],0
        mov     byte ptr [bx + 4],0             ; Base = 0
        mov     byte ptr [bx + 5],D_DATA0       ; Ring 0 Data
        mov     byte ptr [bx + 6],8fh           ; Page Granularity/High Limit
        mov     byte ptr [bx + 7],0

        mov     bx,DEBX_GSEL                    ; BIG selector for all addresses
        mov     cx,DEB1_GSEL                    ; start of 5 working Selector
        mov     dx,GDTD_GSEL
        mov     ax,4400h                        ; Initialize Deb386
        call    [MyDebugEntry]

        mov     ax,LAST
        mov     es,ax
        mov     ds,ax
        mov     di,offset LAST:emm386name       ; (ES:DI) = module name
        mov     si,offset LAST:debsegtable      ; (DS:SI) = segment table
        mov     cx,debsegtablelen
deb_sym_loop:
        lodsw
        mov     bx,ax
        sub     bx,R_CODE                       ; (BX) = segment number
        push    cx
        lodsw
        mov     cx,ax                           ; (CX) = segment/selector
        lodsw
        mov     dx,ax                           ; (DX) = selector
        lodsw                                   ; (AX) = function/type
        call    MyDebugEntry
        pop     cx
        loop    deb_sym_loop

deb_done:
        pop     es
        pop     ds
        popa
endif
        ret
InitDeb endp


ifdef DEBUG

;******************************************************************************
;       DebDefineSeg - Define EMM386 segment to debugger
;
;
;    ENTRY:     Real/Virtual Mode
;               AL = segment type for debugger
;               BX = segment number as fixed up by loader
;               CX = segment address
;               DX = segment selector
;
;    EXIT:      Real Mode
;               Kernel debugger initialized
;
;    USED:      AX
;
;******************************************************************************

        public  DebDefineSeg

DebDefineSeg    proc    near

        push    es
        push    di

        mov     ah, 50h
        sub     bx, R_CODE              ; convert to segment #

        mov     di,LAST
        mov     es,di
        mov     di,offset LAST:emm386name       ; (ES:DI) = module name

        call    [MyDebugEntry]

        pop     di
        pop     es
        ret

DebDefineSeg    endp

endif

LAST    ends

R_CODE  segment
    ASSUME   CS:R_CODE

ReInitDeb proc near
    ASSUME   DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING
        pusha
        mov     bx,DEBX_GSEL                    ; BIG selector for all addresses
        mov     cx,DEB1_GSEL                    ; start of 5 working Selector
        mov     dx,GDTD_GSEL
        mov     ax,4a00h                        ; Reinitialize Deb386
        call    [DebugEntry]
        popa
        ret
ReInitDeb endp

Int68DebugEntry proc far
    ASSUME   DS:NOTHING,ES:NOTHING,SS:NOTHING,GS:NOTHING,FS:NOTHING
        int     68h
NoDebugEntry:
        ret
Int68DebugEntry endp

R_CODE  ends

        END
