;*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 SEQ I/O Processing

;/*****************************************************************************
;* SOURCE FILE NAME = VVSEQIO.ASM
;*
;* DESCRIPTIVE NAME = Virtual Video Device Driver SEQ I/O Processing
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/10/88
;*
;* DESCRIPTION  This module contains the VVD's SEQ I/O handlers.
;*
;* FUNCTIONS    VVReadSEQIndxFgnd()      Read SEQ index byte
;*              VVReadSEQIndxBgnd()      Read SEQ index byte
;*              VVWriteSEQIndxFgnd()     Write SEQ index byte
;*              VVWriteSEQIndxBgnd()     Write SEQ index byte
;*              VVReadSEQIndxFgndW()     Read SEQ index word
;*              VVWriteSEQIndxFgndW()    Write SEQ index word
;*              VVReadSEQDataFgnd()      Read SEQ data byte
;*              VVReadSEQDataBgnd()      Read SEQ data byte
;*              VVWriteSEQDataFgnd()     Write SEQ data byte
;*              VVWriteSEQDataBgnd()     Write SEQ data byte
;*
;* 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.
;*
;*   05/09/91                     fix PM video corruption when session
;*                                switch back to PM while the VDM in a
;*                                multi-plane graphics mode.
;*                                (B790553, B722596)
;*
;*   02/27/92                     B733211 - Performance enhancement to
;*                                320x200 mode.
;*
;*   03/11/92                     B729758 - Fix out of sync problem.
;*
;*   11/03/92                     Limit VVEnableBuffer calls to memory mode reg
;*   02/16/93                     If the SEQMEM_MODE reg bits other than bit 0 are
;*                                changed before the mode set completed, do not EnableBuffer.
;*
;*****************************************************************************/


        .xlist
        include mvdm.inc
        include vddseg.inc
        .list
        include vvd.inc
        include vvdp.inc


        DefCode     EXPORT,SWAP,PASCAL

       IFDEF EGA
        DefFn       VVReadSEQIndxFgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVReadSEQIndxBgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVWriteSEQIndxFgnd
        DefFn       VVWriteSEQIndxBgnd
       ENDIF
       IFDEF EGA
        DefFn       VVReadSEQIndxFgndW
        DefFn       VVWriteSEQIndxFgndW
       ENDIF
       IFDEF EGA
        DefFn       VVReadSEQDataFgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVReadSEQDataBgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVWriteSEQDataFgnd
        DefFn       VVWriteSEQDataBgnd
       ENDIF


        DefCode     IMPORT,SWAP,PASCAL
        DefFn       VVEnableBuffer
        EndCode

        DefCode     IMPORT,GLOBAL,PASCAL
        DefFn       vvShadowIndxBgnd
        DefFn       vvShadowDataBgnd
        EndCode

        DefData     IMPORT,SWAP,C
        PBYTE       pbSEQExtShadowIndx
        PRLE        prleSEQExtShadowData
        PSADAPTERINFO   psCurAdapterInfo
        EndData


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadSEQIndxFgnd()
;*
;* DESCRIPTION   = Read SEQ index byte
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM reads a byte from the SEQ controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*                 Note that the only real purpose this routine serves
;*                 is to enhance operation on 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_SEQINDX)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

align   4                                                       ;          
Procedure VVReadSEQIndxFgnd
        FallInto VVReadSEQIndxBgnd          ;no different from background
EndProc   VVReadSEQIndxFgnd

       ENDIF ;EGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVReadSEQIndxBgnd
       IFDEF EGA
        FallFrom VVReadSEQIndxFgnd
       ENDIF
        mov     al,VDMData.regSEQIndx       ;return SEQ controller index
        ExitProc
EndProc   VVReadSEQIndxBgnd

       ENDIF ;EGAVGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVWriteSEQIndxFgnd
        OUTB    dx,al                       ;output SEQ controller index
        FallInto VVWriteSEQIndxBgnd
EndProc   VVWriteSEQIndxFgnd

       ENDIF ;EGAVGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVWriteSEQIndxBgnd
        FallFrom VVWriteSEQIndxFgnd
        mov     VDMData.regSEQIndx,al       ;stash SEQ controller index

        test    VDMData.flVDMVideo,VDM_PHYSPAGE
        jz      short vvwi_exit

;/*
;**
;**   OK, the magic bit is set, so we have to drop into the magic code that
;**   allows reprogramming of specific bits of certain physical registers, as well
;**   as optional uninterruptible shadowing in external storage.
;**
;*/

        cmp     al,REG_SEQCLKMODE           ;don't shadow the clock     ;          
        jz      short vvwi_exit                                         ;          
        mov     ecx,pbSEQExtShadowIndx
        call    vvShadowIndxBgnd            ;shadow this register

vvwi_exit:
        ExitProc
EndProc   VVWriteSEQIndxBgnd

       ENDIF ;EGAVGA


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadSEQIndxFgndW()
;*
;* DESCRIPTION   = Read SEQ index word
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM reads a word from the SEQ controller
;*                 index register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*                 Note that the only real purpose this routine serves
;*                 is to enhance operation on 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_SEQINDX)
;*
;* OUTPUT        = AX  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadSEQIndxFgndW
        mov     al,VDMData.regSEQIndx       ;get SEQ controller index
        mov     ecx,MAX_SEQREGS-1
        cmp     cl,al
        jb      short vvriw_indexok
        mov     cl,al
vvriw_indexok:
        mov     ah,VDMData.aregSEQData[ecx] ;get indexed SEQ data
        ExitProc
EndProc   VVReadSEQIndxFgndW

       ENDIF ;EGA


       IFDEF EGA

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

        align   4                                                       ;          
Procedure VVWriteSEQIndxFgndW
        OUTW    dx,ax                       ;output index+data
        mov     VDMData.regSEQIndx,al       ;stash SEQ controller index

        mov     ecx,MAX_SEQREGS-1
        cmp     cl,al
        jb      short vvwiw_indexok
        mov     cl,al
vvwiw_indexok:
        mov     VDMData.aregSEQData[ecx],ah ;stash indexed SEQ data as well

;/*
;**
;**   If we're NOT in a graphics mode, then disable all video pages, in
;**   preparation for mode re-determination on the next page fault.  This
;**   allows us to distinguish between text modes and graphics modes that share
;**   the text address space (ie, CGA graphics modes).
;**
;*/

        cmp     VDMData.mstateVideo,MEMORY_GRFX
        jne     short vvwd_disableall
        ExitProc
EndProc   VVWriteSEQIndxFgndW

       ENDIF ;EGA


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadSEQDataFgnd()
;*
;* DESCRIPTION   = Read SEQ data byte
;*
;*                 This registered subroutine is called whenever a
;*                 foreground VDM reads a byte from the SEQ controller
;*                 data register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;*                 Note that the only real purpose this routine serves
;*                 is to enhance operation on 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_SEQDATA)
;*
;* OUTPUT        =  AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 case VGA:
;*                   none
;*                 case OTHER:
;*                   mask index with MAX_SEQREGS-1
;*                   index into SEQ array, return value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadSEQDataFgnd
        FallInto VVReadSEQDataBgnd
EndProc   VVReadSEQDataFgnd

       ENDIF ;EGA


       IFDEF EGAVGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadSEQDataBgnd()
;*
;* DESCRIPTION   = Read SEQ data byte
;*
;*                 This registered subroutine is called whenever a
;*                 background VDM reads a byte from the SEQ controller
;*                 data register (see VDHInstallIOHook for complete
;*                 semantics).
;*
;* INPUT         = EBX -> VDM register frame
;*                 EDX == port number (PORT_SEQDATA)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*
;*     mask index with MAX_SEQREGS-1
;*     index into SEQ array, return value
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadSEQDataBgnd
       IFDEF EGA
        FallFrom VVReadSEQDataFgnd
       ENDIF

       IFDEF SVGA
        mov     ecx,[psCurAdapterInfo]
        call    [ecx].pbfnSVGAReadSEQDataBgnd
        ExitProc
       ELSE
        mov     ecx,MAX_SEQREGS-1
        cmp     cl,VDMData.regSEQIndx                ;get SEQ controller index
        jb      short vvrd_indexok
        movzx   ecx,VDMData.regSEQIndx
vvrd_indexok:
        mov     al,VDMData.aregSEQData[ecx] ;get indexed SEQ data
        ExitProc
       ENDIF
EndProc   VVReadSEQDataBgnd

       ENDIF


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVWriteSEQDataFgnd
        OUTB    dx,al                       ;output SEQ controller data
        FallInto VVWriteSEQDataBgnd
EndProc   VVWriteSEQDataFgnd

       ENDIF ;EGAVGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVWriteSEQDataBgnd
        FallFrom VVWriteSEQDataFgnd

       IFDEF SVGA                                    ;SVGA
        movzx   ecx,VDMData.regSEQIndx
        mov     ah, VDMData.aregSEQData[ecx]         ;           
        push    eax
        push    ecx
        mov     ecx,[psCurAdapterInfo]
        push    eax
        call    [ecx].pfnSVGAWriteSEQDataBgnd
        pop     ecx
        pop     eax
       ELSE
        mov     ecx,MAX_SEQREGS-1
        cmp     cl,VDMData.regSEQIndx                ;get SEQ controller index
        jb      short vvwd_indexok
        movzx   ecx,VDMData.regSEQIndx
vvwd_indexok:
        mov     VDMData.aregSEQData[ecx],al ;stash the indexed SEQ data
vvwd_svga2:
       ENDIF                                         ;SVGA

;/*
;**
;**   If we're NOT in a graphics mode, then disable all video pages, in
;**   preparation for mode re-determination on the next page fault.  This
;**   allows us to distinguish between text modes and graphics modes that share
;**   the text address space (ie, CGA graphics modes).
;**
;*/

        cmp     VDMData.mstateVideo,MEMORY_GRFX
        jne     short vvwd_disableall
        test    VDMData.flVDMVideo,VDM_PHYSPAGE
        jz      short vvwd_exit

;/*
;**
;**   OK, the magic bit is set, so we have to drop into the magic code that
;**   allows reprogramming of specific bits of certain physical registers, as well
;**   as optional uninterruptible shadowing in external storage.
;**
;*/

        cmp     cl,REG_SEQCLKMODE           ;don't shadow clock data    ;          
        jz      short vvwd_exit                                         ;          
        mov     ecx,prleSEQExtShadowData[ecx*4]
        jecxz   short vvwd_exit
        call    vvShadowDataBgnd
        jmp     short vvwd_exit

vvwd_disableall:
        cmp     cl,REG_SEQMEMMODE                    ;known register?
;**     ja      short vvwd_exit                      ;no, so don't fiddle with buffer
        jne     short vvwd_exit                      ;          

       IFDEF SVGA                                    ;          
        push    ax
        and     ax, 11h                              ;if bit 0 has been changed, enable
        cmp     ah, al
        pop     ax
        jne     short @F
                                                     ;if bit 3 has been changed while the mode
        and     ax, 88h                              ;changing, do not enable
        cmp     ah, al
        je      short vvwd_exit
        test    VDMData.flVDMVideo, VDM_MODECHANGING
        jnz     short vvwd_exit
@@:
       ENDIF                                         ;          
        CallFn  VVEnableBuffer,<FALSE, ebx>

vvwd_exit:
        ExitProc
EndProc   VVWriteSEQDataBgnd

       ENDIF


        EndCode     EXPORT,SWAP,PASCAL


        END
