;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _ahead.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for Ahead SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;* $Id: _ahead.asm 1.2 1993/09/24 05:22:51 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _ahead.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
;*
;****************************************************************************

grAHEAD_A           =   0   ; Ahead A chipset
grAHEAD_B           =   1   ; Ahead B chipset

;----------------------------------------------------------------------------
; AHEADA_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    AHEADA_bank far

		push    ax
        push    dx
		push    cx
		mov     ch,al
		mov     dx,03CCh            ; bit 0 in bit 5 of Misc Output reg
		in      al,dx               ; Read Misc output register
		mov     dl,0C2h
		and     al,11011111b
		shr     ch,1                ; Need to set the bit?
		jnc     @@SkpA              ; No, so skip it
		or      al,00100000b
@@SkpA: out     dx,al               ; Set the new value
		mov     dx,3CEh             ; bits 3-1 in bits 2-0 of Segment Reg
		mov     al,0Dh              ; Index 0Dh for segment reg
		mov     ah,ch               ; ch contains top three bits shr 1
		out     dx,ax               ; Set the new value
		pop     cx
		pop     dx
		pop     ax
		ret

ENDP    AHEADA_bank

AHEADA_bank_len =   ($-AHEADA_bank)

;----------------------------------------------------------------------------
; AHEADB_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    AHEADB_bank far

		push    ax
        push    dx
        mov     ah,al               ; Combine read/write bank numbers
        shl     ah,4
        or      ah,al
        mov     al,0Dh              ; Index of Bank Switch register
        mov     dx,3CEh
		out     dx,ax               ; Set the register
        pop     dx
        pop     ax
		ret

ENDP    AHEADB_bank

AHEADB_bank_len =   ($-AHEADB_bank)

;----------------------------------------------------------------------------
; AHEADB_rbank  Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    AHEADB_rbank    far

		push    ax
		push    dx
		mov     ah,al               ; Read bank number in bits 3-0
		mov     al,0Dh              ; Index of Bank Switch register
		mov     dx,3CEh
		out     dx,al
		inc     dl
		in      al,dx               ; Read old register value
		and     al,0F0h             ; Mask out bits 3-0
		or      al,ah               ; Combine with new value
		out     dx,al               ; Set the new register value
		pop     dx
		pop     ax
		ret

ENDP    AHEADB_rbank

AHEADB_rbank_len    =   ($-AHEADB_rbank)

;----------------------------------------------------------------------------
; AHEADB_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    AHEADB_page16 far

		SetLowStartAddress
		mov     dx,03CEh
		mov     al,01Ch
		out     dx,al               ; Index the start address register
		inc     dx
		in      al,dx               ; Read current value
		and     al,0FCh             ; Mask out old address values
		and     bl,3                ; Mask out bottom two bits
		or      al,bl               ; Or in the new start address
		out     dx,al               ; Output the address
		ret

ENDP    AHEADB_page16

AHEADB_page16_len =   ($-AHEADB_page16)

;----------------------------------------------------------------------------
; AHEADB_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    AHEADB_page256 far

		SetLowStartAddress256
		mov     dx,03CEh
		mov     al,01Ch
		out     dx,al               ; Index the start address register
		inc     dx
		in      al,dx               ; Read current value
		and     al,0FCh             ; Mask out old address values
		and     bl,3                ; Mask out bottom two bits
		or      al,bl               ; Or in the new start address
		out     dx,al               ; Output the address
		ret

ENDP    AHEADB_page256

AHEADB_page256_len =   ($-AHEADB_page256)

;----------------------------------------------------------------------------
; AHEAD_setup   Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    AHEAD_setup near

        modinx  3CEh, 0Fh, 20h, 20h ; Enable extended registers
        modinx  3CEh, 0Ch, 20h, 20h ; Enable enhanced mode
        ret

ENDP    AHEAD_setup

AHEAD_setup_len =   ($-AHEAD_setup)

;----------------------------------------------------------------------------
; AHEAD_exit    Return the SuperVGA to default operation
;----------------------------------------------------------------------------
PROC    AHEAD_exit  near

        modinx  3CEh, 0Fh, 20h, 0h  ; Disable extended registers
        modinx  3CEh, 0Ch, 20h, 0h  ; Disable enhanced mode
        ret

ENDP    AHEAD_exit

AHEAD_exit_len  =   ($-AHEAD_exit)

;----------------------------------------------------------------------------
; AHEAD_init
;----------------------------------------------------------------------------
; We have an Ahead A or B SuperVGA. The Ahead B supports extended page
; flipping and dual banking, so setup as appropriate.
;----------------------------------------------------------------------------
PROC    AHEAD_init  near

        mov     [TwoBanks],false
        mov     [WriteBank16],offset AHEADA_bank
        mov     [WriteBank16Len],AHEADA_bank_len
        mov     [WriteBank256],offset AHEADA_bank
        mov     [WriteBank256Len],AHEADA_bank_len
        mov     [SetupSVGA],offset AHEAD_setup
        mov     [SetupSVGALen],AHEAD_setup_len
        mov     [ExitSVGA],offset AHEAD_exit
        mov     [ExitSVGALen],AHEAD_exit_len

        cmp     [CntChipID],grAHEAD_B
        jne     @@Exit

; We have an Ahead B SuperVGA which has different bank switching and
; supported extended page flipping.

        mov     [TwoBanks],true
        mov     [WriteBank16],offset AHEADB_bank
        mov     [WriteBank16Len],AHEADB_bank_len
        mov     [WriteBank256],offset AHEADB_bank
        mov     [WriteBank256Len],AHEADB_bank_len
        mov     [ReadBank16],offset AHEADB_rbank
        mov     [ReadBank16Len],AHEADB_rbank_len
        mov     [ReadBank256],offset AHEADB_rbank
        mov     [ReadBank256Len],AHEADB_rbank_len
		mov     [NewPage16],offset AHEADB_page16
		mov     [NewPage16Len],AHEADB_page16_len
		mov     [NewPage256],offset AHEADB_page256
		mov     [NewPage256Len],AHEADB_page256_len

@@Exit:
        ret

ENDP    AHEAD_init
