;       SCCSID = @(#)dostask.asm        6.3 91/09/03
;      SCCSID = @(#)dostask.asm 6.3 91/09/03
PAGE    ,132
NAME    DOSTASK
TITLE   DOSTASK.ASM - External debugger task routines

;***    DOSTASK.ASM
;
;
;       The external debugger routines that implemenent
;       the ".p", ".r" and ".k" commands and the debugger
;       call outs that handle per task addressing.
;
;----------------------------------------------------------------------------
;****************************************************************************
;* Change log flagged with a @#nnnx                                    ;
;*   where the nnn is any unique number                                ;
;*   where the x is n for new code or a for added code                 ;
;*                  d for deleted code(commented out old code)         ;
;*                  c for changed code                                 ;
;*                                                                     ;
;*  @#001 WTE 05/31/91 Changes made for PTR PB723546,                  ;
;*                     SI reg not set to AddrS                         ;
;*                                                                     ;
;*  @#002 MTH 08/14/91 Changes made for PTR PB725079                   ;
;*  - added fixes so 'BT' command would work in 2.0                    ;@#002n
;*  21 May 1996 155531  RJM Fix .MAMC not to be like .MAMCA              ;
;*                                                                     ;
;*---------------------------------------------------------------------
;*
;****************************************************************************

INCL_MI =       1
INCL_ERROR_H =  1
INCL_ERROR2_H = 1

.xlist
;        include dosseg.inc
        include basemaca.inc
        include osmaca.inc
        include mi.inc
        include ostypes.inc
        include osconst.inc
        include dossymc.inc
        include vmowner.inc
        include sched.inc
        include sem.inc
        include screen.inc
;        include proc.inc
        include sigdef.inc
        include except.inc
        include infoseg.inc
        include curdir.inc
        include dirent.inc
        include find.inc
        include pgexport.inc
        include vmexport.inc
        include selxport.inc
        include tkexport.inc
        include tkptda.inc
        include sysinvar.inc
;        include kmode.inc
        include mvdmexp.inc
        include pglocal.inc
        include debseg.inc
        include debmac.inc
        include debequ.inc
        include debinit.inc
        include debsym.inc
        include debprt.inc
        include debdesc.inc
        include bseerr.inc
        include ldrvars.inc

        CpuMode 386
.list
;        ReferFlat       _mte_h,DWORD
;        ReferFlat       _DosModMte,BYTE
;        ReferFlat       _R0CS,WORD
;        ReferFlat       _R2CS,WORD
;        ReferFlat       _R3CS,WORD
;        ReferFlat       _R0DS,WORD
;        ReferFlat       _R2DS,WORD
;        ReferFlat       _R3DS,WORD
;        ReferFlat       _papTCBSlots,DWORD
;        ReferFlat       _uskdbSlot,WORD
;        ReferFlat       _ulkdbAddr,DWORD
;        ReferFlat       _ulkdbAddrLDT,DWORD
;        ReferFlat       _StartDFIRST,BYTE
;        ReferFlat       _TKSSBase,DWORD
;        ReferFlat       _pTCBCur,DWORD
;        ReferFlat       _pPTDACur,DWORD
;        ReferFlat       _cInDos,BYTE
;        ReferFlat       InterruptLevel,DWORD
;        ReferFlat       _pShSemTbl,DWORD
;        ReferFlat       _ulShTblSize,DWORD
;        ReferFlat       _TKSSBase,DWORD

;        ReferGlobal     MaxThreads,WORD
;        ReferGlobal     papTCBPtrs,WORD
;        ReferGlobal     InDos,BYTE
;        ReferGlobal     TaskNumber,WORD
;        ReferGlobal     FirstPacket,BYTE
;        ReferGlobal     LastPacket,BYTE
;        ReferGlobal     SysSemDataTable,BYTE

;        ReferGDT        GDT_PTDA,BYTE
;        ReferGDT        GDT_LDT,BYTE
         ReferGDT        GDT_Buffers,BYTE
;        ReferGDT        GDT_SFT,BYTE

;        EXTRN32         _tkKDBDaemon
;        EXTRN32         _TKWakeup
;        EXTRN32         _pgIsInCore
;        EXTRN32         pgSwitchRet
;        EXTRN32         _TKMakePresentKDB

;        EXTRNF32        KMExitKmodeEvents

Extern  CEntryGetProcStat, FAR          ;155531

GSEL                    equ     offset DOSGDTDATA:
LINES_PER_PAGE          equ     23
PS_NAME_LENGTH          equ     9               ; NO ROOM FOR EXTENSION!

; ProcStat      struc flags

psflags record  PF_3XBOX:1,     \
                PF_THREAD1:1,   \
                PF_CURRENT:1,   \
                PF_HASCHILD:1,  \
                PF_CHILD:1,     \
                PF_DEBCUR:1,    \
                PF_BLKINFO:1,   \
                PF_USER:1,      \
                PF_TSDSWAPPED:1,\
                PF_NOARGS:1,    \
                PF_QUEUEINFO:1

; .PQ command   struc flags
;               Bit clear if field points to self.  (Print blanks if set)

pqflags record  PRIQ_NEXTQ:1,     \
                PRIQ_PREVQ:1,     \
                PRIQ_HIGHER:1,    \
                PRIQ_LOWER:1,     \
                PRIQ_NEXT:1,      \
                PRIQ_PREV:1,

ProcStat        struc
        PS_BlockID              dd      0
        PS_SemInfo              dd      0
        PS_SemDebugAddr         dd      0
        PS_UserESP              dd      0       ; user's ESP
        PS_UserEIP              dd      0       ; user's EIP
        PS_pFrameBase           dd      0       ; pointer to frame base
        PS_pcriFrameType        dd      0       ; pointer to frame cri
        PS_iSlot                dw      0       ; Slot index
        PS_PTDAhandle           dw      0
        PS_Pid                  dw      0       ; pid
        PS_Ppid                 dw      0       ; parent pid
        PS_Csid                 dw      0       ; command subtree pid
        PS_MTEhandle            dw      0
        PS_Ordinal              dw      0       ; 1 based thread number
        PS_TCBcount             dw      0       ; Number of active threads
        PS_NextSlot             dw      0
        PS_MSW                  dw      0       ; MSW from PTDA
        PS_DispBP               dw      0       ; saved kernel BP
        PS_DispSP               dw      0       ; saved kernel SP (TSD-relative)
        PS_UserSS               dw      0       ; user's SS
        PS_UserCS               dw      0       ; user's CS
        PS_TCBCurrTCB           dw      0       ; CurrTCB when TCB is active
        PS_TCBCurrTSD           dw      0       ; CurrTSD when TSD is active
        PS_ParmBytes            dw      0       ; # parm bytes on user stack
        PS_priority             dw      0       ; Thread's priority
        PS_Flags                dw      0
        PS_AddrPTDA             db      size AddrS dup(0)
        PS_AddrTCB              db      size AddrS dup(0)
        PS_AddrTSD              db      size AddrS dup(0)
        PS_Name                 db      PS_NAME_LENGTH dup(0)
        PS_ScreenGroup          db      0       ; screen group number
        PS_state                db      0       ; Thread's state
        PS_Qstate               db      0       ; Thread's Queue state
        PS_QFlags               dw      0       ; Q flags - See PQ_ defines
        PS_AddrPriNextQ         db      size AddrS dup(0)
        PS_AddrPriPrevQ         db      size AddrS dup(0)
        PS_AddrPriHigher        db      size AddrS dup(0)
        PS_AddrPriLower         db      size AddrS dup(0)
        PS_AddrPriNext          db      size AddrS dup(0)
        PS_AddrPriPrev          db      size AddrS dup(0)
ProcStat        ends

DataSegmentStart

Extern  dumpInfoStruc, WORD

Extern  DebData, WORD
Extern  DefType, WORD
Extern  DisAddr, WORD
Extern  EnterAddr, WORD
Extern  DumpAddr, WORD
Extern  RegSA, WORD
Extern  pRegSA, WORD
; Extern  DosLinAddr, BYTE
; Extern  KDPpMTE,DWORD
; Extern  TrapNumber,WORD
; Extern  ErrorCode,WORD

Static  RegSave,        STRUC   RegSA_frame,    <>
Static  CurrTask,       WORD,   0               ; current task number
Static  CurrOldCS,      WORD,   0               ; old CS value
Static  CurrOldEIP,     DWORD,  0               ; old EIP value
Static  CurrOldSS,      WORD,   0               ; old SS value
Static  CurrOldESP,     DWORD,  0               ; old ESP value
Static  CurrOldEBP,     DWORD,  0               ; old EBP value
Static  SPchanged,      BYTE,   0               ; if !0, SP changed

Static  addrsSwapIn,    STRUC,  AddrS,          <>
Static  addrsTemp,      STRUC,  AddrS,          <>
Static  laddrSwapIn,    DWORD,  0
Static  laddrLDTSwapIn, DWORD,  0
Static  slotSwapIn,     DWORD,  0
Static  errSwapIn,      DWORD,  0
Static  TrapNumberSav,  WORD,   0
Static  ErrorCodeSav,   WORD,   0
Static  CurrTaskSav,    WORD,   0               ; current task number

;*      Process status print routines

Static ProcStatHeader1, STRING, <" Slot  Pid  Ppid Csid Ord  Sta Pri  pTSD     pPTDA    pTCB     Disp SG Name", CR, LF>
Static ProcStatHeader2, STRING, <" Slot  Sta BlockID  Name     Type        Addr    Symbol", CR, LF>
Static ProcStatHeader3, STRING, <" Slot  Pid  Ord  pPTDA    Name     pstkframe  CS:EIP        SS:ESP     cbargs", CR, LF>
Static ProcStatHeader4, STRING, <" Slot  QSt Pri  pTCB     PriNextQ PriPrevQ PriHigh  PriLow   PriNext  PriPrev  ", CR, LF>

StateMsgs       label   word

        .errnz  ($ - StateMsgs) - (STATE_VOID*2)
        dw      dataOFFSET VOIDmsg              ; 0
        .errnz  ($ - StateMsgs) - (STATE_READY*2)
        dw      dataOFFSET READYmsg             ; 1
        .errnz  ($ - StateMsgs) - (STATE_BLOCKED*2)
        dw      dataOFFSET BLOCKmsg             ; 2
        .errnz  ($ - StateMsgs) - (STATE_SUSPENDED*2)
        dw      dataOFFSET SUSPENDEDmsg         ; 3
        .errnz  ($ - StateMsgs) - (STATE_CRITSEC*2)
        dw      dataOFFSET CRITSECmsg           ; 4
        .errnz  ($ - StateMsgs) - (STATE_RUNNING*2)
        dw      dataOFFSET RUNNINGmsg           ; 5
        .errnz  ($ - StateMsgs) - (STATE_READYBOOST*2)
        dw      dataOFFSET RDYBOOSTmsg          ; 6
        .errnz  ($ - StateMsgs) - (STATE_TSD*2)
        dw      dataOFFSET TSDmsg               ; 7
        .errnz  ($ - StateMsgs) - (STATE_DELAYED*2)
        dw      dataOFFSET DELAYEDmsg           ; 8
        .errnz  ($ - StateMsgs) - (STATE_FROZEN*2)
        dw      dataOFFSET FROZENmsg            ; 9
        .errnz  ($ - StateMsgs) - (STATE_GETSTACK*2)
        dw      dataOFFSET GETSTACKmsg          ; 10
        .errnz  ($ - StateMsgs) - (STATE_BADSTACK*2)
        dw      dataOFFSET BADSTACKmsg          ; 11
        .errnz  ($ - StateMsgs) - (STATE_MAX*2) ; verify all states covered
        dw      dataOFFSET INVAL12msg           ; 12
        dw      dataOFFSET INVAL13msg           ; 13
        dw      dataOFFSET INVAL14msg           ; 14
        dw      dataOFFSET INVAL15msg           ; 15
        .errnz  ($ - StateMsgs) - (16*2)        ; verify all masks covered

Static  VOIDmsg,        STRING, "---"
Static  READYmsg,       STRING, "rdy"
Static  BLOCKmsg,       STRING, "blk"
Static  SUSPENDEDmsg,   STRING, "sus"
Static  CRITSECmsg,     STRING, "crt"
Static  RUNNINGmsg,     STRING, "run"
Static  RDYBOOSTmsg,    STRING, "bst"
Static  TSDmsg,         STRING, "tsd"
Static  DELAYEDmsg,     STRING, "dly"
Static  FROZENmsg,      STRING, "frz"
Static  GETSTACKmsg,    STRING, "gsk"
Static  BADSTACKmsg,    STRING, "bad"
Static  INVAL12msg,     STRING, "12?"
Static  INVAL13msg,     STRING, "13?"
Static  INVAL14msg,     STRING, "14?"
Static  INVAL15msg,     STRING, "15?"

Global VDMmsg,          STRING, "*vdm"
Static AGERthreadmsg,   STRING, "*ager"
Static TSDthreadmsg,    STRING, "*tsd"
Static CTXHthreadmsg,   STRING, "*ctxh"
Static KDBthreadmsg,    STRING, "*kdb"
Static LAZYWthreadmsg,  STRING, "*lazyw"           ;@#002n
Static ASYNRthreadmsg,  STRING, "*asyncr"
Global SYIthreadmsg,    STRING, "*sysinit"

ThreadMsgs      label   word
        dw      dataOFFSET VDMmsg               ; any VDM pid
        dw      dataOFFSET AGERthreadmsg        ; pid 1, thread 1
        dw      dataOFFSET TSDthreadmsg         ; pid 1, thread 2
        dw      dataOFFSET CTXHthreadmsg        ; pid 1, thread 3
        dw      dataOFFSET KDBthreadmsg         ; pid 1, thread 4
        dw      dataOFFSET LAZYWthreadmsg       ; pid 1, thread 5 @#002n
        dw      dataOFFSET ASYNRthreadmsg       ; pid 1, thread 6 @#002n
        dw      dataOFFSET SYIthreadmsg         ; pid 1, thread 7
MAXTHREADMSGS = (($ - ThreadMsgs)/2)

PrintProcStat   label   byte
        JumpIfBitSet    PS_Flags, PF_CHILD, pps00
        JumpIfBitSet    PS_Flags, PF_CURRENT, pps05
        OutBlank
        JumpOp          pps10

pps00   label           byte
        OutStr          "     "
        JumpOp          pps25

pps05   label           byte
        OutStr          "*"

pps10   label           byte
        OutWordHexPtr   PS_iSlot
        JumpIfBitSet    PS_Flags, PF_DEBCUR, pps15
        OutBlank
        JumpOp          pps20

pps15   label           byte
        OutStr          "#"

pps20   label           byte
        OutBlank
        JumpIfBitSet    PS_Flags, PF_BLKINFO, pps40
        JumpIfBitSet    PS_Flags, PF_QUEUEINFO, pps35

pps25   label           byte
        OutWordHexPtr   PS_Pid
        OutBlank
        JumpIfBitSet    PS_Flags, PF_USER, pps30

        OutWordHexPtr   PS_Ppid
        OutBlank

        OutWordHexPtr   PS_Csid
        OutBlank

pps30   label           byte
        OutWordHexPtr   PS_Ordinal
        OutBlanks        1
        JumpIfBitSet    PS_Flags, PF_USER, pps60
        JumpIfBitClr    PS_Flags, PF_CHILD, pps40
        OutStr          "child"
        OutBlanks       13
        JumpOp          pps50

pps35   label           byte
        OutMsgBitFlc    PS_Qstate, 0, 4, StateMsgs
        JumpOp          pps45

pps40   label           byte
        OutMsgBitFlc    PS_state, 0, 4, StateMsgs

pps45   label           byte
        OutBlank
        JumpIfBitSet    PS_Flags, PF_BLKINFO, pps55

        OutWordHexPtr   PS_priority
        OutBlank
        JumpIfBitSet    PS_Flags, PF_QUEUEINFO, pps65

pps50   label           byte
        OutDwordHexPtr  PS_AddrTSD.AddrOff
        OutBlank
        JumpOp          pps60

pps55   label           byte
        OutDwordHexPtr  PS_BlockID
        OutBlank
        JumpIfBitSet    PS_Flags, PF_BLKINFO, pps80

pps60   label           byte
        OutDwordHexPtr  PS_AddrPTDA.AddrOff
        OutBlank
        JumpIfBitSet    PS_Flags, PF_USER, pps80

pps65   label           byte
        OutDwordHexPtr  PS_AddrTCB.AddrOff
        OutBlank

        JumpIfBitSet    PS_Flags, PF_QUEUEINFO, pps85
        JumpIfBitSet    PS_Flags, PF_TSDSWAPPED, pps70
        OutWordHexPtr   PS_DispSP
        JumpOp          pps75

pps70   label byte
        OutBlanks       4

pps75   label byte
        OutBlank

        OutByteHexPtr   PS_ScreenGroup
        OutBlank

pps80   label           byte
        OutStrPtr       PS_Name, PS_NAME_LENGTH
        JumpIfBitClr    PS_Flags, PF_USER, pps90

        JumpIfBitF      PS_pFrameBase, 0, 32, 0, pps90
        OutBlank
        OutDwordHexPtr  PS_pFrameBase

        JumpIfBitSet    PS_Flags, PF_TSDSWAPPED, pps90

        OutBlank
        OutWordHexPtr   PS_UserCS
        OutStr          ":"
        OutDwordHexPtr  PS_UserEIP

        OutBlank
        OutWordHexPtr   PS_UserSS
        OutStr          ":"
        OutDwordHexPtr  PS_UserESP

        JumpIfBitSet    PS_Flags, PF_NOARGS, pps90
        OutBlank
        OutWordHexPtr   PS_ParmBytes
        JumpOp          pps90

pps85   label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_NEXTQ, pps85a
        OutBlanks       9
        JumpOp          pps85b

pps85a  label           byte
        OutDwordHexPtr  PS_AddrPriNextQ.AddrOff
        OutBlank

pps85b  label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_PREVQ, pps85c
        OutBlanks       9
        JumpOp          pps85d

pps85c  label           byte
        OutDwordHexPtr  PS_AddrPriPrevQ.AddrOff
        OutBlank

pps85d  label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_HIGHER, pps85e
        OutBlanks       9
        JumpOp          pps85f

pps85e  label           byte
        OutDwordHexPtr  PS_AddrPriHigher.AddrOff
        OutBlank

pps85f  label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_LOWER, pps85g
        OutBlanks       9
        JumpOp          pps85h

pps85g  label           byte
        OutDwordHexPtr  PS_AddrPriLower.AddrOff
        OutBlank

pps85h  label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_NEXT, pps85i
        OutBlanks       9
        JumpOp          pps85j

pps85i  label           byte
        OutDwordHexPtr  PS_AddrPriNext.AddrOff
        OutBlank

pps85j  label           byte
        JumpIfBitClr    PS_QFlags, PRIQ_PREV, pps85k
        OutBlanks       9
        JumpOp          pps90

pps85k  label           byte
        OutDwordHexPtr  PS_AddrPriPrev.AddrOff
        OutBlank

pps90   label           byte
        EndOp

extrn   _usDefaultSlot:word
DataSegmentEnd

CodeSegmentStart

Extern  perr, NEAR
Extern  ErrBreak, NEAR
Extern  command, NEAR
Extern  getdbit, FAR


;***    DumpUserStack
;
;       This is the ".K[S|B] [slot | * | #]" command.  It determines
;       which slot to operate on, calls GetProc*() routines to get info
;       for that slot, and then passes the user's SS:BP and CS:IP values
;       for that slot to PrintStack().
;
;       ENTRY   NONE
;
;       EXIT    NONE
;
;       USES    AX, BX, CX, DX, SI, DI, Flags
;
        assumeDATA   <ds, es, ss>

KM_REG_EFLAG    equ offset cri_eflag
KM_REG_EBP      equ offset cri_ebp
; LARRYB

DefProc DumpUserStack, NEAR, PUBLIC

LocVar  InUserSpace,BYTE
LocVar  Slot,WORD
LocVar  PS_Buffer,<size ProcStat>
LocVar  SSBPaddr,<size AddrS>
LocVar  CSIPaddr,<size AddrS>
LocVar  SizeFlag,WORD

BeginProc
        mov     [SizeFlag],0            ; 16 bit stack frame (0)
        Pcall   PeekChr
        jz      short dus20
        cmp     al,'S'
        je      short dus10
        cmp     al,'B'
        jne     short dus20
        inc     [SizeFlag]              ; 32 bit stack frame (1)
dus10:  Pcall   SkipB
        jmp     short dus30

dus20:  dec     [SizeFlag]              ; default size indication (-1)
dus30:  mov     dx,[CurrTask]           ; use CurrTask by default
        Pcall   ScanP                   ; get cmdlin parameters
        jz      short dus60
        cmp     al,'#'                  ; use debugger's current slot?
        je      short dus50             ; yes; that's the default
        cmp     al,'*'                  ; use currently scheduled slot?
        je      short dus40             ; yes; go get TaskNumber
        Pcall   EvalWord                ; (DX) = slot number
        jmp     short dus60

;       We come here to operate on the currently scheduled slot

dus40:  mov     dx,_usDefaultSlot       ; (DX) = slot number
        Pcall   SkipB
        jmp     short dus60

;       We come here to use the default (debugger's, see .S) slot

dus50:  Pcall   SkipB

;       Now the slot number is in DX.  If it's the currently scheduled
;       slot, and we aren't InDos, then .K is just like K, so call it

dus60:  mov     [InUserSpace],0         ; assume not
        cmp     dx,_usDefaultSlot       ; current scheduled slot?
        jne     short dus70             ; no, continue as normal
;        cmp     [InDos],0               ; in dos?
        jne     short dus70             ; yes, continue as normal
        mov     [InUserSpace],1         ; no, make a note of it
dus70:  cmp     [InUserSpace],1         ; can we call K?
        jne     short dus75             ; nope, go get info
        mov     di,[SizeFlag]
        Pcall   DumpStack2              ; yes, call "K" command
        jmp     short dusx

;       Get user info for the selected slot

dus75:  mov     [Slot],dx               ; save slot number
        lea     bx,PS_Buffer
;        Pcall   GetProcStat, <GET_PROC_USER, Slot, bx>

        lea     si,PS_Buffer
;        mov     cx,KM_REG_EFLAG
;        Pcall   GetRegister             ; (AX:DX) = user's eflags

        mov     di,EXPR_TYPE_SEL        ; (DI) = address type
        test    ax,(F_VM SHR 16)
        jz      short dus80
        mov     di,EXPR_TYPE_SEG        ; (DI) = address type

dus80:
;        mov     cx,KM_REG_EBP
;        Pcall   GetRegister             ; (AX:DX) = user's EBP

        lea     bx,SSBPaddr             ; (BX) = AddrS pointer
        Pcall   FillAddr, <bx, [PS_Buffer.PS_UserSS], dx, ax, [Slot], di>

        lea     bx,CSIPaddr             ; (BX) = AddrS pointer
        Pcall   FillAddr, <bx, [PS_Buffer.PS_UserCS], \
                           [PS_Buffer.PS_UserEIP.LowWord], \
                            [PS_Buffer.PS_UserEIP.HighWord], [Slot], di>

        lea     si,CSIPaddr             ; (SI) = CS:EIP AddrS
        mov     di,[SizeFlag]
        cmp     di,-1
        jne     short dus90

        push    ds
        push    si
        call    _getdbit
        add     sp,4
;        Ccall   getdbit, <si>

        mov     di,ax                   ; (DI) = 0 if d bit clear, !0 if set
dus90:  lea     bx,SSBPaddr             ; (BX) = SS:EBP AddrS
        Pcall   PrintStack
dusx:
EndProc

;***    DebGetCurrHobPTDA
;
;       Return the current hobPTDA to the caller.
;       ENTRY:  NONE
;       EXIT:   if carry clear, no errors
;                       (DX) = current slot's hobPTDA
;               if carry set,
;                       (AX) = error code, 0 = descriptor not copied
;       USES:   AX, BX, CX, DX, SI, DI, Flags

DefProc DebGetCurrHobPTDA,NEAR,PUBLIC
        assumeDATA <ds, es, ss>
LocVar  PS_Buffer,<size ProcStat>
BeginProc
        lea     bx,PS_Buffer
;        Pcall   GetProcStat, <GET_PROC_NORM, [CurrTask], bx>

        push    -1                      ; 155531 request default slot
        push    ds                      ; 155531 Sel     of PS_Buffer
        push    bx                      ; 155531 Offset  of PS_Buffer
        call far ptr _CEntryGetProcStat ; 155531 call 'C' code routine
        add     sp,4

        mov     dx,[PS_Buffer].PS_PTDAhandle

        clc                             ;155531
        or      bx,dx                   ;155531  zero handle?
        jnz     dgps1                   ;155531
        stc                             ;155531
dgps1:                                  ;155531

EndProc

;***    DebGetPDE - Returns the PDE for the linear address
;
;       ENTRY:  (EAX) = linear address
;               (BX)  = task number
;
;       EXIT:   If carry clear,
;                       (ECX) = PDE
;               If carry set,
;                       (ECX) = PDE (0)
;                       (AX) = error code
;                       if (AX) == 0,
;                           get PTE from current context
;
;       USES:   EAX, EBX, ECX, EDX, ESI, EDI, Flags
;
        assumeDATA <ds, es, ss>

DefProc DebGetPDE, NEAR, PUBLIC

LocVar  dgp_laddr, DWORD
LocVar  dgp_addrPTDA, <size AddrS>
LocVar  dgp_addrsTemp, <size AddrS>

BeginProc
        or      bx,bx
        jnz     short dgp10
        mov     bx,_usDefaultSlot       ; if zero, then get current task number
dgp10:  xor     ax,ax
        stc
dgpx:
EndProc


;***    DebGetFrame - return the frame number from a PDE or PTE
;
;       ENTRY   (EAX) = associated linear address
;               (ECX) = PDE or PTE (present bit is clear)
;               (BX)  = task number
;       EXIT    If carry clear,
;                   (EDX) = PTE frame
;               If carry set,
;                   (AX) = debugger error code
;       USES    EAX, EBX, ECX, EDX, ESI, EDI, Flags

        assumeDATA <ds, es, ss>

DefProc DebGetFrame, NEAR, PUBLIC

LocVar  dgf_pte, DWORD
LocVar  dgf_flags, DWORD
LocVar  dgf_frame, DWORD
LocVar  dgf_lin, DWORD

BeginProc
        jecxz   short dgf20             ; jump if pte is invalid
        mov     [dgf_lin],eax
        mov     [dgf_pte],ecx

;        movzx   esp,sp
;        push    ds
;        push    es
;        FlatContext <ds,es>,eax

;       translate not-present pte to frame:
;       frame = pgIsInCore(ppte), -1 if error

;        CCALL32 _pgIsInCore <dgf_pte>
;        pop     es
;        pop     ds
;    assumeDATA <ds, es>
;        mov     edx,eax
;        add     eax,1                   ; set carry if error (-1) returned
; LARRYB
        mov     edx,-1          ; return -1 for now
        clc
        jnc     dgfx
dgf10:  mov     ax,DEBERR_PAGE_NOT_PRESENT
        stc
        jmp     short dgfx

dgf20:  mov     ax,DEBERR_INVALID_ADDRESS
        stc
dgfx:
EndProc

;***    GetPTDAaddr
;
;       Get the address of a task's PTDA.
;
;       ENTRY:  (AX) = task number
;               (BX) = AddrS struc to put address
;       EXIT:   if carry clear,
;                       no error
;               if carry set,
;                       (AX) = error code
;       USES:   AX, Flags
;
        assumeDATA <ds, es, ss>

DefProc GetPTDAaddr,NEAR
        SaveReg <dx, si>

        cmp     ax, _dumpInfoStruc.max_threads ;  (CX) = number of process slots

        jae     short gpa2              ; jump if task number too high
        push    ax                      ; save the task number
; get the address of papTCBPtrs
        Pcall   FillSelAddr <bx, _dumpInfoStruc+64, _dumpInfoStruc+66, 0>
        Pcall   GetWord                 ; read the offset of the table
; address of the start of the table
        pop     ax                      ; get the task number back
        shl     ax,2                    ; times 4 to index dwords
        add     dx,ax                   ; plus the starting offset
        Pcall   FillSelAddr <bx, _dumpInfoStruc+64, dx, 0>
        Pcall   GetDword                ; get the TCB address
        mov     si,ax
        or      si,dx                   ; Is address zero?
        jz      short gpa2              ;  yes, bad slot

;       (BX) = pointer to AddrS
;       (AX) = high word of address
;       (DX) = low word of address

        Pcall   FillLinAddr <bx,dx,ax>
        Pcall   GetDwordOff <word ptr TCBpPTDA, 0> ; (AX:DX) = PTDA address
        Pcall   FillLinAddr <bx,dx,ax>
        or      ax,dx                   ; PTDA address valid?
        jz      short gpa2              ;  no, return error (OR clears carry)
        jmp     short gpa3              ; Success

gpa2:   mov     ax,DEBERR_INVALID_TASK_NUMBER
        stc                             ; map every error into this one
gpa3:   RestReg <si, dx>
EndProc

ifdef CRSLATER

;***    GetRegister
;
;       Get the user's register.
;
;       ENTRY:  (CX) = register number
;               (SI) = PS structure pointer
;
;       EXIT:   (AX:DX) = register value
;               if carry clear,
;                       no error
;               if carry set,
;                       register number invalid
;
;       USES:   AX, BX, CX, DX, Flags
;
        assumeDATA <ds, es, ss>

DefProc GetRegister,NEAR,LOCAL

LocVar  grg_addrsTemp, <size AddrS>
LocVar  grg_flags, WORD
LocVar  grg_offset, WORD

BeginProc
        lea     bx,[grg_addrsTemp]
        Pcall   FillLinAddr, <bx, [si].PS_pcriFrameType>
        Pcall   GetDwordOff, <cx, 0>    ; (AX) = offset, (DX) = flags
        jc      short grg35
        mov     [grg_flags],dx
        mov     [grg_offset],ax
        test    dx,KM_RIP_INVALID
        jnz     short grg35
        test    dx,KM_RIP_TSD_RELATIVE
        jnz     short grg10
        Pcall   FillLinAddr, <bx, [si].PS_pFrameBase>
        jmp     short grg20

grg10:  lea     ax,[si].PS_AddrTSD
        Pcall   CopyAddr, <ax, bx>
grg20:  Pcall   AddAddr, <[grg_offset], 0>
        test    [grg_flags],KM_RIP_WORD
        jz      short grg40
        Pcall   GetWord                 ; (DX) = register
        jc      short grg30
        xor     ax,ax                   ; CARRY CLEAR
        jmp     short grgx

grg30:  or      [si].PS_Flags,mask PF_TSDSWAPPED ; TSD must be swapped out
grg35:  xor     ax,ax
        xor     dx,dx
        stc
        jmp     short grgx

grg40:  Pcall   GetDword                ; (AX:DX) = register
        jc      short grg30
grgx:
EndProc

endif ; CRSLATER

;***    InvalidHandle - print invalid handle message
;
;       ENTRY:  (DX) = bad handle
;
;       EXIT:   Does not return
;
;       USES:   NONE
;
        assumeDATA <ds, es, ss>

DefProc InvalidHandle,NEAR,PUBLIC
        putstr  "Bad handle: "
        Pcall   out16
        Jump    CmdBreak
EndProc NoGen

IFDEF   KDP
;***    KDPNextModule - Finds next module mte handle.
;
;       USHORT KDPNextModule(VMHOB *phmte, ULONG *ppmte);
;
;       ENTRY:  None
;
;       EXIT:   (AX) = 0, No error
;               *phmte = next mte handle
;               *ppmte = flat mte pointer
;
;               (AX) != 0, No more modules
;
;       USES:   AX
;
        assumeDATA <ds, es, ss>

DefProc KDPNextModule, NEAR, PUBLIC, C
ArgVar  phmte,          WORD            ; mte handle buffer
ArgVar  ppmte,          WORD            ; flat mte pointer buffer

BeginProc
        SaveReg <ecx,dx,bx>
        mov     ecx,KDPpMTE             ; (ECX) = last pMTE returned
        push    ds
        FlatContext <ds>,ax
        jecxz   short knm10             ; if (last pMTE != NULL)

        mov     ecx,[ecx].mte_link      ;    (ECX) = last pMTE->mte_link
        jmp     short knm20             ; else

knm10:  mov     ecx,_mte_h              ;    (ECX) = mte list head

knm20:  mov     ax,ERROR_MOD_NOT_FOUND  ; initialize return value
        jecxz   short knm30             ; if (pMTE != NULL)

        mov     dx,[ecx].mte_handle     ;    (DX) = mte handle
        .errnz  NO_ERROR
        xor     ax,ax                   ;    (AX) = NO_ERROR
knm30:  pop     ds
        assumeDATA <ds>
        mov     bx,[ppmte]
        mov     [bx],ecx                ; *ppmte = pMTE
        mov     KDPpMTE,ecx             ; last pMTE returned = pMTE
        mov     bx,[phmte]
        mov     [bx],dx                 ; *hmte = mte handle
        RestoreReg <bx,dx,ecx>
EndProc

;***    KDPhmte2pmte - Translate mte handle to flat mte pointer
;
;       USHORT KDPhmte2pmte(VMHOB hmte, ULONG *ppmte);
;
;       ENTRY:  (hmte) = mte handle (0 implies DosModMte)
;               (ppmte) = pointer to space for flat pMTE
;
;       EXIT:   (AX) = 0, No error
;               *ppmte = flat mte pointer
;
;               (AX) != 0, invalid handle
;
;       USES:   AX
;
        assumeDATA <ds, es, ss>

DefProc KDPhmte2pmte, NEAR, PUBLIC, C

ArgVar  hmte,           WORD            ; mte handle
ArgVar  ppmte,          WORD            ; mte pointer buffer

BeginProc
        SaveReg <bx,ecx>
        .errnz  NO_ERROR
        xor     ax,ax                   ; initialize return value
        mov     ecx,offset FLAT:_DosModMte
                                        ; (ECX) = DosModMTE
        mov     bx,[hmte]               ; (BX) = mte handle
        or      bx,bx                   ; if (mte handle != 0) {
        jz      short khp3

        push    ds
        FlatContext <ds>,cx
        mov     ecx,ds:_mte_h           ;  (ECX) = mte list head
khp1:   cmp     ds:[ecx].mte_handle,bx  ;  while (ECX)->mte_handle != mte_handle
        je      short khp2              ;   {

        mov     ecx,ds:[ecx].mte_link   ;   (ECX) = (ECX)->mte_link
        or      ecx,ecx                 ;   if (ECX) = NULL
        jnz     short khp1

        mov     ax,ERROR_MOD_NOT_FOUND  ;      (AX) = ERROR_MOD_NOT_FOUND
                                        ;      break
                                        ;   }
khp2:   pop     ds
        assumeDATA <ds>
                                        ; }
khp3:   mov     bx,[ppmte]
        mov     [bx],ecx                ; *ppmte = (ECX)
khpx:   RestoreReg <ecx,bx>
EndProc

;***    KDPpmte2name - Translate mte flat pointer to module name
;
;       ENTRY:  hmte = mte handle
;               pbuf = buffer for name
;
;       EXIT:   (AX) = name length (including terminating zero)
;
;       USES:   AX
;
        assumeDATA <ds, es, ss>

DefProc KDPpmte2name, NEAR, PUBLIC, C

ArgVar  pmte,           DWORD           ; module mte
ArgVar  pbuf,           WORD            ; module name buffer

BeginProc
        SaveReg <edi>
        mov     edi,[pmte]              ; if (pmte != NULL) {
        or      edi,edi
        je      short khnx

        mov     ax,[pbuf]               ;  (AX) = name buffer
        SaveReg <ds,esi>
        FlatContext <ds>,si
        mov     edi,ds:[edi].mte_swapmte;  (EDI) = pointer to swappable mte
        mov     esi,ds:[edi].smte_path  ;  (ESI) = pmte->mte_path
        mov     di,ax                   ;  (DI) = name buffer

khn1:   lods    byte ptr ds:[esi]       ;   (ES:DI)++ = (AL) = (DS:ESI)++
        stosb
        or      al,al                   ;  } WHILE (AL != NULL)
        jnz     short khn1

        RestoreReg <esi,ds>             ; }
        assumeDATA <ds>

        sub     di,[pbuf]

khnx:   mov     ax,di                   ; return(Name length)
        RestoreReg <edi>
EndProc

;***    KDPObjInfo - convert mte, obj/seg index to selector, base, flags
;
;       ENTRY:  koi_hmte = module mte handle
;               koi_iote = obj/seg table index
;               koi_psel = address to store selector
;               koi_offset = address to store base
;               koi_pflags = address to store flags
;
;       USES:   Flags
;
        assumeDATA <ds, es, ss>

DefProc KDPObjInfo, NEAR, PUBLIC, C

ArgVar  koi_hmte,       WORD            ; module mte
ArgVar  koi_iote,       WORD            ; object table index
ArgVar  koi_psel,       WORD            ; pointer to selector
ArgVar  koi_poffset,    WORD            ; pointer to dword offset
ArgVar  koi_pflags,     WORD            ; pointer to object flags
LocVar  koi_pmte,       DWORD           ; pointer to module mte

BeginProc
        SaveReg <eax,ebx>
        lea     bx,[koi_pmte]
        Ccall   KDPhmte2pmte,<[koi_hmte],bx>
        or      ax,ax
        jnz     koix

        mov     eax,[koi_pmte]          ; (EAX) = pMTE
        SaveReg <ecx,edx,edi,esi>
        push    ds
        FlatContext <ds>,dx
        movzx   ecx,[koi_iote]          ; fetch object table index
        dec     ecx

;;davidj 03/15/93
ifdef BORG
        push    eax                     ; what format module ?
        mov     ax,[eax].mte_flags2
        and     ax,MTEFORMATMASK
        or      ax,MTEFORMATNE
        pop     eax
else
        cmp     word ptr ds:[eax].mte_magic,454EH     ; NEMAGIC = 0x454E "NE"
endif
;;davidj
        mov     esi,ds:[eax].mte_swapmte ; (ESI) = pointer to swappable mte
        mov     esi,ds:[esi].smte_objtab ; (ESI) = seg/obj table
        je      koi30                   ; jump if segment table

        imul    ecx,size ldrote_s       ; use object table format
        add     ecx,esi                 ; (ECX) = object table entry

        mov     esi,ds:[ecx].ote_flags  ; (ESI) = object flags
        mov     edx,ds:[ecx].ote_base   ; (EDX) = object base

        mov     edi,ds:[eax].mte_mflags
        test    edi,DOSMOD
        jz      short koi5

        mov     ax,ds:[ecx].ote_selector
        test    esi,OBJBIGDEF
        jz      koi40
        jmp     koi50

koi5:   test    esi,OBJBIGDEF
        jz      short koi20             ; jump if 16:16 object

        test    esi,OBJEXEC             ; 0:32 object
        jz      short koi10
        mov     ax,ds:_R0CS             ; Code object
        test    edi,VDDMOD
        jnz     short koi50
        mov     ax,ds:_R3CS
        test    esi,OBJIOPL
        jz      short koi50
        mov     ax,ds:_R2CS
        jmp     short koi50

koi10:  mov     ax,ds:_R0DS             ; Data object
        test    edi,VDDMOD
        jnz     short koi50
        mov     ax,ds:_R3DS
        test    esi,OBJIOPL
        jz      short koi50
        mov     ax,ds:_R2DS
        jmp     short koi50

;       (EDX) = linear address

koi20:  and     edx,SEL_LADDR_MASK      ; 16:16 object
        shr     edx,SEL_LADDR_SHIFT
        mov     ax,dx                   ; (AX) = selector
        or      ax,SEL_LDTBIT           ; All DLL objects are LDT
        or      ax,SEL_RPL2
        test    esi,OBJIOPL
        jnz     short koi40
        or      ax,SEL_RPL3
        jmp     short koi40

koi30:  imul    ecx,size ldrste_s       ; use segment table format
        add     ecx,esi                 ; (ECX) = segment table entry

        mov     ax,ds:[ecx].ste_selector ; (AX) = selector
        movzx   esi,ds:[ecx].ste_flags  ; (ESI) = segment flags

koi40:  xor     edx,edx                 ; Base = 0

koi50:  mov     bx,[koi_poffset]
        mov     es:[bx],edx             ; Store base

        mov     bx,[koi_psel]
        mov     es:[bx],ax              ; Store selector

        mov     bx,[koi_pflags]
        mov     es:[bx],esi             ; Store flags

        pop     ds
        assumeDATA <ds>
        RestoreReg <esi,edi,edx,ecx>
koix:   RestoreReg <ebx,eax>
EndProc
ENDIF

CodeSegmentEnd

        end
