📄 video.s
字号:
/****************************************************************************** * video.S * * Display adapter & video mode setup, version 2.13 (14-May-99) * * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz> * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson * * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999 * * Updated and ported for Xen by Keir Fraser <keir@xensource.com> June 2007 */ .code16#include "video.h"/* Scratch space layout: trampoline_end to trampoline_end+0x1000. */#define modelist bootsym(trampoline_end) /* 2kB (256 entries) */#define vesa_glob_info (modelist + 0x800) /* 1kB */#define vesa_mode_info (vesa_glob_info + 0x400) /* 1kB *//* Retrieve Extended Display Identification Data. */#define CONFIG_FIRMWARE_EDID/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */#undef CONFIG_VIDEO_400_HACK/* Positions of various video parameters passed to the kernel *//* (see also include/linux/tty.h) */#define PARAM_CURSOR_POS 0x00#define PARAM_VIDEO_MODE 0x02#define PARAM_VIDEO_COLS 0x03#define PARAM_VIDEO_LINES 0x04#define PARAM_HAVE_VGA 0x05#define PARAM_FONT_POINTS 0x06#define PARAM_CAPABILITIES 0x08#define PARAM_LFB_LINELENGTH 0x0c#define PARAM_LFB_WIDTH 0x0e#define PARAM_LFB_HEIGHT 0x10#define PARAM_LFB_DEPTH 0x12#define PARAM_LFB_BASE 0x14#define PARAM_LFB_SIZE 0x18#define PARAM_LFB_COLORS 0x1c#define PARAM_VESAPM_SEG 0x24#define PARAM_VESAPM_OFF 0x26#define PARAM_VESA_ATTRIB 0x28#define _param(param) bootsym(boot_vid_info)+(param)video: xorw %ax, %ax movw %ax, %gs # GS is zero cld call basic_detect # Basic adapter type testing (EGA/VGA/MDA/CGA) cmpb $0,_param(PARAM_HAVE_VGA) je 1f # Bail if there's no VGA movw bootsym(boot_vid_mode), %ax # User selected video mode cmpw $ASK_VGA, %ax # Bring up the menu jz vid2 call mode_set # Set the mode jc vid1 leaw bootsym(badmdt), %si # Invalid mode ID call prtstrvid2: call mode_menuvid1: call store_edid call mode_params # Store mode parameters1: ret# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.basic_detect: movb $0, _param(PARAM_HAVE_VGA) movb $0x12, %ah # Check EGA/VGA movb $0x10, %bl int $0x10 cmpb $0x10, %bl # No, it's a CGA/MDA/HGA card. je basret movw $0x1a00, %ax # Check EGA or VGA? int $0x10 cmpb $0x1a, %al # 1a means VGA... jne basret # anything else is EGA. incb _param(PARAM_HAVE_VGA) # We've detected a VGAbasret: ret# Store the video mode parameters for later usage by the kernel.# This is done by asking the BIOS except for the rows/columns# parameters in the default 80x25 mode -- these are set directly,# because some very obscure BIOSes supply insane values.mode_params: cmpb $0, bootsym(graphic_mode) jnz mopar_gr movb $0x03, %ah # Read cursor position xorb %bh, %bh int $0x10 movw %dx, _param(PARAM_CURSOR_POS) movb $0x0f, %ah # Read page/mode/width int $0x10 movw %ax, _param(PARAM_VIDEO_MODE) # Video mode and screen width movw %gs:(0x485), %ax # Font size movw %ax, _param(PARAM_FONT_POINTS) # (valid only on EGA/VGA) movw bootsym(force_size), %ax # Forced size? orw %ax, %ax jz mopar1 movb %ah, _param(PARAM_VIDEO_COLS) movb %al, _param(PARAM_VIDEO_LINES) retmopar1: movb %gs:(0x484), %al # On EGA/VGA, use the EGA+ BIOS incb %al # location of max lines.mopar2: movb %al, _param(PARAM_VIDEO_LINES) ret# Fetching of VESA frame buffer parametersmopar_gr: leaw vesa_mode_info, %di movb $0x23, _param(PARAM_HAVE_VGA) movw 16(%di), %ax movw %ax, _param(PARAM_LFB_LINELENGTH) movw 18(%di), %ax movw %ax, _param(PARAM_LFB_WIDTH) movw 20(%di), %ax movw %ax, _param(PARAM_LFB_HEIGHT) movb 25(%di), %al movb $0, %ah movw %ax, _param(PARAM_LFB_DEPTH) movl 40(%di), %eax movl %eax, _param(PARAM_LFB_BASE) movl 31(%di), %eax movl %eax, _param(PARAM_LFB_COLORS) movl 35(%di), %eax movl %eax, _param(PARAM_LFB_COLORS+4) movw 0(%di), %ax movw %ax, _param(PARAM_VESA_ATTRIB)# get video mem size leaw vesa_glob_info, %di xorl %eax, %eax movw 18(%di), %ax movl %eax, _param(PARAM_LFB_SIZE)# store mode capabilities movl 10(%di), %eax movl %eax, _param(PARAM_CAPABILITIES)# switching the DAC to 8-bit is for <= 8 bpp only movw _param(PARAM_LFB_DEPTH), %ax cmpw $8, %ax jg dac_done# get DAC switching capability xorl %eax, %eax movb 10(%di), %al testb $1, %al jz dac_set# attempt to switch DAC to 8-bit movw $0x4f08, %ax movw $0x0800, %bx int $0x10 cmpw $0x004f, %ax jne dac_set movb %bh, bootsym(dac_size) # store actual DAC sizedac_set:# set color size to DAC size movb bootsym(dac_size), %al movb %al, _param(PARAM_LFB_COLORS+0) movb %al, _param(PARAM_LFB_COLORS+2) movb %al, _param(PARAM_LFB_COLORS+4) movb %al, _param(PARAM_LFB_COLORS+6)# set color offsets to 0 movb $0, _param(PARAM_LFB_COLORS+1) movb $0, _param(PARAM_LFB_COLORS+3) movb $0, _param(PARAM_LFB_COLORS+5) movb $0, _param(PARAM_LFB_COLORS+7)dac_done:# get protected mode interface informations movw $0x4f0a, %ax xorw %bx, %bx xorw %di, %di int $0x10 cmp $0x004f, %ax jnz no_pm movw %es, _param(PARAM_VESAPM_SEG) movw %di, _param(PARAM_VESAPM_OFF)no_pm: pushw %ds popw %es ret# The video mode menumode_menu: leaw bootsym(keymsg), %si # "Return/Space/Timeout" message call prtstr call flushnokey: call getkt cmpb $0x0d, %al # ENTER ? je listm # yes - manual mode selection cmpb $0x20, %al # SPACE ? je defmd1 # no - repeat call beep jmp nokeydefmd1: ret # No mode chosen? Default 80x25listm: call mode_table # List mode tablelistm0: leaw bootsym(name_bann), %si # Print adapter name call prtstr movw bootsym(card_name), %si orw %si, %si jnz an2 leaw bootsym(vga_name), %si jmp an1an2: call prtstr leaw bootsym(svga_name), %sian1: call prtstr leaw bootsym(listhdr), %si # Table header call prtstr movb $0x30, %dl # DL holds mode number leaw modelist, %silm1: cmpw $ASK_VGA, (%si) # End? jz lm2 movb %dl, %al # Menu selection number call prtchr call prtsp2 lodsw call prthw # Mode ID call prtsp2 lodsw call prtdec # Width movb $0x78, %al # the letter 'x' call prtchr lodsw call prtdec # Height testb $0xff,(%si) jnz 1f push %si leaw bootsym(textmode), %si call prtstr pop %si lodsw jmp 2f1: movb $0x78, %al # the letter 'x' call prtchr lodsw call prtdec # Depth2: movb $0x0d, %al # New line call prtchr movb $0x0a, %al call prtchr incb %dl # Next character cmpb $'z'+1, %dl jnz skip_bail leaw bootsym(menu_bail_msg), %si call prtstr jmp lm2skip_bail: cmpb $'i', %dl jnz skip_pause push %si push %dx leaw bootsym(menu_more_msg), %si # '<press space>' call prtstr call flush1: call getkey cmpb $0x20, %al # SPACE ? jne 1b # yes - manual mode selection leaw bootsym(crlft), %si call prtstr pop %dx pop %siskip_pause: cmpb $'9'+1, %dl jnz lm1 movb $'a', %dl jmp lm1lm2: leaw bootsym(prompt), %si # Mode prompt call prtstr leaw bootsym(edit_buf), %di # Editor bufferlm3: call getkey cmpb $0x0d, %al # Enter? jz lment cmpb $0x08, %al # Backspace? jz lmbs cmpb $0x20, %al # Printable? jc lm3 cmpw $bootsym(edit_buf)+4, %di # Enough space? jz lm3 stosb call prtchr jmp lm3lmbs: cmpw $bootsym(edit_buf), %di # Backspace jz lm3 decw %di movb $0x08, %al call prtchr call prtspc movb $0x08, %al call prtchr jmp lm3 lment: movb $0, (%di) leaw bootsym(crlft), %si call prtstr leaw bootsym(edit_buf), %si cmpb $0, (%si) # Empty string = default mode jz lmdef cmpb $0, 1(%si) # One character = menu selection jz mnusel cmpw $0x656d, (%si) # 'me' jnz lmhx cmpw $0x756e, 2(%si) # 'nu' jnz lmhx jmp listm
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -