;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        PAGE    ,132
        TITLE   Virtual Video CRT I/O Processing

;/*****************************************************************************
;*
;* SOURCE FILE NAME = VVCRTIO.ASM
;*
;* DESCRIPTIVE NAME = Virtual Video Device Driver CRT I/O Processing
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/10/88
;*
;* DESCRIPTION  This module contains the VVD's CRT I/O handlers.
;*
;* FUNCTIONS
;*              VVReadCRTIndxFgnd()     Read CRT index byte
;*              VVReadCRTIndxBgnd()     Read CRT index byte
;*              VVWriteCRTIndxFgnd()    Write CRT index byte
;*              VVWriteCRTIndxBgnd()    Write CRT index byte
;*              VVReadCRTIndxFgndW()    Read CRT index word
;*              VVWriteCRTIndxFgndW()   Write CRT index word foreground
;*              VVWriteCRTIndxBgndW()   Write CRT index word background
;*              VVReadCRTDataFgnd()     Read CRT data byte
;*              VVReadCRTDataBgnd()     Read CRT data byte
;*              VVWriteCRTDataFgnd()    Write CRT data byte
;*              VVWriteCRTDataBgnd()    Write CRT data byte
;*              vvUpdateCursorData()    Return current cursor data
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   11/10/88                     JTP - Created.
;*   07/18/91                     B724762 - Only shadow the CRTC register
;*                                if the target/source I/O port matches
;*                                the current video mode (MONO/COLOR).
;*   09/14/91                     Delete window syncronization references
;*                                (B726840)
;*   02/27/92                     B733211 - Performance enhancement to
;*                                320x200 mode.
;*   08/03/93                     72133 - Avoid Trap D in the PM Shield
;*                                by screening CRTC programming in the
;*                                the background.
;*   06/04/93              F69306  - Add support for S3
;*   11/02/93              75458  S3 Merge
;*   08/18/93   J-TS0818  JS05766 ET4000 VTEXT driver cannot be installed
;*                                in windowed VDM.
;*   01/12/93  ChangeTeam  76726  Avoid video corruption in Flight Simulator 5.0
;*****************************************************************************/


        .xlist

        include mvdm.inc
        include vddseg.inc
IFDEF   GALE                                                            ;J-TS00V
        include struc30.inc                                             ;J-TS00V
ENDIF   ;GALE                                                           ;J-TS00V
        .list
        include vvd.inc
        include vvdp.inc


        DefData     IMPORT,SWAP,C
        ULONG       TKSSBase            ;required for SSToDS macro
       IFDEF SVGA
        PBYTE       abCRTMask                           ;          
IFDEF   VTEXT                                                           ;J-TS00V
        ULONG       ulSVGAAdapterType                                   ;J-TS00V
ENDIF   ;VTEXT                                                          ;J-TS00V
       ENDIF
        EndData


        DefCode     IMPORT,SWAP,PASCAL
        DefFn       vvAddEvent
        DefFn       vvUpdateScreenState
IFDEF   GALE                                                            ;J-TS00V
        DefFn       mapc                                                ;J-TS00V
ENDIF   ;GALE                                                           ;J-TS00V
IFDEF   VTEXT                                                           ;J-TS00V
        DefFn       vvUpdateCursorDataVtext                             ;J-TS00V
ENDIF   ;VTEXT                                                          ;J-TS00V
        EndCode


        DefCode     EXPORT,SWAP,PASCAL

       IFNDEF VGA
        DefFn       VVReadCRTIndxFgnd
       ENDIF
        DefFn       VVReadCRTIndxBgnd
       IFNDEF VGA
        DefFn       VVWriteCRTIndxFgnd
       ENDIF
        DefFn       VVWriteCRTIndxBgnd
       IFNDEF VGA
        DefFn       VVReadCRTIndxFgndW
       ENDIF
        DefFn       VVWriteCRTIndxBgndW
        DefFn       VVWriteCRTIndxFgndW
       IFNDEF VGA
        DefFn       VVReadCRTDataFgnd
       ENDIF
        DefFn       VVReadCRTDataBgnd
       IFNDEF VGA
        DefFn       VVWriteCRTDataFgnd
       ENDIF
        DefFn       VVWriteCRTDataBgnd

        DefFn       vvUpdateCursorData

IFDEF   XVIO                                                            ;J-TS00V
        DefFn       vxUpdateCursorData                                  ;J-TS00V
ENDIF   ;XVIO                                                           ;J-TS00V

        IFNDEF VGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadCRTIndxFgnd()
;*
;* DESCRIPTION   = Read CRT index byte
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM reads a byte from the CRT controller index register
;*                 (see VDHInstallIOHook for complete semantics).
;*
;*                 Note that the only real purpose this routine serves is to
;*                 enhance operation on MONO/CGA/EGA adapters, which are
;*                 normally not readable.  This provides applications with a
;*                 benefit of operating in V86-mode that should in no way
;*                 affect compatibility.
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 case VGA:
;*                   none
;*                 case OTHER:
;*                   return CRT index value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadCRTIndxFgnd
        FallInto VVReadCRTIndxBgnd
EndProc   VVReadCRTIndxFgnd

       ENDIF ;VGA


;/***************************************************************************
;*
;* FUNCTION NAME = VVReadCRTIndxBgnd()
;*
;* DESCRIPTION   = Read CRT index byte
;*
;*                 This registered subroutine is called whenever a
;*                 background VDM reads a byte from the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;* OUTPUT        =
;*                 AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadCRTIndxBgnd
       IFNDEF VGA
        FallFrom VVReadCRTIndxFgnd
       ENDIF
        mov     al,VDMData.regCRTIndx       ;return CRT controller index

;/*
;**
;**    Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**    emulate the true effect when the target port is invalid
;**    under the current mode.  For example, if the VDM is currently
;**    in MONO mode then all accesses to the 3Dx are invalid.
;*/

       IFDEF EGAVGA                                                     ;          
        mov     ecx,PORT_MONOCRTINDX        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short rCRTIndxChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTINDX        ;no, VDM is in Color mode   ;          
rCRTIndxChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jz      short rCRTIndxExit          ;yes                        ;          
        mov     al,0FFh                     ;no, return emulated value  ;          
rCRTIndxExit:                                                           ;          
       ENDIF                                                            ;          

        ExitProc
EndProc   VVReadCRTIndxBgnd


       IFNDEF VGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTIndxFgnd()
;*
;* DESCRIPTION   = Write CRT index byte
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM writes a byte to the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 case VGA:
;*                   none
;*                 case OTHER:
;*                   update hardware
;*                   update CRT index value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteCRTIndxFgnd
        OUTB    dx,al                       ;output CRT controller index
        FallInto VVWriteCRTIndxBgnd
EndProc   VVWriteCRTIndxFgnd

       ENDIF ;VGA


;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTIndxBgnd()
;*
;* DESCRIPTION   = Write CRT index byte
;*
;*                 This registered subroutine is called whenever a
;*                 background VDM writes a byte to the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteCRTIndxBgnd
       IFNDEF VGA
        FallFrom VVWriteCRTIndxFgnd
       ENDIF

;/*
;**
;**     Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**     emulate the true effect when the target port is invalid
;**     under the current mode.  For example, if the VDM is currently
;**     in MONO mode then all accesses to the 3Dx are invalid.
;**
;*/

       IFDEF EGAVGA                                                     ;          
        mov     ecx,PORT_MONOCRTINDX        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short wCRTIndxChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTINDX        ;no, VDM is in Color mode   ;          
wCRTIndxChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jnz     short wCRTIndxExit          ;no                         ;          
       ENDIF                                                            ;          
        mov     VDMData.regCRTIndx,al       ;stash CRT controller index

wCRTIndxExit:                                                           ;          
        ExitProc
EndProc   VVWriteCRTIndxBgnd


       IFNDEF VGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadCRTIndxFgndW()
;*
;* DESCRIPTION   = Read CRT index word
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM reads a word from the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*                 Note that the only real purpose this routine serves
;*                 is to enhance operation on MONO/CGA/EGA adapters, which
;*                 are normally not readable. This provides applications
;*                 with a benefit of operating in V86-mode that should in
;*                 no way affect compatibility.
;*
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        = AX  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadCRTIndxFgndW

;/*
;**
;**    Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**    emulate the true effect when the target port is invalid
;**    under the current mode.  For example, if the VDM is currently
;**    in MONO mode then all accesses to the 3Dx are invalid.
;**
;*/

       IFDEF EGA                                                        ;          
        mov     ecx,PORT_MONOCRTINDX        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short rCRTWordChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTINDX        ;no, VDM is in Color mode   ;          
rCRTWordChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jz      short rCRTWord              ;yes                        ;          
        mov     ax,0FFFFh                   ;no, return emulated value  ;          
        ExitProc premature                                              ;          
       ENDIF                                                            ;          
rCRTWord:                                                               ;          

        mov     al,VDMData.regCRTIndx       ;get CRT controller index
        movzx   ecx,al                      ;form our own index
        cmp     cl,REG_CRTLPENHI            ;lightpen status register?
        je      short vvrifw_gethw          ;yes, read hardware directly
        cmp     cl,REG_CRTLPENLO            ;other lightpen status register?
        je      short vvrifw_gethw          ;yes, read hardware directly
       IFDEF TSENG
       IFDEF EGA
        cmp     cl,REG_TSENG_CRTLPEN2       ;yet another status register?
        je      short vvrifw_gethw          ;yes, read hardware directly
       ENDIF
       ENDIF

        and     cl,MAX_CRTREGS-1            ;don't over-index
        mov     ah,VDMData.aregCRTData[ecx] ;get indexed CRT data
        ExitProc premature

vvrifw_gethw:
        INB     ah,dx                       ;read data directly from hardware
        ExitProc
EndProc   VVReadCRTIndxFgndW

       ENDIF ;VGA


;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTIndxFgndW()
;*
;* DESCRIPTION   = Write CRT index word foreground
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM writes a word to the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*
;* INPUT         = AX == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteCRTIndxFgndW
        OUTW    dx,ax                       ;output index+data
        FallInto VVWriteCRTIndxBgndW
EndProc   VVWriteCRTIndxFgndW


;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTIndxBgndW()
;*
;* DESCRIPTION   = Write CRT index word background
;*
;*                 This registered subroutine is called whenever a
;*                 background VDM writes a word to the CRT controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*
;* INPUT         =  AX == data to write
;*                  EBX -> VDM register frame
;*                  EDX == port number (PORT_MONOCRTINDX or PORT_COLRCRTINDX)
;*
;* OUTPUT        =  None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteCRTIndxBgndW


;/*
;**
;**    Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**    emulate the true effect when the target port is invalid
;**    under the current mode.  For example, if the VDM is currently
;**    in MONO mode then all accesses to the 3Dx are invalid.
;**
;*/

       IFDEF EGAVGA                                                     ;          
        mov     ecx,PORT_MONOCRTINDX        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short wCRTWordChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTINDX        ;no, VDM is in Color mode   ;          
wCRTWordChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jnz     short wCRTWordExit          ;no                         ;          
       ENDIF                                                            ;          

        mov     VDMData.regCRTIndx,al       ;stash CRT controller index
        movzx   ecx,al                      ;form our own index
        and     cl,MAX_CRTREGS-1            ;don't over-index (critical!)
        mov     al,ah
        inc     edx                         ;for VVWriteCRTDataBgnd     ;          
        testb   VDMData.flVDMVideo,VDM_WINDOWED
        jnz     VVWriteCRTDataBgnd

;/*
;**
;**    Don't allow the VDM to clear CRTC registers 00h - 06h and
;**    0Fh - 18h because the changes will cause vvUpdateScreenState
;**    to record bogus information that may lead to Traps and Hangs
;**    in the PM Shield.
;**
;*/
        or      al,al                                                   ;          
        jnz     wCRTSaveIt                                              ;          
        cmp     ecx,REG_CRTOVERFLOW             ;Index 07h              ;          
        jb      wCRTSkipIt                                              ;          
        cmp     ecx,REG_CRTVERTSTRTRC           ;Index 10h              ;          
        jb      wCRTSaveIt                                              ;          
        cmp     ecx,REG_CRTUNDLINELOC           ;Index 14h               76726
        je      wCRTSaveIt                                              ;76726
        cmp     ecx,REG_CRTLINECMP              ;Index 18h              ;          
        jbe     wCRTSkipIt                                              ;          
wCRTSaveIt:                                                             ;          
        mov     VDMData.aregCRTData[ecx],al ;stash indexed CRT data as well
wCRTSkipIt:                                                             ;          
        ExitProc

wCRTWordExit:                                                           ;          
EndProc   VVWriteCRTIndxBgndW


       IFNDEF VGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadCRTDataFgnd()
;*
;* DESCRIPTION   = Read CRT data byte
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM reads a byte from the CRT controller
;*                 data register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*                 Note that the only real purpose this routine serves
;*                 is to enhance operation on MONO/CGA/EGA adapters, which
;*                 are normally not readable. This provides applications
;*                 with a benefit of operating in V86-mode that should in
;*                 no way affect compatibility.
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTDATA or PORT_COLRCRTDATA)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 case VGA:
;*                   none
;*                 case OTHER:
;*                   if REG_CRTLPENHI, REG_CRTLPENLO
;*                     return hardware
;*                   else
;*                     mask index with MAX_CRTREGS-1
;*                     index into CRT array, return value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadCRTDataFgnd
        FallInto VVReadCRTDataBgnd
EndProc   VVReadCRTDataFgnd

       ENDIF ;VGA


;/***************************************************************************
;*
;* FUNCTION NAME = VVReadCRTDataBgnd()
;*
;* DESCRIPTION   = Read CRT data byte
;*
;*                 This registered subroutine is called whenever a background
;*                 VDM reads a byte from the CRT controller data register
;*                 (see VDHInstallIOHook for complete semantics).
;*
;*
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTDATA or PORT_COLRCRTDATA)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 if REG_CRTLPENHI, REG_CRTLPENLO
;*                   return simulated hardware value
;*                 else
;*                   mask index with MAX_CRTREGS-1
;*                   index into CRT array, return value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadCRTDataBgnd
       IFNDEF VGA
        FallFrom VVReadCRTDataFgnd
       ENDIF

;/*
;**
;**     Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**     emulate the true effect when the target port is invalid
;**     under the current mode.  For example, if the VDM is currently
;**     in MONO mode then all accesses to the 3Dx are invalid.
;**
;*/

       IFDEF EGAVGA                                                     ;          
        mov     ecx,PORT_MONOCRTDATA        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short rCRTDataChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTDATA        ;no, VDM is in Color mode   ;          
rCRTDataChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jz      short rCRTData              ;yes                        ;          
        mov     al,0FFh                     ;no, return emulated value  ;          
        ExitProc premature                                              ;          
rCRTData:                                                               ;          
       ENDIF                                                            ;          

        movzx   ecx,VDMData.regCRTIndx      ;get CRT controller index

;/*
;**
;**   Note: the VGA doesn't support a light-pen, so there's no need to special-
;**         case those registers for a VGA.  That's also why the gethw and getvirt
;**         sections (below) can be conditionally assembled.
;**
;*/

       IFNDEF VGA
        cmp     cl,REG_CRTLPENHI            ;lightpen status register?
        je      short vvrdb_gethw           ;yes, read (virtual) hardware
        cmp     cl,REG_CRTLPENLO            ;other lightpen status register?
        je      short vvrdb_gethw           ;yes, read (virtual) hardware
       ENDIF

       IFDEF TSENG
       IFDEF EGA
        cmp     cl,REG_TSENG_CRTLPEN2       ;yet another status register?
        je      short vvrdb_gethw           ;yes, read hardware directly
       ENDIF
       ENDIF

        and     cl,MAX_CRTREGS-1            ;don't over-index
        mov     al,VDMData.aregCRTData[ecx] ;get indexed CRT data
       IFDEF SVGA                                                       ;J-TS0818
IFDEF   VTEXT                                                           ;J-TS0818
        .if     <VDMData.flVDMGale ne 0> or                             ;J-TS0818
        .if     <bit VDMData.GaleData.flVtext and VDMV_VTEXT_INSTALLED> ;J-TS0818
            .if     <ulSVGAAdapterType eq TSENG_ADAPTER> and            ;J-TS0818
            .if     <cl eq 33h>                                         ;J-TS0818
                mov     al, VDMData.GaleData.TsengExtStartAddr          ;J-TS0818
            .endif                                                      ;J-TS0818
        .endif                                                          ;J-TS0818
ENDIF   ;VTEXT                                                          ;J-TS0818
       ENDIF                                                            ;J-TS0818
        ExitProc premature

       IFNDEF VGA
vvrdb_gethw:
        testb   VDMData.flVDMVideo,VDM_FGND
        jz      short vvrdb_getvirt
        INB     al,dx                       ;read data directly from hardware
        ExitProc premature

vvrdb_getvirt:
        mov     al,0                        ;return simulated hardware value
        ExitProc
       ENDIF
EndProc   VVReadCRTDataBgnd


       IFNDEF VGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTDataFgnd()
;*
;* DESCRIPTION   = Write CRT data byte
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM writes a byte to the CRT controller data register (see
;*                 VDHInstallIOHook for complete semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTDATA or PORT_COLRCRTDATA)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 case VGA:
;*                   none
;*                 case OTHER:
;*                   update hardware
;*                   mask index with MAX_CRTREGS-1
;*                   index into CRT array, update value
;*
;*
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteCRTDataFgnd
        OUTB    dx,al                       ;output CRT controller data
        FallInto VVWriteCRTDataBgnd
EndProc   VVWriteCRTDataFgnd

       ENDIF ;VGA


;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteCRTDataBgnd()
;*
;* DESCRIPTION   = Write CRT data byte
;*
;*                 This registered subroutine is called whenever a background
;*                 VDM writes a byte to the CRT controller data register (see
;*                 VDHInstallIOHook for complete semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_MONOCRTDATA or PORT_COLRCRTDATA)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 mask index with MAX_CRTREGS-1
;*                 index into CRT array, update value
;*
;**************************************************************************/

        DefData EXPORT,SWAPINST,C
        _BYTE   nFlips,0
        EndData
        align   4                                                       ;          
Procedure VVWriteCRTDataBgnd
       IFNDEF VGA
        FallFrom VVWriteCRTDataFgnd
       ENDIF

       IFDEF SYNCFLIP
        LocalVar flDirtyTemp,ULONG
        EnterProc
       ENDIF

;/*
;**
;**    Although 3Bx and 3Dx are available on the EGA/VGA, we must
;**    emulate the true effect when the target port is invalid
;**    under the current mode.  For example, if the VDM is currently
;**    in MONO mode then all accesses to the 3Dx are invalid.
;**
;*/

       IFDEF EGAVGA                                                     ;          
        mov     ecx,PORT_MONOCRTDATA        ;assume MONO port access    ;          
        test    VDMData.regMiscOut,MISCOUT_COLRPORTS                    ;          
        jz      short wCRTDataChk           ;MONO emulation?            ;          
        mov     ecx,PORT_COLRCRTDATA        ;no, VDM is in Color mode   ;          
wCRTDataChk:                                                            ;          
        cmp     ecx,edx                     ;access allowed?            ;          
        jnz     vvwdb_exit                  ;no, no op access           ;          
       ENDIF                                                            ;          

        movzx   ecx,VDMData.regCRTIndx      ;get CRT controller index
        and     cl,MAX_CRTREGS-1            ;don't over-index
       IFDEF SVGA
;/*
;** If the index is not part of the trap list, don't shadow it.
;** This will prevent BIOS and DOS applications from erroneously
;** modifying read-only registers in the backgroud.
;** It turns out cheaper to preserve original index by push/pop then to
;** implement anything else. The whole trap mask test costs 32 cycles.
;*/
IFDEF   VTEXT                                                           ;J-TS00V
        .if     <VDMData.flVDMGale ne 0> or                             ;J-TS0818
        .if     <bit VDMData.GaleData.flVtext and VDMV_VTEXT_INSTALLED> ;J-TS00V
            .if     <ulSVGAAdapterType eq S3_ADAPTER> and               ;J-TS00V
            .if     <ecx eq 39h>                                        ;J-TS00V
                mov     VDMData.GaleData.S3RegLock2, al                 ;J-TS00V
            .endif                                                      ;J-TS00V
            .if     <ulSVGAAdapterType eq TSENG_ADAPTER> and            ;J-TS0818
            .if     <ecx eq 33h>                                        ;J-TS0818
                mov     VDMData.GaleData.TsengExtStartAddr, al          ;J-TS0818
            .endif                                                      ;J-TS0818
        .endif                                                          ;J-TS00V
ENDIF   ;VTEXT                                                          ;J-TS0818
        push    ecx                         ;          
        mov     ah, 1
        and     cl, 7                       ;get the modulo 8 into cl
        shl     ah, cl                      ;get the right bit offset into ah
        mov     ecx, [esp]                  ;get cx again
        shr     ecx, 3                      ;get the right byte offset in the abCRTMask
        test    byte ptr abCRTMask[ecx], ah ;set the 0 flag
        pop     ecx                         ;get the original index, balance the stack
        jz      vvwdb_exit                  ;if not in the trap list, just exit
IFDEF   VTEXT                                                           ;J-TS00V
        .if     <VDMData.flVDMGale ne 0> or                             ;J-TS0818
        .if     <bit VDMData.GaleData.flVtext and VDMV_VTEXT_INSTALLED> ;J-TS00V
            .if     <ulSVGAAdapterType eq S3_ADAPTER> and               ;J-TS00V
            .if     <ecx ge 40h> and                                    ;J-TS00V
            .if     <ecx le 5fh>                                        ;J-TS00V
                push    ax                                              ;J-TS00V
                mov     al, VDMData.GaleData.S3RegLock2                 ;J-TS00V
                and     al, 0e0h                                        ;J-TS00V
                cmp     al, 0a0h                                        ;J-TS00V
                pop     ax                                              ;J-TS00V
                jne     vvwdb_exit                                      ;J-TS00V
            .endif                                                      ;J-TS00V
        .endif                                                          ;J-TS00V
ENDIF   ;VTEXT                                                          ;J-TS00V
       ENDIF
        mov     ah,VDMData.aregCRTData[ecx] ;save previous CRT data

;/*
;**
;**    Don't allow the VDM to clear CRTC registers 00h - 06h and
;**    0Fh - 18h because the changes will cause vvUpdateScreenState
;**    to record bogus information that may lead to Traps and Hangs
;**    in the PM Shield.
;**
;*/
        or      al,al                                                   ;          
        jnz     bwCRTSaveIt                                             ;          
        cmp     ecx,REG_CRTOVERFLOW             ;Index 07h              ;          
        jb      bwCRTSkipIt                                             ;          
        cmp     ecx,REG_CRTVERTSTRTRC           ;Index 10h              ;          
        jb      bwCRTSaveIt                                             ;          
        cmp     ecx,REG_CRTUNDLINELOC           ;Index 14h               76726
        je      wCRTSaveIt                                              ;76726
        cmp     ecx,REG_CRTLINECMP              ;Index 18h              ;          
        jbe     bwCRTSkipIt                                             ;          
bwCRTSaveIt:                                                            ;          
        mov     VDMData.aregCRTData[ecx],al ;stash the indexed CRT data
bwCRTSkipIt:                                                            ;          
;/*
;**
;**   Check for page flip or cursor change, and add window event if necessary
;**
;*/

        testb   VDMData.flVDMVideo,VDM_WINDOWED
exit2:  jz      vvwdb_exit
        testb   VDMData.flVDMVideo,VDM_STATEINIT
        jz      exit2

vvwdb_checklvb:
        cmp     cl,REG_CRTSTARTADDRHI
        mov     ch,01h
        je      short vvwdb_lvbupdate
        cmp     cl,REG_CRTSTARTADDRLO
;       mov     ch,02h                                                  ;B729786
        jne     short vvwdb_checkmode

vvwdb_lvbupdate:
        or      [nFlips],ch
        movzx   eax,word ptr VDMData.aregCRTData[REG_CRTSTARTADDRHI]
        or      eax,eax                     ;try to determine if a valid
        jz      short vvwdb_lvbreset        ;offset exists yet
        xchg    al,ah
        mov     ecx,2000                    ;a likely offset
        push    eax
        div     ecx
        pop     eax
        or      edx,edx                     ;any remainder?
        jz      short vvwdb_lvbreset        ;no, reset
        cmp     [nFlips],01h                ;STARTADDRHI changed?       ;B729786
        jne     short vvwdb_exit            ;no, I give up
vvwdb_lvbreset:
        mov     [nFlips],0

;/*
;**
;**   Call vvUpdateScreenState strictly to update offPhysVRAMVisible
;**
;*/

        CallFn  vvUpdateScreenState,<CURRENT_VDM, FALSE>

        or      VDMData.flVDMVideo,VDM_SHADOWINVALID
       IFNDEF SYNCFLIP
        or      VDMData.flDirtyPages,-1     ;let next timer update handle this
       ELSE
        SSToDS  eax,flDirtyTemp
        mov     dword ptr [eax],-1
        CallFn  vvAddEvent,<CURRENT_VDM, VVDEVENT_LVB, eax, 0>
       ENDIF
        jmp     short vvwdb_exit

vvwdb_checkmode:
        mov     [nFlips],0
        cmp     al,ah                       ;did app *change* or simply rewrite?
        je      short vvwdb_exit            ;did not change!

       IFDEF MONOCGA
        cmp     cl,REG_CRTVERTTOTAL
       ENDIF
       IFDEF EGAVGA
        cmp     cl,REG_CRTLINECMP
        je      short vvwdb_modeupdate
        cmp     cl,REG_CRTVERTDSPEND
       ENDIF
        jne     short vvwdb_checkcursor

vvwdb_modeupdate:
        CallFn  vvUpdateScreenState,<CURRENT_VDM, TRUE>
        jmp     short vvwdb_exit

vvwdb_checkcursor:
        cmp     cl,REG_CRTCURLOCHI
        je      short vvwdb_cursorupdate
        cmp     cl,REG_CRTCURLOCLO
        je      short vvwdb_cursorupdate
        cmp     cl,REG_CRTCURSTSCAN
        je      short vvwdb_cursorupdate
        cmp     cl,REG_CRTCURENDSCAN
        jne     short vvwdb_exit

vvwdb_cursorupdate:
        or      VDMData.PtrData.flPtrVideo,PTR_HWDIRTY
        CallFn  vvUpdateCursorData,<CURRENT_VDM>

vvwdb_exit:
        ExitProc
EndProc   VVWriteCRTDataBgnd


;/***************************************************************************
;*
;* FUNCTION NAME = vvUpdateCursorData()
;*
;* DESCRIPTION   = Return current cursor data
;*
;*
;* INPUT         = hvdm -> VDM
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure vvUpdateCursorData
        ArgVar  hvdm,HVDM

        EnterProc
        push    ebx
        push    edi

        mov     ebx,[hvdm]
        lea     edi,VDMData.vvCursor[ebx]
IFDEF   GALE                                                            ;J-TS00V
        .if     <VDMData.flVDMGale[ebx] ne 0> and                       ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 03h> or                     ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 73h>                        ;J-TS00V
            mov     cx, VDMData.GaleData.GaleCursor.GaleCurMode[ebx]    ;J-TS00V
            mov     al, 19                                              ;J-TS00V
            call    mapc                                                ;J-TS00V
            .if     <ch ae 19> or                   ; hidden cursor     ;J-TS00V
            .if     <ch a cl>                       ; or invalid type   ;J-TS00V
                mov     [edi].vvc_fVisible,FALSE                        ;J-TS00V
            .else                                                       ;J-TS00V
                mov     [edi].vvc_fVisible,TRUE                         ;J-TS00V
            .endif                                                      ;J-TS00V
            .if     <cl ae 19>                      ; too large cursor  ;J-TS00V
                mov     cl, 18                                          ;J-TS00V
            .endif                                                      ;J-TS00V
            movzx   eax,cl                                              ;J-TS00V
            mov     [edi].vvc_ulScanEnd,eax                             ;J-TS00V
            movzx   eax,ch                                              ;J-TS00V
            mov     [edi].vvc_ulScanStart,eax                           ;J-TS00V
            movzx   eax,byte ptr VDMData.GaleData.GaleCursor.GaleCurPos[ebx]    ;J-TS00V
            mov     [edi].vvc_col,eax                                   ;J-TS00V
            movzx   eax,byte ptr VDMData.GaleData.GaleCursor.GaleCurPos[ebx+1]  ;J-TS00V
            mov     [edi].vvc_row,eax                                   ;J-TS00V
            jmp     vvqcd_add_event                                     ;J-TS00V
        .endif                                                          ;J-TS00V
ENDIF   ;GALE                                                           ;J-TS00V
IFDEF   VTEXT                                                           ;J-TS00V
        .if     <bit VDMData.GaleData.flVtext[ebx] and VDMV_VTEXT_INSTALLED> and    ;J-TS00V
        .if     <bit VDMData.GaleData.flVtext[ebx] and VDMV_SUPPORTED_TEXT_MODE>    ;J-TS00V
            CallFn  vvUpdateCursorDataVtext, <ebx>                      ;J-TS00V
            jmp     vvqcd_add_event                                     ;J-TS00V
        .endif                                                          ;J-TS00V
ENDIF   ;VTEXT                                                          ;J-TS00V
        mov     ax,word ptr VDMData.aregCRTData[REG_CRTCURLOCHI][ebx]
        xchg    al,ah
        mov     cx,word ptr VDMData.aregCRTData[REG_CRTSTARTADDRHI][ebx]
        xchg    cl,ch
        sub     ax,cx

;/*
;**
;**   Check the cursor location, because apps can program huge values into it
;**   (eg, when Lotus hides the cursor).  Anything larger than the current
;**   visible screen size gets mapped to the last visible byte + 1 here, to avoid
;**   any possibility of division overflow....
;**
;*/

        mov     [edi].vvc_fVisible,TRUE     ;assume cursor is visible
        mov     dx,word ptr VDMData.nbPhysVRAMVisible[ebx]
        shr     dx,1
        cmp     ax,dx
        jb      short vvqcd_ok
        mov     ax,dx
        mov     [edi].vvc_fVisible,FALSE    ;cursor is not visible

vvqcd_ok:
        movzx   ecx,VDMData.aregCRTData[REG_CRTHORZDSPEND][ebx]
       IFDEF EGAVGA
        inc     cl                          ;# of chars/row in EGA/VGA
       ENDIF                                ;register is 1 less than actual #
        mov     dx,ax                       ;begin check for division underflow
        sub     eax,eax
        jecxz   short vvqcd_skipdiv
        dec     eax                         ;AL == 0FFh
        mul     cl
        cmp     dx,ax
        ja      short vvqcd_divbad
        mov     ax,dx                       ;end check
vvqcd_divbad:
        div     cl
vvqcd_skipdiv:
        movzx   ecx,al                      ;AL == row #
        mov     [edi].vvc_row,ecx
        mov     cl,ah                       ;AH == column #
        mov     [edi].vvc_col,ecx
        mov     ax,word ptr VDMData.aregCRTData[REG_CRTCURSTSCAN][ebx]
        testb   VDMData.PtrData.flPtrVideo[ebx],PTR_HARDWARE
        jz      short vvqcd_nothwptr        ;hardware cursor not enabled
        testb   VDMData.PtrData.flPtrVideo[ebx],PTR_HWDIRTY
        jz      short vvqcd_invisible       ;cursor should not be seen in window
vvqcd_nothwptr:
        test    al,20h                      ;cursor-off bit set?
        jnz     short vvqcd_invisible       ;yes
        and     ax,1F1Fh
       IFDEF VGA
        cmp     al,ah                       ;start greater than end?
        ja      short vvqcd_invisible       ;yes (no split cursors on VGA)
       ENDIF
       IFDEF EGA
        dec     ah                          ;on IBM EGA, ending line is 1 less
       ENDIF
        mov     cl,VDMData.aregCRTData[REG_CRTMAXSCAN][ebx]
        and     cl,1Fh
        cmp     al,cl                       ;is start scan line > max scan line?
        ja      short vvqcd_invisible       ;yes, assume invisible
        cmp     ah,cl                       ;is end scan line > max scan line?
        jbe     short vvqcd_checkmode       ;no
        mov     ah,cl                       ;yes, so set to largest allowed value
vvqcd_checkmode:
        cmp     VDMData.mstateVideo[ebx],MEMORY_TEXT
        je      short vvqcd_exit
vvqcd_invisible:
        mov     [edi].vvc_fVisible,FALSE    ;cursor is not visible
vvqcd_exit:
        mov     cl,al                       ;AL == start scan #
        mov     [edi].vvc_ulScanStart,ecx
        mov     cl,ah                       ;AH == stop scan #
        mov     [edi].vvc_ulScanEnd,ecx
IFDEF   GALE                                                            ;J-TS00V
vvqcd_add_event:                                                        ;J-TS00V
ENDIF   ;GALE                                                           ;J-TS00V
;                  VDMData.flVDMXVideo[ebx],VDMX_SYNCOUTPUT
;                  short vvqcd_done
        CallFn  vvAddEvent,<ebx, VVDEVENT_CURSOR, edi, 0>
vvqcd_done:
        pop     edi
        pop     ebx
        ExitProc

EndProc   vvUpdateCursorData

IFDEF   XVIO                                                            ;J-TS00V
                                                                        ;J-TS00V
;***LP  vxUpdateCursorData() - Set current cursor data for XVIO         ;J-TS00V
;                                                                       ;J-TS00V
;   Constructs current row, column, start and end scan lines, and       ;J-TS00V
;   current visibility for cursor.                                      ;J-TS00V
;                                                                       ;J-TS00V
;   ENTRY                                                               ;J-TS00V
;       hvdm -> VDM                                                     ;J-TS00V
;   EXIT                                                                ;J-TS00V
;       None                                                            ;J-TS00V
;   USES                                                                ;J-TS00V
;       All but EBX, ESI, EDI, EBP, DS and ES                           ;J-TS00V
;                                                                       ;J-TS00V
;   CONTEXT                                                             ;J-TS00V
;       Task-time                                                       ;J-TS00V
;                                                                       ;J-TS00V
;   PSEUDO-CODE                                     REFERENCES          ;J-TS00V
;                                                                       ;J-TS00V
                                                                        ;J-TS00V
Procedure vxUpdateCursorData                                            ;J-TS00V
        ArgVar  hvdm,HVDM                                               ;J-TS00V
                                                                        ;J-TS00V
        EnterProc                                                       ;J-TS00V
        pushad                                                          ;J-TS00V
        mov     ebx,[hvdm]                                              ;J-TS00V
        lea     edi,VDMData.XVIOData.vxCursor[ebx]                      ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 03h> or                     ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 73h> or                     ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 11h> or                     ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 12h> or                     ;J-TS00V
        .if     <VDMData.ulBIOSMode[ebx] eq 72h>                        ;J-TS00V
            movzx   eax,byte ptr VDMBase.rb_wVCursorMode[ebx]           ;J-TS00V
            mov     [edi].vxc_ulScanEnd,eax         ; end position      ;J-TS00V
            movzx   eax,byte ptr VDMBase.rb_wVCursorMode[ebx+1]         ;J-TS00V
            mov     [edi].vxc_ulScanStart,eax       ; start position    ;J-TS00V
            mov     [edi].vxc_attribute,0000h       ; normal            ;J-TS00V
            movzx   eax,byte ptr VDMBase.rb_awVCursorPos[ebx]           ;J-TS00V
            mov     [edi].vxc_col,eax               ; column position   ;J-TS00V
            movzx   eax,byte ptr VDMBase.rb_awVCursorPos[ebx+1]         ;J-TS00V
            mov     [edi].vxc_row,eax               ; row position      ;J-TS00V
        .endif                                                          ;J-TS00V
        popad                                                           ;J-TS00V
        ExitProc                                                        ;J-TS00V
                                                                        ;J-TS00V
EndProc   vxUpdateCursorData                                            ;J-TS00V
                                                                        ;J-TS00V
ENDIF   ;XVIO                                                           ;J-TS00V

        EndCode     EXPORT,SWAP,PASCAL


        END
