;****************************************************************************
;*
;*                        The Universal VESA VBE
;*
;*                  Copyright (C) 1993 Kendall Bennett.
;*                          All rights reserved.
;*
;* Filename:    $RCSfile: _s3.asm $
;* Version:     $Revision: 1.2 $
;*
;* Language:    8086 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: Assembly language support routines for S3 SuperVGA's.
;*
;*              Contains code to perform initialisation, bank switching
;*              and extended page flipping if possible.
;*
;*              Note that the code to perform bank switching and page
;*              flipping must be _completely_ relocatable, so you cannot
;*              access any global variables from within these routines.
;*              For this reason if bank switching is performed differently
;*              in 16 color planar modes, you must have a separate
;*              routine for the 16 color modes.
;*
;* $Id: _s3.asm 1.2 1993/09/24 05:23:19 kjb release $
;*
;* Revision History:
;* -----------------
;*
;* $Log: _s3.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
;*
;****************************************************************************

grS3_911            =   0   ; S3 86c911 SuperVGA chip
grS3_924            =   1   ; S3 86c924 SuperVGA chip
grS3_801_805        =   2   ; S3 86c801/86c805 SuperVGA chip
grS3_928            =   4   ; S3 86c928 SuperVGA chip

;----------------------------------------------------------------------------
; S3_bank16 Change to a new 64k bank (reading and writing) - 16 color mode
;----------------------------------------------------------------------------
;
; Changes to a new 64k bank for reading and writing on the S3 86c911 and
; S3 86c924 chipsets when running in 16 color planar mode.
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    S3_bank16   far

		push    ax
        push    cx
        push    dx
        mov     dx,3D4h
        shl     al,2                ; bank = bank * 4 in 16 color modes
        mov     ch,al               ; Save value for later
        and     al,0Fh              ; Mask off all but bottom 4 bits
        mov     cl,al
        mov     ax,4838h            ; Enable extended registers
        out     dx,ax
        mov     al,31h              ; Index of S3R1
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of S3R1
        or      al,9                ; Set bits 0 and 3
        or      al,1001b
        out     dx,al               ; Write value back again
        dec     dl
        mov     al,35h              ; Index of S3R5
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of S3R5
        and     al,0F0h             ; Mask off low nybble
        or      al,cl               ; Or in new bank number
        out     dx,al               ; Write the value back again
        dec     dl
S3MOD2: mov     al,grS3_911         ; Default to 911 chipset (modified)
        cmp     al,grS3_801_805
        jb      @@911               ; Chip is a 911 or 924
        mov     ax,0A039h           ; Unlock system control registers
        out     dx,ax
        mov     al,51h              ; Index of CR51
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of CR51
        and     al,0C0h             ; Clear out old values
        and     ch,30h              ; Mask out appropriate bits
        shr     ch,2
        or      al,ch               ; Or in top 2 bits of bank number
        out     dx,al               ; Write the value back again
        dec     dl
        mov     ax,0039h            ; Lock system control registers
        out     dx,ax
@@911:  mov     ax,0038h            ; Disable extended registers
        out     dx,ax
        pop     dx
        pop     cx
        pop     ax
		ret

ENDP

S3_bank16_len   =   ($-S3_bank16)   ; Length of relocatable routine

;----------------------------------------------------------------------------
; S3_bank256    Change to a new 64k bank (reading and writing)
;----------------------------------------------------------------------------
;
; Changes to a new 64k bank for reading and writing on the S3 86c911 and
; S3 86c924 chipsets in 256 color and above modes.
;
; Entry:        AX  - Number of 64k bank
;
; Registers:    All preserved!
;
;----------------------------------------------------------------------------
PROC    S3_bank256  far

		push    ax
        push    cx
        push    dx
        mov     dx,3D4h
        mov     ch,al               ; Save value for later
        and     al,0Fh              ; Mask off all but bottom 4 bits
        mov     cl,al
        mov     ax,4838h            ; Enable extended registers
        out     dx,ax
        mov     al,31h              ; Index of S3R1
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of S3R1
        or      al,9                ; Set bits 0 and 3
        or      al,1001b
        out     dx,al               ; Write value back again
        dec     dl
        mov     al,35h              ; Index of S3R5
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of S3R5
        and     al,0F0h             ; Mask off low nybble
        or      al,cl               ; Or in new bank number
        out     dx,al               ; Write the value back again
        dec     dl
S3MOD1: mov     al,grS3_911         ; Default to 911 chipset (modified)
        cmp     al,grS3_801_805
        jb      @@911               ; Chip is a 911 or 924
        mov     ax,0A039h           ; Unlock system control registers
        out     dx,ax
        mov     al,51h              ; Index of CR51
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of CR51
        and     al,0C0h             ; Clear out old values
        and     ch,30h              ; Mask out appropriate bits
        shr     ch,2
        or      al,ch               ; Or in top 2 bits of bank number
        out     dx,al               ; Write the value back again
        dec     dl
        mov     ax,0039h            ; Lock system control registers
        out     dx,ax
@@911:  mov     ax,0038h            ; Disable extended registers
        out     dx,ax
        pop     dx
        pop     cx
        pop     ax
		ret

ENDP

S3_bank256_len  =   ($-S3_bank256)  ; Size of relocatable routine

;----------------------------------------------------------------------------
; S3_page   Set the extended CRT starting address for S3 chipsets.
;----------------------------------------------------------------------------
;
; 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    S3_page far

        SetLowStartAddress
        mov     bh,bl               ; Save top 4 bits
        mov     dx,3D4h             ; DX := CRTC I/O port
        mov     ax,4838h            ; Enable extended registers
        out     dx,ax
        mov     al,31h              ; Index of S3R1
        out     dx,al
        inc     dl
        in      al,dx               ; Read old value of S3R1
        and     al,0CFh             ; Mask off bits 5-4
        and     bl,3                ; Mask off bottom two bits
        shl     bl,4                ; Shift into bit pos 5-4
        or      al,bl               ; Or in starting address value
        out     dx,al               ; Set the new value
        dec     dl
S3MOD3: mov     al,grS3_911         ; Default to 911 chipset (modified)
        cmp     al,grS3_801_805
        jb      @@911               ; Chip is a 911 or 924
        mov     ax,0A039h           ; Unlock system control registers
        out     dx,ax
        mov     al,51h              ; Index of CR51
        out     dx,al
        inc     dl
        in      al,dx               ; Read value of CR51
        and     al,3                ; Clear out old values
        shr     bh,2
        and     bh,3                ; Mask off bottom two bits
        or      al,bh               ; Or in top 2 bits of start address
        out     dx,al               ; Write the value back again
        dec     dl
        mov     ax,0039h            ; Lock system control registers
        out     dx,ax
@@911:  mov     ax,0038h            ; Disable extended registers
        out     dx,ax
        ret

ENDP

S3_page_len     =   ($-S3_page)     ; Length of relocatable routine

;----------------------------------------------------------------------------
; S3_init
;----------------------------------------------------------------------------
; We have an S3 based video card, so set up a few things specific to this
; card.
;----------------------------------------------------------------------------
PROC    S3_init

; Setup the correct vectors to use the S3 bank switching and paging routines

        mov     [TwoBanks],false
        mov     [WriteBank16],offset S3_bank16
        mov     [WriteBank16Len],S3_bank16_len
        mov     [WriteBank256],offset S3_bank256
        mov     [WriteBank256Len],S3_bank256_len
		mov     [NewPage16],offset S3_page
		mov     [NewPage16Len],S3_page_len
		mov     [NewPage256],offset S3_page
        mov     [NewPage256Len],S3_page_len

; Bank switching on the 801/805/928 chipsets is more complicated, as you
; can possibly access up to 4Mb of memory (on the 928) which needs to be
; addressed. We use modify the code in the bank switching routine depending
; on the type of chipset currently installed.

        mov     al,[BYTE CntChipID]
        mov     [BYTE S3MOD1+1],al  ; Modify the bank16 code
        mov     [BYTE S3MOD2+1],al  ; Modify the bank256 code
        mov     [BYTE S3MOD3+1],al  ; Modify the page flipping code
        ret

ENDP    S3_init
