;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _tseng.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for Tseng Labs SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;* $Id: _tseng.asm 1.2 1993/09/24 05:23:45 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _tseng.asm $
;* Revision 1.2  1993/09/24  05:23:45  kjb
;* Fixed a number of bugs.
;*
;* Revision 1.1  1993/09/19  01:27:05  kjb
;* Initial revision
;*
;****************************************************************************

grET3000            =   0   ; Tseng Labs ET3000
grET4000            =   1   ; Standard Tseng ET4000 board
grET4000_SPEEDSTAR  =   2   ; Diamond Speedstar 24 ET4000 board (24 bit)
grET4000_GENOA      =   3   ; Genoa 7900 ET4000 board (24 bit)
grET4000_W32        =   4   ; ET4000/W32 accelerator chip

;----------------------------------------------------------------------------
; ET3000_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET3000_bank far

		push    ax
        push    dx
        and     al,7                ; Mask out bottom 3 bits
        mov     ah,al               ; Combine read and write bank values in al
        shl     ah,3
        or      al,ah
        or      al,40h              ; Set bit 6 to select 64k segments
        mov     dx,3CDh             ; Point to memory segment register
        out     dx,al               ; Set the new bank value
        pop     dx
        pop     ax
		ret

ENDP    ET3000_bank

ET3000_bank_len =   ($-ET3000_bank)

;----------------------------------------------------------------------------
; ET3000_rbank  Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET3000_rbank    far

		push    ax
        push    dx
        mov     ah,bl               ; Save value of bl
        and     al,7                ; Mask out bottom 3 bits
        shl     al,3                ; Shift into position
        mov     bl,al
        mov     dx,3CDh
        in      al,dx               ; Read current value
        and     al,0C7h             ; Mask out read bank select value
        or      al,bl               ; Or in the new read bank value
        out     dx,al               ; Set the new bank value
        mov     bl,ah               ; Restore value of bl
        pop     dx
        pop     ax
		ret

ENDP    ET3000_rbank

ET3000_rbank_len    =   ($-ET3000_rbank)

;----------------------------------------------------------------------------
; ET3000_page16   Set the extended CRT starting address.
;----------------------------------------------------------------------------
;
; Entry:        BL  - Index of start address low register
;               BH  - Bits 7-0 of new start address
;               CL  - Index of start address high register
;               CH  - Bits 15-8 of new start address
;               SI  - Bits 16+ for new start address
;
; Registers:    AX,BX,CX,DX,SI
;
;----------------------------------------------------------------------------
PROC    ET3000_page16 far

		SetLowStartAddress
		mov     dx,3D4h             ; DX := CRTC I/O port
		mov     al,23h              ; Index extended start address
        out     dx,al
        inc     dx
        in      al,dx               ; Read current value
        and     al,0FDh             ; Zero out start address
        and     bl,1                ; Only one bit is valid
        shl     bl,1                ; Put bit into correct pos.
        or      al,bl               ; Or in the new start address
        out     dx,al               ; Output the address
        ret

ENDP    ET3000_page16

ET3000_page16_len     =   ($-ET3000_page16)

;----------------------------------------------------------------------------
; ET3000_page256   Set the extended CRT starting address.
;----------------------------------------------------------------------------
;
; Entry:        BL  - Index of start address low register
;               BH  - Bits 7-0 of new start address
;               CL  - Index of start address high register
;               CH  - Bits 15-8 of new start address
;               SI  - Bits 16+ for new start address
;
; Registers:    AX,BX,CX,DX,SI
;
;----------------------------------------------------------------------------
PROC    ET3000_page256 far

		SetLowStartAddress256
		mov     dx,3D4h             ; DX := CRTC I/O port
        mov     al,23h              ; Index extended start address
        out     dx,al
        inc     dx
        in      al,dx               ; Read current value
        and     al,0FDh             ; Zero out start address
        and     bl,1                ; Only one bit is valid
        shl     bl,1                ; Put bit into correct pos.
        or      al,bl               ; Or in the new start address
        out     dx,al               ; Output the address
        ret

ENDP    ET3000_page256

ET3000_page256_len     =   ($-ET3000_page256)

;----------------------------------------------------------------------------
; ET3000_setup  Setup the ET3000 for correct operation
;----------------------------------------------------------------------------
PROC    ET3000_setup    near

        modinx  3C4h, 4, 2, 2       ; Enable access to all video memory
        ret

ENDP    ET3000_setup

ET3000_setup_len        =   ($-ET3000_setup)

;----------------------------------------------------------------------------
; ET4000_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET4000_bank far

		push    ax
        push    dx
        and     al,0Fh              ; Mask out bottom 4 bits
        mov     ah,al               ; Combine read and write values in al
        shl     ah,4
        or      al,ah
        mov     dx,3CDh             ; Point to memory segment register
        out     dx,al               ; Set the new bank value
        pop     dx
        pop     ax
		ret

ENDP    ET4000_bank

ET4000_bank_len     =   ($-ET4000_bank)

;----------------------------------------------------------------------------
; ET4000_rbank  Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET4000_rbank    far

		push    ax
        push    dx
        mov     ah,bl               ; Save value of bl
        and     al,0Fh              ; Mask out bottom 4 bits
        shl     al,4                ; Shift into position
        mov     bl,al
        mov     dx,3CDh
        in      al,dx               ; Read current value
        and     al,00Fh             ; Mask out read bank select bits 7-4
        or      al,bl               ; Or in the new read bank value
        out     dx,al               ; Set the new bank value
        mov     bl,ah               ; Restore value of bl
        pop     dx
        pop     ax
		ret

ENDP    ET4000_rbank

ET4000_rbank_len    =   ($-ET4000_rbank)

;----------------------------------------------------------------------------
; ET4000_page   Set the extended CRT starting address.
;----------------------------------------------------------------------------
;
; Entry:        BL  - Index of start address low register
;               BH  - Bits 7-0 of new start address
;               CL  - Index of start address high register
;               CH  - Bits 15-8 of new start address
;               SI  - Bits 16+ for new start address
;
; Registers:    AX,BX,CX,DX,SI
;
;----------------------------------------------------------------------------
PROC    ET4000_page far

        SetLowStartAddress
        mov     dx,3D4h             ; DX := CRTC I/O port
        mov     al,33h              ; Index extended start address
        out     dx,al
        inc     dx
        in      al,dx               ; Read current value
        and     al,0FCh             ; Zero out start address
        and     bl,3                ; Mask out all but bottom 2 bits
        or      al,bl               ; Or in new start address
        out     dx,al               ; Output the address
        ret

ENDP    ET4000_page

ET4000_page_len     =   ($-ET4000_page)

;----------------------------------------------------------------------------
; ET4000W32_bank    Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET4000W32_bank  far

		push    ax
        push    dx
        push    ax
        and     al,0Fh              ; Mask out bottom 4 bits
        mov     ah,al               ; Combine read and write values in al
        shl     ah,4
        or      al,ah
        mov     dx,3CDh             ; Point to memory segment register
        out     dx,al               ; Set the new bank value
        pop     ax                  ; Restore bank number
        and     al,30h              ; Mask out top 2 bits
        mov     ah,al               ; Combine read and write values in al
        shr     al,4
        or      al,ah
        mov     dx,3CBh
        out     dx,al               ; Set the high bank bits
        pop     dx
        pop     ax
		ret

ENDP    ET4000W32_bank

ET4000W32_bank_len      =   ($-ET4000W32_bank)

;----------------------------------------------------------------------------
; ET4000W32_rbank   Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ET4000W32_rbank far

		push    ax
        push    bx
        push    dx
        push    ax
        and     al,0Fh              ; Mask out bottom 4 bits
        shl     al,4                ; Shift into position
        mov     bl,al
        mov     dx,3CDh
        in      al,dx               ; Read current value
        and     al,00Fh             ; Mask out read bank select bits 7-4
        or      al,bl               ; Or in the new read bank value
        out     dx,al               ; Set the new bank value
        pop     ax                  ; Restore bank number
        and     al,30h              ; Mask out top two bits
        mov     bl,al
        mov     dx,3CBh
        in      al,dx               ; Read current value
        and     al,30h              ; Mask out read bank select bits 5-4
        or      al,bl               ; Or in the new value
        out     dx,al               ; Set the new high bits
        pop     dx
        pop     bx
        pop     ax
		ret

ENDP    ET4000W32_rbank

ET4000W32_rbank_len =   ($-ET4000W32_rbank)

;----------------------------------------------------------------------------
; ET4000W32_page    Set the extended CRT starting address.
;----------------------------------------------------------------------------
;
; Entry:        BL  - Index of start address low register
;               BH  - Bits 7-0 of new start address
;               CL  - Index of start address high register
;               CH  - Bits 15-8 of new start address
;               SI  - Bits 16+ for new start address
;
; Registers:    AX,BX,CX,DX,SI
;
;----------------------------------------------------------------------------
PROC    ET4000W32_page  far

        SetLowStartAddress
        mov     dx,3D4h             ; DX := CRTC I/O port
        mov     al,33h              ; Index extended start address
        out     dx,al
        inc     dx
        in      al,dx               ; Read current value
        and     al,0FCh             ; Zero out start address
        and     bl,3                ; Mask out all but bottom 2 bits
        or      al,bl               ; Or in new start address
        out     dx,al               ; Output the address
        ret

ENDP    ET4000W32_page

ET4000W32_page_len      =   ($-ET4000W32_page)

;----------------------------------------------------------------------------
; ET4000_setup  Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    ET4000_setup    near

        cmp     [CntColors],gr64kColor
        jne     @@Done
        mov     ax,10F2h
        mov     bl,2
        int     10h                 ; Convert mode to 64k colors
@@Done:
        ret

ENDP    ET4000_setup

ET4000_setup_len    =   ($-ET4000_setup)

;----------------------------------------------------------------------------
; TSENG_init
;----------------------------------------------------------------------------
; We have an Tseng Labs video card, so initialise depending on chipset.
;----------------------------------------------------------------------------
PROC    TSENG_init

        mov     [TwoBanks],true
        cmp     [BYTE CntChipID],grET4000_W32
        je      @@ET4000W32
        cmp     [BYTE CntChipID],grET3000
        jne     @@ET4000

; We have an ET3000 based SuperVGA, so set up vectors for the ET3000

@@ET3000:
        mov     [WriteBank16],offset ET3000_bank
        mov     [WriteBank16Len],ET3000_bank_len
        mov     [WriteBank256],offset ET3000_bank
        mov     [WriteBank256Len],ET3000_bank_len
        mov     [ReadBank16],offset ET3000_rbank
        mov     [ReadBank16Len],ET3000_rbank_len
        mov     [ReadBank256],offset ET3000_rbank
        mov     [ReadBank256Len],ET3000_rbank_len
		mov     [NewPage16],offset ET3000_page16
		mov     [NewPage16Len],ET3000_page16_len
		mov     [NewPage256],offset ET3000_page256
		mov     [NewPage256Len],ET3000_page256_len
		mov     [SetupSVGA],offset ET3000_setup
        mov     [SetupSVGALen],ET3000_setup_len
        ret

; We have an ET4000 base SuperVGA, so set up the vectors

@@ET4000:
        mov     [WriteBank16],offset ET4000_bank
        mov     [WriteBank16Len],ET4000_bank_len
        mov     [WriteBank256],offset ET4000_bank
        mov     [WriteBank256Len],ET4000_bank_len
        mov     [ReadBank16],offset ET4000_rbank
        mov     [ReadBank16Len],ET4000_rbank_len
        mov     [ReadBank256],offset ET4000_rbank
        mov     [ReadBank256Len],ET4000_rbank_len
		mov     [NewPage16],offset ET4000_page
		mov     [NewPage16Len],ET4000_page_len
		mov     [NewPage256],offset ET4000_page
        mov     [NewPage256Len],ET4000_page_len
		mov     [SetupSVGA],offset ET4000_setup
        mov     [SetupSVGALen],ET4000_setup_len
        ret

; We have an ET4000/W32 based SuperVGA, so set up the vectors

@@ET4000W32:
        mov     [WriteBank16],offset ET4000W32_bank
        mov     [WriteBank16Len],ET4000W32_bank_len
        mov     [WriteBank256],offset ET4000W32_bank
        mov     [WriteBank256Len],ET4000W32_bank_len
        mov     [ReadBank16],offset ET4000W32_rbank
        mov     [ReadBank16Len],ET4000W32_rbank_len
        mov     [ReadBank256],offset ET4000W32_rbank
        mov     [ReadBank256Len],ET4000W32_rbank_len
		mov     [NewPage16],offset ET4000W32_page
		mov     [NewPage16Len],ET4000W32_page_len
		mov     [NewPage256],offset ET4000W32_page
        mov     [NewPage256Len],ET4000W32_page_len
		mov     [SetupSVGA],offset ET4000_setup
        mov     [SetupSVGALen],ET4000_setup_len
        ret

ENDP
