;; ============================================================================================
;;
;; Copyright (C) 2001,2002 the LGPL VGABios developers Team
;;
;; This library is free software; you can redistribute it and/or
;; modify it under the terms of the GNU Lesser General Public
;; License as published by the Free Software Foundation; either
;; version 2 of the License, or (at your option) any later version.
;;
;; This library is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; Lesser General Public License for more details.
;;
;; You should have received a copy of the GNU Lesser General Public
;; License along with this library; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
;;
;; ============================================================================================
;;
;; This VGA Bios is specific to the plex86/bochs Emulated VGA card.
;; You can NOT drive any physical vga card with it.
;;
;; ============================================================================================
;;
; Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
; other than GPL or LGPL is available it will apply instead, Oracle elects to use only
; the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
; a choice of LGPL license versions is made available with the language indicating
; that LGPLv2 or any later version may be used, or where a choice of which version
; of the LGPL is applied is otherwise unspecified.
include vgadefs.inc
public vgabios_int10_handler
VGAROM segment public 'CODE'
; Implemented in C
extrn _int10_func:near
extrn _vgabios_init_func:near
ifdef VBE
; Implemented in separate assembly module
extrn vbe_biosfn_return_current_mode:near
extrn vbe_biosfn_display_window_control:near
extrn vbe_biosfn_set_get_logical_scan_line_length:near
extrn vbe_biosfn_set_get_display_start:near
extrn vbe_biosfn_set_get_dac_palette_format:near
extrn vbe_biosfn_set_get_palette_data:near
extrn vbe_biosfn_return_protected_mode_interface:near
endif
ifdef VGA_DEBUG
extrn _int10_debugmsg:near
extrn _printf:near
extrn _unimplemented:near
extrn _unknown:near
endif
vgabios_start:
db 055h, 0AAh ; ROM signature, required for expansion ROMs
db 40h ; ROM module length in units of 512 bytes */
vgabios_entry_point:
jmp _vgabios_init_func
org 1Eh
db 'IBM',0
;;
;; int10 handled here
;;
.286
vgabios_int10_handler:
pushf
ifdef VGA_DEBUG
push es
push ds
pusha
mov bx, 0C000h
mov ds, bx
call _int10_debugmsg
popa
pop ds
pop es
endif
cmp ah, 0Fh
jne int10_test_1A
call biosfn_get_video_mode
jmp int10_end
int10_test_1A:
cmp ah, 1Ah
jne int10_test_0B
call biosfn_group_1A
jmp int10_end
int10_test_0B:
cmp ah, 0Bh
jne int10_test_1103
call biosfn_group_0B
jmp int10_end
int10_test_1103:
cmp ax, 1103h
jne int10_test_12
call biosfn_set_text_block_specifier
jmp int10_end
int10_test_12:
cmp ah, 12h
jne int10_test_101B
cmp bl, 10h
jne int10_test_BL30
call biosfn_get_ega_info
jmp int10_end
int10_test_BL30:
cmp bl, 30h
jne int10_test_BL31
call biosfn_select_vert_res
jmp int10_end
int10_test_BL31:
cmp bl, 31h
jne int10_test_BL32
call biosfn_enable_default_palette_loading
jmp int10_end
int10_test_BL32:
cmp bl, 32h
jne int10_test_BL33
call biosfn_enable_video_addressing
jmp int10_end
int10_test_BL33:
cmp bl, 33h
jne int10_test_BL34
call biosfn_enable_grayscale_summing
jmp int10_end
int10_test_BL34:
cmp bl, 34h
jne int10_normal
call biosfn_enable_cursor_emulation
jmp int10_end
int10_test_101B:
cmp ax, 101Bh
je int10_normal
cmp ah, 10h
ifndef VBE
jne int10_normal
else
jne int10_test_4F
endif
call biosfn_group_10
jmp int10_end
ifdef VBE
int10_test_4F:
cmp ah, 4Fh
jne int10_normal
cmp al, 3
jne int10_test_vbe_05
call vbe_biosfn_return_current_mode
jmp int10_end
int10_test_vbe_05:
cmp al, 5
jne int10_test_vbe_06
call vbe_biosfn_display_window_control
jmp int10_end
int10_test_vbe_06:
cmp al, 6
jne int10_test_vbe_07
call vbe_biosfn_set_get_logical_scan_line_length
jmp int10_end
int10_test_vbe_07:
cmp al, 7
jne int10_test_vbe_08
call vbe_biosfn_set_get_display_start
jmp int10_end
int10_test_vbe_08:
cmp al, 8
jne int10_test_vbe_09
call vbe_biosfn_set_get_dac_palette_format
jmp int10_end
int10_test_vbe_09:
cmp al, 9
jne int10_test_vbe_0A
call vbe_biosfn_set_get_palette_data
jmp int10_end
int10_test_vbe_0A:
cmp al, 0Ah
jne int10_normal
call vbe_biosfn_return_protected_mode_interface
jmp int10_end
endif
int10_normal:
push es
push ds
pusha
;; We have to set ds to access the right data segment
mov bx, 0C000h
mov ds, bx
call _int10_func
popa
pop ds
pop es
int10_end:
popf
iret
;;--------------------------------------------------------------------------------------------
biosfn_group_0B:
cmp bh, 0
je biosfn_set_border_color
cmp bh, 1
je biosfn_set_palette
ifdef VGA_DEBUG
call _unknown
endif
ret
biosfn_set_border_color:
push ax
push bx
push cx
push dx
push ds
mov dx, BIOSMEM_SEG
mov ds, dx
mov dx, VGAREG_ACTL_RESET
in al, dx
cmp byte ptr ds:[BIOSMEM_CURRENT_MODE], 3
jbe set_border_done
mov dx, VGAREG_ACTL_ADDRESS
mov al, 00h
out dx, al
mov al, bl
and al, 0Fh
test al, 08h
jz set_low_border
add al, 08h
set_low_border:
out dx, al
mov cl, 1
and bl, 10h
set_intensity_loop:
mov dx, VGAREG_ACTL_ADDRESS
mov al, cl
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
and al, 0EFh
or al, bl
mov dx, VGAREG_ACTL_ADDRESS
out dx, al
inc cl
cmp cl, 4
jne set_intensity_loop
set_border_done:
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop ds
pop dx
pop cx
pop bx
pop ax
ret
biosfn_set_palette:
push ax
push bx
push cx
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov cl, 01
and bl, 01
set_cga_palette_loop:
mov dx, VGAREG_ACTL_ADDRESS
mov al, cl
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
and al, 0FEh
or al, bl
mov dx, VGAREG_ACTL_ADDRESS
out dx, al
inc cl
cmp cl, 4
jne set_cga_palette_loop
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop cx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_get_video_mode:
push ds
mov ax, BIOSMEM_SEG
mov ds, ax
push bx
mov bx, BIOSMEM_CURRENT_PAGE
mov al, [bx]
pop bx
mov bh, al
push bx
mov bx, BIOSMEM_VIDEO_CTL
mov ah, [bx]
and ah, 80h
mov bx, BIOSMEM_CURRENT_MODE
mov al, [bx]
or al, ah
mov bx, BIOSMEM_NB_COLS
mov ah, [bx]
pop bx
pop ds
ret
;--------------------------------------------------------------------------------------------
biosfn_group_10:
cmp al, 0
jne int10_test_1001
jmp biosfn_set_single_palette_reg
int10_test_1001:
cmp al, 1
jne int10_test_1002
jmp biosfn_set_overscan_border_color
int10_test_1002:
cmp al, 2
jne int10_test_1003
jmp biosfn_set_all_palette_reg
int10_test_1003:
cmp al, 3
jne int10_test_1007
jmp biosfn_toggle_intensity
int10_test_1007:
cmp al, 7
jne int10_test_1008
jmp biosfn_get_single_palette_reg
int10_test_1008:
cmp al, 8
jne int10_test_1009
jmp biosfn_read_overscan_border_color
int10_test_1009:
cmp al, 9
jne int10_test_1010
jmp biosfn_get_all_palette_reg
int10_test_1010:
cmp al, 10h
jne int10_test_1012
jmp biosfn_set_single_dac_reg
int10_test_1012:
cmp al, 12h
jne int10_test_1013
jmp biosfn_set_all_dac_reg
int10_test_1013:
cmp al, 13h
jne int10_test_1015
jmp biosfn_select_video_dac_color_page
int10_test_1015:
cmp al, 15h
jne int10_test_1017
jmp biosfn_read_single_dac_reg
int10_test_1017:
cmp al, 17h
jne int10_test_1018
jmp biosfn_read_all_dac_reg
int10_test_1018:
cmp al, 18h
jne int10_test_1019
jmp biosfn_set_pel_mask
int10_test_1019:
cmp al, 19h
jne int10_test_101A
jmp biosfn_read_pel_mask
int10_test_101A:
cmp al, 1Ah
jne int10_group_10_unknown
jmp biosfn_read_video_dac_state
int10_group_10_unknown:
ifdef VGA_DEBUG
call _unknown
endif
ret
biosfn_set_single_palette_reg:
cmp bl, 14h
ja no_actl_reg1
push ax
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, bl
out dx, al
mov al, bh
out dx, al
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop ax
no_actl_reg1:
ret
;--------------------------------------------------------------------------------------------
biosfn_set_overscan_border_color:
push bx
mov bl, 11h
call biosfn_set_single_palette_reg
pop bx
ret
;--------------------------------------------------------------------------------------------
biosfn_set_all_palette_reg:
push ax
push bx
push cx
push dx
mov bx, dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov cl, 0
mov dx, VGAREG_ACTL_ADDRESS
set_palette_loop:
mov al, cl
out dx, al
mov al, es:[bx]
out dx, al
inc bx
inc cl
cmp cl, 10h
jne set_palette_loop
mov al, 11h
out dx, al
mov al, es:[bx]
out dx, al
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop cx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_toggle_intensity:
push ax
push bx
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 10h
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
and al, 0F7h
and bl, 01
shl bl, 3
or al, bl
mov dx, VGAREG_ACTL_ADDRESS
out dx, al
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_get_single_palette_reg:
cmp bl, 14h
ja no_actl_reg2
push ax
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, bl
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
mov bh, al
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop ax
no_actl_reg2:
ret
;;--------------------------------------------------------------------------------------------
biosfn_read_overscan_border_color:
push ax
push bx
mov bl, 11h
call biosfn_get_single_palette_reg
mov al, bh
pop bx
mov bh, al
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_get_all_palette_reg:
push ax
push bx
push cx
push dx
mov bx, dx
mov cl, 0
get_palette_loop:
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, cl
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
mov es:[bx], al
inc bx
inc cl
cmp cl, 10h
jne get_palette_loop
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 11h
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
mov es:[bx], al
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop cx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_set_single_dac_reg:
push ax
push dx
mov dx, VGAREG_DAC_WRITE_ADDRESS
mov al, bl
out dx, al
mov dx, VGAREG_DAC_DATA
pop ax
push ax
mov al, ah
out dx, al
mov al, ch
out dx, al
mov al, cl
out dx, al
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_set_all_dac_reg:
push ax
push bx
push cx
push dx
mov dx, VGAREG_DAC_WRITE_ADDRESS
mov al, bl
out dx, al
pop dx
push dx
mov bx, dx
mov dx, VGAREG_DAC_DATA
set_dac_loop:
mov al, es:[bx]
out dx, al
inc bx
mov al, es:[bx]
out dx, al
inc bx
mov al, es:[bx]
out dx, al
inc bx
dec cx
jnz set_dac_loop
pop dx
pop cx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_select_video_dac_color_page:
push ax
push bx
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 10h
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
and bl, 01
jnz set_dac_page
and al, 07Fh
shl bh, 7
or al, bh
mov dx, VGAREG_ACTL_ADDRESS
out dx, al
jmp set_actl_normal
set_dac_page:
push ax
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 14h
out dx, al
pop ax
and al, 80h
jnz set_dac_16_page
shl bh, 2
set_dac_16_page:
and bh, 0Fh
mov al, bh
out dx, al
set_actl_normal:
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_read_single_dac_reg:
push ax
push dx
mov dx, VGAREG_DAC_READ_ADDRESS
mov al, bl
out dx, al
pop ax
mov ah, al
mov dx, VGAREG_DAC_DATA
in al, dx
xchg al, ah
push ax
in al, dx
mov ch, al
in al, dx
mov cl, al
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_read_all_dac_reg:
push ax
push bx
push cx
push dx
mov dx, VGAREG_DAC_READ_ADDRESS
mov al, bl
out dx, al
pop dx
push dx
mov bx, dx
mov dx, VGAREG_DAC_DATA
read_dac_loop:
in al, dx
mov es:[bx], al
inc bx
in al, dx
mov es:[bx], al
inc bx
in al, dx
mov es:[bx], al
inc bx
dec cx
jnz read_dac_loop
pop dx
pop cx
pop bx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_set_pel_mask:
push ax
push dx
mov dx, VGAREG_PEL_MASK
mov al, bl
out dx, al
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_read_pel_mask:
push ax
push dx
mov dx, VGAREG_PEL_MASK
in al, dx
mov bl, al
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_read_video_dac_state:
push ax
push dx
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 10h
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
mov bl, al
shr bl, 7
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 14h
out dx, al
mov dx, VGAREG_ACTL_READ_DATA
in al, dx
mov bh, al
and bh, 0Fh
test bl, 01
jnz get_dac_16_page
shr bh, 2
get_dac_16_page:
mov dx, VGAREG_ACTL_RESET
in al, dx
mov dx, VGAREG_ACTL_ADDRESS
mov al, 20h
out dx, al
ifdef VBOX
mov dx, VGAREG_ACTL_RESET
in al, dx
endif ; VBOX
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_set_text_block_specifier:
push ax
push dx
mov dx, VGAREG_SEQU_ADDRESS
mov ah, bl
mov al, 03
out dx, ax
pop dx
pop ax
ret
;;--------------------------------------------------------------------------------------------
biosfn_get_ega_info:
push ds
push ax
mov ax, BIOSMEM_SEG
mov ds, ax
xor ch, ch
mov bx, BIOSMEM_SWITCHES
mov cl, [bx]
and cl, 0Fh
mov bx, BIOSMEM_CRTC_ADDRESS
mov ax, [bx]
mov bx, 0003h
cmp ax, VGAREG_MDA_CRTC_ADDRESS
jne mode_ega_color
mov bh, 01
mode_ega_color:
pop ax
pop ds
ret
;;--------------------------------------------------------------------------------------------
biosfn_select_vert_res:
; res : 00 200 lines, 01 350 lines, 02 400 lines
push ds
push bx
push dx
mov dl, al
mov ax, BIOSMEM_SEG
mov ds, ax
mov bx, BIOSMEM_MODESET_CTL
mov al, [bx]
mov bx, BIOSMEM_SWITCHES
mov ah, [bx]
cmp dl, 1
je vert_res_350
jb vert_res_200
cmp dl, 2
je vert_res_400
ifdef VGA_DEBUG
mov al, dl
xor ah, ah
push ax
mov bx, msg_vert_res
push bx
call _printf
add sp, 4
endif
jmp set_retcode
vert_res_400:
; reset modeset ctl bit 7 and set bit 4
; set switches bit 3-0 to 09
and al, 07Fh
or al, 010h
and ah, 0F0h
or ah, 009h
jnz set_vert_res
vert_res_350:
; reset modeset ctl bit 7 and bit 4
; set switches bit 3-0 to 09
and al, 06Fh
and ah, 0F0h
or ah, 009h
jnz set_vert_res
vert_res_200:
; set modeset ctl bit 7 and reset bit 4
; set switches bit 3-0 to 08
and al, 0EFh
or al, 080h
and ah, 0F0h
or ah, 008h
set_vert_res:
mov bx, BIOSMEM_MODESET_CTL
mov [bx], al
mov bx, BIOSMEM_SWITCHES
mov [bx], ah
set_retcode:
mov ax, 1212h
pop dx
pop bx
pop ds
ret
ifdef VGA_DEBUG
msg_vert_res:
db "Select vert res (%02x) was discarded", 13, 10, 0
endif
biosfn_enable_default_palette_loading:
push ds
push bx
push dx
mov dl, al
and dl, 01
shl dl, 3
mov ax, BIOSMEM_SEG
mov ds, ax
mov bx, BIOSMEM_MODESET_CTL
mov al, [bx]
and al, 0F7h
or al, dl
mov [bx], al
mov ax, 1212h
pop dx
pop bx
pop ds
ret
biosfn_enable_video_addressing:
push bx
push dx
mov bl, al
and bl, 01
xor bl, 01
shl bl, 1
mov dx, VGAREG_READ_MISC_OUTPUT
in al, dx
and al, 0FDh
or al, bl
mov dx, VGAREG_WRITE_MISC_OUTPUT
out dx, al
mov ax, 1212h
pop dx
pop bx
ret
biosfn_enable_grayscale_summing:
push ds
push bx
push dx
mov dl, al
and dl, 01h
xor dl, 01h
shl dl, 1
mov ax, BIOSMEM_SEG
mov ds, ax
mov bx, BIOSMEM_MODESET_CTL
mov al, [bx]
and al, 0FDh
or al, dl
mov [bx], al
mov ax, 1212h
pop dx
pop bx
pop ds
ret
biosfn_enable_cursor_emulation:
push ds
push bx
push dx
mov dl, al
and dl, 01
xor dl, 01
mov ax, BIOSMEM_SEG
mov ds, ax
mov bx, BIOSMEM_MODESET_CTL
mov al, [bx]
and al, 0FEh
or al, dl
mov [bx], al
mov ax, 1212h
pop dx
pop bx
pop ds
ret
;;--------------------------------------------------------------------------------------------
biosfn_group_1A:
cmp al, 0
je biosfn_read_display_code
cmp al, 1
je biosfn_set_display_code
ifdef VGA_DEBUG
call _unknown
endif
ret
biosfn_read_display_code:
push ds
push ax
mov ax, BIOSMEM_SEG
mov ds, ax
mov bx, BIOSMEM_DCC_INDEX
mov al, [bx]
mov bl, al
xor bh, bh
pop ax
mov al, ah
pop ds
ret
biosfn_set_display_code:
push ds
push ax
push bx
mov ax, BIOSMEM_SEG
mov ds, ax
mov ax, bx
mov bx, BIOSMEM_DCC_INDEX
mov [bx], al
ifdef VGA_DEBUG
mov al, ah
xor ah, ah
push ax
mov bx, msg_alt_dcc
push bx
call _printf
add sp, 4
endif
pop bx
pop ax
mov al, ah
pop ds
ret
ifdef VGA_DEBUG
msg_alt_dcc:
db "Alternate Display code (%02x) was discarded", 13, 10, 0
endif
VGAROM ends
end