Category : C Source Code
Archive   : SVGAKT31.ZIP
Filename : SV_BANKS.ASM

 
Output of file : SV_BANKS.ASM contained in archive : SVGAKT31.ZIP
;****************************************************************************
;*
;* MegaGraph Graphics Library
;*
;* Copyright (C) 1993 Kendall Bennett.
;* All rights reserved.
;*
;* Filename: $RCSfile: sv_banks.asm $
;* Version: $Revision: 1.2 $
;*
;* Language: 80386 Assembler
;* Environment: IBM PC (MS DOS)
;*
;* Description: This source file contains the code needed to change banks
;* on supported SuperVGA adapters, along with tables to find
;* the correct routines for a specified video card.
;*
;* The code in here originally appeared in John Bridges
;* VGAKIT library, and has been modified to work with the
;* MGL. Specifically support for individually setting the
;* read and write banks has been included, along with adapter
;* initialisation code (such as accessing extended registers
;* etc).
;*
;* To set up separate read/write banks, you must first call
;* NewBank to set the read/write banks to the same value,
;* then call ReadBank to change the read bank value.
;*
;* $Id: sv_banks.asm 1.2 1993/03/07 04:05:36 kjb Exp $
;*
;* Revision History:
;* -----------------
;*
;* $Log: sv_banks.asm $
;* Revision 1.2 1993/03/07 04:05:36 kjb
;* Bug fixes.
;*
;* Revision 1.1 1993/03/03 10:26:52 kjb
;* Initial revision
;*
;****************************************************************************

; Table of SuperVGA bank switching routines by video card.

SVGAInfoTable:
dw false, VESA_bank, VESA_bank, VESA_init, NONE_exit
dw true, ATI_bank, ATI_rbank, ATI_init, NONE_exit
dw false, AHEADA_bank, AHEADA_bank, AHEAD_init, AHEAD_exit
dw true, AHEADB_bank, AHEADB_rbank, AHEAD_init, AHEAD_exit
dw false, CHIPS451_bank, CHIPS451_bank, CHIPS_init, CHIPS_exit
dw false, EVEREX_bank, EVEREX_bank, EVEREX_init, NONE_exit
dw true, GENOA_bank, GENOA_rbank, NONE_init, NONE_exit
dw true, OAK_bank, OAK_rbank, NONE_init, NONE_exit
dw true, PARADISE_bank, PARADISE_rbank, PARADISE_init, PARADISE_exit

dw false, TRIDENT_bank, TRIDENT_bank, TRIDENT_init, NONE_exit
dw false, TRIDENT_bank, TRIDENT_bank, TRIDENT_init, NONE_exit
dw true, VIDEO7V5_bank, VIDEO7V5_rbank, VIDEO7_init, VIDEO7_exit
dw true, ET3000_bank, ET3000_rbank, NONE_init, NONE_exit
dw true, ET4000_bank, ET4000_rbank, ET4000_init, NONE_exit
dw true, NCR_bank, NCR_rbank, NCR_init, NONE_exit
dw false, S3_bank, S3_bank, S3_init, NONE_exit
dw false, ACUMOS_bank, ACUMOS_bank, ACUMOS_init, ACUMOS_exit
dw false, AL2101_bank, AL2101_bank, AL2101_init, NONE_exit
dw true, MXIC_bank, MXIC_rbank, MXIC_init, MXIC_exit
dw true, P2000_bank, P2000_rbank, NONE_init, NONE_exit
dw true, RT3106_bank, RT3106_rbank, RT3106_init, NONE_exit
dw false, CIRRUS_bank, CIRRUS_bank, CIRRUS_init, CIRRUS_exit

SVGAInfo:
TwoBanks dw 0 ; Flags if two banks available
NewBank dw NONE_bank ; Address of read/write bank switch routine
ReadBank dw NONE_bank ; Address of read bank routine
InitSVGA dw NONE_init ; Address of card Init routine
ExitSVGA dw NONE_exit ; Address of card close routine
SVGAInfoSize = ($-SVGAInfo) ; Size of the above table

CurBank dw 0FFh ; Currently active read/write bank
VesaGran db 0 ; VESA Granularity
VesaBank dd 0 ; Address of VESA bank switch routine
VesaBuf db 256 dup (?) ; Place to store VESA Info

VesaModes: dw 100h, grSVGA_640x400x256
dw 101h, grSVGA_640x480x256
dw 102h, grSVGA_800x600x16
dw 103h, grSVGA_800x600x256
dw 104h, grSVGA_1024x768x16
dw 105h, grSVGA_1024x768x256
dw 106h, grSVGA_1280x1024x16
dw 107h, grSVGA_1280x1024x256
dw 10Dh, grSVGA_320x200x32k
dw 10Fh, grSVGA_320x200x16m
dw 110h, grSVGA_640x480x32k
dw 112h, grSVGA_640x480x16m
dw 113h, grSVGA_800x600x32k
dw 115h, grSVGA_800x600x16m
dw 116h, grSVGA_1024x768x32k
dw 118h, grSVGA_1024x768x16m
dw 119h, grSVGA_1280x1024x32k
dw 11Bh, grSVGA_1280x1024x16m
dw 0

;----------------------------------------------------------------------------
; SetupBanks Setup the SuperVGA bank switching routines
;----------------------------------------------------------------------------
;
; Given the id of the SuperVGA card that is installed, this routine sets
; up the following bank switching code.
;
; Registers: AX,CX,SI,DI
;
;----------------------------------------------------------------------------
PROC SetupBanks near

mov [ReadBank],offset NONE_bank
mov [InitSVGA],offset NONE_init
mov ax,[CntDriver]
cmp ax,grSVGA
jl @@Exit ; Not a SuperVGA adapter

mov si,offset SVGAInfoTable
mov ax,[CntDriver] ; AX := number of current driver
sub ax,grSVGA ; Adjust to start at 0 for SVGA's
mov cx,SVGAInfoSize
mul cx
add si,ax ; SI := index into table of SVGA banks
mov di,offset SVGAInfo
push cs
pop es
rep movs [BYTE es:di],[BYTE es:si]

@@Exit:
mov [CurBank],0FFh ; Set the bank to nothing to start with
ret

ENDP SetupBanks

;----------------------------------------------------------------------------
; NewBank Change to a new 64k bank on a SuperVGA card (reading and writing)
;----------------------------------------------------------------------------
;
; Changes to a new 64k bank given the specified index. The global variable
; CurBank is updated to reflect the current bank number and can be used
; to avoid unnecessary bank switching.
;
; These routines should set both the read and write bank for cards that
; support multiple banks to the same bank number.
;
; Note that the value of all regs MUST be preserved across this call.
;
; Entry: AX - Number of 64k bank (0-15 for 1Mb cards)
;
; Registers: None.
;
;----------------------------------------------------------------------------

NONE_bank:
ret

VESA_bank:
mov [CurBank],ax ; Save the new bank number for later
push ax
push bx
push dx
mul [VesaGran] ; Adjust with granularity factor
push ax
mov dx,ax ; Select window position
xor bx,bx ; BH := 0 (Select SVGA memory window)
; BL := 0 (window to set)
call [VesaBank] ; Change bank A
pop dx ; Select window position
inc bx ; BL := 1 (window to set)
call [VesaBank] ; Change bank B
pop dx
pop bx
pop ax
ret

ATI_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

AHEADA_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

AHEADB_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

CHIPS451_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov ah,al
mov al,0Bh ; Index of Single/Low Map register
mov dx,3D6h
out dx,ax ; Set the register value
pop dx
pop ax
sti
ret

CHIPS452_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov ah,al
shl ah,2 ; Change 64k bank into 16k bank number
mov al,10h ; Index of Single/Low Map register
mov dx,3D6h
out dx,ax ; Set the register value
pop dx
pop ax
sti
ret

CHIPS453_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov ah,al
shl ah,4 ; Change 64k bank into 4k bank number
mov al,10h ; Index of Single/Low Map register
mov dx,3D6h
out dx,ax ; Set the register value
pop dx
pop ax
sti
ret

EVEREX_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
push cx
mov cl,al
mov dx,3C4h
mov al,8
out dx,al
inc dl
in al,dx
dec dl
shl al,1
shr cl,1
rcr al,1
mov ah,al
mov al,8
out dx,ax ; Bit 0 stored in 3C4 index 8 bit 7
mov dl,0CCh
in al,dx
mov dl,0C2h
and al,0DFh
shr cl,1
jc @@Nob2
or al,20h
@@Nob2: out dx,al ; Bit 1 stored in 3C2 bit 5
pop cx
pop dx
pop ax
sti
ret

GENOA_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov ah,al ; Put read bank in bits 2-0 ...
shl al,3 ; ... write bank in bits 5-3
or ah,al
or ah,40h ; Set MEM bit
mov al,6 ; Index of Memory Segment Register
mov dx,3C4h
out dx,ax ; Set the read/write banks
pop dx
pop ax
sti
ret

OAK_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

PARADISEPVGA_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov dx,3CEh
shl al,4 ; change 64k bank into 4k bank number
mov ah,al
mov al,9 ; Index of PROA register
out dx,ax ; Program PROA register
pop dx
pop ax

sti
ret

PARADISE_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov dx,3CEh
shl al,4 ; change 64k bank into 4k bank number
mov ah,al
mov al,9 ; Index of PROA register (read bank)
out dx,ax ; Program PROA register
mov al,0Ah ; Index of PROB register (write bank)
out dx,ax ; Program PROB register
pop dx
pop ax
sti
ret

TRIDENT_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
xor al,2 ; Adjust page bit
mov ah,al
mov dx,3C4h
mov al,0Bh ; Index of Chip Version register
out dx,al ; Program index
inc dl
xor al,al
out dx,al ; Force old definitions
in al,dx ; Force new definitions
dec dl
mov al,0Eh ; Index of New Mode Control Reg
out dx,ax ; Program the page value
pop dx
pop ax
sti
ret

NCR_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
shl al,2 ; Change 64k bank into 16k bank number
cmp [CntColors],gr16Color
jne @@NCR1
shl al,2 ; Change 64k bank into 4k bank number
@@NCR1: mov ah,al
mov al,18h
mov dx,3C4h
out dx,ax ; Set write bank number
mov al,1Ch
out dx,ax ; Set read bank number
pop dx
pop ax
sti
ret

VIDEO7_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push cx
push dx
and al,0Fh ; Mask to 4 bits
mov ch,al
mov dx,3C4h
mov ah,ch
and ah,1
mov al,0F9h ; Index of Extended Page Select register
out dx,ax ; Program PS bit in register
mov al,ch
and al,1100b ; Bits 3-2 for read field
mov ah,al
shr ah,2 ; Bits 1-0 for write field
or ah,al ; Combine two values
mov al,0F6h
out dx,al ; Index the bank select register
inc dl
in al,dx ; Read old value
and al,11110000b ; Zero out old bits
or al,ah ; Combine with new values
out dx,al ; Program the values
mov ah,ch
and ah,10b ; Mask out bit 2
shl ah,4 ; Put into bit 5
mov dx,3CCh ; Address Miscellaneous register
in al,dx ; Read old value
and al,0DFh ; Zero bit 5
mov dx,3C2h
or al,ah ; Or in the page bit
out dx,al ; Program the new value
pop dx
pop cx
pop ax
sti
ret

VIDEO7V5_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
and al,0Fh ; Mask to 4 bits
shl al,4 ; Shift into bits 7-4
mov ah,al
mov dx,3C4h
mov al,0E8h ; Index of write bank register
out dx,ax ; Program the write bank
mov al,0E9h ; Index of read bank register
out dx,ax ; Program the read bank
pop dx
pop ax
sti
ret

ET3000_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
and al,7 ; Mask out bottom 3 bits
mov ah,al ; Combine read and write bank values in al
shl ah,3
or al,ah
or al,40h ; Set bit 6 to select 64k segments
mov dx,3CDh ; Point to memory segment register
out dx,al ; Set the new bank value
pop dx
pop ax
sti
ret

ET4000_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
and al,0Fh ; Mask out bottom 4 bits
mov ah,al ; Combine read and write values in al
shl ah,4
or al,ah
mov dx,3CDh ; Point to memory segment register
out dx,al ; Set the new bank value
pop dx
pop ax
sti
ret

S3_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push cx
push dx
mov dx,3D4h
cmp [CntColors],gr16Color
jne @@S31
shl al,2 ; bank = bank * 4 in 16 color modes
@@S31: 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
mov ax,0038h ; Disable extended registers
out dx,ax
pop dx
pop cx
pop ax
sti
ret

CIRRUS_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

ACUMOS_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

AL2101_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov dx,3D6h
out dx,al ; Set read bank register
inc dx
out dx,al ; Set write bank
pop dx
pop ax
sti
ret

MXIC_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
and al,0Fh ; Mask out all but 4 bottom bits
mov ah,al ; Combine read/write bank numbers
shl al,4
or ah,al
mov al,0C5h ; Index of bank switch register
mov dx,3C4h
out dx,ax ; Set the register value
pop dx
pop ax
sti
ret

P2000_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov dx,3D6h
out dx,al ; Set write bank register
inc dx
out dx,al ; Set read bank
pop dx
pop ax
sti
ret

RT3106_bank:
mov [CurBank],ax ; Save the new bank number for later
cli
push ax
push dx
mov dx,3D6h
out dx,al ; Set write bank register
inc dx
out dx,al ; Set read bank
pop dx
pop ax
sti
ret

;----------------------------------------------------------------------------
; ReadBank Change to a new 64k read bank on a SuperVGA card
;----------------------------------------------------------------------------
;
; Changes to a new 64k bank for reading given the specified index. The write
; bank should be preserved across this call.We also trash the value in
; CurBank to indicate that bank switching needs to be done again to set
; the read and write banks to the same value.
;
; Note that the value of all regs MUST be preserved across this call.
;
; Entry: AX - Number of 64k bank (0-15 for 1Mb cards)
;
; Registers: None.
;
;----------------------------------------------------------------------------

VESA_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
push ax
push bx
push dx
mul [VesaGran] ; Adjust with granularity factor
mov dx,ax ; Select window position
xor bh,bh ; BH := 0 (Select SVGA memory window)
mov bl,1 ; Window to set
call [VesaBank] ; Change bank
pop dx
pop bx

pop ax
ret

ATI_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
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
sti
ret

AHEADB_rbank:
mov [CurBank],ax ; Save the new bank number for later
cli
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
sti
ret

GENOA_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
and al,7 ; Mask out bottom three bits
mov ah,al
mov dx,3C4h
mov al,6 ; Index of Memory Segment Register
out dx,al ; Output index
inc dl
in al,dx ; Read current value
and al,0F8h ; Zero bits 2-0
or al,ah ; Or in new value
out dx,al ; Output the new bank
pop dx
pop ax
sti
ret

OAK_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
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
sti
ret

PARADISE_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov dx,3CEh
shl al,4 ; change 64k bank into 4k bank number
mov ah,al
mov al,09h ; Index of PROA register (read bank)
out dx,ax ; Program PROA register
pop dx
pop ax
sti
ret

NCR_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
shl al,2 ; Change 64k bank into 16k bank number
cmp [CntColors],gr16Color
jne @@NCR2
shl al,2 ; Change 64k bank into 4k bank number
@@NCR2: mov ah,al
mov al,1Ch
mov dx,3C4h
out dx,ax ; Set read bank number
pop dx
pop ax
sti
ret

VIDEO7V5_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
and al,0Fh ; Mask to 4 bits
shl al,4 ; Shift into bits 7-4
mov ah,al
mov dx,3C4h
mov al,0E9h ; Index of read bank register
out dx,al ; Program the value
pop dx
pop ax
sti
ret

ET3000_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov ah,bl ; Save value of bl
and al,7 ; Mask out bottom 3 bits
shl al,3 ; Shift into position
mov bl,al
mov dx,3CDh
in al,dx ; Read current value
and al,0C7h ; Mask out read bank select value
or al,bl ; Or in the new read bank value
out dx,al ; Set the new bank value
mov bl,ah ; Restore value of bl
pop dx
pop ax
sti
ret

ET4000_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov ah,bl ; Save value of bl
and al,0Fh ; Mask out bottom 4 bits
shl al,4 ; Shift into position
mov bl,al
mov dx,3CDh
in al,dx ; Read current value
and al,00Fh ; Mask out read bank select bits 7-4
or al,bl ; Or in the new read bank value
out dx,al ; Set the new bank value
mov bl,ah ; Restore value of bl
pop dx
pop ax
sti
ret

AL2101_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov dx,3D6h
out dx,al ; Set read bank register
pop ax
pop dx
sti
ret

MXIC_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
and al,0Fh ; Mask out all but 4 bottom bits
shl al,4
mov ah,al
mov al,0C5h ; Index of bank switch register
mov dx,3C4h
out dx,al
inc dx
in al,dx ; Read old value
and al,0Fh ; Mask out old read bank values
or al,ah
out dx,al ; Set the register value
pop dx
pop ax
sti
ret

P2000_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov dx,3D7h
out dx,al ; Set read bank
pop dx
pop ax
sti
ret

RT3106_rbank:
mov [CurBank],0FFh ; Trash CurBank with invalid value
cli
push ax
push dx
mov dx,3D6h
out dx,al ; Set read bank register
pop ax
pop dx
sti
ret

;----------------------------------------------------------------------------
; InitBank Initialise the SuperVGA card for bank switching if required
;----------------------------------------------------------------------------
;
; Peforms any initialisations required by the SuperVGA card prior to bank
; switching (accessing extended registers, setting the mode etc).
;
; Note: All register may be used without concern for saving their values
;
; Registers: All.
;
;----------------------------------------------------------------------------

PROC NONE_init near
ret
ENDP NONE_init

;----------------------------------------------------------------------------
; VESA_init
;----------------------------------------------------------------------------
; We have a VESA SuperVGA adapter, so determine the granularity and address
; of the VESA bank switching routine. We simply determine whether we are
; in 16 or 256 color video modes, and get information about these modes.
;----------------------------------------------------------------------------
PROC VESA_init near

push cs
pop es
mov di,offset VesaBuf ; ES:DI -> Buffer for VESA info
mov bx,[CntMode]
mov si,offset VesaModes ; CS:SI -> Table of VESA video modes

mov cx,102h ; 800 x 600 16 color
cmp bx,grVGA_640x480x16
jle @@NonVESA
mov cx,101h ; 640 x 480 256 color
cmp bx,grVGA_320x200x256
je @@NonVESA

@@ModeLoop:
lods [WORD cs:si]
mov cx,ax ; CX := VESA Mode Number
jcxz @@Exit ; Fall through if no match
lods [WORD cs:si]
cmp ax,bx
jne @@ModeLoop

mov ax,4F01h
int 10h ; Call the video BIOS to get info

mov ax,[CntMode]
mov bx,[WORD VesaBuf+16]
call setBytesPerLine
mov [BytesPerLine],bx
jmp @@SaveValues

@@NonVESA:
mov ax,4F01h
int 10h

@@SaveValues:
mov ax,[WORD VesaBuf+12]; Save pointer to bank switching routine
mov [WORD VesaBank],ax
mov ax,[WORD VesaBuf+14]
mov [WORD VesaBank+2],ax

mov cx,[WORD VesaBuf+4] ; Load VESA granularity value
mov al,1
cmp cx,0 ; Some BIOS'S fuck this up!
je @@NoDivide
mov ax,64
div cl
@@NoDivide:
mov [VesaGran],al ; Save the granularity scale factor

; Now determine if this video card supports multiple banks

mov ax,[WORD VesaBuf+2] ; Get Window attributes
and ah,0111b ; Mask out appropriate bits
cmp ah,0011b ; Check if second window is only readable
jne @@Exit ; No, so we are done

mov [TwoBanks],true
mov [ReadBank],offset VESA_rbank

@@Exit:
ret

ENDP VESA_init

;----------------------------------------------------------------------------
; 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

push bp

cmp [CntChipID],grATI_18800
jne @@Not18800

; We have an 18800 based ATI SuperVGA, so modify to not use separate read
; write banks.

mov [TwoBanks],false
mov [ReadBank],offset ATI_bank
jmp @@Exit

; We have an 18800-1 or 28800 Chip, so setup for dual bank mode

@@Not18800:
modinx 1CEh, 0BEh, 01000b, 01000b ; Set bit 3 ATI Register E

@@Exit:
pop bp
ret

ENDP ATI_init

;----------------------------------------------------------------------------
; AHEAD_init
;----------------------------------------------------------------------------
; We have an Ahead A or B SuperVGA. We simply enable the extended registers
; to save time during bank switching.
;----------------------------------------------------------------------------
PROC AHEAD_init near

outp 3CEh, 0Fh, 20h ; Enable extended registers
modinx 3CEh, 0Ch, 20h, 20h ; Enable enhanced mode
ret

ENDP AHEAD_init

;----------------------------------------------------------------------------
; CHIPS_init
;----------------------------------------------------------------------------
; We have a Chips & Technologies 82c451/452/453. To save time during
; bank switching, we enable the SuperVGA extended registers here.
; We also determine the type of chipset installed and setup bank switching
; and page flipping according to the chip type.
;----------------------------------------------------------------------------
PROC CHIPS_init near

outp 46E8h, 1Eh ; Place chip in setup mode
outp 103h, 80h ; Enable extended registers
outp 46E8h, 0Eh ; Bring chip out of setup mode
modinx 3D6h, 4, 4, 4 ; Enable bank access and extended CRTC
modinx 3D6h, 0Dh, 3, 1 ; Enable extended paging

; Set the bank switching code according to the C&T chipset type

mov bx,[CntChipID] ; BX := chip id

cmp bx,grCHIPS_82c451
je @@Chips451 ; Done for 82c451
cmp bx,grCHIPS_82c452
je @@Chips452

mov [NewBank],offset CHIPS453_bank
mov [ReadBank],offset CHIPS453_bank
jmp @@Exit

@@Chips452:
mov [NewBank],offset CHIPS452_bank
mov [ReadBank],offset CHIPS452_bank
jmp @@Exit

; Extended page flipping is not available on 82c451 chips, so disable it

@@Chips451:
mov [WORD cs:CHIPSPageOfs],offset NONE_page

@@Exit:
ret

ENDP CHIPS_init

;----------------------------------------------------------------------------
; EVEREX_init
;----------------------------------------------------------------------------
; Some Everex video boards are based on Trident or ET4000 chips. Detect
; them here, and setup to use the correct bank switching and page flipping
; routines.
;----------------------------------------------------------------------------
PROC EVEREX_init near

mov ax,[CntChipID] ; AX := chipset ID
cmp ax,grEVEREX_Ev236 ; UltraGraphics - Trident Chip
je @@TridentChip
cmp ax,grEVEREX_Ev620 ; Vision VGA - Trident Chip
je @@TridentChip
cmp ax,grEVEREX_Ev629 ; ViewPoint TC - ET4000 Chip
je @@ET4000Chip
cmp ax,grEVEREX_Ev673 ; EVGA - Trident Chip
je @@TridentChip
cmp ax,grEVEREX_Ev678 ; Viewpoint - Trident Chip
jne @@Exit ; Normal Everex chip, all done

; Based on Trident chip, so determine the type (8800 or 8900).

@@TridentChip:
mov [TwoBanks],false
mov [NewBank],offset TRIDENT_bank
mov [ReadBank],offset TRIDENT_bank
mov [WORD cs:EVEREXPageOfs],offset TRIDENT88_page

wrinx 3C4h, 0Bh, 0 ; Force old definitions
inp 3C5h ; Force new definitions
and al,0Fh
cmp al,2
je @@Exit ; Done for Trident 8800
mov [WORD cs:EVEREXPageOfs],offset TRIDENT89_page
jmp @@Exit

@@ET4000Chip:
mov [TwoBanks],true
mov [NewBank],offset ET4000_bank
mov [ReadBank],offset ET4000_rbank
mov [WORD cs:EVEREXPageOfs],offset ET4000_page
jmp @@Exit

@@Exit:
ret

ENDP EVEREX_init

;----------------------------------------------------------------------------
; PARADISE_init
;----------------------------------------------------------------------------
; We have a Paradise PVGA1A or WD90Cxx SuperVGA. We simply enable access
; to the extended registers to save time during bank switching.
;----------------------------------------------------------------------------
PROC PARADISE_init near

; Enable paradise extensions

wrinx 3CEh, 0Fh, 5 ; Turn off write protect on VGA registers
wrinx 3C4h, 6h, 48h ; Unlock extended sequencer regs
wrinx 3D4h, 29h, 85h ; Turn on access to PR10-17

; Turn off the standard VGA mem bit, to allow access to all of the SuperVGA
; video memory for extended page flipping.

modinx 3D4h, 2Fh, 2, 0 ; Clear out the VGA MEM bit

; Now determine the Paradise Chipset type. The WD90C10 and above chipsets
; support the dual banking mode.

cmp [CntChipID],grPARA_90C10
jge @@HaveDualMode

; Have an old PVGA1 or WD90C00 video card without dual banking support

mov [TwoBanks],false
mov [NewBank],offset PARADISEPVGA_bank
mov [ReadBank],offset PARADISEPVGA_bank
jmp @@Exit

; We have a WD90C1x/3x chipset, so set up for dual banking
; operation (read/write operation).

@@HaveDualMode:
modinx 3CEh, 0Bh, 8, 8 ; Enable both PROA and PROB
modinx 3C4h, 11h, 80h, 80h ; Set PROA for read, PROB for write

@@Exit:
ret

ENDP PARADISE_init

;----------------------------------------------------------------------------
; TRIDENT_init
;----------------------------------------------------------------------------
; We have a Trident 8800 or 8900 SuperVGA. Setup for a pagesize of 64k
; before doing bank switching.
;----------------------------------------------------------------------------
PROC TRIDENT_init

modinx 3CEh, 6, 4, 4 ; Set pagesize to 64k
ret

ENDP TRIDENT_init

;----------------------------------------------------------------------------
; VIDEO7_init
;----------------------------------------------------------------------------
; We have a Video7 V7VGA SuperVGA. Enable access to the extended registers
; to save time during bank switching.
;----------------------------------------------------------------------------
PROC VIDEO7_init

outp 3C4h, 6, 0EAh ; Enable extended registers

; Determine if the chip is revision five or later, so we can support
; dual read/write bank operation.

rdinx 3C4h, 08Eh ; Read Chip Revision register
cmp al,05Ah ; Is this a version 5 chip?
jl @@HaveV5 ; We have a version 5 or later chip

; If the card is a 1024i, I am not sure if it has a version 4 or version 5
; chip in it. I assume here that it has a version 5 chip. If it does not,
; (or does not seem to work), uncomment the following code and replace
; the above line:
;
; jg @@NotV5 ; version 1-3 V7VGA's
; cmp al,050h
; jge @@HaveV5 ; Yes, version 5 chip

@@NotV5:
mov [TwoBanks],false
mov [NewBank],offset VIDEO7_bank
mov [ReadBank],offset VIDEO7_bank
jmp @@Exit

; We have a V7VGA revision 5 or later chip, so setup for dual paging
; mode

@@HaveV5:
modinx 3C4h, 0E0h, 80h, 80h ; Set split bank mode

@@Exit:
ret

ENDP VIDEO7_init

;----------------------------------------------------------------------------
; ET4000_init
;----------------------------------------------------------------------------
; We have an ET4000 video card, so enable access to extended registers
; before bank switching.
;----------------------------------------------------------------------------
PROC ET4000_init

outp 3BFh, 3
outp 3D8h, 0A0h ; Enable ET4000 extensions

; Check the type of video board, modifying the 24 bit mode tables if
; we have a Speedstar 24 or Genoa 7900 board.

cmp [CntChipID],grET4000_MEGAEVA
je @@Done

; We have a Speedstar 24 or Genoa 7900, both which only support the
; 640x480 video modes. Note that on both these cards, the bytes per line
; value for the mode is 2048, not 1920 (so you don't have problems with
; pixels crossing bank boundaries!!).

mov [DWORD cs:ET4_640x350x16m],0
mov [DWORD cs:ET4_640x400x16m],0
mov bx,2048
mov ax,grSVGA_640x480x16m
call setBytesPerLine

cmp [CntChipID],grET4000_SPEEDSTAR
jne @@HaveGenoa

mov [DWORD cs:ET4_640x480x16m],02E10E0h
jmp @@Done

@@HaveGenoa:
mov [DWORD cs:ET4_640x480x16m],03E10F0h


@@Done:
ret

ENDP

;----------------------------------------------------------------------------
; NCR_init
;----------------------------------------------------------------------------
; We have an NCR 77C22E SuperVGA, so set up for dual banking mode of
; operation. We also program the low portions of the bank switching
; registers with zeroes.
;----------------------------------------------------------------------------
PROC NCR_init

modinx 3C4h, 1Eh, 010100b, 010100b
wrinx 3C4h, 19h, 0 ; Set primary offset low to 0
wrinx 3C4h, 1Dh, 0 ; Set secondary offset low to 0
ret

ENDP

;----------------------------------------------------------------------------
; S3_init
;----------------------------------------------------------------------------
; We have an S3 based video card, so set up a few things specific to this
; card.
;----------------------------------------------------------------------------
PROC S3_init

; The S3 Chipset uses large bytes per line values in 256, 32k and 64k
; color video modes to make the copper's life a little easier (and ours
; a little harder :-). Change the bytes per line values in the table
; to the correct values.

call ModifyS3BytesPerLine
ret

ENDP S3_init

;----------------------------------------------------------------------------
; CIRRUS_init
;----------------------------------------------------------------------------
; We have a Cirrus 5422 SuperVGA, so enable access to extended registers.
;----------------------------------------------------------------------------
PROC CIRRUS_init

wrinx 3C4h, 6, 12h ; Enable extended registers
ret

ENDP CIRRUS_init

;----------------------------------------------------------------------------
; ACUMOS_init
;----------------------------------------------------------------------------
; We have an AcuMos SuperVGA, so enable access to extended registers.
;----------------------------------------------------------------------------
PROC ACUMOS_init

wrinx 3C4h, 6, 12h ; Enable extended registers
ret

ENDP ACUMOS_init

;----------------------------------------------------------------------------
; AL2101_init
;----------------------------------------------------------------------------
; We have an Advance Logic 2101 SuperVGA, so set up for separate read
; write bank switching. This is supposed to work according to the
; docs on the AL2101, but it doesn't (it works for the RealTek instead!)
; Very wierd!!
;----------------------------------------------------------------------------
PROC AL2101_init

; modinx 3CEh, 0Fh, 4, 4 ; Set bit 2 of Extended function register
ret

ENDP AL2101_init

;----------------------------------------------------------------------------
; MXIC_init
;----------------------------------------------------------------------------
; We have an MXIC SuperVGA, so enable access to extended registers.
;----------------------------------------------------------------------------
PROC MXIC_init

wrinx 3C4h, 0A7h, 087h ; Enable extended registers
ret

ENDP MXIC_init

;----------------------------------------------------------------------------
; RT3106_init
;----------------------------------------------------------------------------
; We have a RealTek 3106 SuperVGA. This code is supposed to work on the
; advance logic's ALG2101 chip, but apparantly works on the RT3106!
;----------------------------------------------------------------------------
PROC RT3106_init

modinx 3CEh, 0Fh, 4, 4 ; Set bit 2 of Extended function register
ret

ENDP RT3106_init

;----------------------------------------------------------------------------
; ExitBank Deinitialises the SuperVGA card back to normal operation.
;----------------------------------------------------------------------------
;
; Returns the SuperVGA card back to it's default state, such as turning
; off access to all extended registers that were set by the initialisation
; routines.
;
; Note: All register may be used without concern for saving their values
;
; Registers: All.
;
;----------------------------------------------------------------------------

PROC NONE_exit near
ret
ENDP NONE_exit

PROC AHEAD_exit near

outp 3CEh, 0Fh, 0 ; Disable extended registers
ret

ENDP AHEAD_exit

PROC CHIPS_exit near

outp 46E8h, 1Eh ; Place chip in setup mode
outp 103h, 0 ; Disable extended registers
outp 46E8h, 0Eh ; Bring chip out of setup mode
ret

ENDP CHIPS_exit

PROC PARADISE_exit near

wrinx 3CEh, 0Fh, 0 ; Turn on write protect on VGA registers
wrinx 3CEh, 6h, 0 ; Turn on write protect on extended seq
ret

ENDP PARADISE_exit

PROC VIDEO7_exit

outp 3C4h, 6, 0AEh ; Disable extended registers
ret

ENDP VIDEO7_exit

PROC CIRRUS_exit

wrinx 3C4h, 6, 0 ; Disable extended registers
ret

ENDP CIRRUS_exit

PROC ACUMOS_exit

wrinx 3C4h, 6, 0 ; Disable extended registers
ret

ENDP ACUMOS_exit

PROC MXIC_exit

wrinx 3C4h, 0A7h, 0 ; Disable extended registers
ret

ENDP MXIC_exit


  3 Responses to “Category : C Source Code
Archive   : SVGAKT31.ZIP
Filename : SV_BANKS.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/