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

;/*****************************************************************************
;*
;* SOURCE FILE NAME = VVATCIO.ASM
;*
;* DESCRIPTIVE NAME = Virtual Video Device Driver ATC I/O Processing  
;*
;*
;* VERSION      V2.0
;*
;* DATE         11/10/88
;*
;* DESCRIPTION  This module contains the VVD's ATC I/O handlers.
;*              
;* FUNCTIONS    VVReadATCFgnd()      Read ATC byte foreground
;*              VVReadATCBgnd()      Read ATC byte background
;*              VVWriteATCFgnd()     Write ATC byte foreground
;*              VVWriteATCBgnd()     Write ATC byte background
;*              VVReadATCFgndW()     Read ATC word foreground
;*              VVWriteATCFgndW()    Write ATC word background
;*              VVReadATC1Fgnd()     Read ATC1 byte foreground
;*              VVReadATC1Bgnd()     Read ATC1 byte background
;*              
;* 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/28/91                     Make sure ATC flip-flop is kept track
;*                                correctly B722943.
;*
;*   01/29/92                     ATC Reads mess up the flip-flop state
;*                                B731859.
;*
;*   02/27/92                     B733211 - Performance enhancement to
;*                                320x200 mode
;*
;*****************************************************************************/


        .xlist
        INCL_MI equ 1                   
        include mvdm.inc
        include vddseg.inc
        .list
        include vvd.inc
        include vvdp.inc


        DefCode     EXPORT,SWAP,PASCAL

       IFDEF EGA
        DefFn       VVReadATCFgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVReadATCBgnd
        DefFn       VVWriteATCFgnd
        DefFn       VVWriteATCBgnd
       ENDIF
       IFDEF EGA
        DefFn       VVReadATCFgndW
        DefFn       VVWriteATCFgndW
       ENDIF
       IFDEF EGA
        DefFn       VVReadATC1Fgnd
       ENDIF
       IFDEF EGAVGA
        DefFn       VVReadATC1Bgnd
       ENDIF


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadATCFgnd()
;*
;* DESCRIPTION   = Read ATC byte foreground 
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM reads a byte from the ATC controller 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_ATC0)
;*
;* OUTPUT        = AL  == data read                  
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadATCFgnd
        FallInto VVReadATCBgnd
EndProc   VVReadATCFgnd

       ENDIF ;EGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVReadATCBgnd
       IFDEF EGA
        FallFrom VVReadATCFgnd
       ENDIF
        mov     al,VDMData.regATCIndx       ;return ATC controller index
        ExitProc
EndProc   VVReadATCBgnd

       ENDIF ;EGAVGA


       IFDEF EGAVGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteATCFgnd()
;*
;* DESCRIPTION   = Write ATC byte foreground 
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM writes a byte to the ATC controller register (see
;*                 VDHInstallIOHook for complete semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_ATC0 or, on an EGA, PORT_ATC1)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 update hardware
;*                 if ATC flip-flop clear
;*                   update ATC index value
;*                 else
;*                   mask index with MAX_ATCREGS-1
;*                   index into ATC array, update value
;*                 toggle ATC flip-flop
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteATCFgnd
       IFDEF VGA
        push    edx
        cmp     edx,PORT_ATC1
        jne     short vvwatc_not1
        dec     edx
vvwatc_not1:

       ENDIF                                                            

        OUTB    dx,al                       ;output ATC controller index/data
       IFDEF VGA

;/*
;**
;**         Since we don't trap read access to 3BA/3DA while the VDM is
;**         foreground (for performance reasons), we must be able to some
;**         how maintain the flip-flop state by confirming the Data
;**         value written sticks if the last I/O to the ATC is not PAL Enable.
;**
;*/

        mov     ecx,eax                     ;CL = Index/Data written   ;          
        INB     al,dx                       ;Read it back              ;          
        xchg    eax,ecx                     ;AL = orig. Index/Data     ;          
                                            ;CL = Current Index        ;          
        cmp     cl,ATCPAL_ENABLE            ;PAL enabled?              ;          
        mov     VDMData.stateATC,ATC_INDEX  ;assume Index              ;          
        pop     edx                         ;balance stack             ;          
        jnz     ff_index                    ;exit on PAL enable        ;          
        mov     VDMData.regATCIndx,cl       ;save PAL enable bits      ;          
        jmp     vvwatc_exit                 ;                          ;          
ff_index:                                   ;                          ;          
        cmp     VDMData.regATCIndx,cl       ;Index changed?            ;          
        jnz     ff_ok                       ;                          ;          
        mov     VDMData.stateATC,NULL       ;must be Datat Data        ;          
ff_ok:
       ENDIF
        FallInto VVWriteATCBgnd
EndProc   VVWriteATCFgnd

       ENDIF ;EGAVGA


       IFDEF EGAVGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteATCBgnd()
;*
;* DESCRIPTION   = Write ATC byte background 
;*
;*                 This registered subroutine is called whenever a background
;*                 VDM writes a byte to the ATC controller register (see
;*                 VDHInstallIOHook for complete semantics).
;*
;* INPUT         = AL == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_ATC0 or, on an EGA, PORT_ATC1)
;*
;* OUTPUT        =
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 if ATC flip-flop clear
;*                   update ATC index value
;*                 else
;*                   mask index with MAX_ATCREGS-1
;*                   index into ATC array, update value
;*                 toggle ATC flip-flop
;*                 
;**************************************************************************/

        DefData IMPORT,SWAPINST,C
        _BYTE   nFlips,0
        EndData

        align   4                                                       ;          
Procedure VVWriteATCBgnd
        FallFrom VVWriteATCFgnd
        movzx   ecx,VDMData.regATCIndx      ;get ATC controller index
        and     cl,MAX_ATCREGS-1            ;don't over-index (critical!)
        .ERRNZ  ATC_DATA  NE 0
        .ERRNZ  ATC_INDEX NE -1
        .ERRNZ  regATCIndx NE aregATCData-1
        or      ecx,VDMData.stateATC        ;convert to -1 if in INDEX state
        mov     VDMData.aregATCData[ecx],al ;stash the indexed ATC data

;/*
;**                                                                     ;          
;**     Keep the flip flop at reset state if Palette is being reenable. ;          
;**                                                                     ;          
;**     Note:  This is a        safe assumption to make because most    ;          
;**            DOS applications will make sure the flip-flop is always  ;          
;**            reset (through reading of either 3BA or 3DA) before      ;          
;**            the ATC change starts.                                   ;          
;**                                                                     ;          
;*/

        cmp     al,ATCPAL_ENABLE            ;palette enable and         ;          
        jnz     flip_flipflop                                           ;          
        cmp     VDMData.regATCIndx,al       ;PAL Enable?                ;          
        jnz     flip_flipflop               ;flip flop state            ;          
        mov     VDMData.stateATC,NULL       ;force to Index below       ;          
flip_flipflop:                                                          ;          
        not     VDMData.stateATC            ;flip the flop
skip_flipflop:                                                          ;          
        or      VDMData.flVDMVideo,VDM_DIRTYPALETTE
        mov     [nFlips],0                  ;reset our own page-flip flip-flop

       IFDEF VGA
        cmp     edx,PORT_ATC0               ;FLAG: needs to be done
        jne     short vvwatc_exit           ;with true word I/O handler!
        movzx   edx,[ebx].crf_cs
        shl     edx,4
        movzx   ecx,word ptr [ebx].crf_eip
        add     edx,ecx
        dec     edx                         ;EDX -> last ins. executed (sort of)
        cmp     byte ptr [edx],MI_OUT_DX_AX
        jne     short vvwatc_exit
        push    eax                                                    
        mov     al,ah
        mov     edx,PORT_ATC1
        test    VDMData.flVDMVideo,VDM_FGND
        jz      short vvwatc_bgnd
        call    VVWriteATCFgnd              ;fix word I/O on VGA!
        pop     eax                                                    ;          


;/*
;**     CUMULUS VGA BIOS problem workaround
;*/

        cmp     al,ATCPAL_ENABLE            ; workaround the           ;          
        jb      vvwatc_exit                 ; CUMULUS VGA BIOS         ;          
        out     dx,al                       ; problem                  ;          

;/*
;**     End of workaround
;*/


        jmp     short vvwatc_exit
vvwatc_bgnd:
        call    VVWriteATCBgnd              ;fix word I/O on VGA!
        pop     eax                                                    ;          
vvwatc_exit:
       ENDIF

        ExitProc
EndProc   VVWriteATCBgnd

       ENDIF ;EGAVGA


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadATCFgndW()
;*
;* DESCRIPTION   = Read ATC word foreground 
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM reads a word from the ATC 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_ATC0)
;*
;* OUTPUT        = AX  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadATCFgndW
        mov     al,VDMData.regATCIndx       ;get ATC controller index
        movzx   ecx,al                      ;form our own index
        and     cl,MAX_ATCREGS-1            ;don't over-index
        mov     ah,VDMData.aregATCData[ecx] ;get indexed ATC data
        ExitProc
EndProc   VVReadATCFgndW

       ENDIF ;EGA


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVWriteATCFgndW()
;*
;* DESCRIPTION   = Write ATC word background 
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM writes a byte to the ATC controller index register (see
;*                 VDHInstallIOHook for complete semantics).
;*
;* INPUT         = AX == data to write
;*                 EBX -> VDM register frame
;*                 EDX == port number (PORT_ATC0)
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 call VVWriteATCFgnd with low byte
;*                 call VVWriteATCFgnd with high byte
;*                                              
;**************************************************************************/

        align   4                                                       ;          
Procedure VVWriteATCFgndW
        call    VVWriteATCFgnd              ;output the low byte
        mov     al,ah
        call    VVWriteATCFgnd              ;output the high byte
        ExitProc
EndProc   VVWriteATCFgndW

       ENDIF ;EGA


       IFDEF EGA

;/***************************************************************************
;*
;* FUNCTION NAME = VVReadATC1Fgnd()
;*
;* DESCRIPTION   = Read ATC1 byte foreground 
;*
;*                 This registered subroutine is called whenever a foreground
;*                 VDM reads a byte from the ATC controller 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_ATC1)
;*
;* OUTPUT        = AL  == data read
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;* PSEUDO-CODE
;*                 mask index with MAX_ATCREGS-1
;*                 index into ATC array, update value
;*                                        
;**************************************************************************/

        align   4                                                       ;          
Procedure VVReadATC1Fgnd
        FallInto VVReadATC1Bgnd
EndProc   VVReadATC1Fgnd

       ENDIF ;EGA


       IFDEF EGAVGA

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

        align   4                                                       ;          
Procedure VVReadATC1Bgnd
       IFDEF EGA
        FallFrom VVReadATC1Fgnd
       ENDIF
        movzx   ecx,VDMData.regATCIndx      ;get ATC controller index
        and     cl,MAX_ATCREGS-1            ;don't over-index
        mov     al,VDMData.aregATCData[ecx] ;get indexed ATC data
        ExitProc
EndProc   VVReadATC1Bgnd

       ENDIF ;EGAVGA


        EndCode     EXPORT,SWAP,PASCAL


        END
