;       SCCSID = @(#)vioglob.asm	6.2 92/02/13
;# SCCSID = @(#)vioglob.asm	6.2 92/02/13
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************
        PAGE    58,132
        SUBTTL  VIOGLOBALREG
        TITLE   VIOGLOB.ASM
;******************************************************************************
;*******   C H A N G E       H I S T O R Y   **********************************
;******************************************************************************
;???= public build entry
;     08-15-88
;@T2  = 04/03/89 TPL, Sizzle work, PTR B700???
;DTBB1= 08/21/89 WKB, Dynamic Trace
;D549 = 11/07/89 WKB, D549 Changes
;@T52 = 01/15/90 TPL, DCR 704 work
;@T14 = 03/28/90 TPL, Remove duplication of functions
;@T73 = 07/27/90 TPL, Code/data reduction/optimization and swap tune
;@T80 = 02/06/92 TPL, Don't use the reserved register FS, B732479

.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
.list
.386p                                                                   ;D549

EXTRN   DOSALLOCSEG:FAR
EXTRN   DOSCREATETHREAD:FAR
EXTRN   DOSFREESEG:FAR
EXTRN   DOSFSRAMSEMREQUEST:FAR
EXTRN   DOSFSRAMSEMCLEAR:FAR
EXTRN   DOSSMGETMEM:FAR                 ;Get memory from global pool    ;@T73
EXTRN   DOSSMFREEMEM:FAR                ;Free memory pool               ;@T73

public  VIOGLOBALREG
public  VIOGLOBALREG_POSTDT                                             ;DTBB1

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

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

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

        SUBTTL VIOGLOBALREG - REGISTER A GLOBAL VIDEO SUBSYSTEM
        page
;/*********************** START OF SPECIFICATIONS ***************************/
;/* SUBROUTINE NAME: VIOGLOBALREG (not replaceable)                         */
;/*                                                                         */
;/* DESCRIPTIVE NAME: Register a global video subsystem.                    */
;/*                                                                         */
;/* FUNCTION: Record the ASCIIZ module name, procedure name, and the        */
;/*           function mask in the global (common) data area.               */
;/*                                                                         */
;/* NOTES: The length of the ASCIIZ string gvs_MOD is limited to 8 bytes    */
;/*        The length of the ASCIIZ string gvs_EP is limited to 32 bytes    */
;/*                                                                         */
;/* ENTRY POINT: VIOGLOBALREG                                               */
;/*     LINKAGE: FAR CALL (external API)                                    */
;/*                                                                         */
;/* INPUT: "gvs_MOD" - pointer to GVS module's module name                  */
;/*        "gvs_EP" - pointer to GVS module's entry procedure name          */
;/*        "gvs_MASK_HI" - high-order VIO function MASK                     */
;/*        "gvs_MASK_LO" - low-order VIO function MASK                      */
;/*        "reserved" - DWORD field (must be 0)                             */
;/*                                                                         */
;/* EXIT-NORMAL: AX = NO_ERROR                                              */
;/*                                                                         */
;/* EXIT-ERROR: AX = ERROR_VIO_REGISTER - 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       */
;/*          VIOGLOBALREG).                                                 */
;/* INTERNAL                                                                */
;/* REFERENCES: gvs_HAND - global video subsystem module handle             */
;/*             gvs_OFF - global video subsystem entry proc. offset         */
;/*             gvs_SEL - global 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 - GVS entry procedure name          */
;/*             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                    */
;/*             DOSFSRAMSEMCLEAR - clear/release Fast-Safe semaphore        */
;/*             DOSFSRAMSEMREQUEST - request/obtain Fast-Safe semaphore     */
;/*********************** END OF SPECIFICATIONS *****************************/
;VioGlobalReg pseudo code:
;   request regRAMSEM(wait)
;
;   if RAS tracing enabled
;       call DosSysTrace(pre-invocation)
;
;   if parameters valid so far
;       call DosLoadModule
;
;       if NO_ERROR
;           call DosGetProcAddr
;
;           if NO_ERROR
;               grow COMMON data segment for parameter storage
;
;               DosHoldSignal
;               request sgFSRAMSEM(wait)
;               clear regRAMSEM
;
;               store function masks in global data
;               store ASCIIZ strings in global data
;
;               clear sgFSRAMSEM
;
;           call DosFreeModule
;
;   clear regRAMSEM
;
;   if RAS tracing enabled
;       call DosSysTrace(post-invocation)
;
VIOGLOBALREG proc far

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

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

   mov  es,ds:ldtinfo           ;currSG <-- current screen group
   mov  ax,es:[LIS_CurScrnGrp]  ;
   mov  ds:currSG,ax            ;

   .repeat
     push ds                    ;request GVS RAM semaphore
     push offset Igvs_ramsem    ;                                       ;@T52
     push dword ptr wait_lo     ;                                       ;@T73
     call DOSSEMREQUEST         ;
   .until <ax ne ERROR_INTERRUPT>

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

   .if <es:SHELLPID ne 0>   OR          ;disallowed if shell initialized;@T14
   .if <ds:currSG eq 3>                 ;OR if called from POPUP SG
     mov  [bp].rout_savAX,ERROR_VIO_REGISTER
   .elseif <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
   .elseif <<word ptr[bp].glob_rsrv0> ne 0> OR
   .if <<word ptr[bp].glob_rsrv2> ne 0>
     mov  [bp].rout_savAX,ERROR_VIO_INVALID_PARMS
   .else near
     sub  eax,eax                                                       ;@T73
     .if <<word ptr [bp].globhiest> lt maskgloblastplus1> near and
     .if <<dword ptr [bp].globlo>    ne eax> near or                    ;@T73
     .if <<dword ptr [bp].globhiest> ne eax> near                       ;@T73
       push eax                         ;Address of ObjNameBuf          ;@T73
       push ax                          ;ObjNameBufL                    ;@T73
       push dword ptr [bp].globmodoff   ; name                          ;@T73
       push ds                          ;far pointer to GVS module
       push offset gvs_hand             ; handle (returned)             ;@T52
       call DOSLOADMODULE

       mov  [bp].rout_savAX,ax

       .if <zero ax> near                                               ;@T2
         push ds:gvs_hand               ;GVS module handle
         push dword ptr [bp].globepoff  ;Address of procedure name      ;@T73
         push ds                        ;far pointer to GVS
         push offset gvs_off            ; descriptor (returned)         ;@T52
         call DOSGETPROCADDR

         mov  [bp].rout_savAX,ax

         .if <zero ax> near                                             ;@T2
           push ds                      ;                               ;@T73
           lds  si,dword ptr es:Ggvs_AddrLo                             ;@T73
           mov  bx,es:Ggvs_size         ;                               ;@T73
           mov  cx,bx                   ;Save current size in CX        ;@T73
           add  bx,Ggvs_rec_sz          ;BX -> new GVS segment size     ;@T73
           push es
           push offset Ggvs_AddrLo      ;Allocate a bigger chunk        ;@T73
           push bx                      ; to accommdate new size        ;@T73
           call DOSSMGETMEM             ;                               ;@T73

           mov  [bp].rout_savAX,ax

           .if  <zero ax>               ;                               ;@T73
             inc  es:Ggvs_count         ;Update client count            ;@T73
             mov  es:Ggvs_size,bx       ;Record new size                ;@T73

             les  di,dword ptr es:Ggvs_AddrLo                           ;@T73

             add  di,2                  ;Skip pass SubAlloc length word ;@T73
             mov  bx,di                 ;
             add  bx,cx                 ;ES:BX --> Start of new record  ;@T73

             .if  <ncxz>
               push ds                  ;Push DosSMFreeMem arguments    ;@T73
               push si                  ;                               ;@T73

               add  si,2                ;Skip pass SubAlloc length word ;@T73
               cwde                     ;Copy GVS record(s) into the    ;@T73
               shr  cx,2                ;Dword align for rep move       ;@T73
               rep  movsd               ; newly allocated memory block  ;@T73

               call DOSSMFREEMEM        ;Free the old memory block      ;@T73
             .endif

             mov  eax,dword ptr [bp].globloest  ;fill in function masks ;@T73
             mov  dword ptr es:[bx].Ggvs_loest,eax                      ;@T73
;@T73        mov  ax,[bp].globlo        ;
;@T73        mov  es:[bx].Ggvs_lo,ax    ;
             mov  eax,dword ptr [bp].globhi                             ;@T73
             mov  dword ptr es:[bx].Ggvs_hi,eax                         ;@T73
;@T73        mov  ax,[bp].globhiest     ;
;@T73        mov  es:[bx].Ggvs_hiest,ax ;

;@T73        push ds                    ;save DS
;@T73        mov  ds,[bp].globmodsel    ;DS:SI = module name            ;@T2
             lds  si,dword ptr [bp].globmodoff                          ;@T73
             mov  di,bx                 ;
;@T73        add  di,Ggvs_mod           ;
             cld

             .repeat                    ;fill in GVS module name
               lodsb                    ;
               stosb                    ;
             .until <al eq 00H>         ;

             mov  di,bx                 ;ES:DI=entry name dest
             add  di,Ggvs_ep            ;
;@T73        mov  ds,[bp].globepsel     ;DS:SI=entry proc name          ;@T2
             lds  si,dword ptr [bp].globepoff                           ;@T73
             cld

             .repeat                    ;fill in GVS entry proc.
               lodsb                    ;name
               stosb                    ;
             .until <al eq 00H>         ;

;@T73        pop  ds                    ;restore DS
;@T73        xor  ax,ax                 ;restore REALLOCSEG AX
           .endif
           pop  ds                                                      ;@T73
         .endif                 ;if NO_ERROR from DOSGETPROCADDR

         mov  ds:gvs_sel,0000H  ;reset GVS_SEL field
         push ds:gvs_hand       ;free GVS module
         call DOSFREEMODULE     ;
       .endif                   ;if NO_ERROR from DOSLOADMODULE

     .else
       mov  [bp].rout_savAX,ERROR_VIO_INVALID_MASK
     .endif           ;if valid masks

   .endif

   push ds                      ;clear GVS RAM semaphore
   push offset Igvs_ramsem      ;                                       ;@T52
   call DOSSEMCLEAR             ;

   popa
   pop   es
   pop   gs                                                             ;@T80
   leave
   pop   ds
   add   sp,4           ;remove dummy IP and function code
VIOGLOBALREG_POSTDT label far                                           ;DTBB1
   ret   20             ;return and pop parameters
VIOGLOBALREG endp

cseg ends
     end
