;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _oak.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for Oak SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;* $Id: _oak.asm 1.2 1993/09/24 05:23:19 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _oak.asm $
;* Revision 1.2  1993/09/24  05:23:19  kjb
;* Fixed a number of bugs.
;*
;* Revision 1.1  1993/09/19  01:26:54  kjb
;* Initial revision
;*
;****************************************************************************

grOAK_037C          =   0   ; Oak OTI-037C chipset
grOAK_057           =   1   ; Oak OTI-057 chipset
grOAK_067           =   2   ; Oak OTI-067 chipset
grOAK_077           =   3   ; Oak OTI-077 chipset
grOAK_087           =   4   ; Oak OTI-087 chipset

;----------------------------------------------------------------------------
; OAK_bank  Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    OAK_bank    far

		push    ax
        push    dx
        and     al,15
        mov     ah,al               ; Combine read/write bank numbers
        shl     al,4
        or      ah,al
        mov     al,11h              ; Index of bank switch register
        mov     dx,3DEh
        out     dx,ax               ; Set the register value
        pop     dx
        pop     ax
		ret

ENDP    OAK_bank

OAK_bank_len        =   ($-OAK_bank)

;----------------------------------------------------------------------------
; OAK_rbank Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    OAK_rbank   far

		push    ax
        push    dx
        and     al,15
        mov     ah,al               ; AH := read bank number
        mov     al,11h              ; Index of bank switch register
        mov     dx,3DEh
        out     dx,al
        inc     dl
        in      al,dx               ; Read old value
        and     al,0F0h             ; Mask out read bank value
        or      al,ah               ; Or in new value
        out     dx,al               ; Program the new value
        pop     dx
        pop     ax
		ret

ENDP    OAK_rbank

OAK_rbank_len       =   ($-OAK_rbank)

;----------------------------------------------------------------------------
; OAK87_bank    Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    OAK87_bank  far

		push    ax
        push    dx
        and     al,15
        mov     ah,al               ; Combine read/write bank numbers
        mov     al,23h              ; Index of bank switch register
        mov     dx,3DEh
        out     dx,ax               ; Set the write bank number
        inc     al
        out     dx,ax               ; Set the read bank number
        pop     dx
        pop     ax
		ret

ENDP    OAK87_bank

OAK87_bank_len      =   ($-OAK87_bank)

;----------------------------------------------------------------------------
; OAK87_rbank   Change to a new 64k read bank (reading only)
;----------------------------------------------------------------------------
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    OAK87_rbank far

		push    ax
        push    dx
        and     al,15
        mov     ah,al               ; Combine read/write bank numbers
        mov     al,24h              ; Index of bank switch register
        mov     dx,3DEh
        out     dx,ax               ; Set the read bank number
        pop     dx
        pop     ax
		ret

ENDP    OAK87_rbank

OAK87_rbank_len     =   ($-OAK87_rbank)

;----------------------------------------------------------------------------
; OAK_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    OAK_page16   far

		SetLowStartAddress
		mov		dx,3DEh
		mov		al,14h
		out     dx,al
		inc     dx
		in      al,dx               ; Read current value
		dec		dx
		and     al,0F7h             ; Zero out start address bit 16
		push	bx
		and     bl,1                ; Mask out all but bottom bit
		shl		bl,3				; Put in correct position
		or      al,bl               ; Or in new start address
		out     dx,al               ; Output the address
		mov		al,16h
		out     dx,al
		inc     dx
		in      al,dx               ; Read current value
		and     al,0F7h             ; Zero out start address bit 17
		pop		bx					; Restore start address value
		and     bl,2                ; Mask out all but bit 17
		shl		bl,2				; Put in correct position
		or      al,bl               ; Or in new start address
		out     dx,al               ; Output the address
		ret

ENDP    OAK_page16

OAK_page16_len       =   ($-OAK_page16)

;----------------------------------------------------------------------------
; OAK_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    OAK_page256   far

		SetLowStartAddress256
		mov		dx,3DEh
		mov		al,14h
		out     dx,al
		inc     dx
		in      al,dx               ; Read current value
		dec		dx
		and     al,0F7h             ; Zero out start address bit 16
		push	bx
		and     bl,1                ; Mask out all but bottom bit
		shl		bl,3				; Put in correct position
		or      al,bl               ; Or in new start address
		out     dx,al               ; Output the address
		mov		al,16h
		out     dx,al
		inc     dx
		in      al,dx               ; Read current value
		and     al,0F7h             ; Zero out start address bit 17
		pop		bx					; Restore start address value
		and     bl,2                ; Mask out all but bit 17
		shl		bl,2				; Put in correct position
		or      al,bl               ; Or in new start address
		out     dx,al               ; Output the address
		ret

ENDP    OAK_page256

OAK_page256_len       =   ($-OAK_page256)

;----------------------------------------------------------------------------
; OAK_setup    Setup the SuperVGA for correct operation
;----------------------------------------------------------------------------
PROC    OAK_setup  near

		modinx	3CEh, 0Dh, 1Ch, 0Ch	; Enable access to memory above 256k
		cmp		[CntColors],gr16Color
		jne		@@1
		modinx	3CEh, 0Dh, 10h, 10h	; Enable 16 color access above 256k
@@1:	ret

ENDP    OAK_setup

OAK_setup_len  =   ($-OAK_setup)

;----------------------------------------------------------------------------
; OAK_init
;----------------------------------------------------------------------------
; We have a OAK SuperVGA, so setup the appropriate vectors.
;----------------------------------------------------------------------------
PROC    OAK_init

		mov     [TwoBanks],true
		mov     [NewPage16],offset OAK_page16
		mov     [NewPage16Len],OAK_page16_len
		mov     [NewPage256],offset OAK_page256
		mov     [NewPage256Len],OAK_page256_len
		mov     [SetupSVGA],offset OAK_setup
		mov     [SetupSVGALen],OAK_setup_len

        cmp     [BYTE CntChipID],grOAK_087
        je      @@Oak087

; We have an OTI-077 or lower SuperVGA

        mov     [WriteBank16],offset OAK_bank
        mov     [WriteBank16Len],OAK_bank_len
        mov     [WriteBank256],offset OAK_bank
        mov     [WriteBank256Len],OAK_bank_len
        mov     [ReadBank16],offset OAK_rbank
        mov     [ReadBank16Len],OAK_rbank_len
        mov     [ReadBank256],offset OAK_rbank
		mov     [ReadBank256Len],OAK_rbank_len
		ret

; We have an OTI-087 SuperVGA

@@Oak087:
        mov     [WriteBank16],offset OAK87_bank
        mov     [WriteBank16Len],OAK87_bank_len
        mov     [WriteBank256],offset OAK87_bank
        mov     [WriteBank256Len],OAK87_bank_len
        mov     [ReadBank16],offset OAK87_rbank
        mov     [ReadBank16Len],OAK87_rbank_len
        mov     [ReadBank256],offset OAK87_rbank
		mov     [ReadBank256Len],OAK87_rbank_len
		ret

ENDP    OAK_init
