;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _ati.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for ATI SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;* $Id: _ati.asm 1.2 1993/09/24 05:22:51 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _ati.asm $
;* Revision 1.2  1993/09/24  05:22:51  kjb
;* Fixed a number of bugs.
;*
;* Revision 1.1  1993/09/19  01:26:40  kjb
;* Initial revision
;*
;****************************************************************************

grATI_18800         =   0   ; ATI 18800 chip
grATI_18800_1       =   1   ; ATI 18800-1 chip
grATI_28800_2       =   2   ; ATI 28800-2 chip
grATI_28800_4       =   3   ; ATI 28800-4 chip
grATI_28800_5       =   4   ; ATI 28800-5 chip

;----------------------------------------------------------------------------
; ATI_bank  Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ATI_bank    far

		push    ax
		push    dx
		and     al,0Fh              ; Mask out bottom four bits
		mov     ah,al
		shl     ah,4                ; Shift read bank into position
		or      ah,al               ; AH := combined read/write register numbers
		rol     ah,1                ; Shift banks numbers in position
		mov     dx,1CEh             ; Port of extended registers
		mov     al,0B2h
		out     dx,ax               ; Set the ATI Bank Register
		pop     dx
		pop     ax
		ret

ENDP    ATI_bank

ATI_bank_len    =   ($-ATI_bank)

;----------------------------------------------------------------------------
; ATI_rbank Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    ATI_rbank   far

		push    ax
		push    dx
		and     al,0Fh              ; Mask out bottom four bits
		rol     al,5                ; Shift read bank into position
		mov     ah,al
		mov     dx,1CEh             ; Port of extended registers
		mov     al,0B2h
		out     dx,al               ; Index ATI bank register
		inc     dl
		in      al,dx
		and     al,01Eh             ; Zero out bits 7-5 and bit 0
		or      ah,al               ; AL := combined value
		mov     al,0B2h
		out     dx,ax               ; Ouput the new value
		pop     dx
		pop     ax
		ret

ENDP    ATI_rbank

ATI_rbank_len   =   ($-ATI_rbank)

;----------------------------------------------------------------------------
; ATI_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    ATI_page    far

        SetLowStartAddress          ; BX := bits 16+ of address
        mov     dx,1CEh
        mov     al,0B0h             ; Index of start address register
        out     dx,al
        inc     dx
        in      al,dx               ; Read old value
        and     al,3Fh              ; Mask out old bits 7-6
        and     bl,3                ; Mask out bottom two bits
        shl     bl,6                ; Shift into position
        or      al,bl               ; Combine the values
        out     dx,al               ; Output the result
        ret

ENDP    ATI_page

ATI_page_len    =   ($-ATI_page)

;----------------------------------------------------------------------------
; ATI_setup Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    ATI_setup   near

        modinx  1CEh, 0BEh, 01000b, 01000b      ; Enable dual bank mode
        ret

ENDP    ATI_setup

ATI_setup_len   =   ($-ATI_setup)

;----------------------------------------------------------------------------
; ATI_exit  Return the SuperVGA to default operation
;----------------------------------------------------------------------------
PROC    ATI_exit    near

        modinx  1CEh, 0BEh, 01000b, 0           ; Disable dual bank mode
        ret

ENDP    ATI_exit

ATI_exit_len    =   ($-ATI_exit)

;----------------------------------------------------------------------------
; ATI_init
;----------------------------------------------------------------------------
; We have an ATI video card. The 18800-1 and 28800 chips support the dual
; paging mode, but the old 18800 chip does not.
;----------------------------------------------------------------------------
PROC    ATI_init    near

        mov     [TwoBanks],false
        mov     [WriteBank16],offset ATI_bank
        mov     [WriteBank16Len],ATI_bank_len
        mov     [WriteBank256],offset ATI_bank
		mov     [WriteBank256Len],ATI_bank_len
		mov     [NewPage16],offset ATI_page
		mov     [NewPage16Len],ATI_page_len
		mov     [NewPage256],offset ATI_page
		mov     [NewPage256Len],ATI_page_len

        cmp     [BYTE CntChipID],grATI_18800
        je      @@Done

; We have an 18800-1 or 28800 Chip, so setup for dual bank mode

        mov     [TwoBanks],true
        mov     [ReadBank16],offset ATI_rbank
        mov     [ReadBank16Len],ATI_rbank_len
        mov     [ReadBank256],offset ATI_rbank
        mov     [ReadBank256Len],ATI_rbank_len
        mov     [SetupSVGA],offset ATI_setup
        mov     [SetupSVGALen],ATI_setup_len
        mov     [ExitSVGA],offset ATI_exit
        mov     [ExitSVGALen],ATI_exit_len

; ****
;
; It seems that on ATI 28800-5 and above SuperVGA's, the extended
; CRT address bits 16-17+ may not be located in ATI extended register 0,
; but may be located somewhere else. Can someone fix this?
;
; ****

@@Done:
        ret

ENDP    ATI_init
