diff options
Diffstat (limited to 'src/VBox/Devices/Graphics/BIOS/vberom.asm')
-rw-r--r-- | src/VBox/Devices/Graphics/BIOS/vberom.asm | 951 |
1 files changed, 951 insertions, 0 deletions
diff --git a/src/VBox/Devices/Graphics/BIOS/vberom.asm b/src/VBox/Devices/Graphics/BIOS/vberom.asm new file mode 100644 index 00000000..5ff08dda --- /dev/null +++ b/src/VBox/Devices/Graphics/BIOS/vberom.asm @@ -0,0 +1,951 @@ +;; ============================================================================================ +;; +;; Copyright (C) 2002 Jeroen Janssen +;; +;; 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 VBE is part of the VGA Bios specific to the plex86/bochs Emulated VGA card. +;; You can NOT drive any physical vga card with it. +;; +;; ============================================================================================ +;; +;; This VBE Bios is based on information taken from : +;; - VESA BIOS EXTENSION (VBE) Core Functions Standard Version 3.0 located at www.vesa.org +;; +;; ============================================================================================ + + +; 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 +include commondefs.inc + +public _vga_compat_setup +public dispi_set_enable_ +public dispi_set_bank_ +public _dispi_set_bank_farcall +public _dispi_get_max_bpp +public _vbe_has_vbe_display + +public vbe_biosfn_return_current_mode +public vbe_biosfn_display_window_control +public vbe_biosfn_set_get_display_start +public vbe_biosfn_set_get_dac_palette_format +public vbe_biosfn_set_get_palette_data +public vbe_biosfn_return_protected_mode_interface + +VGAROM segment public 'CODE' + +SET_DEFAULT_CPU + +VBE_BYTEWISE_IO EQU 1 + +;; Bytewise in/out +ifdef VBE_BYTEWISE_IO + +public do_out_dx_ax +public do_in_ax_dx + +do_out_dx_ax: + xchg ah, al + out dx, al + xchg ah, al + out dx, al + ret + +do_in_ax_dx: + in al, dx + xchg ah, al + in al, dx + ret + + out_dx_ax EQU call do_out_dx_ax + in_ax_dx EQU call do_in_ax_dx +else + out_dx_ax EQU out dx, ax + in_ax_dx EQU in ax, dx +endif + +;; Vertical retrace waiting +wait_vsync: + push ax + push dx + mov dx, 03DAh ; @todo use a symbolic constant! +wv_loop: + in al, dx + test al, 8 + jz wv_loop + pop dx + pop ax + ret + +wait_not_vsync: + push ax + push dx + mov dx, 03DAh ; @todo use a symbolic constant! +wnv_loop: + in al, dx + test al, 8 + jnz wnv_loop + pop dx + pop ax + ret + + +; AL = bits per pixel / AH = bytes per pixel +dispi_get_bpp: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + cmp al, 4 + jbe get_bpp_noinc + mov ah, al +if VBOX_BIOS_CPU gt 8086 + shr ah, 3 +else + shr ah, 1 + shr ah, 1 + shr ah, 1 +endif + test al, 07 + jz get_bpp_noinc + inc ah +get_bpp_noinc: + pop dx + ret + +; get display capabilities + +_dispi_get_max_bpp: + push dx + push bx + call dispi_get_enable + mov bx, ax + or ax, VBE_DISPI_GETCAPS + call dispi_set_enable_ + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + push ax + mov ax, bx + call dispi_set_enable_ + pop ax + pop bx + pop dx + ret + +dispi_set_enable_: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_ENABLE + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_enable: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_ENABLE + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +dispi_set_bank_: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_bank: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +_dispi_set_bank_farcall: + cmp bx, 0100h + je dispi_set_bank_farcall_get + or bx,bx + jnz dispi_set_bank_farcall_error + mov ax, dx + push dx + push ax + mov ax, VBE_DISPI_INDEX_BANK + mov dx, VBE_DISPI_IOPORT_INDEX + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + in_ax_dx + pop dx + cmp dx,ax + jne dispi_set_bank_farcall_error + mov ax, 004Fh + retf +dispi_set_bank_farcall_get: + mov ax, VBE_DISPI_INDEX_BANK + mov dx, VBE_DISPI_IOPORT_INDEX + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + mov dx,ax + retf +dispi_set_bank_farcall_error: + mov ax, 014Fh + retf + +dispi_set_x_offset: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_x_offset: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +dispi_set_y_offset: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out_dx_ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out_dx_ax + pop dx + ret + +dispi_get_y_offset: + push dx + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + pop dx + ret + +vga_set_virt_width: + push ax + push bx + push dx + mov bx, ax + call dispi_get_bpp + cmp al, 4 + ja set_width_svga + shr bx, 1 +set_width_svga: +if VBOX_BIOS_CPU gt 8086 + shr bx, 3 +else + shr bx, 1 + shr bx, 1 + shr bx, 1 +endif + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ah, bl + mov al, 13h + out dx, ax + pop dx + pop bx + pop ax + ret + +_vga_compat_setup: + push ax + push dx + + ; set CRT X resolution + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_XRES + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + push ax + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ax, 0011h + out dx, ax + pop ax + push ax +if VBOX_BIOS_CPU gt 8086 + shr ax, 3 +else + shr ax, 1 + shr ax, 1 + shr ax, 1 +endif + dec ax + mov ah, al + mov al, 01 + out dx, ax + pop ax + call vga_set_virt_width + + ; set CRT Y resolution + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_YRES + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + dec ax + push ax + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ah, al + mov al, 12h + out dx, ax + pop ax + mov al, 07 + out dx, al + inc dx + in al, dx + and al, 0BDh + test ah, 01 + jz bit8_clear + or al, 02 +bit8_clear: + test ah, 02 + jz bit9_clear + or al, 40h +bit9_clear: + out dx, al + + ; other settings + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov ax, 0009 + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + and al, 60h ; clear double scan bit and cell height + out dx, al + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov al, 17h + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + or al, 03 + out dx, al + 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 + or al, 01 + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + mov al, 20h + out dx, al + mov dx, VGAREG_GRDC_ADDRESS + mov ax, 0506h + out dx, ax + mov dx, VGAREG_SEQU_ADDRESS + mov ax, 0F02h + out dx, ax + + ; settings for >= 8bpp + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out_dx_ax + mov dx, VBE_DISPI_IOPORT_DATA + in_ax_dx + cmp al, 08 + jb vga_compat_end + mov dx, VGAREG_VGA_CRTC_ADDRESS + mov al, 14h + out dx, al + mov dx, VGAREG_VGA_CRTC_DATA + in al, dx + or al, 40h + out dx, al + 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 + or al, 40h + mov dx, VGAREG_ACTL_ADDRESS + out dx, al + mov al, 20h + out dx, al + mov dx, VGAREG_SEQU_ADDRESS + mov al, 04 + out dx, al + mov dx, VGAREG_SEQU_DATA + in al, dx + or al, 08 + out dx, al + mov dx, VGAREG_GRDC_ADDRESS + mov al, 05 + out dx, al + mov dx, VGAREG_GRDC_DATA + in al, dx + and al, 9Fh + or al, 40h + out dx, al + +vga_compat_end: + pop dx + pop ax + + +; Has VBE display - Returns true if VBE display detected + +_vbe_has_vbe_display: + push ds + push bx + mov ax, BIOSMEM_SEG + mov ds, ax + mov bx, BIOSMEM_VBE_FLAG + mov al, [bx] + and al, 01 + xor ah, ah + pop bx + pop ds + ret + + +; Function 03h - Return Current VBE Mode +; +; Input: +; AX = 4F03h +; Output: +; AX = VBE Return Status +; BX = Current VBE Mode +; +; +vbe_biosfn_return_current_mode: + push ds + mov ax, BIOSMEM_SEG + mov ds, ax + call dispi_get_enable + and ax, VBE_DISPI_ENABLED + jz no_vbe_mode + mov bx, BIOSMEM_VBE_MODE + mov ax, [bx] + mov bx, ax + jnz vbe_03_ok +no_vbe_mode: + mov bx, BIOSMEM_CURRENT_MODE + mov al, [bx] + mov bl, al + xor bh, bh +vbe_03_ok: + mov ax, 004Fh + pop ds + ret + + +; Function 05h - Display Window Control +; +; Input: +; AX = 4F05h +; (16-bit) BH = 00h Set memory window +; = 01h Get memory window +; BL = Window number +; = 00h Window A +; = 01h Window B +; DX = Window number in video memory in window +; granularity units (Set Memory Window only) +; Note: +; If this function is called while in a linear frame buffer mode, +; this function must fail with completion code AH=03h +; +; Output: +; AX = VBE Return Status +; DX = Window number in window granularity units +; (Get Memory Window only) + +vbe_biosfn_display_window_control: + cmp bl, 0 + jne vbe_05_failed + cmp bh, 1 + je get_display_window + jb set_display_window + mov ax, 0100h + ret +set_display_window: + mov ax, dx + call dispi_set_bank_ + call dispi_get_bank + cmp ax, dx + jne vbe_05_failed + mov ax, 004Fh + ret +get_display_window: + call dispi_get_bank + mov dx, ax + mov ax, 004Fh + ret +vbe_05_failed: + mov ax, 014Fh + ret + + +; Function 07h - Set/Get Display Start +; +; Input(16-bit): +; AX = 4F07h +; BH = 00h Reserved and must be 00h +; BL = 00h Set Display Start +; = 01h Get Display Start +; = 02h Schedule Display Start (Alternate) +; = 03h Schedule Stereoscopic Display Start +; = 04h Get Scheduled Display Start Status +; = 05h Enable Stereoscopic Mode +; = 06h Disable Stereoscopic Mode +; = 80h Set Display Start during Vertical Retrace +; = 82h Set Display Start during Vertical Retrace (Alternate) +; = 83h Set Stereoscopic Display Start during Vertical Retrace +; ECX = If BL=02h/82h Display Start Address in bytes +; If BL=03h/83h Left Image Start Address in bytes +; EDX = If BL=03h/83h Right Image Start Address in bytes +; CX = If BL=00h/80h First Displayed Pixel In Scan Line +; DX = If BL=00h/80h First Displayed Scan Line +; +; Output: +; AX = VBE Return Status +; BH = If BL=01h Reserved and will be 0 +; CX = If BL=01h First Displayed Pixel In Scan Line +; If BL=04h 0 if flip has not occurred, not 0 if it has +; DX = If BL=01h First Displayed Scan Line +; +; Input(32-bit): +; BH = 00h Reserved and must be 00h +; BL = 00h Set Display Start +; = 80h Set Display Start during Vertical Retrace +; CX = Bits 0-15 of display start address +; DX = Bits 16-31 of display start address +; ES = Selector for memory mapped registers +; +vbe_biosfn_set_get_display_start: + cmp bl, 80h + je set_display_start_wait + cmp bl, 1 + je get_display_start + jb set_display_start + mov ax, 0100h + ret +set_display_start_wait: + call wait_not_vsync + call wait_vsync +set_display_start: + mov ax, cx + call dispi_set_x_offset + mov ax, dx + call dispi_set_y_offset + mov ax, 004Fh + ret +get_display_start: + call dispi_get_x_offset + mov cx, ax + call dispi_get_y_offset + mov dx, ax + xor bh, bh + mov ax, 004Fh + ret + + +; Function 08h - Set/Get Dac Palette Format +; +; Input: +; AX = 4F08h +; BL = 00h set DAC palette width +; = 01h get DAC palette width +; BH = If BL=00h: desired number of bits per primary color +; Output: +; AX = VBE Return Status +; BH = current number of bits per primary color (06h = standard VGA) +; +vbe_biosfn_set_get_dac_palette_format: + cmp bl, 1 + je get_dac_palette_format + jb set_dac_palette_format + mov ax, 0100h + ret +set_dac_palette_format: + call dispi_get_enable + cmp bh, 6 + je set_normal_dac + cmp bh, 8 + jne vbe_08_unsupported + or ax, VBE_DISPI_8BIT_DAC + jnz set_dac_mode +set_normal_dac: + and ax, NOT VBE_DISPI_8BIT_DAC +set_dac_mode: + call dispi_set_enable_ +get_dac_palette_format: + mov bh, 6 + call dispi_get_enable + and ax, VBE_DISPI_8BIT_DAC + jz vbe_08_ok + mov bh, 8 +vbe_08_ok: + mov ax, 004Fh + ret +vbe_08_unsupported: + mov ax, 014Fh + ret + + +; Function 09h - Set/Get Palette Data +; +; Input: +; AX = 4F09h +; (16-bit) BL = 00h Set palette data +; = 01h Get palette data +; = 02h Set secondary palette data +; = 03h Get secondary palette data +; = 80h Set palette data during VRetrace +; CX = Number of entries to update (<= 256) +; DX = First entry to update +; ES:DI = Table of palette values +; Output: +; AX = VBE Return Status +; +; Notes: +; Secondary palette support is a "future extension". +; Attempts to set/get it should return status 02h. +; +; In VBE 3.0, reading palette data is optional and +; subfunctions 01h and 03h may return failure. +; +; The format of palette entries is as follows: +; +; PaletteEntry struc +; Blue db ? ; Blue channel value (6 or 8 bits) +; Green db ? ; Green channel value (6 or 8 bits) +; Red db ? ; Red channel value (6 or 8 bits) +; Padding db ? ; DWORD alignment byte (unused) +; PaletteEntry ends +; +; Most applications use VGA DAC registers directly to +; set/get palette in VBE modes. However, subfn 4F09h is +; required for NonVGA controllers (eg. XGA). +; +vbe_biosfn_set_get_palette_data: + test bl, bl + jz set_palette_data + cmp bl, 01 + je get_palette_data + cmp bl, 03 + jbe vbe_09_nohw + cmp bl, 80h + jne vbe_09_unsupported +if 0 + ; this is where we could wait for vertical retrace +endif +set_palette_data: + DO_pushad + push ds + push es + pop ds + mov al, dl + mov dx, VGAREG_DAC_WRITE_ADDRESS + out dx, al + inc dx + mov si, di +set_pal_loop: +if VBOX_BIOS_CPU ge 80386 + lodsd + ror eax, 16 + out dx, al + rol eax, 8 + out dx, al + rol eax, 8 + out dx, al +else + lodsw + mov bx, ax + lodsw + out dx, al + mov al, bh + out dx, al + mov al, bl + out dx, al +endif + loop set_pal_loop + pop ds + DO_popad +vbe_09_ok: + mov ax, 004Fh + ret + +get_palette_data: + DO_pushad + mov al, dl + mov dx, VGAREG_DAC_READ_ADDRESS + out dx, al + add dl, 2 +if VBOX_BIOS_CPU ge 80386 +get_pal_loop: + xor eax, eax + in al, dx + shl eax, 8 + in al, dx + shl eax, 8 + in al, dx + stosd +else + xor bx, bx +get_pal_loop: + in al, dx + mov bl, al + in al, dx + mov ah, al + in al, dx + stosw + mov ax, bx + stosw +endif + loop get_pal_loop + DO_popad + jmp vbe_09_ok + +vbe_09_unsupported: + mov ax, 014Fh + ret +vbe_09_nohw: + mov ax, 024Fh + ret + + +; Function 0Ah - Return VBE Protected Mode Interface +; +; Input: AX = 4F0Ah VBE 2.0 Protected Mode Interface +; BL = 00h Return protected mode table +; Output: AX = Status +; ES = Real Mode Segment of Table +; DI = Offset of Table +; CX = Length of Table including protected mode code +; (for copying purposes) +; +vbe_biosfn_return_protected_mode_interface: + test bl, bl + jnz _fail + mov di, 0C000h + mov es, di + mov di, offset vesa_pm_start + mov cx, vesa_pm_end - vesa_pm_start + mov ax, 004Fh + ret +_fail: + mov ax, 014fh + ret + +VGAROM ends + +;; +;; 32-bit VBE interface +;; + +.386 + +public vesa_pm_start +public vesa_pm_end + +VBE32 segment public use32 'CODE' + + align 2 + +vesa_pm_start: + dw vesa_pm_set_window - vesa_pm_start + dw vesa_pm_set_display_start - vesa_pm_start + dw vesa_pm_unimplemented - vesa_pm_start + dw vesa_pm_io_ports_table - vesa_pm_start +vesa_pm_io_ports_table: + dw VBE_DISPI_IOPORT_INDEX + dw VBE_DISPI_IOPORT_INDEX + 1 + dw VBE_DISPI_IOPORT_DATA + dw VBE_DISPI_IOPORT_DATA + 1 + dw 3B6h + dw 3B7h + dw 0FFFFh + dw 0FFFFh + +vesa_pm_set_window: + cmp bx, 0 + je vesa_pm_set_display_window1 + mov ax, 0100h + ret +vesa_pm_set_display_window1: + mov ax, dx + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BANK + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + in ax, dx + pop dx + cmp dx, ax + jne illegal_window + mov ax, 004Fh + ret +illegal_window: + mov ax, 014Fh + ret +vesa_pm_set_display_start: + cmp bl, 80h + je vesa_pm_set_display_start1_wait + cmp bl, 00 + je vesa_pm_set_display_start1 + mov ax, 0100h + ret +vesa_pm_set_display_start1_wait: + push edx + mov dx, 03DAh ; @todo: use symbolic constant +wnv_loop_32: + in al, dx + test al, 8 + jnz wnv_loop_32 +wv_loop_32: + in al, dx + test al, 8 + jz wv_loop_32 + pop edx +vesa_pm_set_display_start1: +; convert offset to (X, Y) coordinate +; (would be simpler to change Bochs VBE API...) + push eax + push ecx + push edx + push esi + push edi + shl edx, 16 + and ecx, 0FFFFh + or ecx, edx + shl ecx, 2 + mov eax, ecx + push eax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_VIRT_WIDTH + out dx, ax + mov dx, VBE_DISPI_IOPORT_DATA + in ax, dx + movzx ecx, ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_BPP + out dx, ax + mov dx, VBE_DISPI_IOPORT_DATA + in ax, dx + movzx esi, ax + pop eax + + cmp esi, 4 + jz bpp4_mode + add esi, 7 + shr esi, 3 + imul ecx, esi + xor edx, edx + div ecx + mov edi, eax + mov eax, edx + xor edx, edx + div esi + jmp set_xy_regs + +bpp4_mode: + shr ecx, 1 + xor edx, edx + div ecx + mov edi, eax + mov eax, edx + shl eax, 1 + +set_xy_regs: + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_X_OFFSET + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + pop dx + + mov ax, di + push dx + push ax + mov dx, VBE_DISPI_IOPORT_INDEX + mov ax, VBE_DISPI_INDEX_Y_OFFSET + out dx, ax + pop ax + mov dx, VBE_DISPI_IOPORT_DATA + out dx, ax + pop dx + + pop edi + pop esi + pop edx + pop ecx + pop eax + mov ax, 004fh + ret + +vesa_pm_unimplemented: + mov ax, 014Fh + ret +vesa_pm_end: + +VBE32 ends + + end |