;*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        Video tests                      
                                                      
;/*****************************************************************************
;*
;* SOURCE FILE NAME = VTESTS.ASM
;*
;* DESCRIPTIVE NAME = Video Tests
;*
;*
;* VERSION      V2.0
;*
;* DATE         
;*
;* DESCRIPTION 
;*
;*              1. Reads and writes every plane on the EGA/VGA,
;*                 accessing the full 256k on the adapter.  Its original
;*                 purpose was to time the minimum screen-switch delay if we
;*                 swapped the complete adapter context.
;*
;*              2. Select high-res graphics mode, print some bars, ripple the
;*                 palette a bit.
;*
;*
;* FUNCTIONS    
;*                 Main      Determine video configuration.  Execute the tests.
;*                 Test1     Move or Exchange the contents of the EGA / VGA video planes.
;*                 Test2     Draw color bars on the screen for each video mode.
;*                 Movep     Move the contents from one video plane to another.
;*                 Xchgp     Exchange the contents of two video planes.
;*                 Setega    Set up EGA.
;*                 Setpal    Set up pallette registers.
;*                 Drawbars  Draw color bars on the screen.
;*              
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*
;*****************************************************************************/


        .386c
V386    EQU        1                             ;use 386-specific instrunctions

INCL_NONE        EQU 1
INCL_VIDEOHW     EQU 1
        .xlist
        include vvd.inc                          ;public/exported vvideo stuff
        .list


CSEG        SEGMENT word use16 public 'CODE'
        ASSUME        cs:CSEG,ds:CSEG,es:CSEG,ss:CSEG

        org        100h                          ;COM file


;/***************************************************************************
;*
;* FUNCTION NAME = Main
;*
;* DESCRIPTION   = Determine video configuration.  Execute the tests.
;*
;* INPUT         = None
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL =
;* RETURN-ERROR  =
;*
;**************************************************************************/

main        PROC        far
        int 3
        cld
        mov        sp,offset mystack+256         ;use 256-byte stack


;/*
;** Get hardware configuration information
;*/

        mov        ah,12h                        ;alternate function select
        mov        bl,10h                        ;request ega info
        int        10h
        cmp        bl,4
        jb        main_egavga
        mov        dx,offset msgNotEGA
        mov        ah,9
        int        21h
        jmp        short main_hwtestdone

main_egavga:
        inc        bl
        mov        [n64kEGA],bl
        or        bh,bh                          ;mono configuration?
        jz        main_hwtestdone                ;no
        mov        word ptr [regStatus1],PORT_MONOSTATUS1

main_hwtestdone:
        call        test1
        call        test2

main_exit:
        int        20h
main        ENDP


                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Test1
;*                                                                           
;* DESCRIPTION   = Move or Exchange the contents of the EGA / VGA video planes.
;*
;* INPUT         = None
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

test1        PROC        near
        cmp        [n64kEGA],0                   ;are we EGA/VGA?
        jz        test1_exit                     ;no

        mov        si,offset setgrfx
        call        setega                       ;DS:SI -> "set" table
        mov        ax,cs
        mov        bx,sp
        add        bx,15
        shr        bx,4
        add        bx,ax                         ;BX == 64k scratch segment

        mov        bp,2                          ;do the work 2 times
test1_bigloop:
        mov        ah,0                          ;AH == plane #
test1_tinyloop:
       IFDEF MOVE
        clc
        call        movep                        ;move the plane
        stc
        call        movep                        ;move the plane back
       ELSE
        call        xchgp                        ;exchange the plane
        call        xchgp                        ;2 xchgs, and no one's the wiser!
       ENDIF
        inc        ah
        cmp        ah,3
        jbe        test1_tinyloop
        dec        bp
        jnz        test1_bigloop

        mov        si,offset settext             ;DS:SI -> "set" table to restore state
        call        setega

test1_exit:
        ret
test1        ENDP

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Test2
;*                                                                           
;* DESCRIPTION   = Draw color bars on the screen for each video mode.
;*                                                                           
;* INPUT         = None
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

test2        PROC        near
        cmp        [n64kEGA],0                   ;are we EGA/VGA?
        jz        test2_exit                     ;no

        mov        ah,0Fh                        ;get current video mode
        int        10h
        push        ax                           ;save it
        sub        ax,ax                         ;initial mode index
        mov        [nextmode],ax

test2_loop:
        sub        ax,ax
        mov        si,[nextmode]
        inc        nextmode
        mov        al,egamodes[si]
        cmp        al,0FFh                       ;no more modes?
        je        test2_done                     ;no
        int        10h

        call        setpal                       ;set ega/vga palette

        call        drawbars                     ;draw color bars on the screen

test2_ripple:
        mov        cx,16*2+8
test2_rippleloop:
        call        setpal                       ;set ega/vga palette again
        loop        test2_rippleloop

        sub        ax,ax                         ;wait for a key
        int        16h
        jmp        test2_loop

test2_done:
        pop        ax                            ;retrieve original video mode
        sub        ah,ah
        int        10h                           ;reset it

test2_exit:
        ret
test2        ENDP

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Movep
;*                                                                           
;* DESCRIPTION   = Move the contents from one video plane to another.
;*                                                                           
;* INPUT         = BX == src/dest segment
;*                 AH == plane
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

       IFDEF MOVE
movep        PROC        near                    ;BX == src/dest segment, AH == plane
        push        ds
        push        es
        push        EGAVGAMEM_START SHR 4
        jc        movep_back
        pop        ds
        mov        es,bx
        jmp        short movep_it
movep_back:
        pop        es
        mov        ds,bx
movep_it:
        mov        dx,PORT_GDCINDX
        mov        al,REG_GDCREADMAP
        out        dx,ax                         ;select plane to read...
        mov        dx,PORT_SEQINDX
        mov        al,REG_SEQMAPMASK
        mov        cl,1
        xchg        ah,cl                        ;CL == plane, AH == 1
        shl        ah,cl                         ;AH == plane mask
        out        dx,ax                         ;select plane to write...
        mov        ah,cl                         ;restore plane # to AH
        sub        cx,cx
        sub        si,si
        sub        di,di
       IFDEF V386
        mov        cx,16*1024
        ALIGN 4
        rep        movsd
       ELSE
        mov        cx,0FFFFh
        movsb
        ALIGN 4
        rep        movsb
       ENDIF
        pop        es
        pop        ds
        ret
movep        ENDP                                ;AL, CX, DX, SI, DI, ES destroyed on exit
       ENDIF

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Xchgp
;*                                                                           
;* DESCRIPTION   = Exchange the contents of two video planes.
;*                                                                           
;* INPUT         = BX == src/dest segment
;*                 AH == plane
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

       IFNDEF MOVE
xchgp        PROC        near                    ;BX == src/dest segment, AH == plane
        push        ds
        push        es
       IFDEF SLOWXCHG
        push        EGAVGAMEM_START SHR 4
        pop        ds
        mov        es,bx
       ELSE
        push        EGAVGAMEM_START SHR 4
        pop        es
        mov        ds,bx
       ENDIF
        mov        dx,PORT_GDCINDX
        mov        al,REG_GDCREADMAP
        out        dx,ax                         ;select plane to read...
        mov        dx,PORT_SEQINDX
        mov        al,REG_SEQMAPMASK
        mov        cl,1
        xchg        ah,cl                        ;CL == plane, AH == 1
        shl        ah,cl                         ;AH == plane mask
        out        dx,ax                         ;select plane to write...
        mov        ah,cl                         ;restore plane # to AH
        sub        si,si
        sub        di,di
       IFDEF V386
        mov        cx,16*1024
        mov        dh,ah
       ELSE
        sub        cx,cx
       ENDIF
        ALIGN 4
xchgp_loop:
       IFDEF V386
        mov        eax,es:[di]
        xchg        eax,[si]
        add        si,4
        stosd
       ELSE
        mov        al,es:[di]
        xchg        al,[si]
        inc        si
        stosb
       ENDIF
        loop        xchgp_loop
       IFDEF V386
        mov        ah,dh
       ENDIF
        pop        es
        pop        ds
        ret
xchgp        ENDP                                ;AL, CX, DX, SI, DI, ES destroyed on exit
       ENDIF

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Setega
;*                                                                           
;* DESCRIPTION   = Set up EGA.
;*                                                                           
;* INPUT         = DS:SI -> "set" table                                                           
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

setega        PROC   near                        ;DS:SI -> "set" table
        lodsw
        or        ax,ax
        jz        setega_done
        mov        dx,ax
        lodsw
        test        dx,1                         ;special-handling bit set?
        jz        setega_cont                    ;no
        and        dx,not 1                      ;clear special-handling bit
        stc
        push        dx
        push        ax
        cli
        mov        dx,PORT_SEQINDX
        mov        ax,0100h                      ;clear synchronous reset bit
        out        dx,al
        inc        dx
        mov        al,ah
        out        dx,al
        pop        ax
        pop        dx
setega_cont:
        out        dx,al                         ;do the OUT specified in the tbl
        inc        dx
        mov        al,ah
        out        dx,al
        jnc        setega
        mov        dx,PORT_SEQINDX               ;if special handling was required
        mov        ax,0300h                      ;turn synchronous reset bit back on
        out        dx,al
        inc        dx
        mov        al,ah
        out        dx,al
        sti
        jmp        setega                        ;loop until table exhausted
setega_done:
        ret
setega        ENDP

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Setpal
;*                                                                           
;* DESCRIPTION   = Set up pallette registers.
;*                                                                           
;* INPUT         = None
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

setpal        PROC        near                   ;USES: ax,dx,si,di
        push        cx
        mov        dx,[regStatus1]
setpal_novert:
        in        al,dx                          ;force ATC to address state
        test        al,STATUS1_VERTRTRC          ;vertical retrace?
        jz        setpal_novert                  ;no, wait
        sub        ah,ah
        mov        cx,16                         ;SKIP OVERSCAN FOR NOW
        mov        dx,PORT_ATC0                  ;port for attribute controller
        mov        si,offset apalTable
        mov        di,si
setpal_doreg:
        cli                                      ;keep ints off while in data state
        mov        al,ah
        out        dx,al                         ;address selected
        lodsb
        out        dx,al                         ;data written, back to address state
        sti
        inc        al                            ;this will cause rippling
        stosb
        inc        ah
        cmp        ah,REG_ATCMODECTRL            ;just past the 16 attribute regs now
        jne        setpal_noskip                 ;no
        inc        ah                            ;yes, so now skip to overscan reg
setpal_noskip:
        loop        setpal_doreg
        mov        al,ATCPAL_ENABLE
        cli
        out        dx,al                         ;re-enable palette
        mov        dx,[regStatus1]
        in        al,dx                          ;force attribute controller to addr state
        sti
        pop        cx
        ret
setpal        ENDP

                                                                             
;/***************************************************************************
;*                                                                           
;* FUNCTION NAME = Drawbars
;*                                                                           
;* DESCRIPTION   = Draw color bars on the screen.
;*                                                                           
;* INPUT         = None
;*
;* OUTPUT        = None
;*                                                                           
;* RETURN-NORMAL =                                                           
;* RETURN-ERROR  =                                                           
;*                                                                           
;**************************************************************************/ 

drawbars PROC        NEAR
        sub        bx,bx                         ;initial page (BH) and color (BL)
        sub        dx,dx                         ;initial cursor row and col (DH,DL)
        mov        cx,5                          ;replication constant
drawbar_loop:
        mov        ax,09h*256+219
        int        10h
        inc        bl
        add        dl,cl                         ;advance cursor column
        cmp        dl,80
        jb        drawbar_sameline               ;still on same line
        sub        dl,dl
        inc        dh                            ;advance to new line, column 0
        cmp        dh,25
        jae        drawbar_done                  ;screen is finished
drawbar_sameline:
        mov        ah,02h                        ;tell bios about new cursor position
        int        10h
        jmp        drawbar_loop
drawbar_done:
        ret
drawbars ENDP


;/*
;**  Data begins...
;*/

        EVEN
setgrfx dw        PORT_SEQINDX,        REG_SEQMAPMASK + \
                                (SEQMAP_ALL)*100h
        dw        PORT_SEQINDX+1, REG_SEQMEMMODE + \
                                (SEQMEM_EXTENDED+SEQMEM_ODDEVENSAME)*100h
        dw        PORT_GDCINDX,        REG_GDCREADMAP
        dw        PORT_GDCINDX,        REG_GDCMODE
        dw        PORT_GDCINDX+1, REG_GDCMISC    + \
                                (GDCMISC_64K_A0000)*100h
        dw        0


        EVEN
settext dw        PORT_SEQINDX,        REG_SEQMAPMASK + \
                                (SEQMAP_PLANE0+SEQMAP_PLANE1)*100h
        dw        PORT_SEQINDX+1, REG_SEQMEMMODE + \
                                (SEQMEM_ALPHA+SEQMEM_EXTENDED)*100h
        dw        PORT_GDCINDX,        REG_GDCREADMAP
        dw        PORT_GDCINDX,        REG_GDCMODE    + \
                                (GDCMODE_ODDEVENDIFF)*100h
        dw        PORT_GDCINDX+1, REG_GDCMISC    + \
                                (GDCMISC_ODDTOEVEN+GDCMISC_32K_B8000)*100h
        dw        0


egamodes    db            0,1,2,3,4,6,0Dh,0Eh,10h,0FFh

nextmode    dw            0

n64kEGA     db            0                      ;non-zero implies EGA/VGA
regStatus1  dw            PORT_COLRSTATUS1       ;default port

apalTable   db            0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0

msgNotEGA   db            'No EGA detected',13,10,'$'


mystack LABEL        word                        ;where to place bottom of private stack

CSEG        ENDS

        END        main
