	page 70, 132



;----------------------------------------------------------------------
; Module Name	:VESA452.asm
; Program Name	:VESA452.com
; Description	:This program traps Video BIOS Fuction calls made from an
;		Application program. It is a TSR(Terminate & Stay Resident)
;		program.
; Date		:February 26, 1990
; Version	:1.0
; Programmer	:Rakesh K. Jain
; Copyright (C) Chips and Technologies, Inc. 1990
;----------------------------------------------------------------------

	include	vesa.inc		; to include VESA structures & constants
	include	vesa452.inc		; 452 related stuff

;
; Code Segment Starts
;
	code	segment
	assume	cs:code, ds:code, ss:code, es:code

	org	100h			;for making the program .COM type

begin	:
	jmp	main			; jump to the initialization part


;------------------------------------------------------------------
;	This routine stores BIOS Video Function Number into a Buffer
;	and then calls BIOS fuction.
;------------------------------------------------------------------
VideoHandler proc	near
; look for functions to be implemented here
	cmp	ah, VESA_FUNCTIONS
	jnz	VHNotVGACntlFun

; Its a VESA function
	call	VESAFunctions
	iret

VHNotVGACntlFun:
	pushf			;Push Flags to compensate for IRET
	callfar
oldvect	dw	0
	dw	0		;Old Video Interrupt Vector
	iret
VideoHandler endp



VESAFunctions proc	near
	cmp	al, MAX_FUNCTIONS
	ja	VESAFNotAValidFunction
	cmp	al,5				; Window Control function
	jnz	@F
	push	cs
	call	near ptr SuperVGASetCPUMemWin	; This is far call
	ret
@@:
	pushem	<es,ds,di,si,dx,cx,ax,bx>	; dont change ax, bx order
	xor	ah, ah
	shl	ax, 1				; ax = function index
	xchg	ax, bx
	mov	bx, cs:DispatchTable[bx]	; function ptr in bx
	xchg	ax, bx
	call	ax
DirectReturn:
	popem	<bx,ax,cx,dx,si,di,ds,es>	; dont change ax, bx order
	mov	ax, cs:Status
	ret
VESAFNotAValidFunction:
	cmp	al, 70h
	jne	@f
	call	SetChipsWindowSize
	mov	ax, 704fh
	ret
@@:
	cmp	al, 71h
	jne	@f
	call	GetChipsWindowSize
	mov	ax, 714fh
	ret
@@:
	xor	al, al		; function not supported
	ret
VESAFunctions endp



SuperVGAInfo	proc	near
;
; copy our info structure
;
	cld				; play it safe, don't assume things
	mov	ax, cs
	mov	ds, ax			; Set our data segment
	mov	si, OFFSET VGAInfo
	mov	cx, (SIZE VGAInfoBlock) / 2
	rep movsw
IF	(SIZE VGAInfoBlock) AND 1
	movsb
ENDIF
if 0	;** we assume that 82C452 presence is already been checked, when we installed this TSR
;
; Look for 82C452 (CHIPS Super VGA)
;
	call	ReadChipsVGAId		; Id is returned in ah
;
; if VGA is identified as Chips product then look for specific VGA
; look for Chips Id
;
	cmp	ah, CHIPS_ID	; is it chips Id?
	jnz	VGACError00	; non Chips VGA/EGA
;
; VGA is identified as Chips VGA
;
	mov	ah, 80H		; open extended registers at 3d6/3d7H
	call	ExtRegs
	call	ReadVGATypeNRev
	mov	bl, ah		; place this info to proper reg
	and	ah, 0F0H	; test VGA type
	cmp	ah, CHIPSVGA_452
	jnz	VGACFNot452
;
; 82C452 is found, return success
;
endif	;**0
	mov	Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
if 0	;** Presence of 82c452 is alraedy been checked
VGACError00:
VGACFNot452:
	mov	Status, FAILURE SHL 8 + VESA_FUNCTIONS
	ret
endif	;** 0
SuperVGAInfo	endp



SuperVGAModeInfo proc	near
	cld				; play it safe
	mov	ax, cs
	mov	ds, ax			; Set our data segment
	mov	si, OFFSET ModeInfo
	mov	ax, cx			; VESA Mode No ****** to be changed to bx
	mov	dx, di			; save di in dx
	mov	bx, es			; save es in bx
	call	VESAToInternalMode
	call	InternalModeToIndex
	mov	ax, di			; al = Mode Index
	mov	ah, SIZE ModeInfoBlock
	mul	ah			; ax = +(SIZE ModeInfoBlock)*Index
	add	si, ax			; si = ModeInfo+(SIZE ModeInfoBlock)*Index
	mov	di, dx			; restore di
	mov	es, bx			; restore es
	mov	cx, OBLG_INFO_SIZE
	test	[si].ModeAttributes, MA_EXT_INFO
	jz	@F
	add	cx, EXT_INFO_SIZE
@@:
	push	di			; save start address
	rep movsb
	pop	di			; restore start adress
	mov	ax, word ptr ChipsNoOfWindows
					; al = # of Windows, ah = Window Size
	cmp	al, 1			; Is there only 1 windows supported
	jz	@F			; By default we enable only one window
	mov	es:[di].WinBAttributes,WIN_ATTR	; Enable second window also
	cmp	ah, 64			; Is it Dual page 64K ?
	jz	@F			; Yes, we are all set
	mov	es:[di].WinBSegment, WINB_NADDR	; change selector to dual page 32K windows
@@:
	mov	byte ptr es:[di].WinSize, ah	; copy size of the window
	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
SuperVGAModeInfo endp



SuperVGASetMode	proc	near
	mov	ax, bx				; ax = VESA Mode
	call	VESAToInternalMode		; ax = Internal Mode (BIOS Mode)
	mov	bx, ax				; save internal mode
	and	ah, ah				; see if ah = 0
	jnz	SVSMError
	int	10H				; call BIOS to set mode
; did BIOS set the mode ?
	mov	ax, 40h
	mov	ds, ax
	mov	di, 49h
	and	bl, NOT 80H			; Clear Not-clear-memory bit
	cmp	[di], bl
	jnz	SVSMError
;
; find out what value is to be programmed in the GR06 and XR0B to select
; proper CPU address window. We have table of these value so we have
; to compute index to the table first. There are 4 entries in the table.
;	NumberOfWin	SizeofWin	XR0B	GR06 (Low)
;	1		64 K		0	4
;	1		128K		0	0
;	2		32 K		2	4
;	2		64 K		2	0
; We assume that # of windows and windows size will always have these values
;
	cmp	bl, 6ah			; For all standard modes and 132 column modes
	jb	StandardModes		; don't bother about paging etc
	mov	bx, word ptr cs:ChipsNoOfWindows
					; bl = # of Windows, bh = Window Size
	mov	cl, 6			; # of bits to be shifted
	shr	bl, 1			; 'C' if bl = 1, bl = 0/1
	adc	cl, 0			; cl = 6/5
	shr	bh, cl			; bl = 0/1
	shl	bl, 1
	add	bl, bh
	xor	bh, bh			; bx = index into the table
	shl	bx, 1			; each entry is one word

	mov	dx, 3ceh		; dx = Graphics Controller addr
	mov	al, 6
	out	dx, al
	inc	dx
	in	al, dx
	and	al, 11110011b		; clear memory size bits
	or	al, cs:WinRegTable[bx]	; GR06 value
	out	dx, al

	mov	ah, 80h			; Open extended registers
	call	ExtRegs

	mov	dx, EGA_BASE + EXTR_ADDR
	mov	al, 0bh
	out	dx, al
	inc	dx
	in	al, dx			; read current value
	and	al, 11111101b		; clear dual page bit
	or	al, cs:WinRegTable[bx+1] ; XR0B value
	out	dx, al
StandardModes:

	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
SVSMError:
	mov	cs:Status, FAILURE SHL 8 + VESA_FUNCTIONS
	ret
SuperVGASetMode	endp



SuperVGAGetMode	proc	near
	mov	ax, 0F00H
	int	10H
	xor	ah, ah			
	mov	bx, ax			; save this info in bx
	call	InternalModeToVesa
	jnc	@F
	xchg	ax, bx
@@:
	pop	dx			; get return addr
	pop	ax			; pop bx in ax *******
	push	bx			; push mode to be returned
	push	dx			; 
	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
SuperVGAGetMode	endp



SuperVGAVideoState	proc	near
	mov	ah, 1cH				; ah = BIOS function to save/restore VIDEO state
	mov	al, dl				; al = subfunction
	push	ax				; save function
	push	cx
	test	cx, VS_SUPERVGA_STATE
	jz	SVVSNotSuperVGA0
;
; Super VGA state
;
	cmp	al, VS_GET_BUFSIZE
	jnz	SVVSNotBufSize
;
; get buf size function
;
	cmp	cx, VS_SUPERVGA_STATE		; if it is SUPERVGA_STATE only
	jnz	@F				; save cx, ax and call BIOS
; only SUPERVGA_STATE
	mov	bx, SUPERVGA_SIZE
	pop	cx
	pop	ax				; restore sunfunction
	jmp	SVVSNotSuperVGA1		; don't call BIOS

SVVSNotBufSize:
	cmp	al, VS_SAVE_STATE
	jnz	SVVSNotSaveState
;
; save state function
; es:bx --> pointer to buffer, bx will be updated by routine
;
	call	SaveSuperVGAState
	jmp	short @F
SVVSNotSaveState:
	cmp	al, VS_RESTORE_STATE
	jnz	SVVSNotRestoreState
;
; restore state function
; es:bx --> pointer to buffer, bx will be updated by routine
;
	call	RestoreSuperVGAState
SVVSNotRestoreState:
SVVSNotSuperVGA0:
@@:
	int	10H
	pop	cx				; restore requested state
	pop	ax				; restore subfunction function
	test	cx, VS_SUPERVGA_STATE
	jz	SVVSNotSuperVGA1
; super vga function
	cmp	al, VS_GET_BUFSIZE		; is it GET_BUFSIZE function ?
	jnz	@F				; no
	add	bx, SUPERVGA_SIZE		; add # of full block
SVVSNotSuperVGA1:
	pop	dx				; pop return address
	pop	ax				; pop bx in ax *******
	push	bx				; put bx on stack
	push	dx				; push new address
@@:
	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
SuperVGAVideoState	endp



SuperVGASetCPUMemWin	proc	far
	cmp	bh,01
	je	SuperVGAMapVideoMem
	push	dx				; save page
	mov	ah, 80h
	call	ExtRegs
	pop	dx				; restore page
	mov	ah, dl				; ah = page #
	mov	al, PAGE_REG_A
	and	bl, 01				; consider only LSB
	add	al, bl
;**	push	dx				; Save dx
	mov	dx, EGA_BASE+EXTR_ADDR
	out	dx, ax
	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
;**	pop	dx				; Restore dx
	ret
SuperVGASetCPUMemWin	endp



SuperVGAMapVideoMem	proc	near
	mov	ah, 80h
	call	ExtRegs
	mov	al, PAGE_REG_A
	and	bl, 01				; consider only LSB
	add	al, bl
	mov	dx, EGA_BASE+EXTR_ADDR
	out	dx,al
	inc	dx
	in	al,dx
	xor	ah,ah
	mov	dx,ax
	mov	cs:Status, SUCCESS SHL 8 + VESA_FUNCTIONS
	ret
SuperVGAMapVideoMem	endp



SuperVGADACCntl	proc	near
	ret
SuperVGADACCntl	endp



;----------------------------------------------------------------------
; This routine saves extended registers into a buffer.
; 2 bytes per register are saved. High byte contains reg value and low
; byte reg index.
;
; Entry:
;	es:bx --> pointer to buffer (2 bytes per extended reg)
; Destroyed:
;	ds, si, di, dx & flags
; Preseeved:
;	ax, cx, and bx updated, to be used by BIOS later
;-----------------------------------------------------------------------
SaveSuperVGAState	proc	near
	push	cx
	push	ax				; save important regs
	mov	ah, 80H
	call	ExtRegs				; Open extended registers
	mov	ax, cs
	mov	ds, ax				; ds = cs (our data seg)
	mov	si, OFFSET ExtRegIndex		; pointer to ext reg indices table
	mov	di, bx				; buffer pointer
	mov	dx, EGA_BASE+EXTR_ADDR
	mov	cx, NEXTREGS			; # of ext regs to be saved
SAVSLoop:
	lodsb					; load ext reg index in al
	mov	ah, al				; ah = al = index
	out	dx, al				; index the port
	inc	dx				; dx = data port (3d7)
	in	al, dx				; read value
	dec	dx				; dx = address port
	xchg	al, ah				; ah = value, al = index
	stosw					; store it
	loop	SAVSLoop			; do till all regs are over
	add	bx, 2*NEXTREGS			; increment pointer for BIOS fuction
	pop	ax
	pop	cx				; restore important regs
	ret
SaveSuperVGAState	endp



;----------------------------------------------------------------------
; This routine restores extended registers from user buffer
; Entry:
;	es:bx --> pointer to buffer (2 bytes per extended reg)
; Destroyed:
;	ds, si, dx & flags
; Preseeved:
;	ax, cx, and bx updated, to be used by BIOS later
;-----------------------------------------------------------------------
RestoreSuperVGAState	proc	near
	push	cx
	push	ax				; save important regs
	mov	ah, 80H
	call	ExtRegs				; Open extended registers
	mov	ax, es
	mov	ds, ax
	mov	si, bx				; ds:si --> pointer to save regs
	mov	dx, EGA_BASE+EXTR_ADDR
	mov	cx, NEXTREGS
RSVSLoop:
	lodsw
	out	dx, ax				; output value to appropriate port
	loop	RSVSLoop
	add	bx, 2*NEXTREGS			; increment pointer for BIOS fuction
	pop	ax				; restore important regs
	pop	cx
	ret
RestoreSuperVGAState	endp



;---------------------------------------------------------------------
; This routine converts user given mode into a 82C452 BIOS mode number
; Entry:
;	ax = VESA mode
; Exit:
;	if 'C' is clear, ax = internal mode (60H to 7BH)
;	else	Error... ax not changed
; Destroyed:
;	es, cx, di
;----------------------------------------------------------------------
VESAToInternalMode	proc	near
	mov	di, cs
	mov	es, di
	mov	di, OFFSET VESAModeTable
	mov	cx, NMODES
	push	ax
	and	ah, NOT 80h		; clear memory-not-clear bit
	repnz scasw			; scan til value matches
	jnz	VESATIMInvalidMode
	sub	di, OFFSET VESAModeTable
	shr	di, 1			; Offset to byte table
	mov	al, cs:InternalModeTable[di-1]
	xor	ah, ah
	pop	cx			; pop the original mode number
	and	ch,80h			; extract 15th bit
	or	al,ch			; and OR it to mode number
	clc				; cheer on success
	ret
VESATIMInvalidMode:
	pop	cx			; balance the stack
	stc				; weep on failuare
	ret
VESAToInternalMode	endp


;---------------------------------------------------------------------
; This routine converts internal mode into a VESA given mode number
; Entry:
;	ax = internal mode
; Exit:
;	if 'C' is clear, ax = internal mode (60H to 7BH)
;	else	Error...
; Destroyed:
;	es, cx, di
;----------------------------------------------------------------------
InternalModeToVESA	proc	near
	mov	di, cs
	mov	es, di
	mov	di, OFFSET InternalModeTable
	mov	cx, NMODES
	repnz scasb			; scan til value matches
	jnz	IMTVESAInvalidMode
	sub	di, OFFSET InternalModeTable
	shl	di, 1			; Offset to word table
	mov	al, cs:InternalModeTable[di-2]
	clc				; cheer on success
	ret
IMTVESAInvalidMode:
	stc				; weep on failuare
	ret
InternalModeToVESA	endp



;---------------------------------------------------------------------
; This routine converts an Internal mode into an index (0 to NMODES-1)
; Entry:
;	ax = Internal mode
; Exit:
;	if 'C' is clear, di = index of internal mode table (0 to NMODES -1)
;	else	Error...
; Destroyed:
;	es, cx, di
;----------------------------------------------------------------------
InternalModeToIndex	proc	near
	mov	di, cs
	mov	es, di
	mov	di, OFFSET InternalModeTable
	mov	cx, NMODES
	repnz scasb			; scan til value matches
	jnz	IMTIInvalidMode
	sub	di, OFFSET InternalModeTable+1
	clc				; cheer on success
	ret
IMTIInvalidMode:
	stc				; weep on failuare
	ret
InternalModeToIndex	endp



ExtRegs proc	near
;---------------------------------------------------------------------
; Opens extended register space at 3d6/3d7H
; Entry:
;	ah = 80/40H to open extended register space at 3d6/3b6H
;	ah = 0  to close extended register space
; Destroyed:
;	ax, dx
; Output:
;	None
;---------------------------------------------------------------------

; place VGA in setup mode
	mov	dx, cs:SetupAddr
	mov	al, byte ptr cs:SetupData[0]	; value to place vga in setup mode
	cli				; Disable interrupts
	out	dx, al

; enable/disable extended registers
	push	dx			; save setup address
	mov	dx, 103h
	mov	al, ah			; open extended register at 3d6/3d7H
	out	dx, al
	pop	dx			; restore setup address

; take VGA out of setup mode
	mov	al, byte ptr cs:SetupData[1]	; value to take vga out of setup mode
	out	dx, al
	sti				; Enable interrupt
	ret
ExtRegs endp


;------------------------------------------------------------------------
SetChipsWindowSize proc near

	mov	word ptr cs:ChipsNoOfWindows, dx
;**	.ERRNZ	OFFSET ChipsWindowSize - OFFSET ChipsNoOfWindows -1
	ret

SetChipsWindowSize endp


;------------------------------------------------------------------------
GetChipsWindowSize proc near

	mov	dx, word ptr cs:ChipsNoOfWindows
;**	.ERRNZ	OFFSET ChipsWindowSize - OFFSET ChipsNoOfWindows -1
	ret

GetChipsWindowSize endp


;---------------------------------------------------------------------
;		Resident Data Declaration
;---------------------------------------------------------------------
marker	db	'VESA for 82C452'
marklen	EQU	$ - marker
msg1	db	'VESA Program already installed', NL, EOS

DispatchTable	dw	OFFSET SuperVGAInfo
		dw	OFFSET SuperVGAModeInfo
		dw	OFFSET SuperVGASetMode
		dw	OFFSET SuperVGAGetMode
		dw	OFFSET SuperVGAVideoState
		dw	OFFSET SuperVGASetCPUMemWin
		dw	OFFSET SuperVGAMapVideoMem
		dw	OFFSET SuperVGADACCntl
Status		dw	0			; status of every call

SetupAddr	dw	46e8h			; setup port for PC/AT
SetupData	dw	0e1eh			; setup data for PC/AT

ChipsNoOfWindows	db	1		;** for two undocumented functions
ChipsWindowSize		db	64		;** for two undocumented functions
	.ERRNZ	OFFSET ChipsWindowSize - ChipsNoOfWindows -1 ; don't break sequence
WinRegTable	db	04, 00			; values for GR06 bit 3,2 and XR0B bit 1
		db	00, 00
		db	04, 02
		db	00, 02

ExtRegIndex	LABEL	BYTE
defextregs <02H,05H,0AH,0BH,0CH,0DH,0EH,10H,11H,20H,21H,22H,23H,24H>
defextregs <28H,2BH,30H,31H,32H,33H,34H,35H,36H,37H,38H,39H,3AH>
;;******	db	XR04,XR06,XR14,XR15,XR16,XR18,XR19,XR1A,XR1B,XR1C,XR1D,XR1E
NEXTREGS	equ	$ - ExtRegIndex


IF	(2*NEXTREGS) AND BLOCKSIZE -1
PARTIAL_BLOCK	equ	1			; if partial block add one more block
ELSE
PARTIAL_BLOCK	equ	0
ENDIF

SUPERVGA_SIZE	equ	(((2*NEXTREGS)/BLOCKSIZE) + PARTIAL_BLOCK)


VESAModeTable	dw	102h,71h,104h,100h,101h,7Ah,END_OF_MODES
		; This table hold VESA mode numbers.
		; This the one which is passed to the user in VGAInfo
VESAModeTableLen	equ	($ - VESAModeTable -2)/2

InternalModeTable db	70h,71h,72h,78h,79h,7Ah
		; This table holds internal modes corresponding to VESA modes.
		; Like VESA mode 100 is mapped to internal (BIOS) mode 70H
		; If any new VESA mode is added, the Internal Mode Table
		; should be reordered so that new VESA mode and Internal
		; Mode are in same position in the respective tables and
		; also parameter sequence in InitModeInfo macro should be
		; changed correspondingly

NMODES		equ	$ - InternalModeTable

	.ERRNZ	NMODES - VESAModeTableLen
				; give error on size missmatch of two tables


ModeInfo label	ModeInfoBlock
InitModeInfo	<<Mode70>,<Mode71>,<Mode72>,<Mode78>,<Mode79>,<Mode7A>>

VGAInfo	VGAInfoBlock	<>		; use default values

ChipsString	db	'CHIPS 82C452, the Super VGA', 0




ProgSize label	word		;Create Label to get Size of the Program

;----------------------------------------------------------------------
; ************************ End of Resident Code *********************
;----------------------------------------------------------------------



main	proc	near
	getvector	VideoInt
	mov	ax, OFFSET marker - OFFSET VideoHandler
	mov	cx, marklen
	mov	di, bx
	add	di, ax			; es:[di] Pointer to Previous Marker String
	mov	si, OFFSET marker
	cld
	repe cmpsb
	jcxz	AlreadyLoaded
	jmp	short start
AlreadyLoaded	:
	print	msg1
	int	20h			;Exit to DOS

start	:
;
; Look for 82C452 VGA
;
	call	ReadChipsVGAId
	cmp	ah, CHIPS_ID		; is it chips Id?
	jnz	error_exit		; Chis VGA is not present
	mov	ah, 80h			; open extended reg at 3d6/3d7
	call	ExtRegs
	call	ReadVGATypeNRev
	and	ah, 0f0h		; extract upper nibble
	cmp	ah, CHIPSVGA_452
	jz	ChipsVGAPresent		; Chips 82C452 is present
error_exit:
	print	msg4
	int	20h			;Exit to DOS

ChipsVGAPresent:			; our VGA is present
	print	msg0			;Initial Message
;
; Look for command line parameter for monitor
; es, ds, and cs are same
;
	mov	ax, cs
	mov	es, ax			; es = ds = cs
	mov	di, 80H			; offset of command trail area
	mov	cl, [di]		; al = # of chars in command trail
	and	cl, cl
	jz	MainDefaultMonitor
	inc	di
	mov	al, '+'			; For MultiSync + monitor
	xor	ch, ch			; cx = n chars
	repnz scasb			; read first char
	jnz	MainDefaultMonitor
;
; MultiSync Plus Monitor	
;
	inc	monitor
	print	msg3
	.errnz	MULTISYNC_PLUS -1
MainDefaultMonitor:			; by default 'monitor' is 0 for MultiSync II

;	
; Initialize VGAInfo structure
;
	mov	si, OFFSET VGAInfo
	mov	ax, OFFSET ChipsString
	mov	WORD PTR [si].OEMString, ax
	mov	WORD PTR [si].OEMString+2, ds
	mov	ax, OFFSET VESAModeTable
	mov	WORD PTR [si].VideoModePtr, ax
	mov	WORD PTR [si].VideoModePtr+2, ds

;
; Initialize ModeInfo structure tables
;
	mov	cx, NMODES		; # of modes table support
	mov	si, OFFSET ModeInfo
	xor	bx, bx			; bx = index
	mov	dl, monitor		; monitor type
MainModeInfoLoop:
	mov	al, InternalModeTable[bx]	; al = internal mode
					; according to table
	cmp	dl, MULTISYNC_PLUS
	jz	MainMultiSyncPlus
;
; not a MultiSync Plus monitor. Disable Mode 71H, & 72H
;
	cmp	al, 71H
	jb	MainCommon		; Not 960x720 1024x768 16 col mode
	cmp	al, 72H
	ja	MainCommon		; if(mode > 72H)
;
; mode 71H & 72H can not be handled by MultiSyncII. Disable them.
;
	and 	[si].ModeAttributes, NOT MA_HW_SUPP
	jmp	short MainCommon	; done

;**	jmp	short @F		; do it down

MainMultiSyncPlus:			; all modes are supported
;**	cmp	al, 70H
;**	jz	@F			; MultiSyncPlus can not handle at 40MHz
;**	cmp	al, 79H
;**	jbe	MainCommon
;**;
;**; modes 70, 7a, 7b can not be handled by MultiSyncPlus. Diasable them.
;**;
;**@@:
;**	and 	[si].ModeAttributes, NOT MA_BIOS_INIT

MainCommon:
	mov	ax, OFFSET SuperVGASetCPUMemWin
	mov	WORD PTR [si].WinFuncPtr, ax
	mov	WORD PTR [si].WinFuncPtr+2, ds
	inc	bx			; increase index
	add	si, SIZE ModeInfoBlock
	loop	MainModeInfoLoop

;
; Install interrupt handler
;
	call	ChgVdoVector	;Save Current Video Vector and
						;Change it to New Handler
;
; Terminate But Stay Resident
;
	mov	ah, TSR		;TSR Function Number
	mov	al, 0		;Return code
	mov	dx, OFFSET ProgSize	;Size of the program in bytes
	mov	cl, 4
	shr	dx, cl		;dx = ProgSize/16 (Size in Paragraphs)
	inc	dx
	int	21h
main	endp



;------------------------------------------------------------------
;	This routine saves current Video Vector
;	and initialize it with New Video Interrupt Handler
;------------------------------------------------------------------
ChgVdoVector proc	near
	getvector	VideoInt
	mov	oldvect, bx
	mov	oldvect+2, es	;Save Old Vector
; Set Video Vector to New Handler
	setvector	VideoInt, VideoHandler
	ret
ChgVdoVector endp



ReadChipsVGAId proc	near
;---------------------------------------------------------------------
; read chips global Id register
; Entry:
;	None
; Destroyed:
;	ax, dx
; Output:
;	ah = CHIPS Id (0A5H if successful)
;----------------------------------------------------------------------
; Find which machine Microchannel/AT
	mov	ah,0c0h			; Find out system configuration
	int	15H			; Microchannel or AT
	mov	dx,46e8h		; Assume VGA Setup Port for PC/AT
	mov	ax,0e1eh		; al = 1eH to put VGA in Setup Mode
					; ah = 0eH to place VGA in normal mode
	jc	@F			; call not successful, assume PC/AT
	test	byte ptr es:[bx+5],2	; Is it Microchannel Machine ?
	jz	@F			; No, We already have proper values
	mov	dx,094h			; Yes, Microchannel values
	mov	ax,0ffdfh		; al = df, ah = ff for microchannel
@@:
	mov	cs:SetupAddr, dx	; save it for use in GrOpenExtRegs
	mov	cs:SetupData, ax	; save it for use in GrOpenExtRegs
	cli				; Don't interrupt while doing serious business
	out	dx,al
	push	dx			; save port
	mov	dx,104h			; CHIPS ID Port
	in	al,dx
	pop	dx			; CHIPS VGA Setup Port
	xchg	al,ah			; Save ID in ah, al = value to get outof setup port
	out	dx,al
	sti				; Serious business is over
	ret
ReadChipsVGAId endp



ReadVGATypeNRev proc	near
;----------------------------------------------------------------------
; read chip type and rev no
; Entry:
;	None
; Destroyed:
;	ax, dx
; Output:
;	ah = Chips type and revision no
;----------------------------------------------------------------------

	mov	dx, EGA_BASE+EXTR_ADDR
	xor	al, al			; al = XR00
	out	dx, al
	inc	dx
	in	al, dx			; al = chips type and rev no
	mov	ah, al			; return the info in ah
	ret
ReadVGATypeNRev endp



;----------------------------------------------------------------------
;		 Transient data declaration
;----------------------------------------------------------------------

msg0	db	'VESA452 - VESA BIOS Extension Version 1.0 for 82C452 Super VGA Controller', NL
	db	'Release Version 0.2',NL,NL
	db	'Copyright (C) Chips and Technologies, Inc. 1990. ',NL
	db	NL
	db	'A "+" on command line enables all the modes supported by the video BIOS.',NL
	db	'Default is NEC MultiSync II or equivalent monitor supported modes.',NL
	db	NL,EOS

msg3	db	'Monitor supported is MultiSync Plus',NL,EOS

msg4	db	'Chips and Technologies Super VGA 82C452 is not present.',NL
	db	TAB, 'VESA driver is not installed.',NL,EOS

monitor	db	MULTISYNC_II		; default for MultiSync II

code	ends
	end	begin
