;       SCCSID = @(#)demdisp.asm        6.12 92/04/20
;       SCCSID = @(#)demdisp.asm        6.12 92/04/20
        page   ,132                     ;
        TITLE DEMDISP.ASM - System call entry points and dispatcher
        if1
        %out Assembly of DEMDISP.ASM...
        endif
;
; Dispatcher code
;
;   Revision history:
;
;               danno   16-Nov-1988 Modified for MVDM
;
;   B001 dcr 1330 - 02\07\91 EMK-ADD SUBFUNCTION 6 (GET REAL DOS VERSION)
;                       TO $SET_CTRL_C_TRAPPING (INT 21H, AH=33H).
;
;   B002  9/29/91  CP20 PTR AA04143  Mark Rogalski
;         The filter code may be interrupted by a routine which does INT 21s.
;         Therefore, we need to have an additional stack for these interrupts.
;
;  B003 - 11/25/91 CP20 B730106  Mark Rogalski                          ;BN003
;         All INT 21 calls for function Get_extended_error should now   ;BN003
;         be routed to DOS. The filter will update the DOS variables    ;BN003
;         through the call Set_extended_error when neccessary.          ;BN003
;
; BN004 - 1/30/92  CP20 AA04471  Mark Rogalski                          ;BN004;
;         Need to call DOS to get CurrentPDB directly, so that FSFILTER ;BN004;
;         can be somewhat re-entrant. Also provide re-entrancy          ;BN004;
;         variable for os2_handled.                                     ;BN004;
;
;  B005 - 2/10/92 CP20 B732885  Mark Rogalski                           ;BN005
;         Add variable to hold address of real INDOS variable.          ;BN005
;
;  B006 - 2/25/92 CP20 AZ09092  Mark Rogalski                           ;BN006
;         Do not enable interrupts before using non-reentrant vars.     ;BN006
;
;  B008 - 4/17/92 CP20 B735532  Mark Rogalski                           ;BN008
;         Reset user stack field in PDB before returning to user.       ;BN008
;
;  B009 - 1/7/93 Defect 57180  Doug Azzarito                            ;BN009
;         Save AX for later use in IOCtl calls                          ;BN009
;         This fix was also delta'd as 63235 on 16Mar1993               ;BN009
;
;  B010 - 1/5/94 Defect 75510  John Hare                                ;BN010
;         Test for full 0 - ff range for int21 calls for Novell         ;BN010
;******************************************************************************
.xlist
.xcref
include basemaca.inc
include osmaca.inc
include oldmaca.inc
include demmac.inc
include demver.inc
include dossymc.inc
include v86seg.inc
include demdbcs.inc
include syscalls.inc
include vector.inc
include error.inc
include pdb.inc
include mi.inc
include mvdmexp.inc
include demsvc.inc
include harderr.inc
.cref
.list
        CpuMode 8086

AsmVars <Kanji, Debug>

BREAK   <Copyright notice and version>
V86CODE    SEGMENT


        ReferV86  vheVDM,BYTE
        ReferV86  CurrentPDB,WORD
;m        ReferV86  CntCFlag,BYTE
        ReferV86  User_SS,WORD
        ReferV86  User_SP,WORD
        ReferV86  NSS,WORD                    ;BN002
        ReferV86  NSP,WORD                    ;BN002
        ReferV86  MaxCall,BYTE
        ReferV86  MaxCom,BYTE
;m        ReferV86  VDMNotBusy,WORD           ; VPL Idle detection
        ReferV86  SaveDS,WORD
        ReferV86  SaveBX,WORD
        ReferV86  INDOS,BYTE                  ;BN002
        ReferV86  REAL_INDOS,DWORD            ;BN005
;m        ReferV86  User_ID,WORD
;m        ReferV86  Proc_ID,WORD
        ReferV86  AuxStack,BYTE
        ReferV86  INTSTACK,BYTE               ;BN002
;m        ReferV86  DSKSTACK,BYTE
;m        ReferV86  NoSetDir,BYTE
        ReferV86  FailERR,BYTE
        ReferV86  Errormode,BYTE
        ReferV86  restore_tmp,WORD
        ReferV86  WPERR,BYTE
        ReferV86  Dispatch,WORD
;m        ReferV86  ConSwap,BYTE
        ReferV86  User_In_AX,WORD
        ReferV86  EXTERR_LOCUS,BYTE
        ReferV86  EXTERR,WORD                  ;BN003
        ReferV86  EXTERR_CLASS,BYTE            ;BN003
        ReferV86  EXTERR_ACTION,BYTE           ;BN003
        ReferV86  DPL_EXTERR,WORD              ;BN003
        ReferV86  DPL_EXTERR_LOCUS,BYTE        ;BN003
        ReferV86  DPL_EXTERR_CLASS,BYTE        ;BN003
        ReferV86  DPL_EXTERR_ACTION,BYTE       ;BN003
;m        ReferV86  IdleInt,BYTE
;m        ReferV86  Printer_Flag,BYTE
;m        ReferV86  CPSWFLAG,BYTE              ;AN000;
;m        ReferV86  CPSWSAVE,BYTE              ;AN000;
;m        ReferV86  InterCon,BYTE              ;AN000;
;m        ReferV86  BOOTDRV,BYTE               ;AN000;
        ReferV86  EXTOPEN_ON,BYTE            ;AN000;
        ReferV86  DOS34_FLAG,WORD            ;AN000;
ifdef NOT_MVDM
        ReferV86  ACT_PAGE,WORD              ;AN000;
endif
        ReferV86  poldint21,DWORD            ;mdr
        ReferV86  os2_handled,BYTE           ;mdr
        ReferV86  os2_handled_hold,BYTE      ;BN004



;                                   ;        IF      NOT IBM
;                                   ;        ReferV86  OEM_HANDLER,DWORD
;                                   ;        ENDIF
;                                   ;
;                                   ;        IF      BUFFERFLAG
;                                   ;        I_am    SETVECTFLAG,BYTE,<0>
;                                   ;        ReferV86  BUF_EMS_SEG_CNT,WORD         ; DOS 4.00 EMS seg count           ;AN000;
;                                   ;        ReferV86  BUF_EMS_MODE,BYTE            ; DOS 4.00 EMS mode                ;AN000;
;                                   ;        i_am    BUF_EMS_MAP_USER,12,<0,0,0,0,0,0,0,0,0,0,0,0>
;                                   ;        ENDIF
;                                   ;
;                                   ;        EXTRN   DskStatChk:NEAR
;                                   ;
ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                      ;
;                                      ;;BD001;BREAK   <System call entry points and dispatcher>
;                                      ;;BD001;ASSUME  CS:V86GROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                      ;
;                                      ;BREAK <$Set_CTRL_C_Trapping -- En/Disable ^C check in dispatcher>
;                                      ;
;                                      ;; Inputs:
;                                      ;;       AL = 0 read ^C status
;                                      ;;       AL = 1 Set ^C status, DL = 0/1 for ^C off/on
;                                      ;;                       DL=0, BREAK=OFF   ;BN001;
;                                      ;;                       DL=1, BREAK=ON    ;BN001;
;                                      ;;       AL = 2 Set ^C status to contents of DL.  Output is old state.
;                                      ;;       AL = 3 Get CPSW state to DL        DOS 3.4  (accepted, does nothing)
;                                      ;;       AL = 4 Set CPSW state from DL      DOS 3.4  (accepted, does nothing)
;                                      ;;       AL = 5 get DOS boot drive to DL   ;BC001;
;                                      ;;       AL = 6 Get version number         ;BN001;
;                                      ;;        RETURNS:                         ;BN001;
;                                      ;;           BH = Minor version number     ;BN001;
;                                      ;;           BL = Major version number     ;BN001;
;                                      ;;           DL = DOS internal revision    ;BN001;
;                                      ;;           DH = DOS type flags:          ;BN001;
;                                      ;;              Bit 3   - DOS in ROM       ;BN001;
;                                      ;;              Bit 4   - DOS in HMA       ;BN001;
;                                      ;;              Bit 0-2, 5-7 - Reserved    ;BN001;
;                                      ;
;                                      ;;Note: the DOS version returned when AL=6 is the TRUE version of the    ;BN001;
;                                      ;; operating system.  The INT 21H, AH=30H (GET DOS VERSION), can be told ;BN001;
;                                      ;; to report a "false" DOS version via setting the EXTENDED PROPERTIES   ;BN001;
;                                      ;; for a specific application.                                           ;BN001;
;                                      ;
;                                      ;;               PART OF THE RESPONSE TO OPTION 6, FUNC_GET_DOS_VERSION ;BN001;
;                                      ;DOS_TYPE_FLAGS        EQU 0               ;BN001; NOT "DOS IN ROM" AND
;                                      ;                                          ;BN001; NOT "DOS IN HMA".
;                                      ;                                          ;BN001;   (BITS BOTH OFF)
;                                      ;DOS_INTERNAL_REVISION EQU 0               ;BN001; SET REVISION NUMBER TO
;                                      ;                                          ;BN001;   ORIGINAL VERSION
;                                      ;
;                                      ;;               RESPONSE TO OPTION 0, GET BREAK STATUS ;BN001;
;                                      ;BREAK_BIT             EQU 1               ;BN001; LOW BIT IN DL
;                                      ;;                                         ;BN001; DL=1,BREAK=ON. DL=0,BREAK=OFF
;                                      ;
;                                      ;;               SUBFUNCTIONS RECEIVED IN AL ;BN001;
;                                      ;FUNC_READ_C_STATUS    EQU 0               ;BN001; READ ^C STATUS
;                                      ;FUNC_SET_C_STAT1      EQU 1               ;BN001; SET ^C STATUS, DL=NEW STATE
;                                      ;FUNC_SET_C_STAT2      EQU 2               ;BN001; SET ^C STATUS, DL=OLD STATE
;                                      ;FUNC_GET_DOS_BOOT     EQU 5               ;BN001; GET DOS BOOT DRIVE
;                                      ;FUNC_GET_DOS_VERSION  EQU 6               ;BN001; GET TRUE DOS VERSION
;                                      ;
;                                      ;
;                                      ;        procedure   $SET_CTRL_C_TRAPPING,NEAR
;                                      ;ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                      ;        OR      AL,AL
;                                      ;        JNZ     Check1
;                                      ;;                                         ;BN001;(0) FUNC_READ_C_STATUS
;                                      ;        MOV     DL,CntCFlag               ;BC001;RETURN THE CURRENT BREAK=??
;                                      ;        iret
;                                      ;Check1:
;                                      ;        CMP     AL,FUNC_SET_C_STAT2       ;BC001;;AN000;TEST IS THIS SET BREAK
;                                      ;                                          ;BN001;   (AL=2)?
;                                      ;        JA      CPSWchk                   ;BC001;;AN000;NO, MUST BE BIGGER
;                                      ;        JZ      SetAndRet                 ;BC001;YES IT IS AL=2
;                                      ;                                          ;BN001;NO, MUST BE AL=1 (SET BREAK)
;                                      ;        PUSH    DX                        ;BC001;SAVE CALLER'S REG
;                                      ;        AND     DL,BREAK_BIT              ;BC001;SAVE ONLY THE "BREAK" BIT
;                                      ;        MOV     [CNTCFLAG],DL             ;BC001;SET NEW STATE AS REQUESTED
;                                      ;        POP     DX                        ;BC001;SAVE CALLER'S REG
;                                      ;        IRET
;                                      ;SetAndRet:                                ;BC001;AL=2, SET NEW BREAK STATE
;                                      ;        AND     DL,BREAK_BIT              ;BC001;SAVE ONLY THE "BREAK" BIT
;                                      ;        XCHG    CntCFlag,DL               ;BC001;SET NEW STATE
;                                      ;                                          ;BN001;PASS BACK OLD STATE
;                                      ;        IRET
;                                      ;BadVal:                                   ;BC001;SUBFUNC IN AL NON-SUPPORTED
;                                      ;        MOV     AL,0FFH                   ;BC001;PASS "ERROR" IN AL
;                                      ;        IRET
;                                      ;;; DOS 4.00 File Tagging
;                                      ;
;                                      ;CPSWchk:                                  ;AN000;
;                                      ;;                                         FUNCTION IN AL IS GREATER THAN 2
;                                      ;;       PUSH    AX                        ;AN000;;FT.
;                                      ;;       MOV     AL,[CPSWSAVE]             ;AN000;;FT. DOS 3.4
;                                      ;;       MOV     [CPSWFLAG],AL             ;AN000;;FT. DOS 3.4 in case ABORT
;                                      ;;       POP     AX                        ;AN000;;FT.
;                                      ;        CMP     AL,3                      ;AN000;;FT get CPSW state ?
;                                      ;        JNZ     CPSWset                   ;AN000;;FT. no
;                                      ;;       MOV     DL,CPSWFLAG               ;AN000;;FT. return CPSW state
;                                      ;        IRET                              ;AN000;
;                                      ;CPSWset:                                  ;AN000;
;                                      ;        CMP     AL,4                      ;AN000;;FT. set CPSW state ?
;                                      ;        JA      QueryDOSboot              ;AN000;;FT. check query dos boot drive
;                                      ;;       PUSH    AX                        ;AN000;;FT.
;                                      ;;       CallInstall NLSInstall,NLSFUNC,0  ;AN000;;FT. NLSFUNC installed ?
;                                      ;;       CMP     AL,0FFH                   ;AN000;;FT.
;                                      ;;       POP     AX                        ;AN000;;FT.
;                                      ;;       JNZ     BadVal                    ;AN000;;FT. not loaded, therefore ignore
;                                      ;;;;;    AND     DL,01H                    ;AN000;;FT. only 0 or 1
;                                      ;;;;;    MOV     [CPSWFLAG],DL             ;AN000;;FT. set the flag
;                                      ;;;;;    MOV     [CPSWSAVE],DL             ;AN000;;FT. save one copy
;                                      ;        IRET                              ;AN000;;FT.
;                                      ;QueryDOSboot:                             ;AN000;
;                                      ;        CMP     AL,FUNC_GET_DOS_BOOT      ;BC001;AL=5? IS THIS GET DOS BOOT DR?
;                                      ;        JA      TrueMajMin                ;BC001;NO, NOT AL=5, GUESS AGAIN
;                                      ;                                          ;BN001;YES, AL=5, GET DOS BOOT DRIVE
;                                      ;        MOV     DL,[BOOTDRV]              ;AN000;;MS. put boot drive in DL
;                                      ;        IRET                              ;AN000;;MS.
;                                      ;
;                                      ;TrueMajMin:                               ;BN001; CHECK FOR "GET VERSION NUMBER"
;                                      ;                                          ;BN001; AL IS GREATER THAN 5
;                                      ;        CMP     AL,FUNC_GET_DOS_VERSION   ;BN001;(AL=6?) IS THIS FOR
;                                      ;                                          ;BN001;    "GET VERSION NUMBER"
;                                      ;        JA      BadVal                    ;BN001; IF NOT, INVALID REQUEST
;                                      ;                                          ;BN001; IF SO, CONTINUE
;                                      ;        MOV     BX,(MINOR_VERSION SHL 8) + MAJOR_VERSION ;BN001;
;                                      ;                                          ;BN001; BH=MINOR VERSION
;                                      ;                                          ;BN001; BL=MAJOR VERSION
;                                      ;        MOV     DX,(DOS_TYPE_FLAGS SHL 8) + DOS_INTERNAL_REVISION ;BN001;
;                                      ;                                          ;BN001; DL = DOS internal revision
;                                      ;                                          ;BN001; DH = DOS type flags:
;                                      ;                                          ;BN001;   Bit 3   - DOS in ROM
;                                      ;                                          ;BN001;   Bit 4   - DOS in HMA
;                                      ;                                          ;BN001;   Bit 0-2, 5-7 - Reserved
;                                      ;        IRET                              ;BN001; RETURN TO CALLER
;                                      ;
;                                      ;;; DOS 4.00 File Tagging
;                                      ;
;                                      ;EndProc $SET_CTRL_C_TRAPPING
;                                      ;
;                                      ;BREAK <$Get_current_PDB -- Set/Get PDB value>
;                                      ;;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;                                      ;;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                      ;;                                                                          ;
;                                      ;; The following two routines are dispatched to directly with ints disabled
;                                      ;; immediately after the int 21h entry.  no DIS state is set.
;                                      ;;
;                                      ;; $Set_current_PDB takes BX and sets it to be the current process
;                                      ;;   *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
;                                      ;;
;                                      ;procedure   $SET_CURRENT_PDB,NEAR
;                                      ;        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                      ;;m        PUSH    ES
;                                      ;;m        MOV     ES,BX
;                                      ;;m        SVC     SVC_DEMSETCURRENTPDB
;                                      ;;m        POP     ES
;                                      ;        MOV     [CurrentPDB],BX
;                                      ;        mov     cs:os2_handled,0          ; mdr allow DOS to do this also
;                                      ;        RET                               ; mdr changed from IRET
;                                      ;EndProc $SET_CURRENT_PDB
;                                   ;
;                                   ;;
;                                   ;; $get_current_PDB returns in BX the current process
;                                   ;;   *** THIS FUNCTION CALL IS SUBJECT TO CHANGE!!! ***
;                                   ;;
;                                   ;procedure   $GET_CURRENT_PDB,NEAR
;                                   ;        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                   ;        MOV     BX,[CurrentPDB]
;                                   ;        IRET
;                                   ;EndProc $GET_CURRENT_PDB
;                                   ;;            C  A  V  E  A  T     P  R  O  G  R  A  M  M  E  R             ;
;                                   ;;                                                                          ;
;                                   ;;----+----+----+----+----+----+----+----+----+----+----+----+----+----+----;
;                                   ;
procedure   SYSTEM_CALL,NEAR
;                                   ;
;                                   ;; The Quit entry point is where all INT 20h's come from.  These are old- style
;                                   ;; exit system calls.  The CS of the caller indicates which Process is dying.
;                                   ;; The error code is presumed to be 0.  We simulate an ABORT system call.
;                                   ;;
;                                   ;        entry   QUIT
;                                   ;        MOV     AH,0
;                                   ;        JMP     SHORT SAVREGS
;                                   ;;
; The system call in AH is out of the range that we know how to handle.  We
; arbitrarily set the contents of AL to 0 and IRET.  Note that we CANNOT set
; the carry flag to indicate an error as this may break some programs
; compatability.
;                                   ;;
BADCALL:
        iret
;                                   ;;
;                                   ;; An alternative method of entering the system is to perform a CALL 5 in the
;                                   ;; program segment prefix with the contents of CL indicating what system call
;                                   ;; the user would like.  A subset of the possible system calls is allowed here;
;                                   ;; only the CPM-compatible calls may get dispatched.
;                                   ;;
;                                   ;        entry   CALL_ENTRY              ; System call entry point and dispatcher
;                                   ;        POP     AX                      ; IP from the long call at 5
;                                   ;        POP     AX                      ; Segment from the long call at 5
;                                   ;        POP     [User_SP]               ; IP from the CALL 5
;                                   ;;
;                                   ;; Re order the stack to simulate an interrupt 21.
;                                   ;;
;                                   ;        PUSHF                           ; Start re-ordering the stack
;                                   ;        CLI
;                                   ;        PUSH    AX                      ; Save segment
;                                   ;        PUSH    [User_SP]               ; Stack now ordered as if INT had been used
;                                   ;        CMP     CL,MAXCALL              ; This entry point doesn't get as many calls
;                                   ;        JA      BADCALL
;                                   ;        MOV     AH,CL
;                                   ;        JMP     SHORT SavRegs
;
; This is the normal INT 21 entry point.  We first perform a quick test to see
; if we need to perform expensive DOS-entry functions.  Certain system calls
; are done without interrupts being enabled.
;

entry   COMMAND                        ; Interrupt call entry point (INT 21H)

;       cmp     ah,6fh                 ; mdr compare func num to highest poss.   ; BN010 ;
        cmp     ah,0ffh                ; mdr compare func num to highest poss.   ; BN010 ;
        jbe     SAVREGS                ;BN003  if ok then continue

;BD003  ja      func_too_high          ; mdr if above then go to DOS
;BD003  cmp     ah,59h                 ; mdr if this is call to extended err
;BD003  jne     SAVREGS
;BD003  cmp     cs:os2_handled,1       ; mdr if os/2 handled last call then
;BD003  je      SAVREGS                ; mdr continue here
;BD003 func_too_high:

        jmp     cs:[pOldInt21]         ; mdr else jump to the next handler


;                                   ;        IF      NOT IBM
;                                   ;        CMP     AH,SET_OEM_HANDLER
;                                   ;        JB      NOTOEM
;                                   ;        JMP     $SET_OEM_HANDLER
;                                   ;NOTOEM:
;                                   ;        ENDIF
;
; The following set of calls are issued by the server at *arbitrary* times
; and, therefore, must be executed on the user's entry stack and executed with
; interrupts off.
;
SAVREGS:
        mov     cs:EXTERR,0         ;BN003  clear exterr field
;                                   ;        CMP     AH,GET_CURRENT_PDB
;                                   ;        JZ      $GET_CURRENT_PDB
;                                   ;        CMP     AH,GetCurrentPSP
;                                   ;        JZ      $GET_CURRENT_PDB
;                                   ;        CMP     AH,SET_CURRENT_PDB
;                                   ;        JZ      $SET_CURRENT_PDB
;                                   ;        CMP     AH,Set_CTRL_C_Trapping
;                                   ;        JNZ     chkprt
;                                   ;        JMP     $Set_CTRL_C_Trapping
chkprt:
;
; Preserve all user's registers on his own stack.
;
        CALL    save_world
        MOV     [SaveBX],BX
        MOV     [SaveDS],DS
;                                   ;        MOV     BX,CS
;                                   ;        MOV     DS,BX
;                                   ;        ASSUME  DS:V86GROUP
        lds     bx,[REAL_INDOS]     ;BN005 get address of real indos flag
        inc     byte ptr ds:[bx]    ;BN005 and inc it
        INC     [INDOS]             ;BN002 Flag that we're in the DOS
;                                   ;        XOR     AX,AX
;                                   ;        MOV     [USER_ID],AX
;                                   ;        MOV     AX,CurrentPDB           ; current process
;                                   ;        MOV     [PROC_ID],AX            ; Assume local machine for the moment
;                                   ;;
; Provide one level of reentrancy for INT 24 recallability.
;                                   ;;

        CLI                         ;BN002
        mov     al,os2_handled      ;BN004
        mov     os2_handled_hold,al ;BN004
        MOV     AX,[user_SS]        ;BN002  save the stack addr just in case
        MOV     [NSS],AX            ;BN002
        MOV     AX,[user_SP]        ;BN002
        MOV     [NSP],AX            ;BN002

        MOV     [user_SS],SS
        MOV     [user_SP],SP
;
; save user stack in his area for later returns (possibly from EXEC)
;
        MOV     DS,[CurrentPDB]
;        mov     ah,51h                  ;BN004 get currentPDB from DOS
;        pushf                           ;BN004
;        call    cs:[pOldInt21]          ;BN004
;        mov     ds,bx                   ;BN004 move PDB to DS
ASSUME  DS:NOTHING
        MOV     WORD PTR DS:[PDB_User_stack],SP
        MOV     WORD PTR DS:[PDB_User_stack+2],SS

;                                   ;if 0 ; BUGBUG danno 29-Jan-1989
;                                   ;        MOV     fSharing,0              ; allow redirection
;                                   ;endif ; BUGBUG danno 29-Jan-1989

        POP     AX                  ;BN002  restore the AX reg from the stack  ;BC004
        PUSH    AX                  ;BN002                                     ;BC004

entry   REDISP
        MOV     BX,CS               ; get segment for stack

        CMP     [indos],2           ;BN002 if filter was interrupted use INTSTACK
        je      cmd100              ;BN002
        ja      cmd200              ;BN002 more than once? use current stack

        MOV     SS,BX
        MOV     SP,OFFSET V86GROUP:AUXSTACK   ; Enough stack for interrupts
        jmp     cmd200

cmd100:                                       ;BN002
        MOV     SS,BX                         ;BN002
        MOV     SP,OFFSET V86GROUP:INTSTACK   ;BN002

;                                   ; IF  DBCS                                       ;AN000;
;                                   ;        MOV     BH, BYTE PTR DS:[PDB_InterCon]  ;AN000;; get interim mode  2/13/KK
;                                   ;        MOV     [InterCon], BH                  ;AN000;; 2/13/KK
;                                   ; ENDIF                                          ;AN000;
;                                   ;;        MOV     BX,CS
;                                   ;;        MOV     DS,BX
;                                   ;;        DOSAssume   CS,<DS>,"MSCODE/ReDisp"
;                                   ;;; DOS 3.4 INIT
;                                   ;;       MOV     BL,[CPSWSAVE]           ;AN000;;FT. DOS 3.4
;                                   ;;       MOV     [CPSWFLAG],BL           ;AN000;;FT. DOS 3.4 in case ABORT
;                                   ;;       MOV     [DISK_FULL],0           ;AN000;;MS. no disk full
;                                   ;;        MOV     [EXTOPEN_ON],0          ;AN000;;EO. clear extended open flag
;                                   ;;        MOV     [DOS34_FLAG],0          ;AN000;;MS. clear common flag
;                                   ;;ifdef NOT_MVDM
;                                   ;;        MOV     [ACT_PAGE],-1           ;BN000;BL;AN000;;LB. invalidate active page
;                                   ;;endif
;                                   ;;; DOS 4.00 INIT
cmd200:
        XOR     BH,BH
;                                   ;;        MOV     [CONSWAP],BH            ; random clean up of possibly mis-set flags
;                                   ;;        MOV     [IDLEINT],1             ; presume that we can issue INT 28
;                                   ;;        MOV     BYTE PTR [NoSetDir],BH  ; set directories on search
;                                   ;;        MOV     BYTE PTR [FAILERR],BH   ; FAIL not in progress
        MOV     [vheVDM].vhe_fbMisc,BH  ; no pending hard errors
        MOV     BL,AH
        SHL     BX,1                    ; 2 bytes per call in table
        CLD
;                                   ;;
;                                   ;; Since the DOS maintains mucho state information across system calls, we
;                                   ;; must be very careful about which stack we use.
;                                   ;;
;                                   ;; First, all abort operations must be on the disk stack.  THis is due to the
;                                   ;; fact that we may be hitting the disk (close operations, flushing) and may
;                                   ;; need to report an INT 24.
;                                   ;;
;                                   ;;        OR      AH,AH
;                                   ;        JZ      DSKROUT                 ; ABORT
;                                   ;;
;                                   ;; Second, PRINT and PSPRINT and the server issue GetExtendedError calls at
;                                   ;; INT 28 and INT 24 time.  This call MUST, therefore, use the AUXSTACK.
;                                   ;;
;                                   ;        CMP     AH,GetExtendedError
;                                   ;        JZ      DISPCALL
;
;                                   ;        JMP     SHORT DISPCALL
;                                   ;;
;                                   ;; We are on a system call that is classified as "the rest".  We place
;                                   ;; ourselves onto the DSKSTACK and away we go.  We know at this point:
;                                   ;;
;                                   ;;   o   An INT 24 cannot be in progress.  Therefore we reset errormode and
;                                   ;;       wperr
;                                   ;;   o   That there can be no critical sections in effect.  We signal the
;                                   ;;       server to remove all the resources.
;                                   ;;
;                                   ;DSKROUT:
        MOV     [USER_IN_AX],AX         ; Remember what user is doing   @BN009
;                                   ;        MOV     [EXTERR_LOCUS],errLOC_Unk ; Default
;                                   ;        MOV     [ERRORMODE],0           ; Cannot make non 1-12 calls in
;                                   ;        MOV     [WPERR],-1              ; error mode, so good place to make
;                                   ;;
;                                   ;; Release all resource information
;                                   ;;
;                                   ;        PUSH    AX
;                                   ;        MOV     AH,82h
;                                   ;        INT     int_IBM
;                                   ;        POP     AX
;                                   ;
;                                   ;;
;                                   ;; Since we are going to be running on the DSKStack and since INT 28 people
;                                   ;; will use the DSKStack, we must turn OFF the generation of INT 28's.
;                                   ;;
;                                   ;        MOV     IdleInt,0
;                                   ;        MOV     SP,OFFSET V86GROUP:DSKSTACK
;                                   ;        TEST    [CNTCFLAG],-1
;                                   ;        JZ      DISPCALL                ; Extra ^C checking is disabled
;                                   ;        PUSH    AX
;                                   ;        invoke  DSKSTATCHK
;                                   ;        POP     AX
;                                   ;DISPCALL:
;                                   ;; VPL Idle detection, Note useful work when not polling
;                                   ;        CMP     bx, 18h                 ; bx = 2*function number
;                                   ;        JBE     cmd300                  ;   skip if low call
;                                   ;        CMP     bx, 58h                 ; get time call?
;                                   ;        JE      cmd300                  ;   skip if get time call
;                                   ;        CMP     bx, 54h                 ; get date call?
;                                   ;        JE      cmd300                  ;   skip if get date call
;                                   ;        MOV     VDMNotBusy,0            ; Avoid idle detection sleep
;                                   ;cmd300:
        MOV     BX,Dispatch[BX]
        XCHG    BX,SaveBX
        MOV     DS,SaveDS
;                                   ;
;                                   ;IF      BUFFERFLAG
;                                   ;        mov     cs:[SETVECTFLAG], 0
;                                   ;        cmp     ah, 25h
;                                   ;        jne     saveuser
;                                   ;        cmp     ah, 35h
;                                   ;        jne     saveuser
;                                   ;        mov     cs:[SETVECTFLAG], 1
;                                   ;saveuser:
;                                   ;        invoke  SAVE_USER_MAP               ;AN000;LB.  save EMS map
;                                   ;ENDIF

        mov     cs:os2_handled,1           ; mdr initialize to true
;BD006        STI                         ; stack is in our space now...   BC002

        ASSUME  DS:NOTHING
        CALL    SaveBX

;                                   ;IF      BUFFERFLAG
;                                   ;      invoke  RESTORE_USER_MAP            ;AN000;LB.  retsore EMS map
;                                   ;ENDIF

        entry   LEAVEDOS
ASSUME  SS:NOTHING                      ; User routines may misbehave
        CLI
        MOV     SS,[user_SS]
        MOV     SP,[user_SP]
        MOV     BP,SP

        cmp     cs:os2_handled,1        ; mdr if os/2 did not handle then do not
        jne     over                    ; mdr save any return code
        mov     BYTE PTR [BP.user_AX],AL

        cmp     cs:EXTERR,0             ;BN003  see if exterr was updated
        je      over                    ;BN003  if not, skip over
        mov     ax,cs:EXTERR            ;BN003  transfer the error codes to
        mov     cs:DPL_EXTERR,ax        ;BN003  the DPL (dos parameter list)
        mov     al,cs:EXTERR_LOCUS      ;BN003  area.
        mov     cs:DPL_EXTERR_LOCUS,al  ;BN003
        mov     al,cs:EXTERR_CLASS      ;BN003
        mov     cs:DPL_EXTERR_CLASS,al  ;BN003
        mov     al,cs:EXTERR_ACTION     ;BN003
        mov     cs:DPL_EXTERR_ACTION,al ;BN003
        mov     ax,5d0ah                ;BN003  set DOS extended error
        push    cs                      ;BN003  setup pointer to error info
        pop     ds                      ;BN003  point to our DPL
        mov     dx,offset V86GROUP:DPL_EXTERR   ;BN003
        pushf                           ;BN003  set up for int 21 call
        call    cs:[pOldInt21]          ;BN003  make call to DOS

over:
        MOV     AX,[NSS]               ;BN002  restore original stack values
        MOV     [user_SS],AX           ;BN002
        MOV     AX,[NSP]               ;BN002
        MOV     [user_SP],AX           ;BN002

        dec     [indos]                ;BN002
        lds     bx,[REAL_INDOS]        ;BN005 get address of real indos flag
        dec     byte ptr ds:[bx]       ;BN005 and dec it

; put user stack address back in PDB in case any DOS calls changed it.
;
        MOV     DS,[CurrentPDB]                                        ;BN008
ASSUME  DS:NOTHING                                                     ;BN008
        MOV     WORD PTR DS:[PDB_User_stack],SP                        ;BN008
        MOV     WORD PTR DS:[PDB_User_stack+2],SS                      ;BN008

        CALL    restore_world          ;BC005

        cmp     cs:os2_handled,0       ; mdr if os/2 did not handle call
        jz      get_out                ; mdr go to DOS
        push    ax                     ;BN004
        mov     al,os2_handled_hold    ;BN004
        mov     os2_handled,al         ;BN004
        pop     ax                     ;BN004
        IRET

get_out:
        push    ax                     ;BN004
        mov     al,os2_handled_hold    ;BN004
        mov     os2_handled,al         ;BN004
        pop     ax                     ;BN004
        jmp     cs:[pOldInt21]         ; mdr jump to the next handler

EndProc SYSTEM_CALL

;
; restore_world restores all registers ('cept SS:SP, CS:IP, flags) from
; the stack prior to giving the user control
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
        procedure   restore_world,NEAR
        POP     restore_tmp             ; POP     restore_tmp
        POP     AX                      ; PUSH    ES
        POP     BX                      ; PUSH    DS
        POP     CX                      ; PUSH    BP
        POP     DX                      ; PUSH    DI
        POP     SI                      ; PUSH    SI
        POP     DI                      ; PUSH    DX
        POP     BP                      ; PUSH    CX
        POP     DS                      ; PUSH    BX
        POP     ES                      ; PUSH    AX
        JMP     restore_tmp             ; PUSH    restore_tmp
EndProc restore_world

;
; save_world saves complete registers on the stack
;
        ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
        procedure   save_world,NEAR
        POP     restore_tmp
        PUSH    ES
        PUSH    DS
        PUSH    BP
        PUSH    DI
        PUSH    SI
        PUSH    DX
        PUSH    CX
        PUSH    BX
        PUSH    AX
        JMP     restore_tmp             ; PUSH    restore_tmp
EndProc save_world

;                                   ;IF BUFFERFLAG
;                                   ;
;                                   ;Break   <SAVE_USER_MAP - save map >                                                     ;AN000;
;                                   ;; Inputs:                                                                       ;AN000;
;                                   ;;       none                                                                    ;AN000;
;                                   ;; Function:                                                                     ;AN000;
;                                   ;;       save map                                                                ;AN000;
;                                   ;; Outputs:                                                                      ;AN000;
;                                   ;;       none                                                                    ;AN000;
;                                   ;; No other registers altered                                                    ;AN000;
;                                   ;                                                                                ;AN000;
;                                   ;Procedure   SAVE_USER_MAP,NEAR                                                   ;AN000;
;                                   ;        ASSUME  DS:NOTHING,ES:NOTHING                                           ;AN000;
;                                   ;                                                                                ;AN000;
;                                   ;        CMP     cs:[BUF_EMS_MODE],-1      ;LB. EMS support                      ;AN000;
;                                   ;        JZ      No_user_save              ;LB. no                               ;AN000;
;                                   ;        CMP     cs:[SETVECTFLAG], 1
;                                   ;        jz      No_user_save
;                                   ;;       MOV     [ACT_PAGE],-1             ;LB. invalidate active page           ;AN000;
;                                   ;;       MOV     WORD PTR [LASTBUFFER],-1  ;LB.  and last buffer pointer         ;AN000;
;                                   ;        PUSH    AX                        ;LB. save regs                        ;AN000;
;                                   ;        PUSH    DS                        ;LB. save regs                        ;AN000;
;                                   ;        PUSH    ES                        ;LB.                                  ;AN000;
;                                   ;        PUSH    SI                        ;LB.                                  ;AN000;
;                                   ;        PUSH    DI                        ;LB.                                  ;AN000;
;                                   ;        MOV     SI,OFFSET V86GROUP:BUF_EMS_SEG_CNT     ;LB.                     ;AN000;
;                                   ;        MOV     DI,OFFSET V86GROUP:BUF_EMS_MAP_USER     ;LB.                    ;AN000;
;                                   ;
;                                   ;        PUSH    CS
;                                   ;        POP     ES
;                                   ;        PUSH    CS                        ;LB. ds:si -> ems seg cnt             ;AN000;
;                                   ;        POP     DS                        ;LB.                                  ;AN000;
;                                   ;
;                                   ;        MOV     AX,4F00H                  ;LB. save map                         ;AN000;
;                                   ;        EnterCrit  critDisk               ;LB. enter critical section           ;AN000;
;                                   ;        INT     67H                       ;LB.                                  ;AN000;
;                                   ;        LeaveCrit  critDisk               ;LB. leave critical section           ;AN000;
;                                   ;        POP     DI                        ;LB.                                  ;AN000;
;                                   ;        POP     SI                        ;LB. restore regs                     ;AN000;
;                                   ;        POP     ES                        ;LB.                                  ;AN000;
;                                   ;        POP     DS                        ;LB.                                  ;AN000;
;                                   ;        POP     AX                        ;LB. restore                          ;AN000;
;                                   ;No_user_save:                                                                    ;AN000;
;                                   ;        return                                                                  ;AN000;
;                                   ;EndProc SAVE_USER_MAP                                                            ;AN000;
;                                   ;                                                                                ;AN000;
;                                   ;
;                                   ;Break   <RESTORE_USER_MAP- retore map >                                         ;AN000;
;                                   ;; Inputs:                                                                       ;AN000;
;                                   ;;       none                                                                    ;AN000;
;                                   ;; Function:                                                                     ;AN000;
;                                   ;;       restore_map                                                             ;AN000;
;                                   ;; Outputs:                                                                      ;AN000;
;                                   ;;       none                                                                    ;AN000;
;                                   ;; No other registers altered                                                    ;AN000;
;                                   ;                                                                                ;AN000;
;                                   ;Procedure   RESTORE_USER_MAP,NEAR                                                        ;AN000;
;                                   ;        ASSUME  DS:NOTHING,ES:NOTHING                                           ;AN000;
;                                   ;
;                                   ;        CMP     [BUF_EMS_MODE],-1      ;LB. EMS support                      ;AN000;
;                                   ;        JZ      No_user_restore           ;LB. no                               ;AN000;
;                                   ;        CMP     [SETVECTFLAG], 1
;                                   ;        jz      No_user_restore
;                                   ;        PUSH    AX                        ;LB. save regs                        ;AN000;
;                                   ;        PUSH    DS                        ;LB. save regs                        ;AN000;
;                                   ;        PUSH    SI                        ;LB.                                  ;AN000;
;                                   ;        MOV     SI,OFFSET V86GROUP:BUF_EMS_MAP_USER     ;LB.                    ;AN000;
;                                   ;
;                                   ;        PUSH    CS
;                                   ;        POP     DS
;                                   ;
;                                   ;        MOV     AX,4F01H                  ;LB. restore map                      ;AN000;
;                                   ;        EnterCrit  critDisk               ;LB. enter critical section           ;AN000;
;                                   ;        INT     67H                       ;LB.                                  ;AN000;
;                                   ;        LeaveCrit  critDisk               ;LB. leave critical section           ;AN000;
;                                   ;        POP     SI                        ;LB. restore regs                     ;AN000;
;                                   ;        POP     DS                        ;LB.                                  ;AN000;
;                                   ;        POP     AX                        ;LB.                                  ;AN000;
;                                   ;No_user_restore:                                                                         ;AN000;
;                                   ;        return                                                                  ;AN000;
;                                   ;EndProc RESTORE_USER_MAP
;                                   ;
;                                   ;ENDIF

;
; get_user_stack returns the user's stack (and hence registers) in DS:SI
;
procedure   get_user_stack,NEAR
        LDS     SI,DWORD PTR [user_SP]
        return
EndProc get_user_stack

;                                   ;        IF      NOT IBM
;                                   ;BREAK <Set_OEM_Handler -- Set OEM sys call address and handle OEM Calls
;                                   ;
;                                   ;$SET_OEM_HANDLER:
;                                   ;ASSUME  DS:NOTHING,ES:NOTHING,SS:NOTHING
;                                   ;
;                                   ;; Inputs:
;                                   ;;       User registers, User Stack, INTS disabled
;                                   ;;       If CALL F8, DS:DX is new handler address
;                                   ;; Function:
;                                   ;;       Process OEM INT 21 extensions
;                                   ;; Outputs:
;                                   ;;       Jumps to OEM_HANDLER if appropriate
;                                   ;
;                                   ;        JNE     DO_OEM_FUNC             ; If above F8 try to jump to handler
;                                   ;        MOV     WORD PTR [OEM_HANDLER],DX   ; Set Handler
;                                   ;        MOV     WORD PTR [OEM_HANDLER+2],DS
;                                   ;        IRET                            ; Quick return, Have altered no registers
;                                   ;
;                                   ;DO_OEM_FUNC:
;                                   ;        CMP     WORD PTR [OEM_HANDLER],-1
;                                   ;        JNZ     OEM_JMP
;                                   ;        JMP     BADCALL                 ; Handler not initialized
;                                   ;
;                                   ;OEM_JMP:
;                                   ;        JMP     [OEM_HANDLER]
;                                   ;        ENDIF


V86CODE    ENDS

        END
