;*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
;/*****************************************************************************
;*
;* SOURCE FILE NAME = EGAINIT.ASM
;*
;* DESCRIPTIVE NAME = Initialize the EGA/VGA card for color operation
;*
;*
;* VERSION      V2.0
;*
;* DATE         03/21/87
;*
;* DESCRIPTION  This module contains the function which will program an EGA
;*              or VGA for color operation. This file is part
;*              of the device dependent sources.                           
;*
;*              The display adapter is programmed for a 640x350 or 640x480 
;*              16 color mode of operation.  The palette registers are set 
;*              for the default color configuration.                       
;*                                                                         
;*              The VGA's DACs are assumed to be programmed correctly      
;*
;* FUNCTIONS    ring3_physical_enable
;*              ring3_VioGetPSAddress
;*              physical_enable 
;*              physical_disable 
;*              notify_vdd
;*              notify_vwin
;*              save_textvram 
;*              read_vram
;*              restore_textvram 
;*              write_vram
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   12/05/87                     Written by Walt Moore [waltm]
;*   05/06/88                     Bob Grudem [bobgru] Changed MAX_CHAR/ATTR_USE 
;*                                to 2*50*80 from 50*80.
;*   05/06/88                     Bob Grudem [bobgru] Added "/2" to the check   
;*                                against the number of bytes dirtied.  This is 
;*                                necessary because MAX_CHAR_USE and            
;*                                MAX_ATTR_USE are double the actual number of  
;*                                bytes needed to enable the use of "rep movsw".
;*                                In fact, only every other byte is considered  
;*                                dirtied.  A 43-line by 80 column screen of    
;*                                text escapes our rejection test without this  
;*                                compensation.                                 
;*                                Also only restore the number of dirtied       
;*                                bytes in planes 0 and 1, which means the      
;*                                source pointer into the saved bytes must be
;*                                updated before calling write_vram.         
;*   05/26/88                     Bob Grudem [bobgru] Moved init_hw_regs into 
;*                                separate segments, so it becomes a far proc.
;*   08/02/88                     Jeff Parsons [jeffpar] Now called from the 
;*                                new physical_disable routine.  No longer
;*                                saves plane 3 either.  See restore_textvram 
;*                                for more details.
;*   08/02/88                     Jeff Parsons [jeffpar]
;*                                Major revision.  Called before VioSetMode now,
;*                                so it must do some minimal amount of hardware 
;*                                reprogramming itself.  Also doesn't save plane
;*                                3 anymore, since BVS's random plane 3 trashing
;*                                problem should be fixed Real Soon Now.  And   
;*                                zaps memory clean if we know we can't restore 
;*                                it, including the case of physical_enable     
;*                                being called with "INIT_VRAM".                
;*   01/05/89                     Bob Grudem [bobgru]
;*                                Moved the hardware reprogramming into the     
;*                                function reprogram_hardware, and put that     
;*                                function at the beginning of the _TEXT        
;*                                segment.  See critsec.asm for details of why. 
;*   06/20/91                     Tatchi Lay - Video corruption occurs when
;*                                the Window VDM update thread (see PMVDMP.DLL)
;*                                and the death thread are not serialized.
;*   10/25/91                     John Colleran [johnc] Made ExpressWay changes
;*                                limited to VGA driver.  ExpressWay hardware
;*                                will not be run in EGA mode and the change 
;*                                they gave us read from a port that is write 
;*                                only on the EGA (and CGA).
;*                                                          
;*****************************************************************************/

        .286p

        .xlist

        include cmacros.inc
INCL_DEV                equ     1
INCL_SUB                equ     1
        include pmgre.inc
DINCL_SAVE_SCREEN_BITS  equ     1
DINCL_ENABLE            equ     1
        include driver.inc
        include egafam.inc
        include egamemf.inc
INCL_DOSMEMMGR  equ     1
        include bsedos16.inc
        .list

        ??_out  egainit

        externFP init_hw_regs           ;Initialize ega state code
        externFP VioSetMode
        externFP VioGetPSAddress
        externFP VioSetState
        externFP DosCallback
        externFP DosLockSeg
        externFP DosUnlockSeg
        externFP FSRSemEnter                                            ;B722596
        externFP FSRSemLeave                                            ;B722596

ifdef VGA132
        externA  SCREEN_CBSCAN          ;DAK 03/JUL/90 pitch of screen buffer in bytes
endif
        externA  SCREEN_CX              ;Width  of the screen in pels
        externA  SCREEN_CY              ;Height of the screen in pels
        externA  VISIBLE_SIZE_WORDS     ;# words of screen memory which is
                                        ;  visible (height * width)
        externFP DosRequestVDD
        externFP ring3_CriticalError
        externA  SCREEN_CBRESERVED
IFDEF   SEAMLESS
        externD hWinVDD
        externB fSeamless
        externB semDriver
ENDIF   ;SEAMLESS

sBegin  Code
        externNP global_alloc
        externNP global_free
        externNP reprogram_hardware     ;critsec.asm
sEnd

sBegin  Data
        externB semDriver                                               ;B722596
        externW selTextVram
        externW selDeathToUse
        externB fGrimReaper
        externB sdScreen

        externD hVideoVDD
        externB fbOffScreen
        externB drqVideo
        externW wDisplay
        externB bVGAtype

sEnd    Data

sBegin  Ring3Code
        assumes cs,Ring3Code

;/*
;** Since we don't know what are good defaults for the viomi_fmt_ID
;** and viomi_attrib fields, we'll set the structure length to
;** exclude them and throw in some error checking on the fields.
;*/

CB_VIOSETMODE   equ     viomi_fmt_ID
                .errnz  viomi_attrib-viomi_fmt_ID-1
                .errnz  SIZE viomi_attrib-1    

;/*
;** Palette colors as the EGA/VGA uses the adapter
;*/

PAL_BLACK       equ     0
PAL_BLUE        equ     1
PAL_GREEN       equ     2
PAL_RED         equ     4
PAL_YELLOW      equ     PAL_RED or PAL_GREEN
PAL_CYAN        equ     PAL_GREEN or PAL_BLUE
PAL_MAGENTA     equ     PAL_BLUE or PAL_RED
PAL_WHITE       equ     PAL_RED or PAL_GREEN or PAL_BLUE

PAL_I_BLACK     equ     PAL_BLACK       + (PAL_WHITE    shl 3)
PAL_I_RED       equ     PAL_RED         + (PAL_RED      shl 3)
PAL_I_GREEN     equ     PAL_GREEN       + (PAL_GREEN    shl 3)
PAL_I_YELLOW    equ     PAL_YELLOW      + (PAL_YELLOW   shl 3)
PAL_I_BLUE      equ     PAL_BLUE        + (PAL_BLUE     shl 3)
PAL_I_CYAN      equ     PAL_CYAN        + (PAL_CYAN     shl 3)
PAL_I_MAGENTA   equ     PAL_MAGENTA     + (PAL_MAGENTA  shl 3)
PAL_I_WHITE     equ     PAL_WHITE       + (PAL_WHITE    shl 3)

;/*
;** The following values are the initial values for the palette registers.
;*/

vio_palette_data  label  word

        dw      38                      ;# bytes in structure
        .errnz  viopal_cb
        dw      0                       ;Set palette registers
        .errnz  viopal_type-viopal_cb-2
        dw      0                       ;Start with palette 0
        .errnz  viopal_iFirst-viopal_type-2

        .errnz  viopal_acolor-viopal_iFirst-2
ifdef  VGA
;/*
;** On the VGA, the palette contains indices into the array of color DACs.
;** Since we can program the DACs as we please, we'll just put all the indices
;** down at the beginning of the DAC array.
;*/

        dw      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0Ah, 0Bh, 0Ch, 0Dh, 0Eh, 0Fh
else
;/*
;** On the EGA, the palette selects the hardware colors directly.
;*/

        dw      PAL_BLACK
        dw      PAL_BLUE
        dw      PAL_GREEN
        dw      PAL_CYAN
        dw      PAL_RED
        dw      PAL_MAGENTA
        dw      PAL_YELLOW
        dw      PAL_WHITE
        dw      PAL_I_BLACK
        dw      PAL_I_BLUE
        dw      PAL_I_GREEN
        dw      PAL_I_CYAN
        dw      PAL_I_RED
        dw      PAL_I_MAGENTA
        dw      PAL_I_YELLOW
        dw      PAL_I_WHITE
endif


;/*
;** The following parameters are the parameters passed to VioSetMode
;** to enter the desired graphics mode.
;*/

vio_mode_data   label   byte

        dw      CB_VIOSETMODE
        .errnz  viomi_cb

        db      VGMT_OTHER or VGMT_GRAPHICS
        .errnz  viomi_fbType-viomi_cb-2

        db      BITS_PEL
        .errnz  viomi_color-viomi_fbType-1

        dw      80
        .errnz  viomi_col-viomi_color-1

        dw      24
        .errnz  viomi_row-viomi_col-2

        dw      SCREEN_CX
        .errnz  viomi_hres-viomi_row-2

        dw      SCREEN_CY
        .errnz  viomi_vres-viomi_hres-2
        .errnz  ($-vio_mode_data)-CB_VIOSETMODE

;/***************************************************************************
;*
;* FUNCTION NAME = ring3_physical_enable 
;*
;* DESCRIPTION   = ring3_physical_enable makes the actual calls to Vio to enable
;*                 the desired graphics mode.  This code must reside at ring 3. 
;*                 It will be called from the ring2 code via DosCallback.       
;*
;*                 Registers Preserved:       
;*                       SI,DI,BP,DS          
;*                 Registers Destroyed:       
;*                       AX,BX,CX,DX,ES,FLAGS 
;*                 Calls:
;*                       VioSetMode
;*                       VioSetState
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = Vio return code  
;* RETURN-ERROR  = AX = Vio error return code  
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   ring3_physical_enable,<FAR,PUBLIC,NODATA>

cBegin
        farPtr  pviomi,cs,<Ring3CodeOFFSET vio_mode_data>
        cCall   VioSetMode,<pviomi,0>
        or      ax,ax                   ;If error, bail out
        jnz     pe_fail

        farPtr  pviopal,cs,<Ring3CodeOFFSET vio_palette_data>
        cCall   VioSetState,<pviopal,0>

pe_exit:

cEnd

pe_fail:
        cCall   ring3_CriticalError
        jmp     short pe_exit


cProc   ring3_VioGetPSAddress,<FAR,PUBLIC,NODATA>
cBegin
        xor     ax,ax
        push    ax
        push    ax
        mov     bx,sp
        farPtr  ppaviops,ss,bx
        cCall   VioGetPSAddress,<ppaviops,dx>
        or      ax,ax
        pop     ax
        pop     dx
        jz      ring3_VioGetPS_okay
        xor     ax,ax
        xor     dx,dx
ring3_VioGetPS_okay:
cEnd

sEnd
page

sBegin  Code
        assumes cs,Code

        externW  CodeData

staticD ring3_enable,ring3_physical_enable

ifdef VGA
;/*
;** VGA DAC values for the default palette.
;**
;** These values are actually 18-bit numbers stored into three bytes by
;** setting the high two bits of each byte to zero.  Therefore, 3Fh is
;** the maximum value a color component can have.
;**
;**
;**                r    g    b
;*/

vga_dac_data    label   byte

        db      00h, 00h, 00h           ;black
        db      00h, 00h, 28h           ;blue
        db      00h, 28h, 00h           ;green
        db      00h, 28h, 28h           ;cyan
        db      28h, 00h, 00h           ;red
        db      28h, 00h, 28h           ;magenta
        db      28h, 28h, 00h           ;mustard/brown
        db      20h, 20h, 20h           ;dark gray   2A
        db      35h, 35h, 35h           ;light gray  36
        db      00h, 00h, 3Fh           ;bright blue
        db      00h, 3Fh, 00h           ;bright green
        db      00h, 3Fh, 3Fh           ;bright cyan
        db      3Fh, 00h, 00h           ;bright red
        db      3Fh, 00h, 3Fh           ;bright magenta
        db      3Fh, 3Fh, 00h           ;bright yellow
        db      3Fh, 3Fh, 3Fh           ;bright white

SIZE_VGA_DAC_DATA       equ     $ - vga_dac_data

;/*
;** Use 30% Red 59% Green and 11% Blue (from ppxy\phycolor.asm) to map
;** colors to greys
;*/

;/*
;** The above formula is used as the basis but the colors were adjusted
;** to give a greater distinction between all colors.
;*/

mono_dac_data   label   byte

        db      00h, 00h, 00h           ;black
        db      09h, 09h, 09h           ;blue
        db      19h, 19h, 19h           ;green
        db      1Eh, 1Eh, 1Eh           ;cyan
        db      0Dh, 0Dh, 0Dh           ;red
        db      11h, 11h, 11h           ;magenta
        db      22h, 22h, 22h           ;mustard/brown
        db      20h, 20h, 20h           ;dark gray
        db      35h, 35h, 35h           ;light gray
        db      18h, 18h, 18h           ;bright blue
        db      27h, 27h, 27h           ;bright green
        db      2Eh, 2Eh, 2Eh           ;bright cyan
        db      1Dh, 1Dh, 1Dh           ;bright red
        db      20h, 20h, 20h           ;bright magenta
        db      37h, 37h, 37h           ;bright yellow
        db      3Fh, 3Fh, 3Fh           ;bright white

public  vga_dac_data
public  mono_dac_data
endif

page
;/***************************************************************************
;*
;* FUNCTION NAME = far_physical_enable
;*
;* DESCRIPTION   = Graphics mode is enabled by calling Vio.    
;*
;*                 Registers Preserved:       
;*                       SI,DI,BP,DS          
;*                 Registers Destroyed:       
;*                       AX,BX,CX,DX,ES,FLAGS 
;*                 Calls:
;*                       restore_tex tvram
;*                       ring3_physical_enable
;*                       init_hw_regs
;*
;* INPUT         = fInitMem is INIT_VRAM if called from fill_phys_dev_blk;   
;*                     FALSE if called from Resurrection; attempts a fast    
;*                     video RAM restoration in the latter case              
;*                 cbDirty is the number of VRAM bytes to restore for a fast 
;*                     video RAM restoration                                 
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 0 
;* RETURN-ERROR  = AX = Vio Error code if not successful (AX <> 0)               
;*                      or result of video RAM restoration if fInitMem was FALSE 
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   far_physical_enable,<FAR,PUBLIC,WIN,PASCAL>,<si,di>
        parmW   fInitMem
        parmD   cbDirty
        localW  uRetcode
cBegin

ifdef VGA132
        jmp     DoDos
endif

ifdef VGA
        jmp     DoDos
endif

        jmp     enable_worked                     ;Skip Doscallback here for EGA

DoDos:
        save    <ds>                              ;Trashed by upward ring transition
        cCall   DosCallback,<ring3_enable>

        or      ax,ax
        jz      enable_worked
        jmp     enable_failed

enable_worked:
        mov     cx,VISIBLE_SIZE_WORDS
        cmp     fInitMem,INIT_VRAM      ;init visible VRAM only?
        je      enable_restore          ;yes
        mov     ax,cbDirty.lo
        mov     dx,cbDirty.hi           ;otherwise, init/restore up to
        mov     cx,8000h                          ; 32k words

enable_restore:
        call    restore_textvram        ;go to it!
        mov     uRetcode,ax             ;save return code

ifdef VGA
        jmp     notega
endif

ifdef VGA132
        jmp     notega
endif

                                                  ;EGA only
        save    <ds>                              ;Trashed by upward ring transition
        cCall   DosCallback,<ring3_enable>

        or      ax,ax
        jz      notega
        jmp     enable_failed

notega:

ifdef VGA132  ; DAK

        mov     ax,SCREEN_CBSCAN
        cmp     ax,80
        jz      pitch_OK


iowcrtc macro   a,d
        mov     dx,03d4h                ; crtc reg index
        mov     al,&a                   ; reg address
        out     dx,al                   ; do I/O
        mov     dx,03d5h                ; crtc reg data
        mov     al,&d                   ; data for reg
        out     dx,al                   ; do I/O
        endm

        iowcrtc 11h,0ch                 ; Turn off protect bit

        mov     ah,SCREEN_CBSCAN        ; pitch in bytes
        shr     ah,1                    ; pitch in multiples of 16
        iowcrtc 13h,ah                  ; set it

        iowcrtc 11h,8ch                 ; Turn on protect bit

pitch_OK:
endif  ; DAK

;/*
;** Invalidate selDeathToUse.  Make sd_pBits.sel in the surface valid.
;** Hopefully this will hose anyone who thinks they can just pick up
;** selDeathToUse and use it.
;*/

        mov     ax,INVALID_SEL
        xchg    ax,selDeathToUse
        mov     sdScreen.sd_pBits.sel,ax
        mov     fGrimReaper,0           ;Screen access allowed

;/*
;** Perform special initialization required for interrupt state detection.
;*/

        mov     es,ax
        assumes es,EGAMem
        clc                             ;do complete re-initialization
        call    init_hw_regs

ifdef VGA
        public  vga_special_color
vga_special_color:

;/*
;** This is a VGA, so program the color DACs.
;** Below we do the follow before actually sending out the palette:
;**
;** =)    in      03DAh
;** =)    in      03BAh
;** =)    out     03C0h,014h
;** =)    out     03C0h,0
;** =)    out     03C0h,20h
;**
;** The 1st two IN instructions will selectively reset the Attribute Controller
;** Register flip-flop, 3DAh is for color mode and 3BA is for mono.  The OUT
;** to the Attribute Controller Register (3C0) with a value of 14h selects the
;** Color Select Register as the target, a zero value written to the Color
;** Select Register enables the 1st 16 set of R,G,B values in the DAC for
;** attribute mapping.  The last out to 3C0h is required to re-enable the
;** video for display.
;*/

        cli
        mov     dx,EGA_BASE+FEATURE_CONTROL_1
        in      al,dx                   ; Reset the attr reg
        mov     dl,FEATURE_CONTROL_2
        in      al,dx                   ; Reset the attr reg
        mov     al,COLOR_SELECT
        mov     dl,ATTR_REG
        out     dx,al                   ;select "color select register"
        xor     al,al                   ;set color select register to 0
        out     dx,al                   ;This means we are using "palette 0".

        mov     al,PAL_ADDR_SRC         ;set palette address source flag to TRUE.
        out     dx,al                   ;I think this could be combined with the
                                        ;previous OUT.
        mov     dl,DAC_INDEX
        xor     al,al                   ;AL = 0 = starting index
        out     dx,al                   ;specify starting index
        mov     dl,DAC_DATA             ;DX --> DAC data register
        mov     cx,SIZE_VGA_DAC_DATA

        mov     si,CodeOFFSET mono_dac_data ; reprogram the DACs according
        cmp     wDisplay,DISPLAY_8503       ; to the monitor attached
        je      slow_outs                   ; 8503 and PLASMA are the only
        mov     si,CodeOFFSET vga_dac_data
slow_outs:
        outs    dx,byte ptr cs:[si]     ; I'd sure like to make this loop
        loop    slow_outs               ; into REP OUTSB, but slow boxes die?
        sti
endif
        mov     drqVideo.vvd_pPhysVRAM.lo,0000h
        mov     drqVideo.vvd_pPhysVRAM.hi,000Ah
        mov     drqVideo.vvd_nbReserved.lo,SCREEN_CBRESERVED
        mov     drqVideo.vvd_nbReserved.hi,0
        call    notify_vdd              ;notify the VDD, if any

IFDEF   SEAMLESS
        cmp     fInitMem,INIT_VRAM      ;Is this coming from Enable or Resurrection?
        je      @f                      ;We're being called from Enable
        test    fSeamless,SEAMLESS_ACTIVE
        je      @f
        mov     ax,VDM_RESUME_DRAW      ;Let the VDM's continue using the
        mov     bx,uRetcode             ;Pass the Force Repaint flag to WINDD
        call    notify_vwin             ;  video hardware.
IFDEF   FIREWALLS
        or      ax,ax
        jne     resume_failed
        color_puts      BLUE,BLACK,<   PMVGA: VDM_RESUME_DRAW successful.>
        jmp     short @f
resume_failed:
        color_puts      WHITE,BLUE,<   PMVGA: VDM_RESUME_DRAW failed.>
ENDIF   ;FIREWALLS
@@:
ENDIF   ;SEAMLESS

        mov     ax,uRetcode

enable_failed:                          ;error code already in AX
cEnd

page

;/***************************************************************************
;*
;* FUNCTION NAME = far_physical_disable
;*
;* DESCRIPTION   = Prepare for death.                                           
;*                     
;*                 Registers Preserved:       
;*                       SI,DI,BP,DS          
;*                 Registers Destroyed:       
;*                       AX,BX,CX,DX,ES,FLAGS 
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

IFDEF   SEAMLESS
        externNP SeamlessHeartbeat
ENDIF   ;SEAMLESS

cProc   far_physical_disable,<FAR,PUBLIC,WIN,PASCAL>,<si,di>
cBegin

;/*
;**  Give the VDD a chance to complete all cleanup work first before the
;**  text portion of the VRAM is saved.
;**
;**  Note:  FSRSemEnter is chosen over enter_driver_sem because the call
;**         to req_controller is not needed.
;*/

        sub     ax,ax                   ;AX == 0
        mov     drqVideo.vvd_pPhysVRAM.lo,ax
        mov     drqVideo.vvd_pPhysVRAM.hi,ax
        dec     ax                      ;AX == 0FFFFh
        mov     drqVideo.vvd_nbReserved.lo,ax
        mov     drqVideo.vvd_nbReserved.hi,ax
        call    notify_vdd

IFDEF   SEAMLESS
        test    fSeamless,SEAMLESS_ACTIVE
        je      @f
        mov     ax,VDM_SUSPEND_DRAW     ;Must stop seamless vdm's from
        xor     bx,bx
        call    notify_vwin             ;  tampering with the hardware.
IFDEF   FIREWALLS
        or      ax,ax
        jne     suspend_failed
        color_puts      BLUE,BLACK,<   PMVGA: VDM_SUSPEND_DRAW successful.>
        jmp     short @f
suspend_failed:
        color_puts      WHITE,BLUE,<   PMVGA: VDM_SUSPEND_DRAW failed.>
ENDIF   ;FIREWALLS
@@:
ENDIF   ;SEAMLESS

IFDEF   SEAMLESS
far_physical_disable_retry:
ENDIF   ;SEAMLESS
        cCall   FSRSemEnter,<DataOFFSET semDriver>                      ;B722596
IFDEF   SEAMLESS
        or      ax,ax
        je      @f
        cCall   SeamlessHeartbeat
        jmp     short far_physical_disable_retry
@@:
ENDIF   ;SEAMLESS
        dec     fGrimReaper             ;Make it -1
        mov     ax,INVALID_SEL
        xchg    sdScreen.sd_pBits.sel,ax
        mov     selDeathToUse,ax

        call    save_textvram           ;save VRAM to be trashed
        cCall   FSRSemLeave,<DataOFFSET semDriver>                      ;B722596
cEnd


cProc   notify_vdd,<NEAR,PUBLIC>
cBegin
        test    fbOffScreen,OFFSCR_VDD  ;is VDD open?
        jz      enable_exit             ;no

        sub     dx,dx
        farPtr  hvdd,hVideoVDD.hi,hVideoVDD.lo
        farPtr  cbInput,dx,%(size vvdrq_s)
        farPtr  pInput,ds,<DataOFFSET drqVideo>
        farPtr  cbOutput,dx,dx
        farPtr  pOutput,dx,dx
        cCall   DosRequestVDD,<hvdd,dx,VVDSYSREQ_SETDRQ,cbInput,pInput,cbOutput,pOutput>
enable_exit:
cEnd

IFDEF   SEAMLESS
;/***************************************************************************
;*
;* FUNCTION NAME = notify_vwin
;*
;* DESCRIPTION   = This function tells the VWIN to notify all seamless VDM's
;*                 to stop drawing to the screen or to continue drawing.
;*
;* INPUT         = ax = VDM_SUSPEND_DRAW (4001h) to stop drawing
;*                 ax = VDM_RESUME_DRAW (4002h) to continue drawing
;*                 bx = 1 to force repaint on VDM_RESUME_DRAW, 0 otherwise.
;*                      (This is not relevalnt for VDM_SUSPEND_DRAW)
;*              
;* OUTPUT        = ax = return code from DosRequestVDD
;*              
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

cProc   notify_vwin,<NEAR,PUBLIC>
cBegin
        test    fSeamless,SEAMLESS_ACTIVE
        je      not_seamless

        sub     dx,dx
        farPtr  hvdd,hWinVDD.hi,hWinVDD.lo
        farPtr  cbInput,dx,ax
        farPtr  pInput,dx,dx
        farPtr  cbOutput,dx,bx
        farPtr  pOutput,dx,dx
        cCall   DosRequestVDD,<hvdd,-1,VWIN_SIGVDMDIRTY,cbInput,pInput,cbOutput,pOutput>
not_seamless:
cEnd
ENDIF   ;SEAMLESS


page

;/***************************************************************************
;*
;* FUNCTION NAME = save_textvram 
;*
;* DESCRIPTION   = Allocates a segment into which we save 8000 bytes of       
;*                 char/attr data (50 lines being the most a typical VIO text 
;*                 application will ever touch), and 8192 bytes from the 1st  
;*                 font block in plane 2. Note that although text information 
;*                 is contained only in even-address bytes in planes 0 and 1, 
;*                 the odd-address bytes seem to matter too.  They would      
;*                 certainly matter for the low-res CGA graphics modes, which 
;*                 use plane 0 for even bits and plane 1 for odd bits, but VIO
;*                 probably just returns -1 for the dirty count in that case, 
;*                 just because it isn't a text mode.  This is currently only 
;*                 called during Death(), and must be done AFTER the          
;*                 selDeathToUse selector is made valid.                      
;*                                                                            
;*                 Registers Preserved:                                                                       
;*                       BP,DS                                                                                
;*                 Registers Destroyed:                                                                       
;*                       AX,BX,CX,DX,SI,DI,ES,FLAGS                                                           
;*                 Calls:
;*                       global_alloc
;*                                                                            
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 0 
;* RETURN-ERROR  = AX = Dos Error code 
;*
;**************************************************************************/

ifdef VGA
MAX_CHAR_USE    equ     60*132*2                 ;9600 bytes (plane 0)  ;SVGA
MAX_ATTR_USE    equ     60*132*2        ;9600 bytes (plane 1)  ;SVGA
else
MAX_CHAR_USE    equ     43*80*2         ;6880 bytes (plane 0)
MAX_ATTR_USE    equ     43*80*2         ;6880 bytes (plane 1)
endif
MAX_FONT_USE    equ     256*32          ;8192 bytes (plane 2)
MAX_SAVE_SIZE   equ     MAX_CHAR_USE + MAX_ATTR_USE + MAX_FONT_USE + MAX_FONT_USE

        assumes ds,Data
        assumes es,nothing

cProc   save_textvram,<NEAR,PUBLIC>
        localW  selTemp
cBegin
        lea     bx,selTemp
        mov     ax,MAX_SAVE_SIZE and 0FFFFh
        mov     dx,MAX_SAVE_SIZE shr 16
        mov     cx,SEG_DISCARDABLE
        call    global_alloc
        xchg    ax,cx
        or      ax,ax
        jnz     save_exit               ;exit w/error
        mov     ax,selTemp
        mov     selTextVram,ax

        cld
        mov     es,ax
        assumes es,nothing
        sub     di,di                   ;ES:DI -> top of private segment

ifdef VGA
;/*
;** Is this an ExpressWay adapter; if so then do a special mode switch
;** VGA == 0FFh   ExpressWay == 0
;*/
        cmp     bVGAtype,VGA_EXPRESSWAY
        jne     st_do_save

;/*
;** Patch for save_textvram and restore_textvram
;** Corrupts ax and dx (but these are unlikely to be long term storage for
;**  anything, and could be saved)
;** Function:
;**  Sets the byte/word flag (which controls RAM remapping in Expressway) to
;**   the state that it is in in text modes for the save / restore function,
;**   and then restores it to its correct value. This code should be added to
;**   both save_textvram and restore_textvram
;*/

        mov     dx,3dah
        in      al,dx
        mov     dx,3c0h
        mov     al,0
        out     dx,al           ; turn video off first

        mov     dx,3d4h         ; Access CRTC register index 17h
        mov     al,17h
        out     dx,al
        inc     dx
        in      al,dx           ; Read value
        push    ax
        and     al,0bfh         ; Clear bit 6 (byte/word bit)
        out     dx,al           ; Write it back

endif   ;VGA


st_do_save:
        mov     ds,selDeathToUse
        assumes ds,EGAMem               ;DS:0  -> top of VRAM

        sub     ah,ah                   ;read from plane 0
        mov     cx,MAX_CHAR_USE/2       ;this many words
        call    read_vram

        inc     ah                      ;read from plane 1
        mov     cx,MAX_ATTR_USE/2       ;this many words
        call    read_vram

        inc     ah                      ;read from plane 2
        mov     cx,MAX_FONT_USE/2       ;this many words
        call    read_vram

        inc     ah                                ;read from plane 3 ;SVGA
        mov     cx,MAX_FONT_USE/2       ;this many words ;SVGA
        call    read_vram                            ;SVGA

        cCall   DosUnlockSeg,<es>       ;allow segment to be discarded now

        mov     ds,CodeData
        assumes ds,Data
 
ifdef   VGA
        cmp     bVGAtype,VGA_EXPRESSWAY
        jne     st_nearly_done

        pop     ax              ; Retrieve register value
        mov     ah,al           ; Put value at correct end of register
        mov     dx,3d4h         ; Access CRTC register index 17h
        mov     al,17h
        out     dx,ax

endif   ;VGA


st_nearly_done:

        xor     ax,ax                   ;show success

save_exit:
cEnd

cProc   read_vram,<PUBLIC,NEAR>
cBegin
        mov     al,GRAF_READ_MAP        ;plane # already in AH
        mov     dx,EGA_BASE+GRAF_ADDR
        out16   dx,ax                   ;select plane # to read
        sub     si,si
        rep     movsw                   ;transfer to private segment
cEnd

page

;/***************************************************************************
;*
;* FUNCTION NAME = restore_textvram 
;*
;* DESCRIPTION   = Copies the data from our temporary TextVram segment back
;*                 to VRAM, if the number of dirtied VRAM bytes does not   
;*                 exceed the number we saved at time of Death().  Assuming
;*                 that's the case, the shell will not need to perform any 
;*                 repainting.  Otherwise, an error is propagated back to  
;*                 the shell.  This is currently only called during        
;*                 Resurrection(), and must be done BEFORE selDeathToUse is
;*                 invalidated.                                            
;*                                                                         
;*                 Registers Preserved:                                                                  
;*                       BP,DS,ES                                                                        
;*                 Registers Destroyed:                                                                  
;*                       AX,BX,CX,DX,SI,DI,FLAGS                                                         
;*                 Calls:
;*                       global_free
;*                                                                         
;* INPUT         = ECX = max words of VRAM to restore            
;*                      (VISIBLE_SIZE_WORDS implies init only)                                                           
;*                 EAX = count of VRAM bytes dirtied since Death                                                         
;*                                                                         
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = AX = 0 if successful
;* RETURN-ERROR  = AX = 1 if VRAM buffer has to be re-initialized.
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   restore_textvram,<PUBLIC,NEAR>

cBegin
        cld
        mov     es,selDeathToUse
        assumes es,EGAMem               ;ES:0 -> top of VRAM

        save    <ax,cx,dx>
        cCall   reprogram_hardware

        cmp     cx,VISIBLE_SIZE_WORDS
        jne     @F
        jmp     restore_initonly        ;init visible VRAM only
@@:
        mov     bx,selTextVram
        or      bx,bx                   ;any selector there?
        jz      restore_bad             ;no
        or      dx,dx
        jnz     restore_bad             ;count definitely too big
        cmp     ax,(MAX_CHAR_USE+MAX_ATTR_USE)/2
        ja      restore_bad             ;count too big (too much dirtied)

        push    ax
        cCall   DosLockSeg,<bx>
        or      ax,ax
        pop     ax
        jnz     restore_bad             ;segment was discarded, too bad

        mov     ds,bx
        assumes ds,nothing
        mov     bx,ax                   ;set up adjusted word count
        shr     bx,1                    ;BX = total words

ifdef   VGA

;/*
;** Patch for save_textvram and restore_textvram
;** Corrupts ax and dx (but these are unlikely to be long term storage for
;**  anything, and could be saved)
;** Function:
;**  Sets the byte/word flag (which controls RAM remapping in Expressway) to
;**   the state that it is in in text modes for the save / restore function,
;**   and then restores it to its correct value. This code should be added to
;**   both save_textvram and restore_textvram
;*/

        mov     dx,3dah
        in      al,dx
        mov     dx,3c0h
        mov     al,0
        out     dx,al           ; turn video off first

        mov     dx,3d4h         ; Access CRTC register index 17h
        mov     al,17h
        out     dx,al
        inc     dx
        in      al,dx           ; Read value
        push    ax
        and     al,0bfh         ; Clear bit 6 (byte/word bit)
        out     dx,al           ; Write it back

;/*
;** Patch for VGAs that have problems switching from text modes to PM
;**  eq. new Compaq VGA
;*/
        mov     dx,3dah         ; reset the flip-flop
        in      al,dx
        mov     dx,3c0h
        mov     al,10h          ; index the mode control reg of Attr controller
        out     dx,al
        mov     al,01h          ; set it treat data as graphics
        out     dx,al

endif   ;VGA

        mov     al,0001b                ;write to plane 0
        mov     cx,bx                   ; 
        xor     si,si                   ;DS:SI -> top of private segment
        call    write_vram              ; 

        shl     al,1                    ;write to plane 1
        mov     cx,bx                   ; 
        mov     si,MAX_CHAR_USE
        call    write_vram              ; 

        shl     al,1                    ;write to plane 2
        mov     cx,MAX_FONT_USE/2       ;this many words
        mov     si,MAX_CHAR_USE+MAX_ATTR_USE
        call    write_vram

        shl     al,1                              ;write to plane 3 ;SVGA
        mov     cx,MAX_FONT_USE/2       ;this many words ;SVGA
        mov     si,MAX_CHAR_USE+MAX_ATTR_USE+MAX_FONT_USE ;SVGA
        call    write_vram

ifdef   VGA

        pop     ax              ; Retrieve register value
        mov     ah,al           ; Put value at correct end of register
        mov     dx,3d4h         ; Access CRTC register index 17h
        mov     al,17h
        out     dx,ax

endif   ;VGA

        mov     ds,CodeData
        assumes ds,Data
        sub     ax,ax                   ;show success
        jmp     short restore_exit

restore_bad:
        or      fbOffScreen,OFFSCR_TRASHED
                                        ;error: cannot restore
restore_initonly:
        mov     ax,0                    ;don't change flags!
        mov     di,ax                   ;clear video ram
        rep     stosw
        je      restore_exit
        inc     ax                      ;on error, return error (AX=1)

restore_exit:
        push    ax
        sub     cx,cx
        xchg    cx,selTextVram
        call    global_free
        pop     ax
cEnd

cProc   write_vram,<PUBLIC,NEAR>
cBegin
        mov     dx,EGA_BASE+SEQ_DATA
        out     dx,al                   ;select plane # to write
        sub     di,di
        rep     movsw                   ;transfer back to screen surface
cEnd

sEnd


end
