;       SCCSID = @(#)viorout.asm        6.12 92/02/24
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
        PAGE    58,132
        SUBTTL  Data declarations, etc.
        TITLE   VIOROUT.ASM -- VIDEO SUBSYSTEM ROUTER
;******************************************************************************
;*******   C H A N G E       H I S T O R Y   **********************************
;******************************************************************************
;$A2= only allow certain calls during POPUP & don't save/restore cursor type
;     6-23-86 (7.32)
;$??= open each screen group's semaphore under shell PID in VIOSHELLINIT
;     6-26-86 (7.32)
;$A3= store VIO function code being serviced in INSTANCE:VIO_FUNC
;     6-26-86 (7.32)
;$A4= request current foreground screen group's semaphore during VIOPRTSC
;     6-27-86 (7.32)
;$A5= add support for parms on VIOSRFBLOCK/VIOSRFUNBLOCK to close window
;     during normal popups, block poperr's siblings, block popee, and SETMODE.
;     7-03-86 (7.33)
;$A6= for VIOPRTSC: call fgSG's AVS if registered, else call shellPID's AVS/BVS
;     ?-??-?? (?.??) (i.e. NOT YET COMPLETE)
;$A7= expect parameters for VIOREGISTER in same order as listed in spec.
;     7-07-86 (7.33)
;$A8= for each call to DOSOPENSEM, if error call  DOSCREATESEM
;     7-08-86 (7.33)
;$A9= if ERROR_SEM_OWNER_DIED from DOSSEMREQUEST and SGDATA[currSG].pop_mode
;     = 1, call DOSSMSGENDPOPUP so sess. mgr. will know to terminate the popup
;     7-09-86 (7.33)
;$A10= save/restore BX in VIOSHELLINIT procedure
;      7-10-86 (7.33)
;$A11= only complete VIOINIT once!
;      7-11-86 (7.33)
;$A12= set currSG at each entry point (from GDT info seg)
;      7-14-86 (7.34)
;$B1= use DOSEXITLIST to recover from aborted popups
;     7-16-86 (7.36)
;$B2= freeze popups during VIOPRTSC with PRTSCSEM system semaphore
;     7-16-86 (7.36)
;$B3= start to open/create semaphores from SG 0, not currSG (in VIOSHELLINIT)
;     7-17-86 (7.36)
;$B4= block fgSG during VIOPRTSC
;     7-18-86 (7.36)
;$B5= add new VIO calls VIOGETFONT and VIOGETCONFIG
;     7-18-86 (7.36)
;$B6= reset registers in at earlier spot in VIOPOPUP
;     7-22-86 (7.37)
;$B7= add 2 word parameters to VIOSHELLINIT (for BVS)
;     7-22-86 (7.37)
;$B8= add support for DOSSYSTRACE
;     7-24-86 (7.40)
;$B9= No longer assume DS is set already in GETINFOSEGS procedure
;     7-28-86 (7.40)
;$C1= Reset POP_MODE flag before calling sess. mgr. to switch SGs
;     7-28-86 (7.40)
;$C2= skip screen groups in CTRL-NUMLOCK state in SRFBLOCK/SRFUNBLOCK
;     7-31-86 (7.40)
;$C3= popped DS too many times in VIOENDPOPUP (oops!!!)
;     7-31-86 (7.40)
;$C4= allow HARD_ERROR popups over top of regular popups
;     8-05-86 (7.42)
;$C5= use DOSHOLDSIGNAL for crit. section during calls to subsystem(s)
;     8-12-86 (7.43)
;$C6= use a RAM semaphore REGRAMSEM to synch register/deregister requests
;     8-14-86 (?.??)
;$C7= remove PRTSCSEM references
;     8-18-86 (?.??)
;$C8= save/restore ret. code in VIOPOPUP
;     9-11-86 (?.??)
;$C9= check for CTRL-NUMLOCK/CTRL-S pause requests
;     9-12-86 (?.??)
;$D0= move POP_MODE flag to INSTANCE data segment
;     9-19-86 (7.58)
;$D1= DX <-- currPID after MUL instruction, not before
;     9-19-86 (7.58)
;$D2= zero-out data area grown by DOSREALLOCSEG
;     9-30-86 (7.62)
;$D3= get currTID from INFOSEG, not INSTANCE data variable
;     10-07-86 (7.63)
;$D4= get rid of DS:VIO_FUNC, get function code from stack ALWAYS!!
;     10-16-86 (7.66)
;$D5= use stack frame to store masks (thread dependent)
;     10-17-86 (7.67)
;$Y9= correct logic to clear sys-sem after registered scrn-switcher type calls
;     07-14-87
;$Z1= if PRTSC/PRTSCTOGGLE replaced, release created threads
;     06-04-87
;$Z2= DOSLOADMODULE/DOSFREEMODULE every time replaced PRTSC/PRTSCTOGGLE called
;     05-21-87
;$Z3= don't free registered module before calling vioattach, done in DEREGISTER
;     05-21-87
;$Z4= vioattach: don't open per-screen-group sem if ALREADY open!
;     05-18-87
;$Z5= vioattach should ignore DOSGETDBCSEV error codes
;     03-18-87
;$Z6= if resource allocation error, signal HET and wait to be killed
;     03-02-87
;$Z7= add 1 to MAX NUM SCREEN GROUPS (numSGs) for "detach SG"
;     11-18-86
;$Z8= expand FUNC_TBL for new API
;     11-18-86
;$Z9= disallow calls from DETACHed processes @@11
;     11-03-86
;%A0= Use FS RAM sems instead of system sems.
;     07-30-87
;%A1= Support for AVIO calls
;     07-30-87
;P3426= Kill process if unable to add VioFSRAMExit routine
;       08-25-88
;P1941= fill in [bp].replacemask from per-session data area
;       09-01-88
;MMIO= Implement Memory-Mapped I/O performance trace hooks
;      11-03-88
;P3910= call DosSleep(0) on viorout exit to smooth-out mutiple callers
;       10-22-88
;P3960= remove call to DosSleep(0) on viorout exit (P3910)
;       11-14-88 (1.2 PTM 2762)
;P3839= initCP called on SG's first VIO call (set video CP to process CP)
;       11-14-88 (1.2 PTM 2502)
;P2859= (1.2 PTM) notify global register subsystem(s) on error condition
;       11-28-88
;P2893= (1.2 PTM) Deadlock when registered subsystem reenter with pause active
;       12-01-88
;P3355= (1.2 PTM) Registered routine's return code destroyed
;       01-09-88
;@T2  = 04/03/89 TPL, Sizzle work, PTR B701685
;@T4  = 05/03/89 TPL, Popup semaphore must be created non-exclusive because
;                     the VioPopUp routine expects the 2nd popup request to
;                     fail if one already exists.  PTR B702162
;@T5  = 05/10/89 TPL, PTR B701685 fix
;@T6  = 06/15/89 TPL, Handle Prtsc properly, PTR B70609
;@T7  = 07/06/89 TPL, Removal of 3xbox code
;@T8  = 08/17/89 TPL, Compress registration mask for BVS, PTR B707524
;DTBB1= 08/21/89 WKB, Add Dynamic Trace in place of Static Trace (DOSSYSTRACE)
;@T11 = 09/05/89 TPL, Register early and late exitlist routine, B785577
;D549 = 11/03/89 WKB,CJJ DCR 549 changes
;@T52 = 01/15/90 TPL, DCR 704 work
;BUG549 = 02/06/90 WKB, Add initCP , B711431
;@T54 = 02/21/90 TPL, DCR 704 fix for MMIO support
;@B46 = 03/22/90 WKB, Fix trap for detached processes, B788511
;@C42  03/26/90  CJJ, SL85039 Don't allow VioPopups until Shell has done a
;                VioSavRedrawWait.
;@T14 = 03/28/90 TPL, Remove duplication of functions
;@T18 = 04/30/90 TPL, B712103 - Optimize popup and screen switch processing
;@T71 = 07/06/90 TPL, Allow Shell to make AVIO calls, Hursley DCR 25177, B714347
;@T73 = 07/27/90 TPL, Code/data reduction/optimization and swap tune
;@C39 = 01/11/91 CJJ, MVDM transparent popup changes, PTR SM84577
;@T72 = 01/21/91 TPL, Hold signal after return from Pause SemWait, B718518
;@C48 = 03/06/91 CJJ, AR07976 Prtsc hangs - clear foreground FSRamSem.
;@B722219 = 06/14/91 WKB, B722219 - Give up timeslice as appropriate
;001B = 07/03/91 TPL, Avoid calling BVS at Process Init time to allow
;                     invalid BVH DLLs to unlink immediately, B724540
;@C51 = 08/01/91  CJJ, Get codepage during session init, VioSetCP in router.
;@GDW = 08/29/91  PTR B726157 - Combine KIO and MIO into MKIO router
;@T80 = 02/06/92 TPL, Don't use the reserved register FS, B732479
;@T85 = 02/23/92 TPL, Reduce usage of DosLoadModule, B733000
;@TAK = 03/06/93 T Kirschner, Defect 62883 VioRegister Trap.
;MDLL = 01/10/94 BJN, Page Tune segments for Merged DLL.

;/*********************** START OF SPECIFICATIONS ***********************/
;/*                                                                     */
;/* Source File Name:  VIOROUT.ASM                                      */
;/*                                                                     */
;/* Descriptive Name:  Video Function Call Router                       */
;/*                                                                     */
;/* Function:  Route VIO function calls to the appropriate video        */
;/*            subsystem based on the current screen group.             */
;/*                                                                     */
;/* Notes:                                                              */
;/*                                                                     */
;/* Entry Points:  getinfosegs, VIOINIT, viorout, vioattach             */
;/*                                                                     */
;/* External References:  Base Video Subsystem, Alternate Video         */
;/*                       Subsystem(s)                                  */
;/*            Routines:  DosGetProcAddr, DosLoadModule, BVSMAIN        */
;/*                                                                     */
;/* Internal References:                                                */
;/*         Common Data: None.                                          */
;/*       Instance Data:                                                */
;/*                  ATTACH - indicates whether VIOATTACH has been      */
;/*                           done or not (1=done, otherwise not done)  */
;/*                           (initially zero)                          */
;/*                  AVS_OFF - Alternate Video Subsystem entry proc.    */
;/*                            offset                                   */
;/*                  AVS_SEL - Alternate Video Subsystem entry proc.    */
;/*                            selector                                 */
;/*                  BVS_OFF - Base Video Subsystem BVSMAIN offset      */
;/*                  BVS_SEL - Base Video Subsystem BVSMAIN selector    */
;/*                  MODHAND - module handle for BVSCGA module          */
;/*                  MASK - VIO function mask                           */
;/*                  SGID - Screen Group ID of this process             */
;/*            Routines: vioattach, getinfosegs                         */
;/*********************** END OF SPECIFICATIONS *************************/


public  viorout         ;NEAR public routines
public  vioattach       ;

IFDEF MMIOPH                                                         ;DTBB1
extrn   viopretrace:NEAR        ;internal call external definitions
extrn   vioposttrace:NEAR       ;
ENDIF                                                                ;DTBB1
extrn   DOSGETDBCSEV:FAR                                             ;BUG549
;@C51 extrn   initCP:NEAR                                            ;BUG549
extrn   VIOGETCURPOS:FAR        ;
extrn   VIOSETCURPOS:FAR        ;
extrn   VIOGETMODE:FAR          ;
extrn   VIOSETMODE:FAR          ;
extrn   VIOSETCP:FAR                                                    ;@C51
extrn   DOSSEMWAIT:FAR          ;
extrn   suicide:NEAR            ;
EXTRN   DOSSLEEP:FAR                                                    ;B722219
extrn   DOSSEMSETWAIT:FAR       ;
extrn   DOSFSRAMSEMREQUEST:FAR
extrn   DOSFSRAMSEMCLEAR:FAR
extrn   VIOFSRAMEXIT0:FAR                                               ;@T11
extrn   VIOFSRAMEXIT:FAR
;extrn  Thunker:NEAR                                                    ;MDLL
;extrn  ThunkerFarRet:FAR                                               ;MDLL
extrn   DOSSCRLOCK:FAR                                                  ;MDLL
extrn   DOSSCRUNLOCK:FAR                                                ;MDLL
extrn   DOSSAVREDRAWWAIT:FAR                                            ;MDLL
extrn   DOSSAVREDRAWUNDO:FAR                                            ;MDLL
extrn   DOSMODEWAIT:FAR                                                 ;MDLL
extrn   DOSMODEUNDO:FAR                                                 ;MDLL
                                                                        ;MDLL
.xlist
include error.inc
include error2.inc
include struc.inc
include infoseg.inc
include vioequ.inc
include viomac.inc
;@T73 include viogdata.inc
include vioextrn.inc
include avioequ.inc
include dc1segs.inc                                                     ;MDLL
.list

.386P                           ;D549

instance segment byte public 'FAR_DATA'   USE16                         ;D549
 origSG         dw  0   ;popup PID's original SG ID                     ;@T52
 origTYPE       dw  0   ;popup PID's original Session Type              ;@T14
 fsRAMoff       dw  0   ;offset into SGCB of currPID's fsRAMsem         ;@T52
 fsRAMsel       dw  0   ;offset into SGCB of currPID's fsRAMsem         ;@T52
 rqdSEMoff      dw  0   ;offset into SGCB of requested fsRAMsem         ;@T52
 rqdSEMsel      dw  0   ;offset into SGCB of requested fsRAMsem         ;@T52
 rqdPOPoff      dw  0   ;offset into SGCB of requested fsRAMsem         ;@T52
 rqdPOPsel      dw  0   ;offset into SGCB of requested fsRAMsem         ;@T52
 _ProcCodePage  LABEL   WORD    ;MKIOCALL needs this             @GDW   ;@T14
 procCP         dw  0   ;return area for DosGetCP                       ;@T52
 procCPlength   dw  0   ;return area for DosGetCP                       ;@T52
 avs_hand       dw  0   ;AVS module handle                              ;@T52
 avs_off        dw  0   ;AVS entry proc. offset                         ;@T52
 avs_sel        dw  0   ;AVS entry proc. selector                       ;@T52
 avs_bvs_bits   dw  0   ;registration bits required by BVS              ;@T52
 Igvs_ramsem    dd  0   ;RAM semaphore to protect Igvs_count            ;@T52
 gvs_hand       dw  0   ;AVS module handle                              ;@T52
 gvs_off        dw  0   ;AVS entry proc. offset                         ;@T52
 gvs_sel        dw  0   ;AVS entry proc. selector                       ;@T52
 pop_mode       dw  0   ;0=no popup, 1=popup                            ;@T52
 popexit        dw  0   ;set if VIOENDPOPUP during exitlist processing  ;@T52
 bvs_hand       dw  0   ;BVS module handle                              ;@T52
 bvs_off        dw  0   ;BVS entry proc. offset                         ;@T52
 bvs_sel        dw  0   ;BVS entry proc. selector                       ;@T52
 smg_hand       dw  0   ;Base Session Manager module handle             ;@T85
 detachpop      dw  0   ;1=allow VIOxxx,  0=AX <-- ERROR_VIO_DETACHED   ;@T52
 prtsc_SSsel    dw  0   ;stack segment selector for AVS_PRTSC           ;@T52
 prtsctog_SSsel dw  0   ;stack segment selector for AVS_PRTSCTOGGLE     ;@T52
 prtsc_ThID     dw  0   ;AVS_PRTSC thread ID                            ;@T52
 prtsctog_ThID  dw  0   ;AVS_PRTSCTOGGLE thread ID                      ;@T52
 tst_sel        dw  0   ;test entry proc. selector                      ;@T52

 _CurrentTYPE   LABEL   WORD    ;MKIOCALL needs this             @GDW   ;@T14
 _currTYPE      LABEL   WORD    ;BMSCALLS needs this                    ;@T14
 procTYPE       dw  0   ;current process type                           ;@T52

 _CurrentPID    LABEL   WORD    ;MKIOCALL needs this             @GDW   ;@T14
 _currPID       LABEL   WORD    ;MOUCALLS needs this                    ;@T14
 currpid        dw  0   ;current PID (local info)                       ;@T52

 fgsg           dw  0   ;current FG screen group (global info)          ;@T52

 _CurrentSGID   LABEL   WORD    ;MKIOCALL needs this             @GDW   ;@T14
 _currSG        LABEL   WORD    ;BMSCALLS needs this                    ;@T14
 currSG         dw  0   ;current screen group (local info)              ;@T52

 InfoSegL       LABEL   WORD    ;ANSICALL needs this                    ;@T14
 ldtinfo        dw  0   ;local info segment selector                    ;@T52

 InfoSegG       LABEL   WORD    ;ANSICALL needs this                    ;@T14
 gdtinfo        dw  0   ;global info segment selector                   ;@T52

 mmio_sel       dw  0   ;Performance Trace (memory mapped I/O) buffer   ;@T52
 oldtimes       dw  0   ;SGDATA[currSG].times at VIOATTACH              ;@T52
 vddhandle      dd  0   ;MVDM VDD handle                                ;@C39
 pu_sem_lo      dw  0   ;currSG's popup system semaphore                ;@T52
 pu_sem_hi      dw  0   ;  handle                                       ;@T52
 prtscsemlo     dw  0   ;currPID's VIOPRTSC system semaphore handle     ;@T52
 prtscsemhi     dw  0   ;                                               ;@T52
 prtsc_avshand  dw  0   ;save area for AVS handle to FREE it later      ;@T52
 exitlist       dw  0   ;1 = early; 0 = late                            ;@T52
 Igvs_end       dw  0   ;end of GVS data area                           ;@T52
 Igvs_last      dw  0   ;offset of last available GVS record            ;@T52
 Igvs_quit      dw  0   ;0=keep on truckin, 1=stop                      ;@T52
 Igvs_count     dw  0   ;number of GVS's attached to by this PID        ;@T52
 gvs_cntr       dw  0   ;counter used to go through list of GVS's       ;@T52
 gvsCURoff      dw  0   ;sel:off of current GVS being called            ;@T52
 gvsCURsel      dw  0   ;                                               ;@T52

IFDEF MMIOPH                                                            ;@T54
 trace1         dw  0         ;data area for DOSSYSTRACE parm list      ;@T54
 trace2         dw  0         ;                                         ;@T54
 trace3         dw  0         ;                                         ;@T54
 trace4         dw  0         ;                                         ;@T54
 trace5plus     db  68 dup(0) ;                                         ;@T54
ENDIF                                                                   ;@T54

 _SGData        LABEL   DWORD ;MKIOCALL needs this               @GDW   ;@T14
 _sgdata_el     LABEL   DWORD ;BMSCALLS needs this                      ;@T14
 SGCB           dd  0   ;D549                                           ;@T52
 SGCB_temp      dd  0   ;D549                                           ;@T52
 pu_sdata       LABEL   DWORD                                           ;@T18
 SGCB_pop       dd  0           ;Hold the original SGCB before popup    ;@T14

;THUNKDEF       DOSSCRLOCK,       szSmgMod, smg_hand, ScrLock,          ;MDLL
;THUNKDEF       DOSSCRUNLOCK,     szSmgMod, smg_hand, ScrUnlock,        ;MDLL
;THUNKDEF       DOSSAVREDRAWWAIT, szSmgMod, smg_hand, SavRedrawWait     ;MDLL
;THUNKDEF       DOSSAVREDRAWUNDO, szSmgMod, smg_hand, SavRedrawUndo     ;MDLL
;THUNKDEF       DOSMODEWAIT,      szSmgMod, smg_hand, ModeWait          ;MDLL
;THUNKDEF       DOSMODEUNDO,      szSmgMod, smg_hand, ModeUndo          ;MDLL
;THUNKDEF       BVSREDRAWSIZE,    Bvs_Mod,  bvs_hand, Redrawsize        ;MDLL
;THUNKDEF       DOSSMSGDOPOPUP,   szSmgMod, smg_hand, DoPopUp           ;MDLL
;THUNKDEF       DOSSMSGENDPOPUP,  szSmgMod, smg_hand, DoEndPopUp        ;MDLL
;THUNKDEF       KBDLOADINSTANCE,  szKbdMod, LoadInstance            ;@T2,@T85
;THUNKDEF       KBDFLUSHBUFFER,   szKbdMod, FlushBuffer             ;@T2,@T85
instance ends

        extrn   _ENDDATA16:byte                                         ;MDLL
        idata_sz        equ     offset _ENDDATA16                       ;MDLL

        public  origSG          ;@T52
        public  origTYPE        ;@T14
        public  fsRAMoff        ;@T52
        public  fsRAMsel        ;@T52
        public  rqdSEMoff       ;@T52
        public  rqdSEMsel       ;@T52
        public  rqdPOPoff       ;@T52
        public  rqdPOPsel       ;@T52
        public  _ProcCodePage   ;MKIOCALL needs this             @GDW
        public  procCP          ;@T52
        public  procCPlength    ;@T52
        public  avs_hand        ;@T52
        public  avs_off         ;@T52
        public  avs_sel         ;@T52
        public  avs_bvs_bits    ;@T52
        public  Igvs_ramsem     ;@T52
        public  gvs_hand        ;@T52
        public  gvs_off         ;@T52
        public  gvs_sel         ;@T52
        public  pop_mode        ;@T52
        public  popexit         ;@T52
        public  bvs_hand        ;@T52
        public  bvs_off         ;@T52
        public  bvs_sel         ;@T52
        public  smg_hand        ;@T85
        public  detachpop       ;@T52
        public  prtsc_SSsel     ;@T52
        public  prtsctog_SSsel  ;@T52
        public  prtsc_ThID      ;@T52
        public  prtsctog_ThID   ;@T52
        public  tst_sel         ;@T52
        public  _CurrentTYPE    ;MKIOCALL needs this ;@T14  @GDW
        public  _currTYPE       ;BMSCALLS needs this ;@T14
        public  procTYPE        ;@T52
        public  _CurrentPID     ;MKIOCALL needs this ;@T14  @GDW
        public  _currPID        ;BMSCALLS needs this ;@T14
        public  currpid         ;@T52
        public  fgsg            ;@T52
        public  _CurrentSGID    ;MKIOCALL needs this ;@T14  @GDW
        public  _currSG         ;BMSCALLS needs this ;@T14
        public  currsg          ;@T52
        public  InfoSegL        ;ANSICALL needs this ;@T14
        public  ldtinfo         ;@T52
        public  InfoSegG        ;ANSICALL needs this ;@T14
        public  gdtinfo         ;@T52
        public  mmio_sel        ;@T52
        public  oldtimes        ;@T52
        public  vddhandle       ;@C39
        public  pu_sem_lo       ;@T52
        public  pu_sem_hi       ;@T52
        public  prtscsemlo      ;@T52
        public  prtscsemhi      ;@T52
        public  prtsc_avshand   ;@T52
        public  exitlist        ;@T52
        public  Igvs_end        ;@T52
        public  Igvs_last       ;@T52
        public  Igvs_quit       ;@T52
        public  Igvs_count      ;@T52
        public  gvs_cntr        ;@T52
        public  gvsCURoff       ;@T52
        public  gvsCURsel       ;@T52

     IFDEF   MMIOPH             ;@T54
        public  trace1          ;@T54
        public  trace2          ;@T54
        public  trace3          ;@T54
        public  trace4          ;@T54
        public  trace5plus      ;@T54
     ENDIF                      ;@T54

        public  _SGData         ;MKIOCALL needs this ;@T14  @GDW
        public  _sgdata_el      ;BMSCALLS needs this ;@T14
        public  SGCB            ;@T52
        public  SGCB_temp       ;@T52
        public  pu_sdata        ;@T18
        public  SGCB_pop        ;@T14

common segment word public 'FAR_DATA'  USE16                       ;D549;@T52
;NEVER MOVE THESE 4 WORDS              ;@T52
;NEVER MOVE THESE 4 WORDS must be at beginning of seg               ;@T52
;NEVER MOVE THESE 4 WORDS              ;@T52
 killSG                 dw  0   ;SGID of process to be killed           ;@T52
 killPID                dw  0   ;PID of process to be killed            ;@T52
 killRAMsem             dd  0   ;wait forever (will be killed by HET)   ;@T52
;NEVER MOVE THESE 4 WORDS              ;@T52
;NEVER MOVE THESE 4 WORDS must be at beginning of seg               ;@T52
;NEVER MOVE THESE 4 WORDS              ;@T52
 RamSem_SGID            dw  -1  ;Ram Sem requseted screen group id      ;B722219
 Ggvs_count             dw  0   ;number of GVS's registered             ;@T73
 Ggvs_AddrLo            dw  0   ;GVS record offset                      ;@T73
 Ggvs_AddrHi            dw  0   ;GVS record selector                    ;@T73
 Ggvs_size              dw  0   ;Current GVS segment size               ;@T73
 dirty                  dw  0                                           ;@T52
 PUgetmode              dw  12                                          ;@T52
 PUMTYPE                db  0                                           ;@T52
 PUMCOLORS              db  0                                           ;@T52
 PUAROWS                dw  0                                           ;@T52
 PUACOLS                dw  0                                           ;@T52
 PUHRES                 dw  0                                           ;@T52
 PUVRES                 dw  0                                           ;@T52

 SYIsetmode             dw  8   ;Proto
 SYITYPE                db  1   ;Proto
 SYICOLORS              db  4   ;Proto
 SYICOLS                dw  80  ;Proto
 SYIROWS                dw  25  ;Proto

 SYIsetmodefl           dw  -1  ;Proto

 SYICP          dw  0   ;return area for DosGetCP                       ;Proto
 SYICPlength    dw  0   ;return area for DosGetCP                       ;Proto

;_shellPID      LABEL   WORD                                            ;@T14
 SHELLPID               dw  0   ;PID of the shell process               ;@T52

 HETPID                 dw  0   ;PID of the harderror process           ;@T52
 shellVSRW_done         dw  0   ;Shell has done a VioSavRedrawWait flag ;@CJ42
 regramsem              dd  0   ;VIOREGISTER/VIODREGISTER sem           ;@T52
 oldfgsgID              dw  0   ;old foreground screen group            ;@T52
 poppersSGID            dw  0   ;popup's screen group (new)             ;@T52
 hard_err               dw  0   ;hard error popup flag                  ;@T52

 tkbuf                  db  tkbuflen dup (0) ;getprocaddr error buffer  ;@TAK
 tkstack                dw  0   ;stack reference                        ;@TAK

 bvs_ep                 dw  3   ;BVSMAIN entry point ordinal       ;@T52,@T18
 bvs_mod                db  'BVSCALLS',0,0      ;BVS module name   ;@T52,@T73
                                                                        ;@T52
;szSmgMod               db  "SESMGR", 0                                 ;MDLL
;szKbdMod               db  "KBDCALLS",0                                ;MDLL
                                                                        ;@T52
 pucsrrow               dw  0   ;popup cursor row save area             ;@T52
 pucsrcol               dw  0   ;popup cursor column save area          ;@T52
 dbcsctrycode           dw  0   ;default ctrycode, currPID's codepage   ;@T52
                        dw  0                                           ;@T52
                                                                        ;@T52
 popupsem               db  '\SEM\VIOPOPUP',00H ;POPUP semaphore name   ;@T52
 prtscsem               db  '\SEM\VIOPRTSC',00H ;Shift-PrtSc sem. name  ;@T52
 vdd1                   db  'VVIDEO1$',0,0   ;primary display for MVDM  ;@C39
                                                                        ;@T52
 beg_names              dw  0000H       ;offset into COMMON data of     ;@T52
                                        ;AVS module names and entry     ;@T52
                                        ;procedure names storage        ;@T52
 loestpopupmask         dw  1111111001100111B ;Bits on indicate which   ;@T52
 lopopupmask            dw  0100000110111111B ;functions are allowed    ;@T52
 hipopupmask            dw  0001111111111100B ;during popups            ;@T52
 hiestpopupmask         dw  0000000000000000B ;                         ;@T52
 fill_popupmask         dw  0                 ;                         ;@T52
                                                                        ;@T52
 loestviossmask         dw  0000000000000000B ;Bits on indicate which   ;@T52
 loviossmask            dw  0001111000000000B ;calls are passed to      ;@T52
 hiviossmask            dw  0000000000000011B ;Screen Switch instead    ;@T52
 hiestviossmask         dw  0000000000000000B ;of BVS                   ;@T52
 fill_viossmask         dw  0                 ;                         ;@T52
                                                                        ;@T52
 loest_ext_mask         dw  0000000000010000B ;Bits on indicate which   ;@T52
 lo_ext_mask            dw  0001111000000000B ;calls are disallowed     ;@T52
 hi_ext_mask            dw  0000000111000111B ;from AVIO sessions       ;@T52
 hiest_ext_mask         dw  0000000000000000B ;                         ;@T52
 fill_ext_mask          dw  0                 ;                         ;@T52
;                                                                       ;@T52
;common2 begin                                                          ;@T52
;                                                                       ;@T52
 map_getphysbuf         dw  0                                           ;@T52
                        dw  0000000000010000B                           ;@T52
 map_getbuf             dw  0                                           ;@T52
                        dw  0000000000001000B                           ;@T52
 map_showbuf            dw  0                                           ;@T52
                        dw  0000000100000000B                           ;@T52
 map_getcurpos          dw  0                                           ;@T52
                        dw  0000000000000001B                           ;@T52
 map_getcurtype         dw  0                                           ;@T52
                        dw  0000000000000010B                           ;@T52
 map_getmode            dw  0                                           ;@T52
                        dw  0000000000000100B                           ;@T52
 map_setcurpos          dw  0                                           ;@T52
                        dw  0000000000100000B                           ;@T52
 map_setcurtype         dw  0                                           ;@T52
                        dw  0000000001000000B                           ;@T52
 map_setmode            dw  0                                           ;@T52
                        dw  0000000010000000B                           ;@T52
 map_readcharstr        dw  0                                           ;@T52
                        dw  0000001000000000B                           ;@T52
 map_readcellstr        dw  0                                           ;@T52
                        dw  0000010000000000B                           ;@T52
 map_wrtnchar           dw  0                                           ;@T52
                        dw  0000100000000000B                           ;@T52
 map_wrtnattr           dw  0                                           ;@T52
                        dw  0001000000000000B                           ;@T52
 map_wrtncell           dw  0                                           ;@T52
                        dw  0010000000000000B                           ;@T52
 map_wrtcharstr         dw  0                                           ;@T52
                        dw  1000000000000000B                           ;@T52
 map_wrtcharstratt      dw  2                                           ;@T52
                        dw  0000000000000001B                           ;@T52
 map_wrtcellstr         dw  2                                           ;@T52
                        dw  0000000000000010B                           ;@T52
 map_wrttty             dw  0                                           ;@T52
                        dw  0100000000000000B                           ;@T52
 map_scrollup           dw  2                                           ;@T52
                        dw  0000000000000100B                           ;@T52
 map_scrolldn           dw  2                                           ;@T52
                        dw  0000000000001000B                           ;@T52
 map_scrolllf           dw  2                                           ;@T52
                        dw  0000000000010000B                           ;@T52
 map_scrollrt           dw  2                                           ;@T52
                        dw  0000000000100000B                           ;@T52
 map_setansi            dw  2                                           ;@T52
                        dw  0000000001000000B                           ;@T52
 map_getansi            dw  2                                           ;@T52
                        dw  0000000010000000B                           ;@T52
 map_prtsc              dw  2                                           ;@T52
                        dw  0000000100000000B                           ;@T52
 map_scrlock            dw  2                                           ;@T52
                        dw  0000001000000000B                           ;@T52
 map_scrunlock          dw  2                                           ;@T52
                        dw  0000010000000000B                           ;@T52
 map_savredrawwait      dw  2                                           ;@T52
                        dw  0000100000000000B                           ;@T52
 map_savredrawundo      dw  2                                           ;@T52
                        dw  0001000000000000B                           ;@T52
 map_popup              dw  2                                           ;@T52
                        dw  0010000000000000B                           ;@T52
 map_endpopup           dw  2                                           ;@T52
                        dw  0100000000000000B                           ;@T52
 map_prtsctoggle        dw  2                                           ;@T52
                        dw  1000000000000000B                           ;@T52
 map_modewait           dw  4                                           ;@T52
                        dw  0000000000000001B                           ;@T52
 map_modeundo           dw  4                                           ;@T52
                        dw  0000000000000010B                           ;@T52
 map_getfont            dw  4                                           ;@T52
                        dw  0000000000000100B                           ;@T52
 map_getconfig          dw  4                                           ;@T52
                        dw  0000000000001000B                           ;@T52
 map_setcp              dw  4                                           ;@T52
                        dw  0000000000010000B                           ;@T52
 map_getcp              dw  4                                           ;@T52
                        dw  0000000000100000B                           ;@T52
 map_setfont            dw  4                                           ;@T52
                        dw  0000000001000000B                           ;@T52
 map_getstate           dw  4                                           ;@T52
                        dw  0000000010000000B                           ;@T52
 map_setstate           dw  4                                           ;@T52
                        dw  0000000100000000B                           ;@T52
 map_register           dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_deregister         dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
;                                                                       ;@T52
;common3 begin                                                          ;@T52
;                                                                       ;@T52
 fill43                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_createca           dw  8                                           ;@T52
                        dw  0000010000000000B                           ;@T52
 map_getcastate         dw  8                                           ;@T52
                        dw  0000100000000000B                           ;@T52
 map_setcastate         dw  8                                           ;@T52
                        dw  0001000000000000B                           ;@T52
 map_destroyca          dw  8                                           ;@T52
                        dw  0010000000000000B                           ;@T52
 map_checkchartype      dw  8                                           ;@T52
                        dw  0100000000000000B                           ;@T52
 fill49                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill50                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill51                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill52                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill53                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill54                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill55                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill56                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill57                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill58                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill59                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill60                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill61                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill62                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill63                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill64                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill65                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill66                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill67                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill68                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill69                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill70                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill71                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill72                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill73                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill74                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill75                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill76                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill77                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill78                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill79                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_associate          dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_createps           dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_deletesetid        dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_destroyps          dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_getdevicecellsize  dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_getorg             dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_createlogfont      dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_querysetids        dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_queryfonts         dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_setdevicecellsize  dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_setorg             dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_showps             dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_getpsaddress       dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill93                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill94                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 fill95                 dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_shieldinit         dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_shieldterm         dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
 map_queryconsole       dw  8                                           ;@T52
                        dw  0000000000000000B                           ;@T52
common ends                                                             ;@T52

        common2_beg     equ     offset map_getphysbuf                   ;@T52

        public  killSG                  ;@T52
        public  killPID                 ;@T52
        public  killRAMsem              ;@T52
        public  RamSem_SGID             ;B722219
        public  Ggvs_count              ;@T73
        public  Ggvs_AddrLo             ;@T73
        public  Ggvs_AddrHi             ;@T73
        public  Ggvs_size               ;@T73
        public  dirty                   ;@T52
        public  PUgetmode               ;@T52
        public  PUMTYPE                 ;@T52
        public  PUMCOLORS               ;@T52
        public  PUAROWS                 ;@T52
        public  PUACOLS                 ;@T52
        public  PUHRES                  ;@T52
        public  PUVRES                  ;@T52
        public  SYIsetmode              ;Proto
        public  SYIsetmodefl            ;Proto
        public  SYICP                   ;Proto
        public  SYICPlength             ;Proto
;       public  _shellPID               ;@T14
        public  SHELLPID                ;@T52
        public  HETPID                  ;@T52
        public  shellVSRW_done          ;@CJ42
        public  regramsem               ;@T52
        public  oldfgsgID               ;@T52
        public  poppersSGID             ;@T52
        public  hard_err                ;@T52
        public  bvs_ep                  ;@T52
        public  bvs_mod                 ;@T52
;MDLL   public  szSmgMod                ;@T52
;MDLL   public  szKbdMod                ;@T52
        public  pucsrrow                ;@T52
        public  pucsrcol                ;@T52
        public  dbcsctrycode            ;@T52
        public  popupsem                ;@T52
        public  prtscsem                ;@T52
        public  vdd1                    ;@C39
        public  beg_names               ;@T52
        public  loestpopupmask          ;@T52
        public  lopopupmask             ;@T52
        public  hipopupmask             ;@T52
        public  hiestpopupmask          ;@T52
        public  fill_popupmask          ;@T52
        public  loestviossmask          ;@T52
        public  loviossmask             ;@T52
        public  hiviossmask             ;@T52
        public  hiestviossmask          ;@T52
        public  fill_viossmask          ;@T52
        public  loest_ext_mask          ;@T52
        public  lo_ext_mask             ;@T52
        public  hi_ext_mask             ;@T52
        public  hiest_ext_mask          ;@T52
        public  fill_ext_mask           ;@T52
        public  map_getphysbuf          ;@T52
        public  map_getbuf              ;@T52
        public  map_showbuf             ;@T52
        public  map_getcurpos           ;@T52
        public  map_getcurtype          ;@T52
        public  map_getmode             ;@T52
        public  map_setcurpos           ;@T52
        public  map_setcurtype          ;@T52
        public  map_setmode             ;@T52
        public  map_readcharstr         ;@T52
        public  map_readcellstr         ;@T52
        public  map_wrtnchar            ;@T52
        public  map_wrtnattr            ;@T52
        public  map_wrtncell            ;@T52
        public  map_wrtcharstr          ;@T52
        public  map_wrtcharstratt       ;@T52
        public  map_wrtcellstr          ;@T52
        public  map_wrttty              ;@T52
        public  map_scrollup            ;@T52
        public  map_scrolldn            ;@T52
        public  map_scrolllf            ;@T52
        public  map_scrollrt            ;@T52
        public  map_setansi             ;@T52
        public  map_getansi             ;@T52
        public  map_prtsc               ;@T52
        public  map_scrlock             ;@T52
        public  map_scrunlock           ;@T52
        public  map_savredrawwait       ;@T52
        public  map_savredrawundo       ;@T52
        public  map_popup               ;@T52
        public  map_endpopup            ;@T52
        public  map_prtsctoggle         ;@T52
        public  map_modewait            ;@T52
        public  map_modeundo            ;@T52
        public  map_getfont             ;@T52
        public  map_getconfig           ;@T52
        public  map_setcp               ;@T52
        public  map_getcp               ;@T52
        public  map_setfont             ;@T52
        public  map_getstate            ;@T52
        public  map_setstate            ;@T52
        public  map_register            ;@T52
        public  map_deregister          ;@T52
        public  fill43                  ;@T52
        public  map_createca            ;@T52
        public  map_getcastate          ;@T52
        public  map_setcastate          ;@T52
        public  map_destroyca           ;@T52
        public  map_checkchartype       ;@T52
        public  fill49                  ;@T52
        public  fill50                  ;@T52
        public  fill51                  ;@T52
        public  fill52                  ;@T52
        public  fill53                  ;@T52
        public  fill54                  ;@T52
        public  fill55                  ;@T52
        public  fill56                  ;@T52
        public  fill57                  ;@T52
        public  fill58                  ;@T52
        public  fill59                  ;@T52
        public  fill60                  ;@T52
        public  fill61                  ;@T52
        public  fill62                  ;@T52
        public  fill63                  ;@T52
        public  fill64                  ;@T52
        public  fill65                  ;@T52
        public  fill66                  ;@T52
        public  fill67                  ;@T52
        public  fill68                  ;@T52
        public  fill69                  ;@T52
        public  fill70                  ;@T52
        public  fill71                  ;@T52
        public  fill72                  ;@T52
        public  fill73                  ;@T52
        public  fill74                  ;@T52
        public  fill75                  ;@T52
        public  fill76                  ;@T52
        public  fill77                  ;@T52
        public  fill78                  ;@T52
        public  fill79                  ;@T52
        public  map_associate           ;@T52
        public  map_createps            ;@T52
        public  map_deletesetid         ;@T52
        public  map_destroyps           ;@T52
        public  map_getdevicecellsize   ;@T52
        public  map_getorg              ;@T52
        public  map_createlogfont       ;@T52
        public  map_querysetids         ;@T52
        public  map_queryfonts          ;@T52
        public  map_setdevicecellsize   ;@T52
        public  map_setorg              ;@T52
        public  map_showps              ;@T52
        public  map_getpsaddress        ;@T52
        public  fill93                  ;@T52
        public  fill94                  ;@T52
        public  fill95                  ;@T52
        public  map_shieldinit          ;@T52
        public  map_shieldterm          ;@T52
        public  map_queryconsole        ;@T52
        public  tkbuf                   ;@TAK
        public  tkstack                 ;@TAK


CTEXT_TUNE4   segment dword public 'code'     USE16                     ;MDLL
        assume  cs:CODE02,ds:instance,es:common,ss:nothing              ;MDLL
        page


        SUBTTL VIOROUT - VIO FUNCTION CALL ROUTER
        page
;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: VIOROUT                                                */
;/*                                                                         */
;/* DESCRIPTIVE NAME: VIO function call router.                             */
;/*                                                                         */
;/* FUNCTION: Route the VIO function call to the current PID's base video   */
;/*           subsystem entry point (i.e., make a FAR CALL to the entry     */
;/*           point specified in this processes instance data fields        */
;/*           bvs_SEL:bvs_OFF or avs_SEL:avs_OFF).                          */
;/*                                                                         */
;/* NOTES: The determination of whether to call the BVS or the AVS is made  */
;/*        based on the function mask and the function call made.  All VIO  */
;/*        calls not replaced by the Alternate Video Subsystem are passed   */
;/*        to the Base Video Subsystem.  Checking to see if the AVS has     */
;/*        replaced only replaceable functions is done in VIOREGISTER.      */
;/*                                                                         */
;/* ENTRY POINT: VIOROUT                                                    */
;/*     LINKAGE: NEAR CALL  (internal call from VIOxxx)                     */
;/*                                                                         */
;/* INPUT: "FC" - VIOxxx function code for BVS/AVS (WORD on stack)          */
;/*                                                                         */
;/* EXIT-NORMAL: AX = return code set by video subsystem                    */
;/*                                                                         */
;/* EXIT-ERROR: AX = error code from VIOATTACH                              */
;/*             AX = error code from the AVS or BVS                         */
;/*                                                                         */
;/* EFFECTS: The contents of AX are destroyed.  Also, on exit the input     */
;/*          parameter (1 WORD) is removed from the stack.                  */
;/* INTERNAL                                                                */
;/* REFERENCES: avs_HAND - alternate video subsystem module handle          */
;/*             avs_OFF - alternate video subsystem entry proc. offset      */
;/*             avs_SEL - alternate video subsystem entry proc. selector    */
;/*             bvs_OFF - base video subsystem entry procedure offset       */
;/*             bvs_SEL - base video subsystem entry procedure selector     */
;/*             currSG - current process's screen group (LDTINFO:8)         */
;/*             OLDTIMES - SGDATA[currSG].TIMES at time of VIOATTACH        */
;/*             SGPIDSYNC - currSG's exclusive synchronization semaphore    */
;/*             SGDATA[currSG].MASK - VIO function mask                     */
;/*             SGDATA[currSG].TIMES - number of VIOREGISTERs for this SG   */
;/*   ROUTINES: VIOATTACH - Attach to video subsystem                       */
;/* EXTERNAL                                                                */
;/* REFERENCES: None.                                                       */
;/*   ROUTINES: avs_SEL:avs_OFF - alternate video subsystem entry proc.     */
;/*             bvs_SEL:bvs_OFF - base video subsystem entry proc.          */
;/*             DOSFREEMODULE - free dynamic-link module                    */
;/*             DOSGETINFOSEG - get global/local info segment selectors     */
;/*             DOSSEMCLEAR - clear/release semaphore                       */
;/*             DOSSEMREQUEST - request/obtain semaphore                    */
;/*********************** END OF SPECIFICATIONS *****************************/
;  viorout psuedo code:
;
;  if
;  .
;  .
;  .
;
;  elseif PrtSc  or  Ctrl-PrtSc
;
;    if currPID  ne  hetPID
;      AX <-- ERROR_VIO_SMG_ONLY
;    else
;      request PrtScSEM (wait)
;      CX <-- fgSG
;      BX <-- start of SGDATA[fgSG]
;      disable signals
;      request fgSG's semaphore (wait)
;
;      if 3XBox  eq  fgSG
;        freeze 3XBox
;      endif
;
;      if function has been registered by fgSG
;
;        if fgSG  ne  popupSG
;          load fgSG's AVS
;
;          if NO_ERROR
;            call AVS
;
;            if AX  eq  -1
;              call BVS
;            endif
;
;          endif
;
;        else
;          call BVS
;        endif
;
;      else
;        call BVS
;      endif
;
;      clear fgSG's semaphore
;      clear PrtScSEM
;      enable signals
;    endif
;
;  else
;    .
;    .
;    .
;
;  endif
;
;
viorout proc near


   push  ds             ;save DS
   enter 10,0           ;setup BP and allocate 5 words local storage for
                        ;function call masks

   mov   word ptr [bp].funcmask,ax      ;API function mask being called ;1.2
   xor   ax,ax                          ;preset AX = NO_ERROR = 0

   push  gs                                                        ;D549,@T80
   push  es             ;save registers
   pusha                ;

   mov   bx,instance            ;DS <-- instance data seg. selector     ;P2859
   mov   ds,bx                                                          ;P2859

   IFDEF MMIOPH                                                         ;DTBB1
   mov   es,ds:gdtinfo                          ;ES <-- global info sel.
   mov   al,es:[SIS_MEC_TABLE].SIS_VIOMEC       ;AL <-- byte w/VIO MEC
   test  al,traceonoffmask                      ;0=OFF, non-0=ON

   .if <nz>                     ;is VIO tracing enabled?                ;@T2
     call  viopretrace          ;
   .endif                       ;
   ENDIF                                                                ;DTBB1

   mov   es,ds:ldtinfo          ;
   mov   al,es:[LIS_ProcType]   ;procTYPE <-- current process type      ;P2859
   cbw                          ;
   mov   ds:procTYPE,ax         ;
   mov   si,es:[LIS_CurThrdID]  ;SI <-- Current Thread ID
   mov   ax,es:[LIS_CurScrnGrp] ;currSG <-- current screen group
   mov   ds:currSG,ax           ;

   .if <ds:procTYPE eq LIS_PT_DETACHED>                                 ;@B46
     mov   [bp].rout_savAX,ERROR_VIO_DETACHED                           ;@B46
   .else near                                                           ;@B46

     mov   ax,common            ;ES <-- common data selector
     mov   es,ax

   ;**************************************************************************
   ;setup function call masks - calculate offset of this function call mask in
   ;                            common2 struc (viocdata.inc)
   ;**************************************************************************
     mov   di,[bp].rout_fc      ;function call                          ;1.2
     shl   di,2                 ;shift left for word offset             ;1.2
     mov   bx,common2_beg       ;ofs of func. call mask        ;1.2,D549,@T52

   ;**************************************************************************
   ;1st word in common2 struc is offset of this function call mask into the
   ;Popup, Screen Switcher and Extended SG masks in commonseg (viocdata.inc)
   ;**************************************************************************
     mov   di,es:[bx][di]       ;DI <-- offset into 4word mask strucs   ;1.2
     mov   cx,di                ;CX <-- offset into 4word mask strucs   ;P1941

     mov   bx,offset loestpopupmask ;get popup mask for this func call  ;@T52
     mov   ax,es:[bx][di]                                               ;1.2
     mov   word ptr [bp].popupokmask,ax                                 ;1.2

     mov   bx,offset loestviossmask ;get screen switcher mask       ;1.2,@T52
     mov   ax,es:[bx][di]                                               ;1.2
     mov   [bp].viossmask,ax                                            ;1.2

     mov   bx,offset loest_ext_mask ;get extended SG mask           ;1.2;@T52
     mov   ax,es:[bx][di]                                               ;1.2
     mov   [bp].extSGmask,ax                                            ;1.2

     and   ax,[bp].funcmask     ;AX <-- 0=OK, !0=not OK from Ext. SG    ;@T14

     lgs   bx,ds:SGCB           ;load with SGCB ptr                ;D549,@T80

     lea   di,[bx].VIO_maskloest;Get masks offset in SGCB          ;D549,@T14
     add   di,cx                ;add offset to particular mask    ;P1941,D549
     mov   dx,gs:[di]           ;                       ;P1941,D549,@T14,@T80
     mov   [bp].replacemask,dx  ;                                 ;P1941,@T14

     mov   dx,ds:currPID        ;DX <-- currPID                         ;@T14

     .if <ds:procTYPE ne LIS_PT_FULLSCRN> and                           ;@T14
     .if <nonzero ax>           ;Disallow certain calls from Ext SGs ;P2859,@T14
       mov   [bp].rout_savAX,ERROR_VIO_EXTENDED_SG
     .else near

       .if <[bp].rout_fc a fc_checkchartype> and
       .if <[bp].rout_fc b fc_shieldinit> and
       .if <ds:procTYPE ne LIS_PT_PRESMGR> and                          ;@T71
       .if <ds:currSG ne 1>                                             ;@T71
         mov   [bp].rout_savAX,ERROR_VIO_NOT_PRES_MGR_SG
       .else near
         mov   cx,[bp].funcmask         ;CX <-- non-zero if
         and   cx,[bp].popupokmask      ;allowed during popup

         .if <ds:pop_mode eq 1> and     ;disallow VIOxxx during
         .if <cxz>              and     ;POPUPs                   ;P2859,@T14
         .if <es:HETPID ne dx>          ;(except from HETPID)
           mov   [bp].rout_savAX,ERROR_VIO_ILLEGAL_DURING_POPUP
         .else

           mov   ax,gs:[bx].VIO_times   ;                          ;@T14,@T80
           .if <ax ne ds:oldtimes>      ;a new AVS has been registered
             call  vioattach            ;get addressability to it
           .else                                                        ;1.2
;@T73        push ds                    ;save instance data             ;@T14
;@T73        mov  ax,global             ;DS <-- GLOBAL data selector    ;1.2
;@T73        mov  ds,ax                 ;                               ;@T14

             mov  ax,es:Ggvs_count      ;AX <-- # GVS's registered ;@T14,@T73

;@T73        pop  ds                    ;restore instance data          ;@T14

             .if <ax ne ds:Igvs_count>  ;Need access to GVS?            ;1.2
               call  vioattach          ;then attach to new GVS's       ;1.2
             .endif                                                     ;1.2

           .endif               ;End of AVS register check              ;@T14

         .endif                 ;End of calls disallowed check          ;@T14

       .endif                   ;End of valid PM call check             ;@T14

     .endif                     ;End of extended SG check (WIN, PM)     ;@T14

   .endif                       ;End of detached process check          ;@T14

   .if <<word ptr [bp].rout_savAX> eq NO_ERROR> near

     ;************************************************************************
     ; Find out if codepage initialization is necessary on the first VIO
     ; call within a newly created session.
     ;
     ; Note:  This change is required to avoid the problem of the BVH DLLs
     ;        not getting unlinked immediately after the DLLs being freed
     ;        by BVS because the call to DEVENABLE failed at Process Init.
     ;        The problem of the DLLs not being freed immediately causes
     ;        the BVS Call Table to not get initialize on the next DEVENABLE
     ;        call since the BVH's Global Data segment was never discarded.
     ;

     test gs:[bx].VIO_sg_init,2                                         ;@T80
     .if <z> and                                                        ;001B
     .if <ds:currSG ne 1>               ;call initCP if not shell SG    ;001B
       or   gs:[bx].VIO_sg_init,2       ;prevent recursion         ;001B,@T80
;@C51;;call initCP                                                      ;001B
       .if <ds:procTYPE eq LIS_PT_FULLSCRN>  OR         ;if FS or Win   ;@C51
       .if <ds:procTYPE eq LIS_PT_VIOWIN>                               ;@C51
         push 0               ;set current session's video codepage     ;@C51
         push ds:procCP                                                 ;@C51
         push 0                                                         ;@C51
         call VIOSETCP                                                  ;@C51

         .if <zero ax>                             ;if codepage set ok  ;@C51
           mov  ax,ds:procCP                                            ;@C51
           mov  gs:[bx].VIO_CodePageID,ax          ;set SG codepage ;@C51,@T80
         .endif                                                         ;@C51
       .endif                                                           ;@C51
     .endif                                                             ;001B

     mov   cx,[bp].funcmask     ;CX=0 if NOT screen switcher call
     and   cx,[bp].viossmask    ;CX<>0 if screen switcher call
     mov   dx,ds:currPID
     mov   ax,[bp].rout_fc      ;AX <-- function code

     .if <nonzero cx> near      ;"if screen switcher type call"   ;P2859,@T14

     ;************************************************************************
     ; Screen Switcher type call
     ;************************************************************************

       mov   ax,[bp].funcmask
       and   ax,[bp].replacemask

       .if <nonzero ax> near    ;"if replaced by AVS function"          ;P2859
         ;********************************************************************
         ; AVS replaced Screen Switcher call
         ;********************************************************************


         .if <si eq gs:[bx].VIO_srwTID> and     ;if save/restore thread ;@T80
         .if <dx eq gs:[bx].VIO_srwPID>         ;                       ;@T80
         .elseif <si eq gs:[bx].VIO_smwTID> and ;                       ;@T80
         .if <dx eq gs:[bx].VIO_smwPID>         ;                       ;@T80

         .elseif <gs:[bx].VIO_avscbptr ne 00> and ;AVS in effect        ;@T80
         les  di,gs:[bx].VIO_avscbptr           ;ptr to avscb           ;@T80
         .if <dx eq es:[di].reg_pid> and        ;if pid that reg'd ;D549,@T14
         .if <si eq es:[di].psThID> or          ;shift-prtsc thread or  ;D549
         .if <si eq es:[di].pstogThID>          ;ctrl-prtsc thread      ;D549
           ;******************************************************************
           ; don't need to serialize because save/restore threads and
           ; prtsc/prtsctoggle threads are already serialized by session manager
           ;******************************************************************

         .else near
           ;******************************************************************
           ; need to serialize using Semaphores
           ;******************************************************************

;@T72      push  1              ;disable signals
;@T72      call  DOSHOLDSIGNAL  ;

           .if <gs:[bx].VIO_paused eq 1> ;Check for CTRL-NUMLOCK/CTRL-S  ;@T80
             ;****************************************************************
             ; PAUSE in effect, wait so no video output is done but only wait
             ; if we don't own the SG sem because if we do, we want to finish
             ; the video call before waiting
             ;****************************************************************

             .if <dx ne gs:[bx].VIO_fsRAMsem.fs_PID> or ;SG semaphore   ;@T80
             .if <si ne gs:[bx].VIO_fsRAMsem.fs_TID>    ;  already owned;@T80
               lea   di,gs:[bx].VIO_pause_sem   ;                  ;@T14,@T80
               .repeat
                 push  gs                       ;Addr. of semaphore     ;@T80
                 push  di                       ;                       ;@T14
;@T18            push  wait_hi                  ;Wait for sem. to clear
                 push  dword ptr -1             ;                       ;@T18
                 call  DOSSEMWAIT               ;
               .until <ax ne ERROR_INTERRUPT>
             .endif                                                     ;P2893

           .endif

           push  1              ;disable signals                        ;@T72
           call  DOSHOLDSIGNAL  ;                                       ;@T72

           ;******************************************************************
           ; loop requesting Screen Group semaphore - loop needed in case
           ; a different thread does a popup and we are switched to it, the
           ; fsRAMsel/off will have changed so we clear this SG semaphore and
           ; wait on the one used in the popup
           ;******************************************************************
           xor   dx,dx
           .repeat

             .if <nonzero dx>           ;don't do this 1st time through ;P2859
               push  es                 ;
               push  bx                 ;
               call  DOSFSRAMSEMCLEAR   ;

               mov ax, es:RamSem_SGID                                   ;B722219
               .if <ax eq ds:currSG>                                    ;B722219
                  sub  eax,eax                                          ;B722219
                  push eax                                              ;B722219
                  call DOSSLEEP           ;give up the timeslice        ;B722219
               .endif                                                   ;B722219
             .endif

             mov   dx,1
             mov   cx,ds:fsRAMsel                                       ;D549
             mov   es,cx                                                ;D549
             mov   bx,ds:fsRAMoff

             .repeat
               push  es                 ;request currSG's FS RAM sem    ;@T14
               push  bx
;@T18          push  wait_hi            ;
               push  dword ptr -1       ;                               ;@T18
               call  DOSFSRAMSEMREQUEST ;
             .until <ax ne ERROR_INTERRUPT>

                                        ;repeat if sysSEMhdlPTR changed
           .until <bx eq ds:fsRAMoff> and                               ;D549
           .until <cx eq ds:fsRAMsel>                                   ;D549

           mov   ds:rqdSEMsel,es        ;keep track of semaphore requestd;D549
           mov   ds:rqdSEMoff,bx
         .endif

         popa
         pop   es
         pop   gs                                                  ;D549,@T80
         leave
         call dword ptr ds:avs_off      ;call Alternate Video Subsystem
         enter 10,0
         push  gs                                                  ;D549,@T80
         push  es
         pusha

         mov   es,ds:ldtinfo            ;SI <-- current Thread ID
         mov   si,es:[LIS_CurThrdID]    ;
         lgs   bx,ds:SGCB               ;load with SGCB ptr        ;D549,@T80
         mov   dx,ds:currPID            ;DX <-- currPID

         .if <si eq gs:[bx].VIO_srwTID> and     ;if save/restore thread ;@T80
         .if <dx eq gs:[bx].VIO_srwPID>         ;                       ;@T80
         .elseif <si eq gs:[bx].VIO_smwTID> and ;                       ;@T80
         .if <dx eq gs:[bx].VIO_smwPID>         ;                       ;@T80

         .elseif <gs:[bx].VIO_avscbptr ne 00> and ;AVS in effect        ;@T80
         les  di,gs:[bx].VIO_avscbptr           ;ptr to avscb           ;@T80
         .if <dx eq es:[di].reg_pid> and        ;if pid that reg'd ;D549,@T14
         .if <si eq es:[di].psThID> or          ;& shift-prtsc thread or;D549
         .if <si eq es:[di].pstogThID>          ;if ctrl-prtsc thread   ;D549
           ;******************************************************************
           ; didn't serialize so don't do anything
           ;******************************************************************

         .else
           ;******************************************************************
           ; clear Screen Group semaphore
           ;******************************************************************

           push  dword ptr ds:rqdSEMoff ;clear SGPIDSYNC           ;D549,@T14
           call  DOSFSRAMSEMCLEAR       ;

           mov ax, common                                               ;B722219
           mov es, ax                                                   ;B722219
           mov ax, es:RamSem_SGID                                       ;B722219
           .if <ax eq ds:currSG>                                        ;B722219
              sub  eax,eax                                              ;B722219
              push eax                                                  ;B722219
              call DOSSLEEP           ;give up the timeslice            ;B722219
           .endif                                                       ;B722219

           push  0                      ;enable signals
           call  DOSHOLDSIGNAL          ;
         .endif

         .if <<word ptr [bp].rout_savAX> eq avstonorm> near
           ;************************************************************
           ;if AVS returns avstonorm (equ -1), that is an indication
           ;to the router that AVS also wants the "default" path taken.
           ;************************************************************
           popa                 ;prepare to call Screen Switcher
           pop  es              ;
           pop  gs              ;                                       ;@T80
           mov  ax,[bp].rout_fc ;  AX <-- VIO function code
           leave                ;

           ;************************************************************
           ;call the appropriate Screen Switcher routine
           ;************************************************************
           .if <ax eq equsavredrawwait>
             CALL DOSSAVREDRAWWAIT                                      ;MDLL
           .elseif <ax eq equmodewait>
             CALL DOSMODEWAIT                                           ;MDLL
           .elseif <ax eq equscrlock>
             CALL DOSSCRLOCK                                            ;MDLL
           .elseif <ax eq equscrunlock>
             CALL DOSSCRUNLOCK                                          ;MDLL
           .elseif <ax eq equsavredrawundo>
             CALL DOSSAVREDRAWUNDO                                      ;MDLL
           .elseif <ax eq equmodeundo>
             CALL DOSMODEUNDO                                           ;MDLL
           .endif

           enter 10,0           ;restore stack for common exit point
           push  gs                                                     ;@T80
           push  es
           pusha                ;
         .endif

       .else near
         ;****************************************************************
         ;function has not been registered, so just call the corresponding
         ;Screen Switcher function - no serialization needed cause Session
         ;Manager does it
         ;****************************************************************
         popa                   ;prepare to call Screen Switcher
         pop   es               ;
         pop   gs               ;                                       ;@T80
         mov   ax,[bp].rout_fc  ;  AX <-- VIO function code
         leave                  ;

         ;**************************************************************
         ;call the appropriate Screen Switcher routine
         ;**************************************************************
         .if <ax eq equsavredrawwait>
           CALL DOSSAVREDRAWWAIT                                        ;MDLL
         .elseif <ax eq equmodewait>
           CALL DOSMODEWAIT                                             ;MDLL
         .elseif <ax eq equscrlock>
           CALL DOSSCRLOCK                                              ;MDLL
         .elseif <ax eq equscrunlock>
           CALL DOSSCRUNLOCK                                            ;MDLL
         .elseif <ax eq equsavredrawundo>
           CALL DOSSAVREDRAWUNDO                                        ;MDLL
         .elseif <ax eq equmodeundo>
           CALL DOSMODEUNDO                                             ;MDLL
         .endif

         enter 10,0             ;restore stack for common exit point
         push  gs               ;                                       ;@T80
         push  es               ;
         pusha                  ;
       .endif

       .if <ds:Igvs_count ne 0> near AND ;if there is at least one GVS  ;1.2
       .if <ds:currSG ne 0> near   AND   ;registered AND caller is from ;1.2
       .if <ds:currSG b 16> near         ;                              ;1.2
         ;****************************************************************
         ; need to call Global Video Sybsystem
         ;****************************************************************

         mov   es,ds:ldtinfo            ;SI <-- current Thread ID       ;1.2
         mov   si,es:[LIS_CurThrdID]    ;                               ;1.2

         lgs   bx,ds:SGCB               ;load with SGCB ptr             ;@T80
         mov   dx,ds:currPID            ;DX <-- currPID                 ;1.2

         mov   ax,[bp].rout_fc                                          ;1.2
         .if <<word ptr [bp].rout_savAX> eq 0> AND      ;if AX = 0, AND ;1.2
         .if <ax eq equsavredrawwait> OR        ;if save/redraw. mode-  ;1.2
         .if <ax eq equmodewait>      OR        ;wait, or scrlock thread;1.2
         .if <ax eq equscrlock>                 ;                       ;1.2
           ;****************************************************************
           ; if no error and saveredrawwait, modewait or scrlock thread
           ; then don't need to serialize
           ;****************************************************************

         .else near                                                     ;1.2
           ;******************************************************************
           ; need to serialize using Semaphores
           ;******************************************************************

           push  1              ;disable signals                        ;1.2
           call  DOSHOLDSIGNAL  ;                                       ;1.2

           ;******************************************************************
           ; loop requesting Screen Group semaphore - loop needed in case
           ; a different thread does a popup and we are switched to it, the
           ; fsRAMsel/off will have changed so we clear this SG semaphore and
           ; wait on the one used in the popup
           ;******************************************************************
           xor   dx,dx                                                  ;1.2
           .repeat                                                      ;1.2

             .if <nonzero dx>           ;don't do this 1st time through ;1.2
               push  es                 ;                               ;1.2
               push  bx                 ;                               ;1.2
               call  DOSFSRAMSEMCLEAR   ;                               ;1.2

               mov ax, common                                           ;B722219
               mov es, ax                                               ;B722219
               mov ax, es:RamSem_SGID                                   ;B722219
               .if <ax eq ds:currSG>                                    ;B722219
                  sub  eax,eax                                          ;B722219
                  push eax                                              ;B722219
                  call DOSSLEEP           ;give up the timeslice        ;B722219
               .endif                                                   ;B722219
             .endif                                                     ;1.2

             mov   dx,1                                                 ;1.2
             mov   cx,ds:fsRAMsel                                       ;D549
             mov   es,cx                                                ;D549
             mov   bx,ds:fsRAMoff                                       ;1.2

             .repeat                                                    ;1.2
               push  es                 ;request currSG's FS RAM sem    ;1.2
               push  bx                 ;                               ;1.2
;@T18          push  wait_hi            ;                               ;1.2
               push  dword ptr -1       ;                           ;1.2,@T18
               call  DOSFSRAMSEMREQUEST ;                               ;1.2
             .until <ax ne ERROR_INTERRUPT>                             ;1.2

                                        ;repeat if sysSEMhdlPTR changed ;1.2
           .until <bx eq ds:fsRAMoff> and                              ;1.2;D549
           .until <cx eq ds:fsRAMsel>                                    ;D549

           mov   ds:rqdSEMsel,es        ;save semaphore requested       ;D549
           mov   ds:rqdSEMoff,bx                                        ;1.2
         .endif                                                         ;1.2

         mov  ax,common                                                 ;1.2
         mov  es,ax                                                     ;1.2

         ;*********************************************************************
         ;calculate offset of this function call mask in common2 (viocdata.inc)
         ;*********************************************************************
         mov  di,[bp].rout_fc   ;DI <-- offset into bit_xxx structure   ;1.2
         shl  di,2              ;                                       ;1.2
         add  di,common2_beg    ;                                       ;1.2

         mov  ax,es:[di]+2      ;setup [bp].funcmask for register comp. ;1.2
         mov  [bp].funcmask,ax  ;                                       ;1.2

         mov  di,es:[di]        ;DI <-- proper offset into Igvs record  ;1.2
         add  di,Igvs_loest     ;for the current function               ;1.2

         mov  bx,idata_sz       ;BX --> first Igvs_record               ;1.2

         .repeat                        ;mark all .replaced fields      ;1.2
           mov  ax,ds:[bx][di]          ;if current function has been   ;1.2
           and  ax,[bp].funcmask        ;registered by a GVS            ;1.2
           mov  ds:[bx].Ireplaced,ax    ;                               ;1.2
           add  bx,Igvs_rec_sz          ;                               ;1.2
         .until <bx a ds:Igvs_last>     ;                               ;1.2

         mov   ds:Igvs_quit,0                                           ;1.2
         popa                                                           ;1.2
         pop  es                                                        ;1.2
         pop  gs                                                        ;@T80
         leave                                                          ;1.2

         mov   ds:gvs_cntr,0    ;reset gvs_cntr                         ;1.2

         ;*********************************************************************
         ; loop calling each Global Video Subsystem if this function replaced
         ;*********************************************************************
         .repeat                                                        ;1.2
           push  ax             ;save registers                         ;1.2
           push  bx             ;                                       ;1.2
           mov   ax,ds:gvs_cntr ;BX <-- first GVS record                ;@T2
           imul  bx,ax,Igvs_rec_sz                                      ;@T2
           add   bx,idata_sz    ;                                       ;@T2

           inc   ds:gvs_cntr    ;set up for next repetition             ;1.2

           .if <<ds:[bx].Ireplaced> ne 0> ;set above if replaced        ;1.2
             mov   ax,ds:[bx].Igvs_off  ;setup GVS address to call      ;1.2
             mov   ds:gvsCURoff,ax      ;                               ;1.2
             mov   ax,ds:[bx].Igvs_sel  ;                               ;1.2
             mov   ds:gvsCURsel,ax      ;                               ;1.2
             pop   bx                                                   ;1.2
             pop   ax                                                   ;1.2
             call  dword ptr ds:gvsCURoff ;call GVS                     ;1.2
             push  ax                     ;save registers               ;1.2
             push  bx                   ;                               ;1.2
           .endif                                                       ;1.2

           mov  ax,ds:gvs_cntr          ;# of GVSs called               ;1.2

           .if <ax eq ds:Igvs_count>    ;if # called = total # of GVSs  ;1.2
             mov  ds:Igvs_quit,1        ;quit out of loop               ;1.2
           .endif                                                       ;1.2

           pop  bx                      ;                               ;1.2
           pop  ax                      ;                               ;1.2
         .until <ds:Igvs_quit eq 1>                                     ;1.2

         enter 10,0                                                     ;1.2
         push  gs                                                       ;@T80
         push  es                                                       ;1.2
         pusha                                                          ;1.2

         mov   es,ds:ldtinfo            ;SI <-- current Thread ID       ;1.2
         mov   si,es:[LIS_CurThrdID]    ;                               ;1.2

         mov   ax,common                ;ES <-- common data selector    ;1.2
         mov   es,ax                    ;                               ;1.2

         lgs   bx,ds:SGCB               ;load with SGCB ptr             ;@T80
         mov   dx,ds:currPID            ;DX <-- currPID                 ;1.2

         mov   ax,[bp].rout_fc                                          ;1.2
         .if <<word ptr [bp].rout_savAX> eq 0> AND      ;if AX = 0, AND ;1.2
         .if <ax eq equsavredrawwait> OR        ;if save/redraw. mode-  ;1.2
         .if <ax eq equmodewait>      OR        ;wait, or scrlock thread;1.2
         .if <ax eq equscrlock>                 ;                       ;1.2
           ;******************************************************************
           ; didn't serialize so don't do anything
           ;******************************************************************

         .else                                                          ;1.2
           ;******************************************************************
           ; clear Screen Group semaphore
           ;******************************************************************

           push  dword ptr ds:rqdSEMoff ;clear SGPIDSYNC       ;1.2,D549,@T14
           call  DOSFSRAMSEMCLEAR       ;                               ;1.2

           mov ax, es:RamSem_SGID                                       ;B722219
           .if <ax eq ds:currSG>                                        ;B722219
              sub  eax,eax                                              ;B722219
              push eax                                                  ;B722219
              call DOSSLEEP           ;give up the timeslice            ;B722219
           .endif                                                       ;B722219

           push  0                      ;enable signals                 ;1.2
           call  DOSHOLDSIGNAL          ;                               ;1.2
         .endif                                                         ;1.2
       .endif                                                           ;1.2

     .elseif <ax eq equprtsctoggle> near or                             ;P2859
     .if <ax eq equprtsc> near                                          ;P2859

     ;************************************************************************
     ; Prtsc or Prtsctoggle call
     ;************************************************************************

       .if <gs:[bx].VIO_paused eq 1>    ;Check for CTRL-NUMLOCK/CTRL-S  ;@T80
         ;****************************************************************
         ; PAUSE in effect, wait so no video output is done but only wait
         ; if we don't own the SG sem because if we do, we want to finish
         ; the video call before waiting
         ;****************************************************************

         .if <dx ne gs:[bx].VIO_fsRAMsem.fs_PID> or  ;SG semaphore      ;@T80
         .if <si ne gs:[bx].VIO_fsRAMsem.fs_TID>     ;  already owned   ;@T80
           lea   di,gs:[bx].VIO_pause_sem                          ;@T14,@T80
           .repeat
             push  gs                   ;Address of semaphore           ;@T80
             push  di                   ;                               ;@T14
;@T18        push  wait_hi              ;Wait for semaphore to clear
             push  dword ptr -1         ;                               ;@T18
             call  DOSSEMWAIT           ;
           .until <ax ne ERROR_INTERRUPT>
         .endif                                                         ;P2893

       .endif

       .if <dx ne es:HETPID>            ;Hard Error Daemon only valid caller
         mov   [bp].rout_savAX,ERROR_VIO_SMG_ONLY
       .else near

         .repeat
           push  dword ptr ds:prtscsemlo ;wait for a VIOPRTSC to complete ;@T14
;@T18      push  wait_hi                ;
           push  dword ptr -1           ;                               ;@T18
           call  DOSSEMREQUEST          ;
         .until <ax ne ERROR_INTERRUPT>

         mov   es,ds:gdtinfo            ;CX <-- current FG SG
         xor   cx,cx                    ;
         mov   cl,es:[SIS_CurScrnGrp]   ;Get foreground session ID      ;@T6

         push  1                        ;disable signals
         call  DOSHOLDSIGNAL            ;

         push  ds                       ;sel:off to SGCB address        ;D549
         push  offset SGCB_temp         ;  (returned)                   ;D549
         push  cx                       ;get SGCB for foreground SG     ;D549
         push  Look_up_SGID                                             ;D549
         call  DOSSMGETSGCB             ;get addressability to SGCB     ;D549

         .if <nonzero ax>               ;can't get addressability       ;D549
           call suicide                 ;kill process                   ;D549
         .endif                                                         ;D549

         lgs   bx,ds:SGCB_temp          ;load fs:[bx] with SGCB ptr     ;@T80
         lea   dx,[bx].VIO_fsRAMsem     ;offset to SG semaphore ;@T2;D549,@T14

         .repeat
           push  gs                     ;request fgSG's FS RAM sem      ;@T80
           push  dx                     ;order to block it from making  ;@T2
;@T18      push  wait_hi                ;VIO calls while VIOPRTSC trys
           push  dword ptr -1           ;to read the screen image       ;@T18
           call  DOSFSRAMSEMREQUEST     ;
         .until <ax ne ERROR_INTERRUPT>

         mov   ax,[bp].funcmask         ;function call mask
         and   ax,gs:[bx].VIO_masklo    ;prtsc/prtsctoggle function mask ;@T80

         .if <nonzero ax>  near         ;function replaced by fgSG AVS  ;P2859
           ;******************************************************************
           ; AVS replaced prtsc/prtsctoggle call
           ;******************************************************************

             les   di,gs:[bx].VIO_avscbptr  ;ptr to avscb               ;@T80
             .if <<word ptr[bp].rout_fc> eq equprtsc>
               ;**************************************************************
               ; prtsc - execute AVS_PRTSC and wait until it's finished
               ;**************************************************************

               push  es
               lea   ax,[di].ps_exit                                    ;D549
               push  ax                 ;when AVS_PRTSC exits
               call  DOSSEMSET          ;unconditionally set RAM sem

               mov   es:[di].prtscAX,0  ;get AVS_PRTSC ret. code        ;D549
               push  es
               lea   ax,[di].ps_enter                                   ;D549
               push  ax
               call  DOSSEMCLEAR        ;unblock AVS_PRTSC thread

               lea   dx,[di].ps_exit                                    ;@T14
               .repeat
                 push  es               ;when cleared, AVS_PRTSC done
                 push  dx                                               ;@T14
;@T18            push  0FFFFH
                 push  dword ptr -1                                     ;@T18
                 call  DOSSEMWAIT         ;wait until signaled
               .until <ax ne ERROR_INTERRUPT>

               mov   ax,es:[di].prtscAX  ;get AVS_PRTSC ret. code       ;D549
               mov   [bp].rout_savAX,ax  ;
             .else
               ;**************************************************************
               ; prtsctoggle - execute AVS_PRTSCTOGGLE and wait til finished
               ;**************************************************************

               push  es
               lea   ax,[di].pstog_exit ;set semaphore that's cleared   ;D549
               push  ax
               call  DOSSEMSET             ;unconditionally set RAM sem

               mov   es:[di].prtsctogAX,0 ;get ret. code from TOGGLE    ;D549
               push  es
               lea   ax,[di].pstog_enter                                ;D549
               push  ax
               call  DOSSEMCLEAR        ;unblock AVS_PRTSCTOGGLE thread

               lea   dx,[di].pstog_exit                                 ;@T14
               .repeat
                 push  es               ;when cleared, AVS_PRTSCTOGGLE done
                 push  dx                                               ;@T14
;@T18            push  0FFFFH
                 push  dword ptr -1                                     ;@T18
                 call  DOSSEMWAIT       ;wait until signaled
               .until <ax ne ERROR_INTERRUPT>

               mov   ax,es:[di].prtsctogAX      ;get AVS_PRTSCTOGGLE rc ;D549
               mov   [bp].rout_savAX,ax         ;
             .endif

             .if <ax eq avstonorm>      ;act as if func. not replaced
               popa
               pop   es
               pop   gs                                                   ;@T80
               leave

               mov   ax,ds:avs_bvs_bits                                   ;@T8
               call  dword ptr ds:bvs_off   ;call BVS

               enter 10,0
               push  gs                                                   ;@T80
               push  es
               pusha
             .endif

         .else
           ;******************************************************************
           ; call BVS prtsc/prtsctoggle
           ;******************************************************************
           popa
           pop   es
           pop   gs                                                     ;@T80
           leave
           xor   ax,ax
           call  dword ptr ds:bvs_off   ;call BVS
           enter 10,0
           push  gs                                                     ;@T80
           push  es
           pusha
         .endif

         .if <ax eq ERROR_VIO_INTERNAL_RESOURCE>;if resource error from
           call suicide                         ;BVS, signal Hard Error
         .endif                                 ;Task to kill this PID

         lgs   bx,ds:SGCB_temp          ;foreground SGCB ptr       ;@C48,@T80
         add   bx,VIO_fsRAMsem          ;offset to SG semaphore      ;@T2,D549

         mov   ax,common        ;ES <-- common data selector            ;@T2
         mov   es,ax            ;                                       ;@T2
       .endif                           ;                               ;P2859

       .if <ds:Igvs_count ne 0> near AND ;if at least one GVS exists    ;1.2
       .if <ds:currSG ne 0> near   AND   ;AND caller is from            ;1.2
       .if <ds:currSG b 16> near         ;                              ;1.2
         ;****************************************************************
         ; need to call Global Video Sybsystem
         ;****************************************************************

         ;*********************************************************************
         ;calculate offset of this function call mask in common2 (viocdata.inc)
         ;*********************************************************************
         mov  di,[bp].rout_fc           ;DI <-- off. into GVS record    ;P2859
         shl  di,2                                                      ;P2859
         add  di,common2_beg                                            ;P2859

         mov  ax,es:[di]+2                                              ;P2859
         mov  [bp].funcmask,ax          ;setup [bp].funcmask for compare;P2859

         mov  di,es:[di]                ;DI <-- proper offset into Igvs ;P2859
         add  di,Igvs_loest             ;record for the current function;P2859

         mov  bx,idata_sz       ;BX --> first Igvs_record               ;1.2

         .repeat                        ;mark all .replaced fields      ;1.2
           mov  ax,ds:[bx][di]          ;if current function has been   ;1.2
           and  ax,[bp].funcmask        ;registered by a GVS            ;1.2
           mov  ds:[bx].Ireplaced,ax    ;                               ;1.2
           add  bx,Igvs_rec_sz          ;                               ;1.2
         .until <bx a ds:Igvs_last>     ;                               ;1.2

         mov   ds:Igvs_quit,0                                           ;1.2
         popa                                                           ;1.2
         pop  es                                                        ;1.2
         pop  gs                                                        ;@T80
         leave                                                          ;1.2

         mov  ds:gvs_cntr,0                                             ;P2859

         ;*********************************************************************
         ; loop calling each Global Video Subsystem if this function replaced
         ;*********************************************************************
         .repeat                                                        ;1.2
           push  ax           ;save registers                           ;1.2
           push  bx           ;                                         ;1.2
           mov   ax,ds:gvs_cntr       ;BX <-- first GVS record          ;@T2
           imul  bx,ax,Igvs_rec_sz    ;                                 ;@T2
           add   bx,idata_sz          ;                                 ;@T2

           inc   ds:gvs_cntr          ;set up for next repetition       ;1.2

           .if <ds:[bx].Ireplaced ne 0>                                 ;1.2
             mov   ax,ds:[bx].Igvs_off;setup GVS address to call        ;1.2
             mov   ds:gvsCURoff,ax    ;                                 ;1.2
             mov   ax,ds:[bx].Igvs_sel;                                 ;1.2
             mov   ds:gvsCURsel,ax    ;                                 ;1.2
             pop   bx                 ;                                 ;1.2
             pop   ax                 ;                                 ;1.2
             call  dword ptr ds:gvsCURoff                               ;1.2
             push  ax                 ;save registers                   ;1.2
             push  bx                 ;                                 ;1.2
           .endif                                                       ;1.2

           mov  ax,ds:gvs_cntr        ;# of GVSs called                 ;1.2

           .if <ax eq ds:Igvs_count>  ;if # called = # of GVSs          ;1.2
             mov  ds:Igvs_quit,1      ;quit loop                        ;1.2
           .endif                                                       ;1.2

           pop  bx                    ;                                 ;1.2
           pop  ax                    ;                                 ;1.2
         .until <ds:Igvs_quit eq 1>                                     ;1.2

         enter 10,0                                                     ;1.2
         push  gs                                                       ;@T80
         push  es                                                       ;1.2
         pusha                                                          ;1.2
       .endif                                                           ;1.2

       .if <ax ne ERROR_VIO_SMG_ONLY>                                   ;P2859

         push  gs               ;clear fgSG's FS RAM sem                ;@T80
         push  bx               ;
         call  DOSFSRAMSEMCLEAR ;

         mov ax, common                                                 ;B722219
         mov es, ax                                                     ;B722219
         mov ax, es:RamSem_SGID                                         ;B722219
         .if <ax eq ds:currSG>                                          ;B722219
            sub  eax,eax                                                ;B722219
            push eax                                                    ;B722219
            call DOSSLEEP           ;give up the timeslice              ;B722219
         .endif                                                         ;B722219

         push  dword ptr ds:prtscsemlo  ;allow screen switching         ;@T14
         call  DOSSEMCLEAR      ;

         push  0                ;enable signals
         call  DOSHOLDSIGNAL    ;

       .endif                                                           ;P2859

     .else near                 ;Non-screen switcher, non-PrtSc calls

     ;************************************************************************
     ; Normal call  (not screen switcher or prtsc type)
     ;************************************************************************

       .if <si eq gs:[bx].VIO_srwTID> and       ;if save/restore thread ;@T80
       .if <dx eq gs:[bx].VIO_srwPID>           ;or HET                 ;@T80
       .elseif <si eq gs:[bx].VIO_smwTID> and   ;                       ;@T80
       .if <dx eq gs:[bx].VIO_smwPID>           ;                       ;@T80

       .elseif <gs:[bx].VIO_avscbptr ne 00> and ;AVS in effect        ;@T80
       les  di,gs:[bx].VIO_avscbptr           ;ptr to avscb           ;@T80
       .if <dx eq es:[di].reg_pid> and        ;if pid that reg'd ;D549,@T14
       .if <si eq es:[di].psThID> or            ;& shift-prtsc thread or;D549
       .if <si eq es:[di].pstogThID>            ;if ctrl-prtsc thread   ;D549
         ;******************************************************************
         ; don't need to serialize because save/restore threads and
         ; prtsc/prtsctoggle threads are already serialized by session manager
         ;******************************************************************

       .else near
         ;******************************************************************
         ; need to serialize using Semaphores
         ;******************************************************************

;@T72    push  1                        ;disable signals
;@T72    call  DOSHOLDSIGNAL            ;

         .if <gs:[bx].VIO_paused eq 1>  ;Check for CTRL-NUMLOCK/CTRL-S  ;@T80
           ;****************************************************************
           ; PAUSE in effect, wait so no video output is done but only wait
           ; if we don't own the SG sem because if we do, we want to finish
           ; the video call before waiting
           ;****************************************************************

           .if <dx ne gs:[bx].VIO_fsRAMsem.fs_PID> or ;SG semaphore     ;@T80
           .if <si ne gs:[bx].VIO_fsRAMsem.fs_TID>    ;  already owned  ;@T80
             lea   dx,[bx].VIO_pause_sem                                ;@T14
             .repeat
               push  gs                 ;Address of semaphore           ;@T80
               push  dx                 ;                               ;@T14
;@T18          push  wait_hi            ;Wait for semaphore to clear
               push  dword ptr -1       ;                               ;@T18
               call  DOSSEMWAIT         ;
             .until <ax ne ERROR_INTERRUPT>
           .endif                                                       ;P2893

         .endif

         push  1                ;disable signals                        ;@T72
         call  DOSHOLDSIGNAL    ;                                       ;@T72

         ;******************************************************************
         ; loop requesting Screen Group semaphore - loop needed in case
         ; a different thread does a popup and we are switched to it, the
         ; fsRAMsel/off will have changed so we clear this SG semaphore and
         ; wait on the one used in the popup
         ;******************************************************************
         xor  dx,dx
         .repeat

           .if <nonzero dx>             ;don't do this 1st time through ;P2859
             push  es                   ;
             push  bx                   ;
             call  DOSFSRAMSEMCLEAR     ;

             mov ax, common                                             ;B722219
             mov es, ax                                                 ;B722219
             mov ax, es:RamSem_SGID                                     ;B722219
             .if <ax eq ds:currSG>                                      ;B722219
                sub  eax,eax                                            ;B722219
                push eax                                                ;B722219
                call DOSSLEEP           ;give up the timeslice          ;B722219
             .endif                                                     ;B722219
           .endif                       ;

           mov   dx,1
           mov   cx,ds:fsRAMsel                                        ;D549
           mov   es,cx                                                 ;D549
           mov   bx,ds:fsRAMoff

           .repeat
             push  es           ;request currSG's FS RAM sem
             push  bx           ;
;@T18        push  wait_hi      ;
             push  dword ptr -1 ;                                       ;@T18
             call  DOSFSRAMSEMREQUEST
           .until <ax ne ERROR_INTERRUPT>

                                        ;if ds:fsRAMoff changed, repeat
         .until <bx eq ds:fsRAMoff> and                                 ;D549
         .until <cx eq ds:fsRAMsel>                                     ;D549

         mov  ds:rqdSEMsel,es           ;save requested semaphore       ;D549
         mov  ds:rqdSEMoff,bx
       .endif

       popa                             ;prepare to call subsystem(s)
       pop   es                         ;
       pop   gs                                                         ;@T80
       mov   ax,[bp].funcmask           ;AX <-- non-zero if func. replaced
       and   ax,[bp].replacemask        ;by AVS subsystem
       leave

       .if <nonzero ax>                 ;function replaced by AVS?      ;P2859
         call dword ptr ds:avs_off      ;call AVS

         .if <ax eq avstonorm>          ;AVS wants BVS to handle it?
           mov  ax,ds:avs_bvs_bits                                      ;@T8
           call dword ptr ds:bvs_off
         .endif

       .else                            ;not replaced call BVS

         .if <ds:pop_mode eq 0>         ;is currPID in a popup?
           mov  ax,ds:avs_bvs_bits                                      ;@T8
           call dword ptr ds:bvs_off
         .else                          ;YES
           xor  ax,ax                   ;tell BVS that there is no AVS
           call dword ptr ds:bvs_off
         .endif

       .endif

       .if <ax eq ERROR_VIO_INTERNAL_RESOURCE>  ;if resource error from
         call suicide                           ;BVS, signal Hard Error
       .endif                                   ;Task to kill this PID

       enter 10,0               ;save registers
       push  gs                                                         ;@T80
       push  es                 ;
       pusha                    ;

       .if <ds:Igvs_count ne 0> near AND ;if there is at least one GVS  ;1.2
       .if <ds:currSG ne 0> near   AND   ;registered AND caller is from ;1.2
       .if <ds:currSG b 16> near         ;                              ;1.2
         ;****************************************************************
         ; need to call Global Video Sybsystem
         ;****************************************************************

         mov  ax,common                                                 ;1.2
         mov  es,ax                                                     ;1.2

         ;*********************************************************************
         ;calculate offset of this function call mask in common2 (viocdata.inc)
         ;*********************************************************************
         mov  di,[bp].rout_fc   ;DI <-- offset into bit_xxx structure   ;1.2
         shl  di,2              ;                                       ;1.2
         add  di,common2_beg    ;                                       ;1.2

         mov  ax,es:[di]+2      ;setup [bp].funcmask for register comp. ;1.2
         mov  [bp].funcmask,ax  ;                                       ;1.2

         mov  di,es:[di]        ;DI <-- proper offset into Igvs record  ;1.2
         add  di,Igvs_loest     ;for the current function               ;1.2

         mov  bx,idata_sz       ;BX --> first Igvs_record               ;1.2

         .repeat                        ;mark all .replaced fields      ;1.2
           mov  ax,ds:[bx][di]          ;if current function has been   ;1.2
           and  ax,[bp].funcmask        ;registered by a GVS            ;1.2
           mov  ds:[bx].Ireplaced,ax    ;                               ;1.2
           add  bx,Igvs_rec_sz          ;                               ;1.2
         .until <bx a ds:Igvs_last>     ;                               ;1.2

         mov   ds:Igvs_quit,0                                           ;1.2
         popa                                                           ;1.2
         pop  es                                                        ;1.2
         pop  gs                                                        ;@T80
         leave                                                          ;1.2

         mov   ds:gvs_cntr,0    ;reset gvs_cntr                         ;1.2

         ;*********************************************************************
         ; loop calling each Global Video Subsystem if this function replaced
         ;*********************************************************************
         .repeat                                                        ;1.2
           push  ax             ;save registers                         ;1.2
           push  bx             ;                                       ;1.2
           mov   ax,ds:gvs_cntr ;BX <-- first GVS record                ;@T2
           imul  bx,ax,Igvs_rec_sz                                      ;@T2
           add   bx,idata_sz    ;                                       ;@T2

           inc   ds:gvs_cntr    ;set up for next repetition             ;1.2

           .if <<ds:[bx].Ireplaced> ne 0>                               ;1.2
             mov   ax,ds:[bx].Igvs_off  ;setup GVS address to call      ;1.2
             mov   ds:gvsCURoff,ax      ;                               ;1.2
             mov   ax,ds:[bx].Igvs_sel  ;                               ;1.2
             mov   ds:gvsCURsel,ax      ;                               ;1.2
             pop   bx                   ;                               ;1.2
             pop   ax                   ;                               ;1.2
             call  dword ptr ds:gvsCURoff                               ;1.2
             push  ax                   ;save registers                 ;1.2
             push  bx                   ;                               ;1.2
           .endif                                                       ;1.2

           mov  ax,ds:gvs_cntr          ;# of GVSs called               ;1.2

           .if <ax eq ds:Igvs_count>    ;if # called = # of GVSs        ;1.2
             mov  ds:Igvs_quit,1        ;quit loop                      ;1.2
           .endif                                                       ;1.2

           pop  bx                      ;                               ;1.2
           pop  ax                      ;                               ;1.2
         .until <ds:Igvs_quit eq 1>                                     ;1.2

         enter 10,0                                                     ;1.2
         push  gs                                                       ;@T80
         push  es                                                       ;1.2
         pusha                                                          ;1.2
       .endif                                                           ;1.2

       mov   es,ds:ldtinfo              ;SI <-- current thread ID
       mov   si,es:[LIS_CurThrdID]      ;

       lgs   bx,ds:SGCB         ;load with SGCB ptr                     ;@T80
       mov   dx,ds:currPID      ;DX <-- current PID

       .if <si eq gs:[bx].VIO_srwTID> and       ;if save/restore thread ;@T80
       .if <dx eq gs:[bx].VIO_srwPID>           ;or HET, DO NOT request ;@T80
       .elseif <si eq gs:[bx].VIO_smwTID> and   ;                       ;@T80
       .if <dx eq gs:[bx].VIO_smwPID>           ;                       ;@T80

       .elseif <gs:[bx].VIO_avscbptr ne 00> and ;AVS in effect        ;@T80
       les  di,gs:[bx].VIO_avscbptr           ;ptr to avscb           ;@T80
       .if <dx eq es:[di].reg_pid> and        ;if pid that reg'd ;D549,@T14
       .if <si eq es:[di].psThID> or            ;& shift-prtsc thread or;D549
       .if <si eq es:[di].pstogThID>            ;if ctrl-prtsc thread   ;D549
         ;******************************************************************
         ; didn't serialize so don't do anything
         ;******************************************************************

       .else
         push  dword ptr ds:rqdSEMoff   ;clear currSG's FS RAM sem ;D549,@T14
         call  DOSFSRAMSEMCLEAR         ;

         mov ax, common                                                 ;B722219
         mov es, ax                                                     ;B722219
         mov ax, es:RamSem_SGID                                         ;B722219
         .if <ax eq ds:currSG>                                          ;B722219
            sub  eax,eax                                                ;B722219
            push eax                                                    ;B722219
            call DOSSLEEP           ;give up the timeslice              ;B722219
         .endif                                                         ;B722219

         push  0                        ;enable signals
         call  DOSHOLDSIGNAL            ;
       .endif

     .endif

   .else  near                                                          ;P2859
     ;********************************************************************
     ; if error before 'if Screen Switcher call' need to pass it to GVS
     ;********************************************************************

     .if <ds:Igvs_count ne 0> near AND  ;if there is at least one GVS   ;1.2
     .if <ds:currSG ne 0> near   AND    ;registered AND caller is from  ;1.2
     .if <ds:currSG b 16> near          ;                               ;1.2
       mov  ax,common                                                   ;1.2
       mov  es,ax                                                       ;1.2

       ;*********************************************************************
       ;calculate offset of this function call mask in common2 (viocdata.inc)
       ;*********************************************************************
       mov  di,[bp].rout_fc     ;DI <-- offset into bit_xxx structure   ;1.2
       shl  di,2                ;                                       ;1.2
       add  di,common2_beg      ;                                       ;1.2

       mov  ax,es:[di]+2        ;setup [bp].funcmask for register comp. ;1.2
       mov  [bp].funcmask,ax    ;                                       ;1.2

       mov  di,es:[di]          ;DI <-- proper offset into Igvs record  ;1.2
       add  di,Igvs_loest       ;for the current function               ;1.2

       mov  bx,idata_sz         ;BX --> first Igvs_record               ;1.2

       .repeat                          ;mark all .replaced fields      ;1.2
         mov  ax,ds:[bx][di]            ;if current function has been   ;1.2
         and  ax,[bp].funcmask          ;registered by a GVS            ;1.2
         mov  ds:[bx].Ireplaced,ax      ;                               ;1.2
         add  bx,Igvs_rec_sz            ;                               ;1.2
       .until <bx a ds:Igvs_last>       ;                               ;1.2

       mov   ds:Igvs_quit,0                                             ;1.2
       popa                                                             ;1.2
       pop  es                                                          ;1.2
       pop  gs                                                          ;@T80
       leave                                                            ;1.2

       mov   ds:gvs_cntr,0      ;reset gvs_cntr                         ;1.2

       ;*********************************************************************
       ; loop calling each Global Video Subsystem if this function replaced
       ;*********************************************************************
       .repeat                                                          ;1.2
         push  ax               ;save registers                         ;1.2
         push  bx               ;                                       ;1.2
         mov   ax,ds:gvs_cntr   ;BX <-- first GVS record                ;@T2
         imul  bx,ax,Igvs_rec_sz                                        ;@T2
         add   bx,idata_sz      ;                                       ;@T2

         inc   ds:gvs_cntr      ;set up for next repetition             ;1.2

         .if <<ds:[bx].Ireplaced> ne 0>                                 ;1.2
           mov   ax,ds:[bx].Igvs_off    ;setup GVS address to call      ;1.2
           mov   ds:gvsCURoff,ax        ;                               ;1.2
           mov   ax,ds:[bx].Igvs_sel    ;                               ;1.2
           mov   ds:gvsCURsel,ax        ;                               ;1.2
           pop   bx                     ;                               ;1.2
           pop   ax                     ;                               ;1.2
           call  dword ptr ds:gvsCURoff                                 ;1.2
           push  ax                     ;save registers                 ;1.2
           push  bx                     ;                               ;1.2
         .endif                                                         ;1.2

         mov  ax,ds:gvs_cntr            ;# of GVSs called               ;1.2

         .if <ax eq ds:Igvs_count>      ;if # called = # of GVSs        ;1.2
           mov  ds:Igvs_quit,1          ;quit loop                      ;1.2
         .endif                                                         ;1.2

         pop  bx                        ;                               ;1.2
         pop  ax                        ;                               ;1.2
       .until <ds:Igvs_quit eq 1>                                       ;1.2

       enter 10,0                                                       ;1.2
       push  gs                                                         ;@T80
       push  es                                                         ;1.2
       pusha                                                            ;1.2
     .endif                                                             ;1.2

   .endif

   IFDEF MMIOPH                                                         ;DTBB1
   mov   es,ds:gdtinfo                          ;ES <-- global info sel.
   mov   al,es:[SIS_MEC_TABLE].SIS_VIOMEC       ;AL <-- byte w/VIO MEC
   test  al,traceonoffmask                      ;0=OFF, non-0=ON

   .if <nz>                                                             ;@T2
     call  vioposttrace ;post-invocation system trace
   .endif
   ENDIF                                                                ;DTBB1

   popa
   pop   es
   pop   gs                                                             ;@T80
   leave

   pop   ds             ;restore DS
   ret   2              ;return to VIOxxx and remove func. code
viorout endp

CTEXT_TUNE4  ends                                                       ;MDLL



cseg    segment dword public 'code'     USE16                           ;MDLL,D549,@T14
        assume  cs:CODE02,ds:instance,es:common,ss:nothing              ;MDLL

        SUBTTL VIOATTACH - ATTACH PROCESS TO VIDEO SUBSYSTEM(S)
        page
;/*********************** START OF SPECIFICATIONS ***********************/
;/* SUBROUTINE NAME: VioAttach                                          */
;/*                                                                     */
;/* DESCRIPTIVE NAME: Attach a process to the current video subsystem   */
;/*                                                                     */
;/* FUNCTION: Get addressability to the base video subsystem            */
;/*           entry procedure for the calling process and store the     */
;/*           address (selector:offset) of the procedure in             */
;/*           the instance data fields bvs_OFF and bvs_SEL. Also, if    */
;/*           an alternate video subsystem has been registered with     */
;/*           VIOREGISTER, then get addressability to it and store      */
;/*           its address in instance data fields avs_OFF and avs_SEL.  */
;/*                                                                     */
;/* NOTES: This call is made internally the first time a process makes  */
;/*        a VIOxxx function call other than VIOREGISTER.               */
;/*                                                                     */
;/* ENTRY POINT: VIOATTACH                                              */
;/*     LINKAGE: NEAR CALL (internal from VIOROUT)                      */
;/*                                                                     */
;/* INPUT: gs:[bx] - ptr to SGCB                                @T80    */
;/*                                                                     */
;/* EXIT-NORMAL: AX = NO_ERROR                                          */
;/*                                                                     */
;/* EXIT-ERROR: AX = error code set by DOSGETPROCADDR.                  */
;/*             AX = error code set by DOSLOADMODULE.                   */
;/*                                                                     */
;/* EFFECTS: The contents of AX are destroyed.                          */
;/*          Also, the calling PID's LDT will be given addressability   */
;/*          to the video subsystem(s)'s code segment, common data      */
;/*          segment, and a brand-new instance data segment.            */
;/*                                                                     */
;/* INTERNAL                                                            */
;/* REFERENCES: avs_HAND - alternate video subsystem module handle      */
;/*             avs_OFF - alt video subsystem entry proc. offset        */
;/*             avs_SEL - alt video subsystem entry proc. selector      */
;/*             bvs_OFF - base video subsystem entry proc. offset       */
;/*             bvs_SEL - base video subsystem entry proc. selector     */
;/*             bvs_MOD - base video subsystem module name              */
;/*             bvs_EP -  base video subsystem entry proc. name         */
;/*             currSG -  current process's screen group (LDTINFO:8)    */
;/*             LDTINFO - local info data segment selector              */
;/*             GDTINFO - global info data segment selector             */
;/*             OLDTIMES - SGDATA[currSG].TIMES at time of VIOATTACH    */
;/*             SGDATA[currSG].ENTRY_PT - AVS entry procedure name      */
;/*             SGDATA[currSG].MASK_HI - AVS high-order function mask   */
;/*             SGDATA[currSG].MASK_LO - AVS low-order function mask    */
;/*             SGDATA[currSG].MODULE - AVS module name                 */
;/*             SGDATA[currSG].TIMES - number of VIOREGISTERs for SG    */
;/*             SGPIDSEM - system synchronization sem. name             */
;/*             SGPIDSYNC - currSG's exclusive system sem. handle       */
;/*   ROUTINES: GetInfoSegs - get local/global info seg selectors       */
;/*                                                                     */
;/* EXTERNAL                                                            */
;/* REFERENCES: None.                                                   */
;/*   ROUTINES: DOSGETPROCADDR - get descriptor for a dynamic-link      */
;/*             DOSLOADMODULE - load dynamic-link module.               */
;/*             DOSOPENSEM - open system semaphore                      */
;/*********************** END OF SPECIFICATIONS *************************/

vioattach proc near

   sub  eax,eax                                                     ;@T8,@T73

   .if <<dword ptr gs:[bx].VIO_maskloest> ne eax> or      ;@T8,D549,@T73,@T80
;  .if <gs:[bx].VIO_masklo    ne ax> or                        ;@T8,D549,@T73
   .if <<dword ptr gs:[bx].VIO_maskhi>    ne eax>         ;@T8,D549,@T73,@T80
;  .if <gs:[bx].VIO_maskhiest ne ax>                           ;@T8,D549,@T73
   ;*************************************************************************
   ; if a function call has been replaced by an AVS, get addresability to AVS
   ;*************************************************************************

     push ds:avs_hand           ;free current AVS module                ;D549
     call DOSFREEMODULE                                                 ;D549

     push word ptr gs:[bx].VIO_avscbptr+2 ;get access to AVSCB selector ;@T80
     call DOSGETSEG                                                     ;D549
     .if  <nonzero ax>          ;if can't access AVSCB, signal hard err ;D549
       call suicide             ;to kill this process                   ;D549
     .endif                                                             ;D549

     les  di,gs:[bx].VIO_avscbptr  ;ptr to AVSCB                        ;@T80

     push ax                                                            ;@T8
     push ax                    ;address to ObjNameBuf                  ;@T8
     push ax                    ;ObjNameBufL (length of ObjNameBuf in bytes)
     push es                    ;sel to AVS module name                 ;D549
     lea  ax,[di].modname       ;add offset to module name         ;D549,@T14
     push ax                                                       ;D549,@T14
     push ds                    ;sel:off to AVS module handle
     push offset avs_hand       ;  (returned)                           ;@T52
     call DOSLOADMODULE         ;load the AVS dynamic-link module

     .if <zero ax>                                                      ;@T2
       push ds:avs_hand         ;module handle
       push es                  ;sel:off to GVS entry proc. name
       lea  ax,[di].epname      ;inc offset past module name       ;D549,@T14
       push ax                  ;offset to entry proc. name        ;D549,@T14
       push ds                  ;sel:off to desc. (returned)
       push offset avs_off                                              ;@T52
       call DOSGETPROCADDR      ;get addressabilty to dynlink proc
     .endif

     .if <nonzero ax>           ;if unable to establish addressability  ;@T8
       call suicide             ;to AVS, signal hard error task to kill ;@T8
     .endif                     ;this process                           ;@T8

     mov  ax,gs:[bx].VIO_bvs_mask                                   ;@T8,@T80
     mov  ds:avs_bvs_bits,ax                                            ;@T8

   .endif

   mov  ax,gs:[bx].VIO_times            ;sync up # of AVS regs          ;@T80
   mov  ds:oldtimes,ax

   mov  ax,common       ;ES <-- COMMON data selector                ;1.2,@T73
   mov  es,ax           ;                                           ;1.2,@T73

   push si              ;Save caller's SI                               ;@T73
   mov  si,es:Ggvs_count                                                ;@T73

   .if <si ne 0> near   ;if at least one GVS has been registered        ;@T73
     ;*************************************************************************
     ; get addressability to Global Video Subsystems
     ;*************************************************************************

     push ds            ;request RAM semaphore to ensure                ;1.2
     push offset Igvs_ramsem    ;non-corruption of Igvs_count field ;1.2,@T52
;    push wait_hi       ;                                           ;1.2,@T18
     push dword ptr -1  ;                                           ;1.2,@T18
     call DOSSEMREQUEST ;                                               ;1.2

     .if <si ne ds:Igvs_count> near     ;INSTANCE count < GLOBAL count  ;@T73
       ;***********************************************************************
       ; grow instance data for GVS
       ;***********************************************************************

       push bx                  ;Save callers BX                        ;1.2
       mov  ax,ds:Igvs_count    ;BX <-- offset to the 1st GVS not       ;@T2
       imul bx,ax,Ggvs_rec_sz   ;       yet attached by this PID        ;@T2
       add  bx,es:Ggvs_AddrLo   ;                                   ;@T2,@T73
       add  bx,2                ;Compensate for SubAlloc length word    ;@T73

;@T73  mov  ax,ds:Igvs_count    ;DI <-- offset of next GVS record       ;@T2
       imul di,ax,Igvs_rec_sz   ;                                       ;@T2
       add  di,idata_sz         ;                                       ;@T2

       sub  eax,eax             ;Assume no error                        ;@T73
       .if  <ds:Igvs_count e 0> ;Make sure current process has          ;@T73
         push es:Ggvs_AddrHi    ; to the GVS segment (once per process) ;@T73
         call DOSGETSEG         ;                                       ;@T73
       .endif                   ;

       .if  <zero ax>           ;                                       ;@T73
         mov    es,es:Ggvs_AddrHi                                       ;@T73
         .repeat                                                        ;1.2
           mov  ax,di           ;AX <-- new INSTANCE segment size       ;1.2
           add  ax,Igvs_rec_sz  ;                                       ;1.2

           push ax              ;new segment size                       ;1.2
           push ds              ;segment to be grown                    ;1.2
           call DOSREALLOCSEG   ;grow INSTANCE for GVS storage          ;1.2

           .if  <zero ax>                                               ;@T73
             mov  ds:[di].Ireplaced,ax                                  ;1.2
             mov  ds:[di].Igvs_zero,ax                              ;1.2,@T73

             push eax           ;Address to ObjNameBuf              ;1.2,@T73
             push ax            ;ObjNameBufL (length in bytes)      ;1.2,@T73
             push es            ;sel:off to GVS module name             ;1.2
             push bx                                               ;@T14,@T73
             push ds            ;sel:off to GVS module handle           ;1.2
             push offset gvs_hand ; (returned)                      ;1.2,@T52
             call DOSLOADMODULE ;load the GVS dynamic-link module       ;1.2

             .if <zero ax>                                          ;@T2,1.2

               push ds:gvs_hand ;module handle                          ;1.2
               push es          ;sel:off to GVS entry proc. name        ;1.2
               lea  ax,[bx].Ggvs_ep                                 ;1.2,@T14
               push ax                                                  ;1.2
               push ds          ;sel:off to desc. (returned)            ;1.2
               push di                                                  ;1.2
               call DOSGETPROCADDR ;get addressabilty to GVS dynlink proc;1.2
             .endif                                                     ;1.2

             .if  <zero ax>                                             ;@T73
               mov  eax,dword ptr es:[bx].Ggvs_loest                ;1.2,@T73
               mov  dword ptr ds:[di].Igvs_loest,eax                ;1.2,@T73
;@T73          mov  ax,es:[bx].Ggvs_lo                                  ;1.2
;@T73          mov  ds:[di].Igvs_lo,ax                                  ;1.2
               mov  eax,dword ptr es:[bx].Ggvs_hi                   ;1.2,@T73
               mov  dword ptr ds:[di].Igvs_hi,eax                   ;1.2,@T73
;@T73          mov  ax,es:[bx].Ggvs_hiest                               ;1.2
;@T73          mov  ds:[di].Igvs_hiest,ax                               ;1.2

               add  di,Igvs_rec_sz ;DI points to next Igvs record       ;1.2
               add  bx,Ggvs_rec_sz ;BX points to next Cgvs record       ;1.2
               inc  ds:Igvs_count                                       ;1.2
;@T73          mov  ax,es:Ggvs_count                                    ;1.2
             .else
               mov  si,ds:Igvs_count                                    ;@T73
             .endif                                                     ;@T73
           .else                                                        ;@T73
             mov  si,ds:Igvs_count                                      ;@T73
           .endif                                                       ;@T73
         .until <si eq ds:Igvs_count>                                   ;1.2
       .endif                                                           ;@T73

       sub  di,Igvs_rec_sz                                              ;1.2
       mov  ds:Igvs_last,di                                             ;1.2

       pop  bx                  ;Restore caller's BX                    ;1.2
     .endif                                                             ;1.2

     push ds                    ;clear semaphore                        ;1.2
     push offset Igvs_ramsem                                        ;1.2;@T52
     call DOSSEMCLEAR                                                   ;1.2
   .endif                                                               ;1.2

   pop  si                      ;Restore caller's SI                    ;@T73

   mov  ax,common       ;ES <-- COMMON data selector                    ;1.2
   mov  es,ax           ;                                               ;1.2

   ret
vioattach endp

cseg    ends
        end     ;D549  VIOINIT
