;*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.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = CRITSEC.ASM
;*
;* DESCRIPTIVE NAME = Critical Sections
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/21/89
;*
;* DESCRIPTION  This file contains critical sections that must be aligned so
;*              as to not cross page boundaries, as well as any data they
;*              access.  We use the fact that segments are aligned on page
;*              boundaries, so that our critical sections will be protected
;*              from page faults as long as they don't fill a whole page.
;*              This can be checked at initialization in a firewall.  In
;*              addition, there are .erre directives at the end of the code
;*              segment in this file to halt compilation if it's size exceeds
;*              a page size.  Unfortunately, the system page size can change
;*              in future releases of OS/2.  If this file compiles, but the
;*              firewall causes a rip, then the page size has probably
;*              changed.  In that case, adjust the PAGESIZE constant defined
;*              on the "make" command line.  Since there's no way to guarantee
;*              that the desired data segment will be in RAM when it is
;*              accessed, any data accessed from within a critical section
;*              must be stored in a fixed memory segment, in this case
;*              PtrData.  The Data segment, if any, in this file may contain
;*              relevant data for the critical code, but data in it cannot be
;*              accessed from within the cli/sti bracket.
;*
;*
;* FUNCTIONS    reprogram_hardware
;*              InitTonysBarNGrill
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/21/89                     Written by Bob Grudem
;*
;*****************************************************************************/

.386
.MODEL FLAT
ASSUME  SS:FLAT, DS:FLAT, CS:FLAT, ES:FLAT
        .xlist
        include pmgre.inc
        DINCL_BITMAP            equ     1
        DINCL_EGAMEM            equ     1
        DINCL_ENABLE            equ     1
        include driver.inc
        include egafam.inc
        include extern.inc
ifdef EGAMEM_IS_STRUCT
        include egamem.inc
endif
if SCAN_CNT EQ 768
        include oem_macs.inc
        include protos.inc
endif
        .list


;.DATA
_DATA SEGMENT DWORD PUBLIC FLAT 'DATA'

;/*
;** Table of data for programming the EGA/VGA, used by reprogram_hardware.
;**
;** The entries with "+1" in the port address are marked for special
;** handling, which means the output must be performed with asynchronous
;** reset.  Since extended time without synchronous reset can cause
;** data loss in video RAM, these entries are output within a critical
;** section to prevent interrupts, and the whole function has been moved
;** to the beginning of its segment to be sure of not crossing a page
;** boundary.  This table is accessed outside of the critical section,
;** so it can be placed in the main Data segment.
;**
;** Some of the entries in this table set important mode values, some others
;** simply set registers to known values.
;*/

        public  inittbl
ALIGN 4
inittbl label   word

        dw      EGA_BASE+SEQ_ADDR+1,  SEQ_MODE+(SM_EXTENDED+SM_ODD_PLANE)*256 ;memory mode
        dw      EGA_BASE+SEQ_ADDR,    SEQ_MAP_MASK+MM_ALL*256 ;enable all planes
        dw      EGA_BASE+GRAF_ADDR,   GRAF_SET_RESET   ;set to black
        dw      EGA_BASE+GRAF_ADDR,   GRAF_ENAB_SR     ;disable all planes
        dw      EGA_BASE+GRAF_ADDR,   GRAF_COL_COMP    ;set to black
        dw      EGA_BASE+GRAF_ADDR,   GRAF_DATA_ROT    ;no rotation, rop=S
        dw      EGA_BASE+GRAF_ADDR,   GRAF_READ_MAP    ;no color compare
        dw      EGA_BASE+GRAF_ADDR,   GRAF_MODE        ;write/read mode 0
        dw      EGA_BASE+GRAF_ADDR+1, GRAF_MISC+(MS_NON_ALPHA+MS_A0000_64K)*256 ;grafx misc
        dw      EGA_BASE+GRAF_ADDR,   GRAF_CDC+0Fh*256 ;set to white
        dw      EGA_BASE+GRAF_ADDR,   GRAF_BIT_MASK+0FFh*256  ;enable all bits
        dw      0                                         ;end-of-table marker

_DATA ENDS
        page
;.CODE
_PtrCode32 SEGMENT DWORD PUBLIC FLAT 'CODE'

    public  begin_crit_code
begin_crit_code label   byte



;/***************************************************************************
;*
;* FUNCTION NAME = reprogram_hardware
;*
;* DESCRIPTION   = The EGA/VGA is reprogrammed to fit our needs.  The details
;*                 are contained in the table inittbl above.  Some output
;*                 sequences in the table could result in loss of data in
;*                 video memory if interrupted.  The possible interruptions
;*                 are page faults and hardware interrupts.  To protect
;*                 against hardware interrupts, cli and sti instructions
;*                 surround the critical section of code.  To protect against
;*                 page faults, the function is near the beginning of its
;*                 segment.  Since segments are loaded on page boundaries, we
;*                 can without much difficulty arrange that the critical
;*                 section does not cross a page boundary (some compile-time
;*                 checking, and a run-time firewall to be precise).
;*
;*                 Registers Preserved:
;*                       BX,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ALIGN 4
reprogram_hardware PROC SYSCALL

        mov     dx,EGA_BASE+IN_STAT_1
        in      al,dx                            ;reset the ATC flip-flop
        mov     dl,IN_STAT_1-20h
        in      al,dx                            ;use mono port too, for good measure
        mov     dl,ATTR_WRITE
        sub     al,al
        out     dx,al                            ;clear palette source bit to turn video off

        mov     esi,OFFSET inittbl
restore_init:                                    ;initialize all regs to default
        lodsw
        or      ax,ax
        jz      restore_initdone
        mov     dx,ax
        lodsw
        test    dx,1                             ;special-handling bit set?
        jz      restore_initcont                 ;no

;/*
;** This next block uses the carry flag to indicate that special handling
;** is in effect.  Notice that after the "stc", no instruction alters the
;**carry flag before the "jnc" can read it.
;*/

        and     dx,not 1                          ;clear special-handling bit
        stc
        mov     di,dx
        mov     cx,ax

        cli                                       ;can't use out16 because of this CLI
        mov     dl,SEQ_ADDR
        mov     ax,0100h                          ;clear synchronous reset bit
        out     dx,ax
        pushf
        mov     ax,wSVGAtype
        cmp     ax,VIDEO7_ADAPTER
        je      @F
        cmp     ax,TSENG_ADAPTER
        je      @F

;/*
;** FIX for timing problem on IBM VGA
;*/
        mov     ax,0007h                          ;select "mystery reg" 7 of sequencer
        out     dx,ax                             ;and write a 0 to it
        mov     ax,013Fh                          ;select "mystery reg" 3Fh of the CRTC
        mov     dl,CRTC_ADDR                      ; 
        out     dx,ax                             ;write a 1 to the color location
        mov     dl,CRTC_ADDR-20h                 ; 
        out     dx,ax                             ;and to the mono location as well
@@:
        popf

;/*
;**END FIX for timing problem on IBM VGA
;*/

        mov     ax,cx
        mov     dx,di
restore_initcont:
        out     dx,ax                             ;do the OUT specified in the tbl
        jnc     restore_init

        mov     dl,SEQ_ADDR                       ;if special handling was required
        mov     ax,0300h                          ;turn synchronous reset bit back on
        out     dx,ax
        sti
        jmp     restore_init                      ;loop until table exhausted
ALIGN 4
restore_initdone:
        mov     dl,SEQ_ADDR
        mov     al,SEQ_MAP_MASK                  ;leave sequencer addr positioned here
        out     dx,al
        ret
reprogram_hardware ENDP

        page
;/***************************************************************************
;*
;* FUNCTION NAME = InitTonysBarNGrill
;*
;* DESCRIPTION   = This function sets the EGA to color-write mode.  This
;*                 means that when a byte is written to video RAM, the four
;*                 lower bits are treated as a solid color to write.  For
;*                 example, if the value written out is 00001010b, then the
;*                 EGA will fill plane 0 through 3 with values 00h, FFh, 00h,
;*                 FFh, respectively.  In processor-write mode, planes 0
;*                 through 3 would get 0Ah, 0Ah, 0Ah, 0Ah, respectively.
;*                 Once a color has been written to video RAM, it can be read
;*                 back to fill the EGA's latches.  The EGA must be set to
;*                 data-read mode, so that the latches get each plane's data
;*                 without any interpretation.  Since the EGA is assumed to
;*                 be processor-write mode throughout the display driver,
;*                 reset it before exiting.  Furthermore, since the
;*                 interrupt-time pointer drawing code must be able to change
;*                 and restore the EGA's state, and our state detection code
;*                 assumes the write mode is processor-write, these
;*                 manipulations must be done inside a cli/sti critical
;*                 section to prevent mouse interrupts.
;*
;*                 Registers Destroyed:
;*                       AX,BX,FLAGS
;*                 Registers Preserved:
;*                       CX,DX,SI,DI,BP,DS,ES
;*
;* INPUT         = BH = background color
;*                 DX = EGA_BASE + GRAF_ADDR
;*                 all EGA color planes enabled for output
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
ALIGN 4
InitTonysBarNGrill PROC SYSCALL USES ESI EDI

        mov     edi,pVRAMInstance

        mov     ax,(M_COLOR_WRITE + M_DATA_READ) shl 8 + GRAF_MODE
        cli
        out     dx,ax

        OVAccess                                  ;access offscreen VRAM
ifdef EGAMEM_IS_STRUCT
        mov     [EDI].EGAMem.tonys_bar_n_grill,bh ;store color in video RAM
        mov     bh,[EDI].EGAMem.tonys_bar_n_grill ;read back to set the latches
else
        mov     [EDI+tonys_bar_n_grill],bh        ;store color in video RAM
        mov     bh,[EDI+tonys_bar_n_grill]        ;read back to set the latches
endif
        OVRestore       ;Restore VGA to previouse state

        mov     ax,(M_PROC_WRITE + M_DATA_READ) shl 8 + GRAF_MODE
        out     dx,ax
        sti
        ret

InitTonysBarNGrill ENDP

;/*
;** This label is compared to DOSPAGESIZE in DeviceSpecificInit
;*/

        public  end_crit_code

end_crit_code   label   byte

_PtrCode32 ENDS
end
