/*****************************************************************************

   (C) Copyright MICROSOFT Corp., 1988-1992

   Title:      DEBUGSYS.INC - VMM debugging include file

   Version:    1.00

   Date:       13-Jun-1988

   Author:     RAL

------------------------------------------------------------------------------

   Change log:

      DATE     REV                 DESCRIPTION
   ----------- --- -----------------------------------------------------------
   13-Jun-1988 RAL
   24-Oct-1988 RAP changed INT from 2E to 41, and added functions for
                   Windows to notify the debugger about segment selectors
   14-Dec-1988 RAP split services into ones available through INT 41h
                   for non-ring 0 clients and those available through INT 21h
                   for ring 0 clients
   11-Dec-1990 ERH Merged WIN386 copy with file actually used by the
                   debugger.
   11-Dec-1990 ERH Merged file describing real mode services with this
                   one.
   24-Feb-1997 AJO Converted from inc to h, added WDeb98 stuff, PTrace stuff

==============================================================================*/

#ifndef _DEBUGSYS_H
#define _DEBUGSYS_H

/*
 * Note: You must define WDEB98 to use any of the new WDEB98 services...
 *
 */

/******************************************************************************

  Real mode Debugger services:

*/

// hooked by the debugger in real mode.
#define D386_RM_Int             0x68 

// debugger identification code
#define D386_Id                 0x0F386 

// minimum INT 68 function code
#define D386_MIN                0x43 

// returns debugger identification, if debugger loaded
#define D386_Identify           0x43 

// partially prepare for protected mode operation.
#define D386_Prepare_PMode      0x44
/* 
   A pointer to a procedure is returned so that the IDT can also be set in
   protected mode

   INPUT:
     AL    0  - retail version of Win386
           1  - debugging version
     BX    a valid selector that gives access to all of memory
     CX    first of 2 selectors reserved for WDeb386 to use
     DX    is GDT selector
     DS:SI pointer to working copy of GDT
     ES:DI pointer to working copy of IDT
   
   RETURN:
     ES:EDI points to a protected mode procedure (selector:offset32) that can 
     be called to set the IDT when it has been created. Takes a function
     number in AL. See the PMINIT equates.
*/


// re-init from real mode after entering pmode
#define D386_Real_Mode_Init     0x45 

// set debugging switches
#define D386_Set_Switches       0x46 
/*
   BL = verbose switch
        - 00b - no segment display
        - 01b - display win386 segments only
        - 10b - display ring 1 segments only
        - 11b - display win386 & ring 1 segs
   BH = conditional brkpts
        0 - off
        1 - on
   -1 for BX means no change (default)
*/

// execute conditional BP (/B option)
#define D386_Execute_Cond       0x47 
// ES:SI points to NUL terminated string to print if conditional flag set.

// undefine the real mode segment's symbols
#define D386_Free_Segment       0x48 
// BX = real mode segment to undefined

// set com port baud rate
#define D386_Set_Baudrate       0x49 
// BX = baud rate

// reinitialize debugger for protected mode
#define D386_Reinit             0x4a
/*
   AL  0  - retail version of Win386
       1  - debugging version of Win386
       2  - 286 DOS extender (3.0)
       3  - 286 DOS extender under VCPI (3.1)
       4  - 286 DOS extender (3.1)
   BX  a valid selector that gives access to all of memory
   CX  first of 2 selectors reserved for wdeb386 to use
   DX  is GDT selector

  This function can after a function 45h only if function 44h was executed in
  the past on the IDT/GDT.
*/

// define debugger's segments
#define D386_Def_Deb_Segs       0x4b

// set com port number
#define D386_Set_Com_Port       0x4c
// BX = com port number
// returns AX != 0, error bad com port

// link sym file map
#define D386_Link_Sym           0x4d
/*
  
   ES:DI pointer to AddrS struc in front of sym file map.
   BX    loader ID (used to unlink sym file maps)
         A loader ID of 0 is used for all the maps
         wdeb386 loads via /S is ran as a program and
         -1 is used by the device driver version.  All
         loader IDs of 0 are automaticly unlinked when
         wdeb386 exits.
*/




// unlink sym file maps
#define D386_Unlink_Sym         0x4e
/* 
   BX = loader ID - this routine looks at all
        of the maps that are currently linked and
        removes the ones that were loaded with this
        ID.
*/




// remove any undefined segments from the name module's symbols
#define D386_Remove_Segs        0x4f 
// ES:DI pointer to module name




// defines the actual segment/selector for a loaded segment to allow for
// symbol processing
#define D386_Load_Segment       0x50
/*
   INPUT:
     AL segment type   0  - code selector
                       1  - data selector
                      10h - code segment
                      11h - data segment
                      20h - real-mode EXE
                      40h - code segment & sel
                      41h - data segment & sel
                      80h - device driver code seg
                      81h - device driver data seg
     If AL = 20h then
        CX = paragraph number
        ES:DI pointer to module name
     Else If AL < 80h then
        BX segment #
        CX actual segment/selector
        DX actual selector  (if 40h or 41h)
        ES:DI pointer to module name
     Else
        ES:DI points to D386_Device_Params struc

     RETURN:
       AL = 1, if successful, else 0
*/





// display a character to the debugging terminal
#define D386_Display_Char       0x51
// AL = char to display



// display a string to the debugging terminal
#define D386_Display_Str        0x52
// ES:SI points to NUL terminated string



// returns if debug VxD has been installed
#define D386_IsVxDInstalled     0x53
// AL == 0 if not install, AL != 0 if installed



// sets that the debug VxD installed/uninstalled
#define D386_VxDInstall         0x54
// BL == 0 if uninstall, BL != 0 if installed



// registers dot command
#define D386_RegisterDotCmd     0x55
/*
   INPUTS
     BL    = command letter
     CX:SI = address of dot command routine
     DX:DI = address of help text

   RETURNS
     AX == 0, no errors
     AX != 0, dot command already used or out of dot commands

   Dot command routine:
   -------------------
   CALLED WITH
     AL    = command character
     DS:SI = linear address of command line terminated by a NULL or ";".
     DS,ES = debugger's data selector

   RETURNS
     AX ==0, no errors
     AX !=0, command line or option error
*/




// de-registers dot command
#define D386_DeRegisterDotCmd   0x56
// BL = command letter




// Printf
#define D386_Printf             0x57
/*
   (DS:SI) = address of format string
   (ES:DI) = address of the start of parameters
   set DS_Printf for format char information
   returns (AX) = number of characters printed
*/



// link symbol file with physical address
#define D386_Link_Sym_Phys      0x58
/* 
   (DX:CX) = physical address of one extra 
             paragraph front of map file image.
   (SI)    = XMS handle (0 if just physical)
   (BX)    = load id
*/




#define D386_CheckMap           0x59
/*
   DX:DI = pointer to module name
   returns AX != 0, map found
           AX == 0, map not found
*/



#define D386_SetAutoLoadSym     0x5a
/*
   (BL) != 0, auto load symbols
   (BL) == 0, don't auto load symbols
*/



#define D386_SetTeftiPort       0x5b
// (BX) = TEFTI port address



// execute debugger command script
#define D386_ExecDebugCommand   0x5c
/* 
   (DS:SI) = ptr to debugger command script str
   (CX) = size of script
*/



// makes the debugger copy its code/data high
#define D386_LoadCodeDataHigh   0x5d
// (DX:BX) = physical address to put debugger



// sets Windows version number
#define D386_SetWinVersion      0x5e
// (DI) = Version number (default if this api not called is 0300h).


// scan for character
#define D386_ScanChar           0x5f
// returns AL == 0, no char. AL != 0, char



// ungetchar scaned character 
#define D386_UnGetChar          0x60
// AL = char


// stop at the CS:IP specified
#define D386_Stop               0x61 
/*
   TOS + 0 = AX
   TOS + 2 = IP
   TOS + 4 = CS
*/

#ifdef WDEB98

// set com port baud rate (beyond 57600)
#define D386_Set_Baudrate_Ex    0x62
// EBX = baud rate, EBX is zero if successful

// programs wdeb with windows info
#define D386_SetBuildInfo       0x63
// DS:EDX points to string of from "4.00.0950" or similar.

// Sets new switches for WDEB
#define D386_Set_Switches_Ex    0x64
// EBX [0:1] controls text packet usage:
//           00 - No change
//           01 - Off
//           10 - On with timeouts (switchbox environment)
//           11 - On with infinite retries
//
// All other bits in EBX are reserved and must be zero.
// 


#define D386_MAX                0x64 // maximum INT 68 function code

#else  // WDEB98

#define D386_MAX                0x61 // maximum INT 68 function code

#endif // WDEB98



// D386_Load_Segment type ates:

#define ST_code_sel     0x0           // code selector
#define ST_data_sel     0x1           // data selector
#define ST_code_seg     0x10          // code segment
#define ST_data_seg     0x11          // data segment
#define ST_dual_code    0x40          // code segment and selector
#define ST_dual_data    0x41          // data segment and selector
#define ST_device_code  0x80          // device driver code segment
#define ST_device_data  0x81          // device driver data segment

// D386_Load_Segment device load parameters structure
// Don't let h2inc see FWORD as it doesn't understand FWORD, QWORD, & TWORD

/*XLATOFF*/
struct D386_Device_Params {
   WORD  DD_logical_seg  ;   // logical segment # from map
   WORD  DD_actual_sel   ;   // actual selector value
   DWORD DD_base         ;   // linear address offset for start of segment
   DWORD DD_length       ;   // actual length of segment
   FWORD DD_name         ;   // 16:32 ptr to null terminated device name
   FWORD DD_sym_name     ;   // 16:32 ptr to null terminated symbolic
                             //   module name (i.e. Win386)
   WORD  DD_alias_sel    ;   // alias selector value (0 = none)
  } ;

/*XLATON*/

/* ASM
D386_Device_Params	STRUC
DD_logical_seg          DW      ?
DD_actual_sel           DW      ?
DD_base                 DD      ?
DD_length               DD      ?
DD_name                 DF      ?
DD_sym_name             DF      ?
DD_alias_sel            DW      ?
D386_Device_Params	ENDS
*/

// WDEB int 2f subfunctions (AH = W386_INT_MULTIPLEX, AL = W386_WDEB)
// Entry: BX = subfunction number

#define WDEB_INT2F_STARTING             0x0       // first time starting
#define WDEB_INT2F_ENDING               0x1       // first time ending
#define WDEB_INT2F_NESTED_STARTING      0x2       // start on level of nesting
#define WDEB_INT2F_NESTED_ENDING        0x3       // end one level of nesting

// PMINIT routine functions

#define PMINIT_INIT_IDT                 0x0     // (ES:EDI) = pointer to PM IDT

#define PMINIT_INIT_PAGING              0x1     // (BX) = phys-linear selector 
                                                // (ECX) = phys-linear bias

#define PMINIT_ENABLE_DEBUG_QUERYS      0x2     // enables dot commands, etc.

#define PMINIT_INIT_SPARE_PTE           0x3     // (EBX) = lin addr of spare PTE
                                                // (EDX) = lin addr the PTE is

#define PMINIT_SET_ENTER_EXIT_VMM       0x4     // (EBX) = Enter VMM routine addr
                                                // (ECX) = Exit VMM routine addr
                                                // This routines must return 
                                                // with a retfd.

#define PMINIT_GET_SIZE_PHYS            0x5     // get debugger size/phys addr
                                                // returns:
                                                //    AL = 0 (don't call AL=1)
                                                //    ECX = size in bytes
                                                //    ESI = starting phys addr
                                                // if this call is ignored
                                                // (AL = 5) then function 1 is
                                                // called with a phys-linear
                                                // region

#define PMINIT_SET_BASE_SPARE_PTE       0x6     // set debugger base/spare PTE
                                                // EBX = laddr of spare PTE
                                                // EDX = laddr the PTE represents
                                                // ESI = starting linear address

#define PMINIT_ENABLE_MEMORY_CONTEXT    0x7     // enables mem context functions

#define PMINIT_MAX                      0x7

/*
   VCPI information, passed to debugger when client is DOS Extender
   running as a VCPI client.  This information is used to get into
   and out of protected mode when running under a VCPI server.


   This structure is also used by the DOS Extender.
*/

// Don't let h2inc see FWORD as it doesn't understand FWORD, QWORD, & TWORD

/*XLATOFF*/
struct WdebVCPIInfo {
   // Enter protected mode information.
   FWORD fnVCPI     ; // VCPI protect mode server entry point
   WORD  rdsVCPI    ; // Selector for VCPI server

   // Enter v86 mode information.
   DWORD laVTP      ; // linear address of data structure containing
                      // values for system registers.
   WORD  Port67     ; // Qualitas magic port for emulating INT 67h
  } ;
/*XLATON*/

/* ASM
WdebVCPIInfo	STRUC
fnVCPI  DF      ?
rdsVCPI	DW	?
laVTP	DD	?
Port67	DW	?
WdebVCPIInfo	ENDS
*/


/*
   The following structure contains the system register contents for the
   VCPI server to use when switching to protected mode.  It is taken
   from dxvcpi.inc in the DOSX project, and is part of the VCPI spec.
*/

struct VTP {
   DWORD zaCr3VTP        ; // physical addr of page directory
   DWORD laGdtrVTP       ; // linear addr in first meg of gdtr
   DWORD laIdtrVTP       ; // linear addr in first meg of idtr
   WORD  selLdtVTP       ; // selector of ldt
   WORD  selTrVTP        ; // selector of tr
   WORD  ipVTP           ; // 48-bit address of protect
   WORD  unusedVTP       ; //   mode entry point to xfer to
   WORD  csVTP           ; //
  } ;  

#define VCPI_RM_CALLOUT_INT     0x67    // v86 mode call to VCPI server


/*
   Send this value in AX to the VCPI server to request V86 to protected
   mode switch or protected to V86 mode switch.
*/
#define VCPI_PROT_ENTRY         0x0DE0C


/*****************************************************************************

   Protected mode Debugger services:

*/


#define Debug_Serv_Int   0x41 // Interrupt that calls Deb386 to perform
                              // debugging I/O, AX selects the function as
                              // described by the following equates

#define DS_Out_Char      0x0  // function to display the char in DL

#define DS_In_Char       0x1  // function to read a char into AL

#define DS_Out_Str       0x2  // function to display a NUL terminated string
                              // pointed to by DS:ESI

#define DS_Is_Char       0x3  // Non blocking In_Chr
                       
#define DS_Out_Str16     0x12 // function to display a NUL terminated string
                              // pointed to by DS:SI
                              // (same as function 2, but for 16 bit callers)

#define DS_ForcedGO16    0x40 // enter the debugger and perform the equivalent
                              // of a GO command to force a stop at the
                              // specified CS:IP
                              // CX is the desired CS
                              // BX is the desired IP

#define DS_LinkMap       0x45 // DX:(E)DI = ptr to paragraph in front of map
                        
#define DS_UnlinkMap     0x46 // DX:(E)DI = ptr to paragraph in front of map
                        
#define DS_CheckMap      0x47 // DX:(E)DI = pointer to module name
                              // returns AX != 0, map found
                              //         AX == 0, map not found

#define DS_IsAutoLoadSym 0x48 // returns AX != 0, auto load symbols
                              //         AX == 0, don't auto load symbols

#define DS_DebLoaded     0x4F // check to see if the debugger is installed and
                              // knows how to deal with protected mode programs
                              // return AX = F386h, if true

#define DS_DebPresent    0x0F386

#define DS_LoadSeg       0x50 // define a segment value for the
                              //  debugger's symbol handling
                              //  SI type   0  - code selector
                              //            1  - data selector
                              //           80h - code segment
                              //           81h - data segment
                              //  BX segment #
                              //  CX actual segment/selector
                              //  DX data instance
                              //  ES:(E)DI pointer to module name
                              // [PTrace]

#define DS_LoadSeg_32    0x0150 // Define a 32-bit segment for Windows 32
                                //  SI type   0  - code selector
                                //            1  - data selector
                                //  DX:EBX points to a D386_Device_Params STRUC
                                //  with all the necessaries in it

#define DS_MoveSeg       0x51   // notify the debugger that a segment has moved
                                // BX old segment value
                                // CX new segment value
                                // [PTrace]

#define DS_FreeSeg       0x52   // notify the debugger that a segment has been
                                // freed
                                // BX segment value
                                // [PTrace]

#define DS_FreeSeg_32    0x0152 // notify the debugger that a segment has been
                                // freed
                                // BX segment number
                                // DX:EDI pointer to module name

#define DS_DGH           0x56   // register "dump global heap" handler
                                // BX is code offset
                                // CX is code segment
                                // [PTrace]

#define DS_DFL           0x57   // register "dump free list" handler
                                // BX is code offset
                                // CX is code segment
                                // [PTrace]

#define DS_DLL           0x58   // register "dump LRU list" handler
                                // BX is code offset
                                // CX is code segment
                                // [PTrace]

#define DS_StartTask     0x59   // notify debugger that a new task is starting
                                // BX is task handle
                                // task's initial registers are stored on the
                                // stack:
                                //       push    cs
                                //       push    ip
                                //       pusha
                                //       push    ds
                                //       push    es
                                //       push    ss
                                //       push    sp
                                // [PTrace]

#define DS_Kernel_Vars   0x5a   // Used by the Windows kernel to tell the
                                // debugger the location of kernel variables
                                // used in the heap dump commands.
                                // BX = version number of this data (03a0h)
                                // DX:CX points to:
                                //      WORD     hGlobalHeap    ****
                                //      WORD     pGlobalHeap    ****
                                //      WORD     hExeHead       ****
                                //      WORD     hExeSweep
                                //      WORD     topPDB
                                //      WORD     headPDB
                                //      WORD     topsizePDB
                                //      WORD     headTDB        ****
                                //      WORD     curTDB         ****
                                //      WORD     loadTDB
                                //      WORD     LockTDB
                                //      WORD     SelTableLen    ****
                                //      DWORD    SelTableStart  ****
                                //      
                                // The starred fields are used by the
                                // heap dump commands which are internal
                                // to WDEB386.


#define DS_VCPI_Notify   0x5b   // notify debugger that DOS extender is
                                // running under a VCPI implementation,
                                // and register VCPI protect mode interface
                                // ES:DI points to a data structure used to
                                // get from V86 mode to Pmode under VCPI.
                                // This is defined in the VCPI version
                                // 1.0 spec.

#define DS_ReleaseSeg    0x5c   // This does the same as a DS_FreeSeg, but
                                // it restores any breakpoints first.
                                // [PTrace]

#define DS_User_Vars     0x5d   // DS:SI = pointer to an array of offsets:
                                // BX = windows version   
                                // CX = number of words in array
                                //      WORD = fDebugUser (1 = DEBUG, 0 = RETAIL)
                                //      WORD = 16 bit offset to hHmenuSel
                                //      WORD = 16 bit offset to hHwndSel
                                //      WORD = 16 bit offset to pclsList
                                //      WORD = 16 bit offset to pdceFirst
                                //      WORD = 16 bit offset to hwndDesktop
                                // This array MUST BE COPIED it goes away
                                // when we return from this service.

#define DS_POSTLOAD      0x60   // Used by the RegisterPTrace interface
#define DS_EXITCALL      0x62   // Somebody will fill these in if we ever
#define DS_INT2          0x63   // figure out what they are supposed to do.
#define DS_LOADDLL       0x64
#define DS_DELMODULE     0x65
#define DS_LOGERROR      0x66   // CX==error code, dx:bx = ptr to optional info
#define DS_LOGPARAMERROR 0x67   // ES:BX = ptr to struct { err, lpfn, param } ;

#define DS_RIN           0x09
#define DS_BANKLINE      0x0A
#define DS_NEWTASK       0x0B
#define DS_FLUSHTASK     0x0C
#define DS_SWITCHOUT     0x0D
#define DS_SWITCHIN      0x0E
//#define DS_KEYBOARD      0x0F   // Conflicts with DS_Out_Symbol

#define DS_IntRings      0x20   // function to tell debugger which INT 1's & 3's
                                // to grab
                                // BX == 0, grab only ring 0 ints
                                // BX != 0, grab all ints

#define DS_IncludeSegs   0x21   // function to tell debugger to go ahead and
                                // process INT 1's & 3's which occur in this
                                // DX:DI points to list of selectors
                                //   (1 word per entry)
                                // CX = # of selectors (maximum of 20)
                                // CX = 0, to remove the list of segs
#define MaxDebugSegs    20

#define DS_CondBP       0x0F001 // conditional break pt, if the command line
                                // switch /B is given when the debugger is run
                                // or the conditional flag is later set, then
                                // this int should cause the program to break
                                // into the debugger, else this int should be
                                // ignored!
                                // ESI points to a nul terminated string to
                                // display if break is to happen.

#define DS_ForcedBP     0x0F002 // break pt, which accomplishes the same thing
                                // as an INT 1 or an INT 3, but is a break point
                                // that should be permanently left in the code,
                                // so that a random search of source code would
                                // not result in the accidental removal of this
                                // necessary break_pt

#define DS_ForcedGO     0x0F003 // enter the debugger and perform the equivalent
                                // of a GO command to force a stop at the
                                // specified CS:EIP
                                // CX is the desired CS
                                // EBX is the desired EIP

#define DS_HardINT1     0x0F004 // check to see if INT 1 hooked for all rings
                                // ENTER: nothing
                                // EXIT: AX = 0, if no, 1, if yes

#define DS_Out_Symbol   0x0F    // find the symbol nearest to the address in
                                // CX:EBX and display the result in the format
                                // symbol name <+offset>
                                // the offset is only included if needed, and
                                // no CR&LF is displayed

#define DS_Disasm_Ins   0x10    // function to disassemble the instruction
                                // pointed to by DS:ESI

#define DS_JumpTableStart      0x70

/***     DS_RegisterDotCommand

       This interface is used to register wdeb386 dot commands by FLAT 32
       bit code.  The following conditions apply:

       * The code will be run at ring 0
       * Interrupts may be enabled
       * Must not access any invalid pages or load invalid selectors
       * Must stay on the stack called with when calling INT 41 services
       * Must not change DS or ES from the FLAT selector

       The help text is printed when .? is executed in the order of
       registration.  The text must include CR/LF at the end; nothing
       is added to the help text.

       ENTRY:  (AX) = 0070h
               (BL) = dot command to register
               (ESI) = linear address of dot command routine
                   Dot command routine:
                       ENTRY:  (AL) = command character
                               (DS, ES) = flat data selector

                       EXIT:   (AX) == 0, no errors
                               (AX) != 0, command line or option error

                       NOTE:   MUST return with a 32 bit FAR return (retfd)
               (EDI) = linear address of help text

       EXIT:   (AX) == 0, no errors
               (AX) != 0, dot command already used or out of dot commands
*/

#define DS_RegisterDotCommand      0x70

/***     DS_RegisterDotCommand16

       This interface is used to register wdeb386 dot commands by 16 bit
       code.  The following conditions apply:

       * The code will be run at ring 0 or in real mode
       * Interrupts may not be enabled
       * Must not access any not present pages or load invalid selectors
       * Must stay on the stack called with when calling INT 41 services

       The help text is printed when .? is executed in the order of
       registration.  The text must include CR/LF at the end; nothing
       is added to the help text.

       ENTRY:  (AX) = 0071h
               (BL) = dot command to register
               (CX:SI) = address of dot command routine
                   Dot command routine:
                       ENTRY:  (AL) = command character
                               (DS, ES) = debugger's data selector

                       EXIT:   (AX) == 0, no errors
                               (AX) != 0, command line or option error

                       NOTE:   MUST return with a 16 bit FAR return (retf)
               (DX:DI) = address of help text

       EXIT:   (AX) == 0, no errors
               (AX) != 0, dot command already used or out of dot commands
*/

#define DS_RegisterDotCommand16         0x71

/***     DS_DeRegisterDotCommand

       This interface is used to de-register wdeb386 dot commands registered
       by the above 16 or 32 bit services.  Care should be used not to
       de-register dot commands that weren't registered by your code.

       ENTRY:  (AX) = 0072h
               (BL) = dot command to de-register

       EXIT:   NONE
*/

#define DS_DeRegisterDotCommand         0x72

/***     DS_Printf

       This function allows formatted output with the standard "C"
       printf syntax.

       ENTRY:  (AX) = 0073h
               (DS:ESI) = address of format string
               (ES:EDI) = address of the start of the dword arguments

       EXIT:   (EAX) = number of characters printed

       Supported types are:

       %%                                                      %
       %[l][h]c                                                character
       %[-][+][ ][0][width][.precision][l|h|p|n]d              decimal
       %[-][0][width][.precision][l|h|p|n]u                    unsigned decimal
       %[-][#][0][width][.precision][l|h|p|n]x                 hex
       %[-][#][0][width][.precision][l|h|p|n]X                 hex
       %[-][0][width][.precision][l|h|p|n]o                    octal
       %[-][0][width][.precision][l|h|p|n]b                    binary
       %[-][width][.precision][l|h|a|F|R|P]s                   string
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]A       address
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]S       symbol
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]G       group:symbol
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]M       map:group:symbol
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]g       group
       %[-][width][.precision][l|h|a|p|n|F|L|R|L|H|N|Z]m       map

       Where "width" or "precision" is a decimal number or the '*' 
       character; '*' causes the field width or precision to be picked
       up from the next parameter. []'ed parameters are optional.


       "\r", "\t", "\n", "\a", "\b", are supported directly.

       Prefixes
       --------

       Used with c,d,u,x,X,o,b:

       Parameter Argument Size
       -----------------------
       word                                    h
       dword                                   l

       Used with s,A,S,G,M,g,m:

       Address Argument Size
       ---------------------
       16 bit DS relative                      h
       16:16 segment:offset                    hF or Fh
       32 bit flat relative                    l
       16:32 segment:offset (2 dwords)         lF or Fl
       pointer to AddrS structure              a
       segment is a real mode segment          R
       segment is a protected mode selector    P

       Default segment type is the current code type.

       Used with A,S,G,M,g,m:

       Address Display Size or Format
       ------------------------------
       16 bit offset                           H
       32 bit offset                           L
       offset only                             N
       no address                              Z

       Default display size depends on the "386env" flag setting.

       Used with S,G,M,g,m:

       gets the previous symbol                p
       gets the next symbol                    n

       Used with A:

       gets the previous symbol address        p
       gets the next symbol address            n

       Used with d,u,x,X,o,b:

       gets the previous symbol offset         p
       gets the next symbol offset             n
*/

#define DS_Printf               0x73

/***     DS_Printf16

       This function allows formatted output with the standard "C"
       printf syntax.

       ENTRY:  (AX) = 0074h
               (DS:SI) = address of format string
               (ES:DI) = address of the start of the word or dword arguments

       EXIT:   (AX) = number of characters printed

       The format options and parameters are the same as DS_Printf except
       the default parameter size is a word (the h option is implicit).
*/

#define DS_Printf16             0x74

/***     DS_GetRegisterSet

       This function copies the current register set.

       ENTRY:  (AX) = 0075h
               (DS:ESI) = address of SaveRegs_Struc structure

       EXIT:   NONE
*/

#define DS_GetRegisterSet       0x75

/***     DS_SetAlternateRegisterSet

       This function temporary sets the debugger's registers to values
       passed in the structure.  If an "r" command is executed or the
       debugged code is returned to (via the "g", "t" or "p" commands),
       the register set reverts to the debugged code's registers.

       ENTRY:  (AX) = 0076h
               (CX) = thread ID, 0 use current thread ID
               (DS:ESI) = address of SaveRegs_Struc structure

       EXIT:   NONE
*/

#define DS_SetAlternateRegisterSet 0x76

/***     DS_GetCommandLineChar

       This services gets the next character off the command line.

       ENTRY:  (AX) = 0077h
               (BL) = 0 just peek the character, don't increment text pointer
                        leading white space isn't ignored
               (BL) = 1 get the character, increment text pointer
                        leading white space is skipped
               (BL) = 2 peek the character, don't increment text pointer
                        leading white space is skipped

       EXIT:   (AL) = command line character
               (AH) == 0 if no more characters (EOL)
               (AH) != 0 if more characters
*/

#define DS_GetCommandLineChar   0x77

/***     DS_EvaluateExpression

       Expressions can be numbers of various radices, symbols, addresses
       or an combination of the above hooked together with various
       operators.  Expressions are separated by blanks or commas.  This
       function is passed a pointer to the beginning of the text of the
       expression (i.e. "%80003444+4232").  The expression is either
       evaluated down into a dword value if there are no addresses or 
       into a linear address.

       ENTRY:  (AX) = 0078h

       EXIT:   (AX) == 0, returning a data value
               (AX) != 0, returning a linear address
               (CX) = thread id
               (EBX) = return value

       NOTE:   If the expression is invalid, this service will not
               return.  A message is printed and control returns to
               the command loop.
*/

#define DS_EvaluateExpression   0x78

/***     DS_VerifyMemory

       ENTRY:  (AX) = 0079h
               (ECX) = length of memory region
               (DS:ESI) = address of memory to verify

       EXIT:   (AX) == 0, no errors
               (AX) != 0, invalid memory
*/

#define DS_VerifyMemory         0x79

/***     DS_PrintRegisters

       This function prints (just like the "r" command) the either the
       debugged code's registers or the alternate register set, set with
       DS_SetAlternateRegisterSet function.

       ENTRY:  (AX) = 007ah

       EXIT:   NONE

       NOTE:   If the CS:EIP is invalid, this service will not return
               because of an error when the code is disassembled.  A 
               message is printed and control returns to the command loop.
*/

#define DS_PrintRegisters       0x7a

/***     DS_PrintStackDump

       This function prints (just like the "k" command) the stack dump
       based on the current register set that may have been set with 
       DS_SetAlternateRegisterSet function.

       ENTRY:  (AX) = 007bh
               (BX) = flags
                       01h - verbose stack dump
                       02h - 16 bit stack dump
                       04h - 32 bit stack dump

       EXIT:   NONE

       NOTE:   If the CS:EIP or SS:EBP are invalid, this service will not
               return because of an error when accessing the stack.  A 
               message is printed and control returns to the command loop.
*/

#define DS_PrintStackDump       0x7b

/***     DS_SetThreadID

       This function sets what the debugger thinks the thread ID is
       for memory address in other address contexts.  It stays set
       until the debugged code is returned to (via "g", "t" or "p")
       or set back to 0.

       ENTRY:  (AX) = 007ch
               (CX) = thread ID or 0 for currently executed thread

       EXIT:   NONE
*/

#define DS_SetThreadID          0x7c

/***     DS_ExecDebugCommand

       This service allows any debugger command to be executed.  In can
       be a multi-lined script with the lines separated by CR, LF.  MUST
       have a "g" command at the end of script so the debugger doesn't
       stop while in the INT 41.

       ENTRY:  (AX) = 007dh
               (DS:ESI) = pointer to debugger command script string
               (CX) = size of script

       EXIT:   NONE

       NOTE:   If the any kind of error happens, this service will not
               return.  A message is printed and control returns to the
               command loop.
*/

#define DS_ExecDebugCommand     0x7d

/***     DS_GetDebuggerInfo

       This service returns various debugger info and routines.

       ENTRY:  (AX) = 007eh
               (DS:ESI) = pointer to DebInfoBuf structure
               (ECX) = size of the above buffer.  Only this many bytes are
                       copied to the buffer this allows more info to be
                       passed in future versions without breaking anything.

       EXIT:   (AX) == 0, no errors
               (AX) != 0, error:   (AX) == 007eh, function not implemented
                                   (AX) == anything else, invalid buffer
*/

#define DS_GetDebuggerInfo      0x7e

/***     DS_CheckFault

       This service checks if the debugger wants control on the fault.

       ENTRY:  (AX) = 007fh
               (BX) = fault number
               (CX) = fault type mask
                       DEBUG_FAULT_TYPE_V86
                       DEBUG_FAULT_TYPE_PM
                       DEBUG_FAULT_TYPE_RING0
                       DEBUG_FAULT_TYPE_FIRST
                       DEBUG_FAULT_TYPE_LAST

       EXIT:   (AX) == 0, handle fault normally
               (AX) != 0, handled by debugger
*/

#define DS_CheckFault           0x7f

/***     DS_SetBreak

       This service allows an error break or ctrl-c handler to be
       set.  The old value that is returned must be save and set
       back to remove the break handler.

       ENTRY:  (AX) = 0080h
               (DS:ESI) = pointer to BreakStruc with the CS:EIP and
               SS:ESP values to be used when a error break or ctrl-c
               happens.  The old value is copied into this buffer.

       EXIT:   (AX) == 0, no error
               (AX) != 0, error on BreakStruc address
*/

#define DS_SetBreak             0x80

/***     DS_RedirectExec

       This service redirects the input and output streams to the
       specified buffers for the debugger command line passed.

       ENTRY:  (AX) = 0081h
               (DS:ESI) = pointer to RedirectExecStruc

       EXIT:   (ECX) = number of bytes written
               (AX) == 0, no error
               (AX) != 0, error
                       1 to 10 = memory access error
                       -1      = buffer overflow
                       -2      = invalid parameter, not on a 386, or reentered
*/

#define DS_RedirectExec         0x81

/***     DS_PassOnDebugCommand

       Used to tell the debugger to pass this dot command on to the
       next handler.

       ENTRY:  (AX) = 0082h

       EXIT:   NONE
*/

#define DS_PassOnDebugCommand   0x82

/***     DS_TrapFault

       Allows ring 3 code to send a fault to the debugger

       ENTRY:  (AX) = 0083h
               (BX) = fault number
               (CX) = faulting CS
               (EDX) = faulting EIP
               (ESI) = fault error code
               (EDI) = faulting flags

       EXIT:   (CX) = replacement CS
               (EDX) = replacement EIP
*/

#define DS_TrapFault            0x83

/***     DS_SetStackTraceCallBack

       Sets the "k" command callback filter used to back trace
       thru thunks.

       ENTRY:  (AX) = 0084h
               (EBX) = linear address of call back routine, zero to uninstall
               (ECX) = linear address of the end of the call back routine
               (EDX) = EIP to use for for faults in call back routine

       EXIT:   NONE

       CALLBACK:
               ENTRY:  (EAX) = linear base of SS
                       (EBX) = linear address of SS:EBP
                       (DS, ES) = flat ds
                       (SS) = NOT flat ds !!!!!!!!!

               EXIT:   (EAX) = FALSE, no thunk
                               TRUE, is a thunk
                                       (CX:ESI) = new SS:EBP
                                       (DX:EDI) = new CS:EIP
*/

#define DS_SetStackTraceCallBack 0x84

/***     DS_RemoveSegs

       Removes all the undefined groups from a map file.

       ENTRY:  (AX) = 0085h
               (ES:EDI) pointer to module name

       EXIT:   NONE
*/

#define DS_RemoveSegs            0x85

/***     DS_DefineDebugSegs

       Defines the debugger's code and data symbols.

       ENTRY:  (AX) = 0086h

       EXIT:   NONE
*/

#define DS_DefineDebugSegs       0x86

/***     DS_SetBaudRate

       Sets the com port's baud rate.
       Use DS_SetBaudRateEx to get 115200bps (only on WDEB98 and up)

       ENTRY:  (AX) = 0087h
               (BX) = baud rate

       EXIT:   NONE
*/

#define DS_SetBaudRate           0x87

/***     DS_SetComPort

       Sets the com port's baud rate

       ENTRY:  (AX) = 0088h
               (BX) = com port number

       EXIT:   (AX) == 0, ok
               (AX) != 0, error bad com port
*/

#define DS_SetComPort            0x88

/***     DS_ChangeTaskNum

       Changes a task number to another task number or
       indicates that the task has gone away.

       ENTRY:  (AX) = 0089h
               (CX) = old task number
               (DX) = new task number or -1 if process terminated.

       EXIT:   NONE
*/

#define DS_ChangeTaskNum         0x89

/***     DS_ExitCleanup

       Called when Windows exits.

       ENTRY:  (AX) = 008ah

       EXIT:   NONE
*/

#define DS_ExitCleanup           0x8a

/***     DS_InstallVGAHandler

       Called when the Debug VxD is initializing (during Device Init),
       to specify an alternate I/O handler for VGA.  The handler accepts the
       following inputs:

           BX == subfunction #:
                   0 == save screen state (switch to debugger context)
                        No inputs/outputs
                   1 == restore screen state (switch to windows context)
                        No inputs/outputs
                   2 == display output character (ie, OEMOutputCharCOM)
                        on input, AL == character
                   3 == check for input character (ie, OEMScanCharCOM)
                        on output, ZR if no chars, else NZ and AL == char

       ENTRY:  (AX) = 008bh
               (DX:EDI) == 16:32 address to call, with BX == subfunction above

       EXIT:   NONE
*/

#define DS_InstallVGAHandler    0x8b

/***     DS_GetComBase

       Called when Debug VxD is initializing (during Device Init),
       to get the base of the com port being used by wdeb386.

       Entry:
               (AX) == 008ch

       Exit:
               (AX) = base of COM port.
*/

#define DS_GetComBase           0x8c

/***     DS_GetSymbol

       Looks up a symbol and returns the linear address and segment/offset.

       ENTRY:  (AX) == 008dh
               (DS:ESI) = ptr to null-terminated symbol

       EXIT:   (AX) == 0, no error
               (AX) == 1, symbol not found
               (AX) == 2, memory not loaded yet
               (ECX) = linear address of variable  (if AX == 0)
               (EDX) = seg:offset of variable      (if AX == 0)    
*/

#define DS_GetSymbol            0x8d

/***     DS_CopyMem

       Copys memory from one AddrS to another AddrS

       ENTRY:  (AX) == 008eh
               (DS:ESI) = pointer to source AddrS block
               (ES:EDI) = pointer to destination AddrS block
               (CX) = number of bytes

       EXIT:   (AX) == 0, no error
               (AX) != 0, invalid address
*/

#define DS_CopyMem              0x8e

#ifdef WDEB98

#define DS_SetBaudRateEx        0x8f

/***     DS_SetBaudRateEx

       Sets the com port's baud rate. Supports >57600kbps
       Only available on WDEB98 and up

       ENTRY:  (AX) = 008fh
               (EBX) = baud rate

       EXIT:   EBX == 0, no error
               EBX != 0, error or not supported function (try DS_SetBaudRate)
*/

#define DS_Reserved0            0x90
#define DS_Reserved1            0x91
#define DS_Reserved2            0x92
#define DS_Reserved3            0x93
#define DS_Reserved4            0x94
#define DS_Reserved5            0x95
#define DS_Reserved6            0x96
#define DS_Reserved7            0x97
#define DS_Reserved8            0x98
#define DS_Reserved9            0x99
#define DS_Reserved10           0x9A
#define DS_Reserved11           0x9B
#define DS_Reserved12           0x9C
#define DS_Reserved13           0x9D
#define DS_Reserved14           0x9E
#define DS_Reserved15           0x9F

/***     DS_InstallVxDThunk

       Installs a private callback for WDeb98 and it's accompanying VxD.
       This routine is the 16 -> 32 bit portion of the thunk layer.

       ENTRY:  (AX) = 00A0h
               (DX:EDI) == 16:32 address to call

       
       BUGBUG: DOC this better!
*/

#define DS_InstallVxDThunk      0xA0

/***     DS_ThunkDownTo16

       Entry into a private callback into 16bit WDeb98 for it's VxD.
       This int is the 32 -> 16 bit portion of the thunk layer.

       ENTRY:  (AX) = 00A1h

       
       BUGBUG: DOC this better!
*/

#define DS_ThunkDownTo16        0xA1

#define DS_JumpTableEnd         0xA1

#else // WDEB98
#define DS_JumpTableEnd         0x8e

#endif // WDEB98

struct SaveRegs_Struc { 
   DWORD Debug_EAX ;
   DWORD Debug_EBX ;
   DWORD Debug_ECX ;
   DWORD Debug_EDX ;
   DWORD Debug_ESP ;
   DWORD Debug_EBP ;
   DWORD Debug_ESI ;
   DWORD Debug_EDI ;
    WORD Debug_ES  ;
    WORD Debug_SS  ;
    WORD Debug_DS  ;
    WORD Debug_FS  ;
    WORD Debug_GS  ;
   DWORD Debug_EIP ;
    WORD Debug_CS  ;
   DWORD dwReserved ;
   DWORD Debug_EFlags ;
   DWORD Debug_CR0 ;
   QWORD Debug_GDT ;
   QWORD Debug_IDT ;
    WORD Debug_LDT ;
    WORD Debug_TR  ;
   DWORD Debug_CR2 ;
   DWORD Debug_CR3 ;
   DWORD Debug_DR0 ;
   DWORD Debug_DR1 ;
   DWORD Debug_DR2 ;
   DWORD Debug_DR3 ;
   DWORD Debug_DR6 ;
   DWORD Debug_DR7 ;
   DWORD Debug_DR7_2 ;
   DWORD Debug_TR6 ;
   DWORD Debug_TR7 ;
    WORD Debug_TrapNumber ; // -1 means no trap number
    WORD Debug_ErrorCode  ; // 0 means no error code
  } ;

// Don't let h2inc see FWORD as it doesn't understand FWORD, QWORD, & TWORD
/*XLATOFF*/
struct DebInfoBuf {
   BYTE DIB_MajorVersion ;
   BYTE DIB_MinorVersion ;
   BYTE DIB_Revision ;
   BYTE DIB_Reserved ;
   DWORD DIB_DebugTrap16 ;  // send 16 bit trap to debugger
   FWORD DIB_DebugTrap32 ;  // send 32 bit trap to debugger
   DWORD DIB_DebugBreak16 ; // 16 bit break in debugger
   FWORD DIB_DebugBreak32 ; // 32 bit break in debugger
   DWORD DIB_DebugCtrlC16 ; // 16 bit check for ctrl C
   FWORD DIB_DebugCtrlC32 ; // 32 bit check for ctrl C
  } ;
/*XLATON*/
/* ASM
DebInfoBuf	STRUC
DIB_MajorVersion	DB	?
DIB_MinorVersion	DB	?
DIB_Revision	DB	?
DIB_Reserved	DB	?
DIB_DebugTrap16	DD	?
DIB_DebugTrap32 DF      ?
DIB_DebugBreak16	DD	?
DIB_DebugBreak32        DF      ?
DIB_DebugCtrlC16	DD	?
DIB_DebugCtrlC32        DF      ?
DebInfoBuf	ENDS
*/

struct BreakStruc {
   DWORD BS_BreakEIP ; // CS:EIP, SS:ESP to go to on a error or ctrlc break
    WORD BS_BreakCS  ; 
   DWORD BS_BreakESP ; 
    WORD BS_BreakSS  ;
  } ;

// Don't let h2inc see FWORD as it doesn't understand FWORD, QWORD, & TWORD
/*XLATOFF*/
struct RedirectExecStruc {
   FWORD RDE_fpbufDebugCommand ; // debugger command script
    WORD RDE_cbDebugCommand    ; // debugger command script len
   FWORD RDE_fpszInput         ; // input stream pointer
    WORD RDE_usFlags           ; // reserved (must be 0)
   DWORD RDE_cbOutput          ; // size of output buffer
   FWORD RDE_fpbufOutput       ; // output buffer pointer
  } ;
/*XLATON*/
/* ASM
RedirectExecStruc	STRUC
RDE_fpbufDebugCommand   DF      ?
RDE_cbDebugCommand	DW	?
RDE_fpszInput   DF      ?
RDE_usFlags	DW	?
RDE_cbOutput	DD	?
RDE_fpbufOutput DF      ?
RedirectExecStruc	ENDS
*/

#define REPEAT_FOREVER_CHAR     0x0fe // send next character until
                                      // end of debugger command
// for printf service
struct AddrS {
   DWORD AddrOff ;
    WORD AddrSeg ;
    BYTE AddrType ;
    BYTE AddrSize ;
    WORD AddrTask ;
  } ;

//AddrTypeSize    equ   word ptr AddrType

#define EXPR_TYPE_SEG   0x0001 // 00000001b  address type segment:offset
#define EXPR_TYPE_SEL   0x0009 // 00001001b  address type selector:offset
#define EXPR_TYPE_LIN   0x0002 // 00000010b  address type linear
#define EXPR_TYPE_PHY   0x000A // 00001010b  address type physical
#define EXPR_TYPE_LOG   0x0008 // 00001000b  logical address (no sel yet)
#define EXPR_TYPE_MOD   0x000B // 00001011b  module address (no sel yet)

#define DEBUG_FAULT_TYPE_V86            0x0001 // 00000001b
#define DEBUG_FAULT_TYPE_PM             0x0002 // 00000010b
#define DEBUG_FAULT_TYPE_RING0          0x0004 // 00000100b
#define DEBUG_FAULT_TYPE_FIRST          0x0008 // 00001000b
#define DEBUG_FAULT_TYPE_LAST           0x0010 // 00010000b

//
//   Interrupt and services that Win386 provides to the debugger
//

#define Win386_Query_Int    0x22 // interrupt for Win386 protected mode
                                 // interface requests

#define Win386_Alive        0       // function 0, query Win386 installation
#define Win386_Q_Ack        0x0F386   // good response from func 43h, of
                                      // INT 68h & func 4fh of INT 41h

#define Win386_Query        1       // function 1, query Win386 state
                                    //   ds:esi points to command string
                                    //   that Win386 needs to process
                                    //   ds:edi points to the SaveRegs_Struc
                                    //   that the debugger has stored all the
                                    //   client register state into.
                                    //   (Win386 just writes the query
                                    //   answers directly to the output
                                    //   device, so no response is returned)

#define Win386_PhysToLinr   2       // function 2, have Win386 convert a
                                    //   physical address into a valid
                                    //   linear address that Deb386 can
                                    //   use.  esi is physicaladdress
                                    //   cx is # of bytes required
                                    //   returns esi as linear address
                                    //   returns ax = 1, if okay, else
                                    //   0, if request couldn't be completed
                                    

#define Win386_AddrValid    3       // function 3, have Win386 check the
                                    //   validity of a linear address
                                    //   esi is linear address to check
                                    //   cx is # of bytes required
                                    //   returns ax = 1, if address okay
                                    //   else ax = 0

#define Win386_MapVM        4       // function 4, make sure that the VM's
                                    //   low memory is mapped in, in case
                                    //   it is touched (a count is maintained)
                                     
#define Win386_UnmapVM      5       // function 5, map out the VM's low
                                    //   memory (dec the count)

#define Win386_GetDLAddr    6       // function 6, return offset of dyna-link
                                    //   service.  EBX = Device ID << 10h +
                                    //   Service #.  Returns EAX = Offset.

#define Win386_GetVXDName   7       // function 7, determines whether an address
                                    //   is within a VXD object.
                                    //   DS:ESI -> buffer to receive object name
                                    //   BX  =  thread number
                                    //   EDX  = linear address to query
                                    //   If EAX == 0, EDX = base address of object
                                    //   If EAX != 0, error

#define Win386_GetPDE       8       // function 8, get pde for a context
                                    //   BX = thread number
                                    //   EDX = linear address
                                    //   if EAX == 0, ECX = PDE
                                    //   if EAX != 0, error

#define Win386_GetFrame     9       // function 9, get phys addr for not pres ptes
                                    //   BX = thread number
                                    //   EDX = linear address
                                    //   ECX = PDE or PTE
                                    //   ESI = 0 if PDE, !0 if PTE
                                    //   if EAX == 0, EDX = physical address
                                    //   if EAX != 0, error

#define Win386_GetLDTAddress 10     // function 10,
                                    //   BX = thread number
                                    //   if EAX == 0,
                                    //     EDI = pointer to LDT
                                    //     ECX = ldt limit
                                    //   if EAX != 0, error

#define Win386_GetThreadID   11     // function 11, AX = Current Thread ID

#define Win386_GetTSHandler  12     // function 12, return offset of transfer-space
                                    //   fault handler.  EBX = 16:16 addr of
                                    //   int 30h.  Returns EAX = Offset or 0.

#define Win386_GetArplHandler 13    // function 12, return offset of ARPL fault
                                    //   fault handler.  Eb = 16:16 addr of
                                    //   ARPL.  Returns EAX = Offset or 0.

#define Max_Win386_Services 13


#endif // _DEBUGSYS_H

