;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _cirrus.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for Cirrus SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;* $Id: _cirrus.asm 1.2 1993/09/24 05:23:19 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _cirrus.asm $
;* Revision 1.2  1993/09/24  05:23:19  kjb
;* *** empty log message ***
;*
;* Revision 1.1  1993/09/19  01:26:54  kjb
;* Initial revision
;*
;****************************************************************************

grCIRRUS_5420       =   0   ; Cirrus 5420 SuperVGA chip
grCIRRUS_5422       =   1   ; Cirrus 5422 SuperVGA chip
grCIRRUS_5424       =   2   ; Cirrus 5424 SuperVGA chip
grCIRRUS_5426       =   3   ; Cirrus 5426 SuperVGA chip
grCIRRUS_5428       =   4   ; Cirrus 5428 SuperVGA chip

;----------------------------------------------------------------------------
; CIRRUS_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    CIRRUS_bank far

		push    ax
		push    dx
		mov     dx,3CEh
		shl     al,4                ; Convert to 4k bank number
		mov     ah,al
		mov     al,9
		out     dx,ax
		pop     dx
		pop     ax
		ret

ENDP    CIRRUS_bank

CIRRUS_bank_len     =   ($-CIRRUS_bank)

;----------------------------------------------------------------------------
; CIRRUS26_bank   Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    CIRRUS26_bank far

		push    ax
		push    dx
		mov     dx,3CEh
		shl     al,2                ; Convert to 16k bank number
		mov     ah,al
		mov     al,9
		out     dx,ax
		pop     dx
		pop     ax
		ret

ENDP    CIRRUS26_bank

CIRRUS26_bank_len	=   ($-CIRRUS26_bank)

;----------------------------------------------------------------------------
; CIRRUS_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    CIRRUS_page far

        SetLowStartAddress
        mov     dx,3D4h             ; DX := CRTC I/O port
        mov     al,1Bh              ; Index of start address register
        out     dx,al
        inc     dx
        in      al,dx               ; Read old value
        and     al,0FAh             ; Clear out bits 0 and 2
        mov     bh,bl
        and     bh,2                ; BH := bit 17 of start address
        shl     bh,1                ; BH := bit 17 in bit pos 2
        and     bl,1                ; BL := bit 16 of start address
        or      bl,bh               ; BL := combined bit 16 and bit 17
        or      al,bl               ; Or in starting address value
        out     dx,al               ; Set the new value
        ret

ENDP    CIRRUS_page

CIRRUS_page_len     =   ($-CIRRUS_page)

;----------------------------------------------------------------------------
; CIRRUS_setup  Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    CIRRUS_setup    near

		wrinx   3C4h, 6, 12h        ; Enable extended registers
        modinx  3D4h, 1Bh, 10b, 10b ; Enable access to upper memory
		ret

ENDP    CIRRUS_setup

CIRRUS_setup_len    =   ($-CIRRUS_setup)

;----------------------------------------------------------------------------
; CIRRUS26_setup  Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    CIRRUS26_setup    near

		wrinx   3C4h, 6, 12h        ; Enable extended registers
		modinx  3D4h, 1Bh, 10b, 10b ; Enable access to upper memory
		modinx	3C4h, 0Fh, 80h, 80h	; Enable access beyond 1Mb
		modinx	3CEh, 0Bh, 20h, 20h	; Enable 16k bank mode
		ret

ENDP    CIRRUS26_setup

CIRRUS26_setup_len	=   ($-CIRRUS26_setup)

;----------------------------------------------------------------------------
; CIRRUS_exit   Return the SuperVGA to default operation
;----------------------------------------------------------------------------
PROC    CIRRUS_exit near

		wrinx   3C4h, 6, 0          ; Disable extended registers
		ret

ENDP    CIRRUS_exit

CIRRUS_exit_len =   ($-CIRRUS_exit)

;----------------------------------------------------------------------------
; CIRRUS_init
;----------------------------------------------------------------------------
; We have a Cirrus 542x SuperVGA, so setup the appropriate vectors.
;----------------------------------------------------------------------------
PROC    CIRRUS_init

        mov     [TwoBanks],false
		mov     [WriteBank16],offset CIRRUS_bank
		mov     [WriteBank16Len],CIRRUS_bank_len
		mov     [WriteBank256],offset CIRRUS_bank
		mov     [WriteBank256Len],CIRRUS_bank_len
		mov     [NewPage16],offset CIRRUS_page
		mov     [NewPage16Len],CIRRUS_page_len
		mov     [NewPage256],offset CIRRUS_page
		mov     [NewPage256Len],CIRRUS_page_len
		mov     [SetupSVGA],offset CIRRUS_setup
		mov     [SetupSVGALen],CIRRUS_setup_len
		mov     [ExitSVGA],offset CIRRUS_exit
		mov     [ExitSVGALen],CIRRUS_exit_len
		cmp		[CntChipID],grCIRRUS_5422
		je		@@Exit

; We have a CL-GD5426 or 5428 chipset, which supports > 1Mb of memory so
; we use a different banking scheme.

		mov     [WriteBank16],offset CIRRUS26_bank
		mov     [WriteBank16Len],CIRRUS26_bank_len
		mov     [WriteBank256],offset CIRRUS26_bank
		mov     [WriteBank256Len],CIRRUS26_bank_len
		mov     [SetupSVGA],offset CIRRUS26_setup
		mov     [SetupSVGALen],CIRRUS26_setup_len

@@Exit:
        ret

ENDP    CIRRUS_init
