;       SCCSID = @(#)vioreg.asm 6.6 92/02/29
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
        PAGE    58,132
        SUBTTL  VIOREGISTER, VIODEREGISTER
        TITLE   VIOREG.ASM
;******************************************************************************
;*******   C H A N G E       H I S T O R Y   **********************************
;******************************************************************************
;@A0= support for VIOREDRAWSIZE (DCR 85)
;     02-10-88
;$A0= zero-out data area grown by DOSREALLOCSEG
;     10-06-86 (7.62)
;$Z2= prevent VIOREGISTER fault on long modname when trace is ON
;     07-16-87
;$Z3= change for DOSEXITLIST (see \\design1\desup gateway \dcr111\dcr0018)
;     07-10-87
;$Z4= new System Trace support
;     06-04-87
;$Z5= create threads for registered PRTSC/PRTSCTOGGLE
;     06-04-87
;$Z6= FREE registered module in VIODEREGISTER
;     05-21-87
;$Z7= Add DOSEXITLIST routine VIOREGEXIT to VIOREGISTER sequence
;     05-12-87
;$Z8= Hold Signals while owning semaphore
;     05-11-87
;$Z9= disallow calls from DETACHed processes @@11
;     11-03-86
;%A0= disallow calls from Extended Screen Groups
;     07-30-87
;%A1= Use FS RAM sems instead of system sems
;     07-30-87
;%A2= Disallow VIOREGISTER between VIOPOPUP and VIOENDPOPUP
;     07-30-87
;P2778= Changes so that VioRedrawSize is unaffected by VioRegister
;       06-07-88
;P2964= Call vioattach from VioEndPopUp if caller's first VIO call
;       06-14-88
;1.1XX= return error code from DodLoadModule to caller.
;       08-03-88
;P3758= only registering PID can clear PrtSC/PrtScToggle mask bits
;       10-02-88
;MMIO= implement Memory Mapped I/O performance trace hooks
;      11-03-88
;P3647= Save and restore BX, SGDATA[currSG] offset
;      01-23-88
;@T2  = 04/03/89 TPL, Sizzle work, PTR B701685
;@T3  = 05/02/89 TPL, MMIO fix, PTR B702148
;@@TB7 = 04/20/89 PTR 701176 Change lt to b so compare is done correctly
;@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, Dynamic Trace
;@T9  = 08/26/89 TPL, Cleanup
;@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
;@T54 = 02/21/90 TPL, DCR 704 fix for MMIO support
;@T13 = 02/27/90 TPL, Fix multiple register/deregister requests, B711643
;@B45 = 03/09/90 WKB, Make ring 2, B711747 (SMG)
;@T13f= 03/20/90 TPL, @T13 fix, B711643
;@T14 = 03/20/90 TPL, Performance optimization work
;@B73 = 06/15/90 WKB, Correct error processing, B713842
;@B74 = 06/15/90 WKB, VioDeRegister returned incorrect code, B713847
;@B75 = 06/25/90 WKB, VioRegister range checking incorrect, B714035
;@T73 = 07/27/90 TPL, Code/data reduction/optimization and swap tune
;@B722219 = 06/14/91 WKB, B722219 - Give up timeslice as appropriate
;@B727455 = 09/28/91 WKB, B727455 - Allow DLL's with 8 character filenames
;@T80 = 02/06/92 TPL, Don't use the reserved register FS, B732479
;D549f= 02/26/92 TPL, B733601 DCR 549 regression
;@TAK = 03/06/93 T Kirschner, Defect 62883 VioRegister Trap.

.xlist
include error.inc
include error2.inc
include struc.inc
include infoseg.inc
include vioextrn.inc
include vioequ.inc
include avioequ.inc
include viomac.inc
include vioidata.inc
include viocdata.inc
;@T73 include viogdata.inc                                          ;1.2,@T73
.list
.386p                           ;D549

IFDEF MMIOPH                                                            ;DTBB1
EXTRN   viopretrace:NEAR
EXTRN   vioposttrace:NEAR
ENDIF                                                                   ;DTBB1
EXTRN   DOSSLEEP:FAR                                                    ;B722219
EXTRN   DOSALLOCSEG:FAR
EXTRN   DOSCREATETHREAD:FAR
EXTRN   DOSFREESEG:FAR
EXTRN   AVS_PRTSC:FAR
EXTRN   AVS_PRTSCTOGGLE:FAR
EXTRN   DOSFSRAMSEMREQUEST:FAR                                          ;%A1I
EXTRN   DOSFSRAMSEMCLEAR:FAR                                            ;%A1I
EXTRN   DOSSMGETMEM:FAR                      ;Dos SesMgr Get Memory  D549
EXTRN   vioattach:NEAR                                                  ;P2964

public  VIOREGISTER
public  VIOREGISTER_POSTDT                                              ;DTBB1
public  VIODEREGISTER
public  VIODEREGISTER_POSTDT                                            ;DTBB1

instance segment byte public 'data' USE16                               ;D549
instance ends

common segment byte public 'far_data'   USE16                      ;D549;@T52
common ends

;@T73 global segment byte public 'far_data'   USE16             ;1.2;D549;@T52
;@T73 global ends                                                        ;1.2

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

        SUBTTL VIOREGISTER - REGISTER A VIDEO SUBSYSTEM
        page
;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: VIOREGISTER (not replaceable)                          */
;/*                                                                         */
;/* DESCRIPTIVE NAME: Register a video subsystem.                           */
;/*                                                                         */
;/* FUNCTION: Record the ASCIIZ module name, procedure name, and the        */
;/*           function mask for the current screen group.                   */
;/*                                                                         */
;/* NOTES: The length of the ASCIIZ string avs_MOD is limited to 128 bytes  */
;/*        The length of the ASCIIZ string avs_EP is limited to 32 bytes    */
;/*        If avs_MASK_HI and avs_MASK_LO both equal zero, then the         */
;/*        currently registered AKS module is deregistered (only the        */
;/*        registering process is allowed to deregister a subsystem).       */
;/*                                                                         */
;/* ENTRY POINT: VIOREGISTER                                                */
;/*     LINKAGE: FAR CALL (external API)                                    */
;/*                                                                         */
;/* INPUT: "avs_MOD" - pointer to AKS module's module name                  */
;/*        "avs_EP" - pointer to AKS module's entry procedure name          */
;/*        "avs_MASK_HI" - high-order VIO function MASK                     */
;/*        "avs_MASK_LO" - low-order VIO function MASK                      */
;/*                                                                         */
;/* EXIT-NORMAL: AX = NO_ERROR                                              */
;/*                                                                         */
;/* EXIT-ERROR: AX = ERROR_VIO_REGISTER - VIOREGISTER disallowed            */
;/* @B73        AX = ERROR_VIO_ILLEGAL_DURING_POPUP - VIOREGISTER disallowed*/
;/*             AX = ERROR_VIO_INVALID_MASK - invalid func. replaced        */
;/*             AX = ERROR_VIO_INVALID_ASCIIZ - invalid ASCIIZ length       */
;/*             AX = error code from DOSGETPROCADDR                         */
;/*             AX = error code from DOSLOADMODULE                          */
;/*                                                                         */
;/* EFFECTS: The contents of AX are destroyed.  Also, this call does not    */
;/*          load the video subsystem load module.  The module will be      */
;/*          loaded for each process in the current screen group at the     */
;/*          time it makes its first VIOxxx function call (other than       */
;/*          VIOREGISTER).                                                  */
;/* 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    */
;/*             currPID - current process's ID (LDTINFO:0)                  */
;/*             currSG - current process's screen group (LDTINFO:8)         */
;/*             LDTINFO - local info data segment selector                  */
;/*             GDTINFO - global info data segment selector                 */
;/*             SGDATA[currSG].MASK_HI - high-order VIO function mask       */
;/*             SGDATA[currSG].MASK_LO - low-order VIO function mask        */
;/*             SGDATA[currSG].MODULE -  video subsystem module name        */
;/*             SGDATA[currSG].ENTRY_PT - AKS entry procedure name          */
;/*             SGDATA[currSG].TIMES - number of VIOREGISTERs for this SG   */
;/*             SGDATA[currSG].PID - registering PID                        */
;/*             SGPIDSEM - system synchronization sem. name                 */
;/*             SGPIDSYNC - currSG's exclusive system sem. handle           */
;/*   ROUTINES: GETINFOSEGS                                                 */
;/* EXTERNAL                                                                */
;/* REFERENCES: None.                                                       */
;/*   ROUTINES: DOSGETPROCADDR - get addressability to dynamic-link module  */
;/*             DOSLOADMODULE - load dynamic-link module                    */
;/*             DOSOPENSEM - open an existing system semaphore              */
;/*             DOSSEMCLEAR - clear/release a semaphore                     */
;/*             DOSSEMREQUEST - request/obtain a semaphore                  */
;/*             DOSSMGETMEM - get memory from Session Manager               */
;/*********************** END OF SPECIFICATIONS *****************************/

VIOREGISTER proc far

   xor   ax,ax          ;preset AX = NO_ERROR
   push  fc_register    ;VIOREGISTER function code
   push  ax             ;dummy nearIP                                   ;@T2
   push  ds             ;save registers
   enter 10,0           ;make stack look like viorout's (use BP)        ;1.2
   push  gs                                                        ;D549,@T80
   push  es             ;save registers
   pusha

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

   mov  es,ds:ldtinfo           ;currSG <-- current screen group
   mov  ax,es:[LIS_CurScrnGrp]  ;
   mov  ds:currSG,ax            ;
   mov  al,es:[LIS_ProcType]    ;procTYPE <-- current process type      ;@T14
   cbw                          ;                                       ;@T14
   mov  ds:procTYPE,ax          ;                                       ;@T14

   .repeat
     push common                ;clear register synch.                  ;@T14
     push offset regramsem      ;RAM semaphore                          ;@T52
;@T73push wait_hi               ;no timeout
     push dword ptr wait_lo     ;
     call DOSSEMREQUEST         ;request REGISTER semaphore
   .until <ax ne ERROR_INTERRUPT>

   IFDEF MMIOPH                                                         ;@T9
   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> near

     mov   al,byte ptr es:[SIS_MEC_TABLE]       ;AL <-- MMIO MEC byte   ;MMIO
     test  al,40h                               ;0=OFF, non-0=ON   ;MMIO,@T3

     .if <nz>                   ;is Performance Trace enabled?          ;MMIO
       mov  es,ds:mmio_sel                                              ;MMIO
       mov  es:[4],mmPREregister                                        ;MMIO
     .endif                                                             ;MMIO

   .endif
   ENDIF                                                                ;@T9

   .if <ds:currSG eq 3>         ;if called from POPUP SG
     mov  [bp].rout_savAX,ERROR_VIO_ILLEGAL_DURING_POPUP                ;@B73
  ;;;mov  [bp].rout_savAX,ERROR_VIO_REGISTER                            ;@B73
   .elseif <ds:procTYPE eq LIS_PT_DETACHED>
     mov  [bp].rout_savAX,ERROR_VIO_DETACHED
   .elseif <ds:procTYPE a LIS_PT_FULLSCRN>                              ;@T14
     mov  [bp].rout_savAX,ERROR_VIO_EXTENDED_SG
   .else near
     lgs  bx,ds:SGCB            ;load with SGCB ptr                 ;D549,@T80

;    mov  ax,global             ;ES <-- GLOBAL data selector        ;1.2,@T73
;    mov  es,ax                 ;                                   ;1.2,@T73

     mov  dx,common             ;ES <-- common data selector            ;@T2,D549
     mov  es,dx                 ;restore ES to COMMON                   ;@T2

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

     .if <ax ne ds:Igvs_count>  ;INSTANCE count != GLOBAL count         ;1.2
       call  vioattach          ;then attach to new GVS's               ;1.2
     .endif                                                             ;1.2

     push 0C001H                ;add routine to DOSEXITLIST             ;@T13
    ;push cs                    ;sel:off to VIOREGEXIT routine          ;@T13
     mov  ax,cs                 ;ring 2                                 ;@B45
     or   ax,3                  ;                                       ;@B45
     push ax                    ;                                       ;@B45
     push offset VIOREGEXIT     ;                                       ;@T13
     call DOSEXITLIST           ;                                       ;@T13

     sub eax,eax                                                        ;@T14
     .if <<dword ptr gs:[bx].VIO_maskloest> eq eax> near and  ;D549,@T14,@T80
     .if <<dword ptr gs:[bx].VIO_maskhi>    eq eax> near      ;D549,@T14,@T80
       ;********************************************************************
       ; if no AVS has already been registered
       ;********************************************************************

       .if <<word ptr [bp].reghi>    b 0200H> near and                  ;@B75
       .if <<word ptr [bp].reghiest> b  masklastplus1> near and   ;@@TB7
       .if <<dword ptr [bp].regloest> ne eax> near or                   ;@T14
       .if <<dword ptr [bp].reghi>    ne eax> near                      ;@T14
         ;******************************************************************
         ; check for valid function call replaced
         ;******************************************************************

         push ds                        ;save DS
         lds  si,dword ptr [bp].regmodoff ;DS:SI --> module name        ;@T14
         xor  cx,cx                     ;initialize CX counter
         cld

         .repeat                        ;validate module name length
           lodsb
           inc  cx
         .until <al eq 00H> or
         .until <cx eq mod_len_max+1>   ;Plus 1 for up to 8 char + NULL @B727455

         mov  dx,cx                     ;save length of module name     ;D549f
;DON'T DESTROY DX ************************ D549

         pop  ds                        ;restore DS

         .if <al eq 00H> near and
         .if <cx gt 0001H> near
           push ds                      ;save DS
           lds  si,dword ptr [bp].regepoff ;DS:SI --> entry proc. name  ;@T14
           xor  cx,cx
           cld

           .repeat                      ;validate entry proc. name length
             lodsb
             inc  cx
           .until <al eq 00H> or
           .until <al eq ' '> or                                        ;D549f
           .until <cx eq ep_len_max+1>  ;up to 32 characters + NULL   @B727455

           mov  si,cx                   ;save entry proc. name length   ;D549f
           pop  ds                      ;restore DS

           .if <al eq 00H> near
;            cbw                        ;Clear AX                       ;@T2@TAK
             lea  eax, tkbuf            ;Object name buffer address     ;@TAK
             push eax                   ;Address of ObjNameBuf      ;@T2,@T73
             push tkbuflen              ;ObjNameBufL                    ;@TAK
;            push ax                    ;ObjNameBufL                    ;@T2@TAK
             push dword ptr [bp].regmodoff                              ;@T73
             push ds                    ;push descriptor to AVS module
             push offset avs_hand       ; handle (returned)             ;@T52
             call DOSLOADMODULE         ;load AVS module

             mov  [bp].rout_savAX,ax                                    ;1.1XX

             .if <zero ax> near                                         ;@T2
               push ds:avs_hand         ;push AVS module handle
               push dword ptr [bp].regepoff                             ;@T73
               push ds                  ;push descriptor to AVS
               push offset avs_off      ; descriptor (returned)         ;@T52
               call DOSGETPROCADDR      ;get entry proc. address

               mov  [bp].rout_savAX,ax

               .if <zero ax>    near                                    ;@T2

                 ;*************************************************************
                 ; allocate memory for AVS control block
                 ;*************************************************************
                 push gs                  ;address of avscb ptr    ;D549,@T80
                 lea  ax,gs:[bx].VIO_avscbptr                      ;D549,@T80
                 push ax                                                ;D549
                 push avsSZ               ;size of avscb           ;D549,@T14
                 call DOSSMGETMEM         ;get memory from SesMgr       ;D549
                 mov  [bp].rout_savAX,ax                                ;D549

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

                 .if <<word ptr [bp].rout_savAX> eq NO_ERROR> near
                   ;*********************************************************
                   ; serialize using SG semaphore
                   ;*********************************************************

                   push 1               ;disable signals
                   call DOSHOLDSIGNAL   ;

                   .repeat
                     push dword ptr ds:fsRAMoff                         ;@T14
                     push dword ptr wait_lo                             ;@T73
                     call DOSFSRAMSEMREQUEST
                   .until <ax ne ERROR_INTERRUPT>
                   mov  [bp].rout_savAX,ax

                   push common                  ;clear register synch.
                   push offset regramsem        ;RAM semaphore          ;@T52
                   call DOSSEMCLEAR             ;release REGISTER semaphore

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

                     ;*********************************************************
                     ; setup function call replacement masks
                     ;*********************************************************
                     mov  ax,[bp].regloest    ;fill in function mask
                     mov  gs:[bx].VIO_maskloest,ax                 ;D549,@T80

                     mov  cx,ax         ;use DX as target             ;@T8,D549
                     shr  ch,1          ;get rid of VioShowBuf bit (8);@T8,D549
                     and  al,07h        ;preserve bits 0, 1 and 2     ;@T8
                     and  cl,0E0h       ;preserve bits 5, 6 and 7     ;@T8,D549
                     shr  cx,2          ;strip off bits 3 and 4       ;@T8,D549
                     or   cl,al         ;restore bits 0, 1 and 2      ;@T8,D549

                     mov  ax,[bp].reglo       ;
                     mov  gs:[bx].VIO_masklo,ax                  ;D549,@T80

                     ror  ax,3          ;rotate 1st 3 bits to the end ;@T8
                     and  ax,0E000h     ;preserve the bits rotated    ;@T8
                     or   cx,ax                                       ;@T8,D549
                     mov  ds:avs_bvs_bits,cx      ;BVS mask           ;@T8,D549
                     mov  gs:[bx].VIO_bvs_mask,cx              ;@T8;D549,@T80

                     mov  eax,dword ptr [bp].reghi                      ;@T73
                     mov  dword ptr gs:[bx].VIO_maskhi,eax    ;D549,@T73,@T80
;@T73                mov  ax,[bp].reghiest    ;
;@T73                mov  gs:[bx].VIO_maskhiest,ax                      ;D549

                     ;*********************************************************
                     ; copy module and entry procedure names into AVSCB
                     ;*********************************************************
                     push di                  ;save offset to AVSCB     ;D549
                     add  di,modname          ;ES:DI = mod. name dest   ;D549

                     push ds                  ;save DS
                     mov  ax,si               ;AX = proc name length    ;D549f
                     lds  si,dword ptr [bp].regmodoff ;DS:SI --> mod name ;@T14
                     cld

;D549f               xor  cx,cx               ;zero CX                  ;D549
                     mov  cx,dx               ;setup mod name size      ;D549f
                     rep  movsb               ;fill in AVS module name  ;D549

                     pop  ds                  ;restore DS

                     pop  di                  ;restore avscb offset     ;D549
                     push di                  ;save avscb offset again  ;D549
                     add  di,epname           ;ES:DI=entry name dest    ;D549
                     push ds                  ;save DS
                     lds  si,dword ptr [bp].regepoff ;DS:SI --> entry name ;@T14
                     cld

                     mov  cx,ax               ;setup ep name size       ;D549f
                     rep  movsb               ;fill in AVS entry proc.  ;D549
;**** OK to use DX ***************D549                                     D549

                     pop  ds                  ;restore DS
                     pop  di                  ;restore offset to avscb  ;D549

                     inc  gs:[bx].VIO_times   ;INC nmbr of REGISTERs ;D549,@T80

                     mov  ax,ds:currPID       ;save PID of caller (only
                     mov  es:[di].reg_pid,ax  ;PID able to deregister)  ;D549,@T14

                     mov  ax,maskprtsc
                     add  ax,maskprtsctoggle
                     and  ax,[bp].reglo
                     push ax            ;save it for next few lines

                     .if <nonzero ax>  near   ;if prtsc/prtsctoggle registered
                       and  ax,maskprtsc

                       .if <nonzero ax>                                 ;@T2
                         ;****************************************************
                         ; if prtsc registered, create AVS_PTRSC thread
                         ;****************************************************

                         push 1000H       ;4K stack for prtsc thread ;@T11,D549
                         push ds          ;sel:off for new selector
                         push offset prtsc_SSsel                        ;@T52
                         push 0           ;NON-shared
                         call DOSALLOCSEG
                         mov  [bp].rout_savAX,ax

                         .if <zero ax>                                  ;@T2

                           push  es             ;RAMsem handle          ;@T13
                           lea   ax,[di].ps_enter                       ;@T13
                           push  ax             ;                       ;@T13
                           call  DOSSEMSET      ;set RAM sem            ;@T13

                           push cs              ;CS:IP for thread to
                           push offset AVS_PRTSC; begin execution
                           push es              ;sel:off for thread ID
                           lea  ax,es:[di].psThID                       ;D549
                           push ax              ;
                           push ds:prtsc_SSsel  ;stack is 4K starting
                           push 0FFFH           ; at 0FFF-0             ;D549
                           call DOSCREATETHREAD
                           mov  [bp].rout_savAX,ax
                         .endif

                       .endif

                       .if <zero ax>                                    ;@T2
                         pop  ax        ;retrieve AX from stack
                         push ax        ;
                         and  ax,maskprtsctoggle

                         .if <ax eq maskprtsctoggle>
                           ;****************************************************
                           ; prtsctoggle registered, create AVS_PTRSCTOGGLE thrd
                           ;****************************************************

                           push 1000H          ;4K stack for prtsctog stk;@T11;D549
                           push ds             ;sel:off for selector
                           push offset prtsctog_SSsel                   ;@T52
                           push 0              ;NON-shared
                           call DOSALLOCSEG
                           mov  [bp].rout_savAX,ax

                           .if <zero ax>                                ;@T2

                             push  es             ;RAMsem handle        ;@T13
                             lea   ax,[di].pstog_enter                  ;@T13
                             push  ax             ;                     ;@T13
                             call  DOSSEMSET      ;set RAM sem          ;@T13

                             push cs              ;CS:IP for thread to
                             push offset AVS_PRTSCTOGGLE; begin exec.
                             push es              ;sel:off for thrd ID
                             lea  ax,es:[di].pstogThiD                  ;D549
                             push ax              ;
                             push ds:prtsctog_SSsel ;stack is 4K
                             push 0FFFH           ; starting at FFF-0     ;D549
                             call DOSCREATETHREAD
                             mov  [bp].rout_savAX,ax

                             xor  ax,ax               ;good return
                           .else
                             ;************************************************
                             ;ERROR - kill AVS_PRTSC thread and wait until
                             ;before freeing memory for AVSCB             ;D549
                             ;************************************************

                             mov  es:[di].prtscAX,0FFFFH ;signal to kill;D549
                                                         ;itself
                             push es                                    ;D549
                             lea  ax,es:[di].ps_exit  ;cleared when     ;D549
                             push ax                  ;prtsc thread gone;D549
                             call DOSSEMSET                             ;D549

                             ;************************************************
                             ;clear prtsc enter semaphore so it will execute
                             ;and see prtscax = -1 to kill itself       ;D549
                             ;************************************************
                             push es                                    ;D549
                             lea  ax,es:[di].ps_enter                   ;D549
                             push ax                                    ;D549
                             call DOSSEMCLEAR

                             .repeat                                    ;D549
                               push es                                  ;D549
                               lea  ax,es:[di].ps_exit                  ;D549
                               push ax                                  ;D549
                               push dword ptr -1                   ;D549,@T73
                               call DOSSEMWAIT                          ;D549
                             .until <ax ne ERROR_INTERRUPT>             ;D549
                           .endif

                         .else
                           xor  ax,ax           ;AX <-- NO_ERROR
                         .endif

                       .else                    ;createthread failed free SS mem
                         push ds:prtsc_SSsel    ;free AVS_PRTSC's
                         call DOSFREESEG        ; stack segment
                       .endif

                     .endif

                     add  sp,2  ;remove AX from stack
                     .if <<word ptr [bp].rout_savAX> ne NO_ERROR>
                       ;******************************************************
                       ; AVS register failed, clear replaced mask & free AVSCB
                       ;******************************************************

                       sub  eax,eax                                     ;@T14
                       mov  dword ptr gs:[bx].VIO_maskloest,eax ;clears ;@T14,@T80
                       mov  dword ptr gs:[bx].VIO_maskhi,eax    ; masks ;@T14,@T80
                       dec  gs:[bx].VIO_times   ;INC nmbr of REGISTERs  ;D549,@T80

                       push gs                  ;free AVSCB memory  ;D549,@T80
                       lea  ax,gs:[bx].VIO_avscbptr                 ;D549,@T80
                       push ax                                           ;D549
                       call DOSSMFREEMEM        ;free memory from SesMgr ;D549
                       mov  dword ptr gs:[bx].VIO_avscbptr,eax ;D549,@T14,@T80

                     .endif

                   .endif

                 .endif                 ;if NO_ERROR from DOSREALLOCSEG

               .endif                   ;if NO_ERROR from DOSGETPROCADDR

               mov  ds:avs_sel,0000H    ;reset AVS_SEL field
               push ds:avs_hand         ;free AKS module
               call DOSFREEMODULE       ;
             .endif                     ;if NO_ERROR from DOSLOADMODULE

           .else
             mov  [bp].rout_savAX,ERROR_VIO_INVALID_ASCIIZ
           .endif       ;if 0 < length of epname < ep_len_max
         .else
           mov  [bp].rout_savAX,ERROR_VIO_INVALID_ASCIIZ
         .endif         ;if 0 < length of modname < mod_len_max
       .else
         mov  [bp].rout_savAX,ERROR_VIO_INVALID_MASK
       .endif           ;if valid masks

     .else
       mov  [bp].rout_savAX,ERROR_VIO_REGISTER
     .endif             ;if AVS not currently registered

   .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
     mov  ax,common                                                     ;1.2
     mov  es,ax                                                         ;1.2

     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 compare   ;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                                                       ;D549,@T80
     leave                                                              ;1.2

     mov   ds:gvs_cntr,0    ;reset gvs_cntr                             ;1.2

     .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                                              ;1.2

       .if <ax eq ds:Igvs_count>                                        ;1.2
         mov  ds:Igvs_quit,1                                            ;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                                                      ;D549,@T80
     push  es                                                           ;1.2
     pusha                                                              ;1.2
   .endif                                                               ;1.2

   .if <ds:procTYPE e LIS_PT_FULLSCRN>  ;Only clear if full screen      ;@T14
     push dword ptr ds:fsRAMoff ;clear FS RAM sem                       ;@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                                                               ;@T14

   push common          ;clear register synch.                          ;D549
   push offset regramsem;RAM semaphore                                  ;@T52
   call DOSSEMCLEAR     ;

   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               ;AL=0 => off,  AL<>0 => on

   .if <nz>
     call vioposttrace    ;post invocation call to system trace
   .endif
   ENDIF                                                                ;DTBB1

   popa
   pop   es
   pop   gs                                                        ;D549,@T80
   leave
   pop   ds
   add   sp,4           ;remove dummy IP and function code
VIOREGISTER_POSTDT label far                                            ;DTBB1
   ret   16             ;return and pop parameters
VIOREGISTER endp

        SUBTTL VIODEREGISTER - DEREGISTER A VIDEO SUBSYSTEM
        page
;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: VIODEREGISTER (not replaceable)                        */
;/*                                                                         */
;/* DESCRIPTIVE NAME: Deregister a video subsystem.                         */
;/*                                                                         */
;/* FUNCTION: Reset the ASCIIZ module name, procedure name, and the         */
;/*           function mask for the current screen group.                   */
;/*                                                                         */
;/* NOTES: If the process issuing a VIODEREGISTER call is not the same      */
;/*        process that successfully issued a VIOREGISTER call, it will     */
;/*        receive an error return code.                                    */
;/*                                                                         */
;/* ENTRY POINT: VIODEREGISTER                                              */
;/*     LINKAGE: FAR CALL (external API)                                    */
;/*                                                                         */
;/* INPUT: None.                                                            */
;/*                                                                         */
;/* EXIT-NORMAL: AX = NO_ERROR                                              */
;/*                                                                         */
;/* EXIT-ERROR: AX = ERROR_VIO_DEREGISTER - VIODEREGISTER disallowed        */
;/*                                                                         */
;/* EFFECTS: The contents of AX are destroyed.                              */
;/*                                                                         */
;/* 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    */
;/*             currPID - current process's ID (LDTINFO:0)                  */
;/*             currSG - current process's screen group (LDTINFO:8)         */
;/*             LDTINFO - local info data segment selector                  */
;/*             GDTINFO - global info data segment selector                 */
;/*             SGDATA[currSG].MASK_HIEST - high-order VIO function mask    */
;/*             SGDATA[currSG].MASK_HI - high-order VIO function mask       */
;/*             SGDATA[currSG].MASK_LO - low-order VIO function mask        */
;/*             SGDATA[currSG].MASK_LOEST - low-order VIO function mask     */
;/*             SGDATA[currSG].MODULE -  video subsystem module name        */
;/*             SGDATA[currSG].ENTRY_PT - AKS entry procedure name          */
;/*             SGDATA[currSG].REG_PID - registering PID                @T14*/
;/*             SGPIDSEM - system synchronization sem. name                 */
;/*             SGPIDSYNC - currSG's exclusive system sem. handle           */
;/*   ROUTINES: getinfosegs                                                 */
;/*                                                                         */
;/* EXTERNAL                                                                */
;/* REFERENCES: None.                                                       */
;/*   ROUTINES: DOSOPENSEM - open an existing system semaphore              */
;/*             DOSSEMCLEAR - clear/release a semaphore                     */
;/*             DOSSEMREQUEST - request/obtain a semaphore                  */
;/*             DOSSMFREEMEM - free memory from Session Manager             */
;/*********************** END OF SPECIFICATIONS *****************************/

VIODEREGISTER proc far
   xor   ax,ax          ;preset AX = NO_ERROR
   push  fc_deregister  ;VIODEREGISTER function code
   push  0              ;dummy nearIP
   push  ds             ;save registers
   enter 10,0           ;make stack look like viorout's (use BP)        ;1.2
   push  gs                                                        ;D549,@T80
   push  es             ;save registers
   pusha

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

   mov  es,ds:ldtinfo           ;currSG <-- current screen group
   mov  ax,es:[LIS_CurScrnGrp]  ;
   mov  ds:currSG,ax            ;
   mov  al,es:[LIS_ProcType]    ;procTYPE <-- current process type      ;@T14
   cbw                          ;                                       ;@T14
   mov  ds:procTYPE,ax          ;

   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 viopretrace
   .endif
   ENDIF                                                                ;DTBB1

   .if <ds:procTYPE eq LIS_PT_DETACHED>
     mov  [bp].rout_savAX,ERROR_VIO_DETACHED
   .elseif <ds:procTYPE ne LIS_PT_FULLSCRN>
     mov  [bp].rout_savAX,ERROR_VIO_EXTENDED_SG
   .else  near                                                          D549

     lgs  bx,ds:SGCB                                               ;D549,@T80

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

;    mov  ax,global             ;ES <-- GLOBAL data selector        ;1.2,@T73
;    mov  es,ax                 ;                                   ;1.2,@T73

     mov  dx,common             ;ES <-- common data selector        ;@T2,D549
     mov  es,dx                 ;restore ES to COMMON                   ;@T2

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

     .if <ax ne ds:Igvs_count>  ;INSTANCE count != GLOBAL count         ;1.2
       call  vioattach          ;then attach to new GVS's               ;1.2
     .endif                                                             ;1.2

     .repeat
       push dword ptr ds:fsRAMoff       ;request fsRAMsem               ;@T14
;@T73  push wait_hi                     ;no timeout (wait indefinitely)
       push dword ptr wait_lo           ;                               ;@T73
       call DOSFSRAMSEMREQUEST
     .until <ax ne ERROR_INTERRUPT>

     .if  <gs:[bx].VIO_avscbptr ne 00> and near ;check that AVS in effect;D549,@T80
     les  di,gs:[bx].VIO_avscbptr                                   ;D549,@T80
     mov  ax,es:[di].reg_pid    ;AX <-- PID that last VIOREGISTERed ;D549,@T14

     .if <ax eq ds:currPID> near

       mov  dx,gs:[bx].VIO_masklo  ;get mask for prtsc and prtsctoggle ;@T13,@T80

       .if  <BIT dx and maskprtsc> ;if prtsc registered                  ;@T13
         mov  es:[di].prtscAX,-1   ;signal PRTSC thread to kill itself   ;D549

         push es                   ;need to wait until prtsc thread is   ;D549
         lea  ax,es:[di].ps_exit   ;gone before freeing memory for AVSCB ;D549
         push ax                   ;so set prtsc exit semaphore          ;D549
         call DOSSEMSET                                                  ;D549

         push es                   ;clear prtsc enter semaphore so it will
         lea  ax,es:[di].ps_enter  ;execute and see prtscax = -1 to kill
         push ax
         call DOSSEMCLEAR

         .repeat                                                          ;D549
           push es                 ;wait till prtsc thread is finished    ;D549
           lea  ax,es:[di].ps_exit                                        ;D549
           push ax                                                        ;D549
;@T73      push 0FFFFH                                                    ;D549
           push dword ptr -1                                         ;D549,@T73
           call DOSSEMWAIT                                                ;D549
         .until <ax ne ERROR_INTERRUPT>                                   ;D549

         push ds:prtsc_SSsel          ;free AVS_PRTSC's stack segment     ;D549
         call DOSFREESEG                                                  ;D549
       .endif                                                             ;D549

       .if  <BIT dx and maskprtsctoggle> ;if prtsctoggle registered       ;@T13
         mov  es:[di].prtsctogAX,-1  ;signal PRTSCTOGGLE to kill itself   ;D549

         push es                    ;need to wait until prtsc thread is   ;D549
         lea  ax,es:[di].pstog_exit ;gone before freeing memory for AVSCB ;D549
         push ax                    ;so set prtsc exit semaphore          ;D549
         call DOSSEMSET                                                   ;D549

         push es                     ;clear prtsc enter semaphore so it will
         lea  ax,es:[di].pstog_enter ;execute and see prtscax = -1 to kill;D549
         push ax
         call DOSSEMCLEAR

         .repeat                                                          ;D549
           push es                 ;wait till prtsc thread is finished    ;D549
           lea  ax,es:[di].pstog_exit                                     ;D549
           push ax                                                        ;D549
;@T73      push 0FFFFH                                                    ;D549
           push dword ptr -1                                         ;D549,@T73
           call DOSSEMWAIT                                                ;D549
         .until <ax ne ERROR_INTERRUPT>                                   ;D549

         push ds:prtsctog_SSsel       ;free AVS_PRTSCTOGGLE's stack seg   ;D549
         call DOSFREESEG                                                  ;D549
       .endif                                                             ;D549

       push es                        ;free AVSCB memory                 ;D549
       push di                                                           ;D549
       call DOSSMFREEMEM              ;free memory from SesMgr           ;D549

       sub  eax,eax                                                      ;@T13
       mov  gs:[bx].VIO_avscbptr,eax  ;zero avscb ptr          ;D549,@T13,@T80

       mov  dword ptr gs:[bx].VIO_maskloest,eax ;clear function mask ;D549,@T13,@T80
       mov  dword ptr gs:[bx].VIO_maskhi,eax                    ;D549,@T13,@T14,@T80
       inc  gs:[bx].VIO_times         ;force VIOATTACH on next call;D549,@T13,@T80
       mov  ds:avs_bvs_bits,ax        ;clear BVS notification bits  ;@T8,@T13
     .else
       .if <ds:currSG eq 3>                                             ;@B74
          mov  [bp].rout_savAX,ERROR_VIO_ILLEGAL_DURING_POPUP           ;@B74
       .else                                                            ;@B74
          mov  [bp].rout_savAX,ERROR_VIO_DEREGISTER
       .endif                                                           ;@B74
     .endif

   .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
     mov  ax,common                                                     ;1.2
     mov  es,ax                                                         ;1.2

     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 compare   ;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                                                       ;D549,@T80
     leave                                                              ;1.2

     mov   ds:gvs_cntr,0    ;reset gvs_cntr                             ;1.2

     .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                                              ;1.2

       .if <ax eq ds:Igvs_count>                                        ;1.2
         mov  ds:Igvs_quit,1                                            ;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                                                      ;D549,@T80
     push  es                                                           ;1.2
     pusha                                                              ;1.2
     mov   ax,common                                                    ;1.2
     mov   es,ax                                                        ;1.2
   .endif                                                               ;1.2

   .if <ds:procTYPE e LIS_PT_FULLSCRN>  ;Only clear if full screen      ;@T14
     push dword ptr ds:fsRAMoff ;clear FS RAM sem                       ;@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                                                               ;@T14

   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               ;AL=0 => off,  AL<>0 => on

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

   popa
   pop   es
   pop   gs                                                        ;D549,@T80
   leave
   pop   ds
   add   sp,4           ;remove dummy IP and function code
VIODEREGISTER_POSTDT label far                                          ;DTBB1
   ret                  ;return
VIODEREGISTER endp


VIOREGEXIT proc far                                                     ;@T13
  public   VIOREGEXIT                                                   ;@T13

  push es                       ;save registers                         ;@T13
  push ds                       ;                                       ;@T13
  push gs                       ;                                  ;@T13,@T80
  push bx                       ;                                       ;@T13
  push di                       ;                                       ;@T13

  mov  ax,instance              ;DS <-- INSTANCE data selector          ;@T13
  mov  ds,ax                    ;                                       ;@T13
  mov  ax,common                ;ES <-- COMMON data selector            ;@T13
  mov  es,ax                    ;                                       ;@T13

  push 2                        ;remove routine from DOSEXITLIST        ;@T13
 ;push cs                       ;sel:off to VIOREGEXIT routine          ;@T13
  mov  ax,cs                    ;ring 2                                 ;@B45
  or   ax,3                     ;                                       ;@B45
  push ax                       ;                                       ;@B45
  push offset VIOREGEXIT        ;                                       ;@T13
  call DOSEXITLIST              ;                                       ;@T13

  lgs  bx,ds:SGCB                                                  ;@T13,@T80

  .repeat                                                               ;@T13
    push dword ptr ds:fsRAMoff  ;request FS RAM sem                ;@T13,@T14
;   push wait_hi                ;no timeout (wait indefinitely)    ;@T13,@T73
    push dword ptr wait_lo      ;                                  ;@T13,@T73
    call DOSFSRAMSEMREQUEST                                             ;@T13
  .until <ax ne ERROR_INTERRUPT>                                        ;@T13

  .if  <gs:[bx].VIO_avscbptr ne 00> and  ;check that AVS in effect ;@T13,@T80
  les  di,gs:[bx].VIO_avscbptr                                     ;@T13,@T80
  mov  ax,es:[di].reg_pid       ;AX <-- PID that last VIOREGISTERed;@T13,@T14

  .if <ax eq ds:currPID>                                                ;@T13

    mov  ax,gs:[bx].VIO_masklo  ;get mask for prtsc and prtsctoggle;@T13,@T80

    .if  <BIT ax and maskprtsc> ;if prtsc registered                    ;@T13
      mov  es:[di].prtscAX,-1   ;signal PRTSC thread to kill itself     ;@T13

      push es                   ;clear prtsc enter semaphore so it will ;@T13
      lea  ax,es:[di].ps_enter  ;execute and see prtscax = -1 to kill   ;@T13
      push ax                                                           ;@T13
      call DOSSEMCLEAR                                                  ;@T13
    .endif                                                              ;@T13

    .if  <BIT ax and maskprtsctoggle> ;if prtsctoggle registered        ;@T13
      mov  es:[di].prtsctogAX,-1  ;signal PRTSCTOGGLE to kill itself    ;@T13

      push es                     ;clear prtsc enter semaphore          ;@T13
      lea  ax,es:[di].pstog_enter ;                                     ;@T13
      push ax                                                           ;@T13
      call DOSSEMCLEAR                                                  ;@T13
    .endif                                                              ;@T13

;   push gs                        ;free AVSCB memory             ;@T13f,@T80
;   lea  ax,gs:[bx].VIO_avscbptr                                  ;@T13f,@T80
;   push ax                                                             ;@T13f
;   call DOSSMFREEMEM              ;free memory from SesMgr             ;@T13f

    sub  ax,ax                                                          ;@T13f
;   mov  gs:[bx].VIO_avscbptr,eax  ;zero avscb ptr                ;@T13f,@T80

;   mov  gs:[bx].VIO_maskloest,ax  ;reset VIO function mask             ;@T13f
    and  gs:[bx].VIO_masklo,not (maskprtsc + maskprtsctoggle)     ;@T13f,@T80
;   mov  gs:[bx].VIO_maskhi,ax                                          ;@T13f
;   mov  gs:[bx].VIO_maskhiest,ax                                       ;@T13f
;   inc  gs:[bx].VIO_times         ;force VIOATTACH on next call        ;@T13f
;   mov  ds:avs_bvs_bits,ax        ;clear BVS notification bits         ;@T13f
  .endif                                                                ;@T13

  push dword ptr ds:fsRAMoff                                       ;@T13,@TL9
  call DOSFSRAMSEMCLEAR                                                 ;@T13

  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 common                   ;clear register synch.                  ;@T13
  push offset regramsem         ;RAM semaphore                          ;@T13
  call DOSSEMCLEAR              ;                                       ;@T13

  pop  di                                                               ;@T13
  pop  bx                       ;restore registers                      ;@T13
  pop  gs                       ;                                  ;@T13,@T80
  pop  ds                       ;                                       ;@T13
  pop  es                       ;                                       ;@T13

  push 3                        ;transfer control to next routine       ;@T13
 ;push cs                       ;sel:off to VIOREGEXIT routine          ;@T13
  mov  ax,cs                    ;ring 2                                 ;@B45
  or   ax,3                     ;                                       ;@B45
  push  ax                      ;                                       ;@B45
  push offset VIOREGEXIT        ;                                       ;@T13
  call DOSEXITLIST              ;                                       ;@T13
VIOREGEXIT endp                                                         ;@T13

cseg ends
     end
