# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1181487488 -3600
# Node ID 3cc79ef896a2c2a0586c987691322105e86e3612
# Parent 6d6b4b48773b7776e3762b998f23cd553f55f8ee
x86: Allow selection of graphical video modes during boot.
The 'vga=' boot option is extended as follows:
----------
'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
'vga=ask':
display a vga menu of available modes
'vga=text-80x<rows>':
text mode, where <rows> is one of {25,28,30,34,43,50,60}
'vga=gfx-<width>x<height>x<depth>':
graphics mode, e.g., vga=gfx-1024x768x16
'vga=mode-<mode>:
specifies a mode as specified in 'vga=ask' menu
(NB. menu modes are displayed in hex, so mode numbers here must
be prefixed with '0x' (e.g., 'vga=mode-0x0318'))
The option 'keep' causes Xen to continue to print to the VGA console even
after domain 0 starts to boot. The default behaviour is to relinquish
control of the console to domain 0.
----------
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/boot/Makefile | 2
xen/arch/x86/boot/cmdline.S | 285 +++++++++++
xen/arch/x86/boot/head.S | 6
xen/arch/x86/boot/trampoline.S | 11
xen/arch/x86/boot/video.S | 994 +++++++++++++++++++++++++++++++++++++++++
xen/arch/x86/boot/video.h | 30 +
xen/arch/x86/setup.c | 82 +++
xen/drivers/video/vga.c | 646 ++------------------------
xen/include/public/xen.h | 2
xen/include/xen/vga.h | 1
10 files changed, 1467 insertions(+), 592 deletions(-)
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/Makefile
--- a/xen/arch/x86/boot/Makefile Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/Makefile Sun Jun 10 15:58:08 2007 +0100
@@ -1,3 +1,3 @@ obj-y += head.o
obj-y += head.o
-head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S
+head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/cmdline.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/cmdline.S Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,285 @@
+/******************************************************************************
+ * cmdline.S
+ *
+ * Early command-line parsing.
+ */
+
+ .code32
+
+#include "video.h"
+
+# NB. String pointer on stack is modified to point past parsed digits.
+.Latoi:
+ push %ebx
+ push %ecx
+ push %edx
+ push %esi
+ xor %ebx,%ebx /* %ebx = accumulator */
+ mov $10,%ecx /* %ecx = base (default base 10) */
+ mov 16+4(%esp),%esi /* %esi = pointer into ascii string. */
+ lodsb
+ cmpb $'0',%al
+ jne 2f
+ mov $8,%ecx /* Prefix '0' => octal (base 8) */
+ lodsb
+ cmpb $'x',%al
+ jne 2f
+ mov $16,%ecx /* Prefix '0x' => hex (base 16) */
+1: lodsb
+2: sub $'0',%al
+ jb 4f
+ cmp $9,%al
+ jbe 3f
+ sub $'A'-'0'-10,%al
+ jb 4f
+ cmp $15,%al
+ jbe 3f
+ sub $'a'-'A',%al
+ jb 4f
+3: cmp %cl,%al
+ jae 4f
+ movzbl %al,%eax
+ xchg %eax,%ebx
+ mul %ecx
+ xchg %eax,%ebx
+ add %eax,%ebx
+ jmp 1b
+4: mov %ebx,%eax
+ dec %esi
+ mov %esi,16+4(%esp)
+ pop %esi
+ pop %edx
+ pop %ecx
+ pop %ebx
+ ret
+
+.Lstrstr:
+ push %ecx
+ push %edx
+ push %esi
+ push %edi
+ xor %eax,%eax
+ xor %ecx,%ecx
+ not %ecx
+ mov 16+4(%esp),%esi
+ mov 16+8(%esp),%edi
+ repne scasb
+ not %ecx
+ dec %ecx
+ mov %ecx,%edx
+1: mov 16+8(%esp),%edi
+ mov %esi,%eax
+ mov %edx,%ecx
+ repe cmpsb
+ je 2f
+ xchg %eax,%esi
+ inc %esi
+ cmpb $0,-1(%eax)
+ jne 1b
+ xor %eax,%eax
+2: pop %edi
+ pop %esi
+ pop %edx
+ pop %ecx
+ ret
+
+.Lstr_prefix:
+ push %esi
+ push %edi
+ mov 8+4(%esp),%esi /* 1st arg is prefix string */
+ mov 8+8(%esp),%edi /* 2nd arg is main string */
+1: lodsb
+ test %al,%al
+ jz 2f
+ scasb
+ je 1b
+ sbb %eax,%eax
+ or $1,%al
+ jmp 3f
+2: xor %eax,%eax
+3: pop %edi
+ pop %esi
+ ret
+
+.Lstrlen:
+ push %ecx
+ push %esi
+ push %edi
+ xor %eax,%eax
+ xor %ecx,%ecx
+ not %ecx
+ mov 12+4(%esp),%edi
+ repne scasb
+ not %ecx
+ dec %ecx
+ mov %ecx,%eax
+ pop %edi
+ pop %esi
+ pop %ecx
+ ret
+
+.Lfind_option:
+ push %ebx
+ push 4+8(%esp)
+ push 4+8(%esp)
+ call .Lstrstr
+ add $8,%esp
+ test %eax,%eax
+ jz 3f
+ cmp %eax,4+4(%esp)
+ je 1f
+ cmpb $' ',-1(%eax)
+ jne 2f
+1: mov %eax,%ebx
+ push 4+8(%esp)
+ call .Lstrlen
+ add $4,%esp
+ xchg %eax,%ebx
+ add %eax,%ebx
+ cmpb $'\0',(%ebx)
+ je 3f
+ cmpb $' ',(%ebx)
+ je 3f
+ cmpb $'=',(%ebx)
+ je 3f
+2: xor %eax,%eax
+3: pop %ebx
+ ret
+
+/* multiboot_info structure offsets. */
+#define MB_flags 0
+#define MB_cmdline 16
+
+cmdline_parse_early:
+ pusha
+
+ /* Bail if there is no command line to parse. */
+ mov sym_phys(multiboot_ptr),%ebx
+ mov MB_flags(%ebx),%eax
+ test $4,%al
+ jz 1f
+ mov MB_cmdline(%ebx),%eax
+ test %eax,%eax
+ jz 1f
+
+ /* Check for 'no-real-mode' command-line option. */
+ pushl $sym_phys(.Lno_rm_opt)
+ pushl MB_cmdline(%ebx)
+ call .Lfind_option
+ test %eax,%eax
+ setnz bootsym_phys(skip_realmode)
+
+ /* Check for 'vga=' command-line option. */
+ movl $sym_phys(.Lvga_opt),4(%esp)
+ call .Lfind_option
+ add $8,%esp
+ test %eax,%eax
+ jz 1f
+ cmpb $'=',3(%eax)
+ jne 1f
+ add $4,%eax
+
+ /* Found the 'vga=' option. Default option is to display vga menu. */
+ movw $ASK_VGA,bootsym_phys(boot_vid_mode)
+
+ /* Check for 'vga=text-80x<rows>. */
+ mov %eax,%ebx
+ push %ebx
+ pushl $sym_phys(.Lvga_text80)
+ call .Lstr_prefix
+ add $8,%esp
+ test %eax,%eax
+ jnz 3f
+
+ /* We have 'vga=text-80x<rows>'. */
+ add $8,%ebx
+ push %ebx
+ call .Latoi
+ add $4,%esp
+ mov %ax,%bx
+ lea sym_phys(.Lvga_text_modes),%esi
+2: lodsw
+ test %ax,%ax
+ jz 1f
+ cmp %ax,%bx
+ lodsw
+ jne 2b
+ mov %ax,bootsym_phys(boot_vid_mode)
+ jmp 1f
+
+ /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
+3: push %ebx
+ pushl $sym_phys(.Lvga_gfx)
+ call .Lstr_prefix
+ add $8,%esp
+ test %eax,%eax
+ jnz 3f
+
+ /* We have 'vga=gfx-<width>x<height>x<depth>'. */
+ /* skip 'gfx-' */
+ add $4,%ebx
+ /* parse <width> */
+ push %ebx
+ call .Latoi
+ pop %esi
+ mov %ax,bootsym_phys(vesa_size)+0
+ /* skip 'x' */
+ lodsb
+ cmpb $'x',%al
+ jne 1f
+ /* parse <height> */
+ push %esi
+ call .Latoi
+ pop %esi
+ mov %ax,bootsym_phys(vesa_size)+2
+ /* skip 'x' */
+ lodsb
+ cmpb $'x',%al
+ jne 1f
+ /* parse <depth> */
+ push %esi
+ call .Latoi
+ pop %esi
+ mov %ax,bootsym_phys(vesa_size)+4
+ /* commit to vesa mode */
+ movw $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
+ jmp 1f
+
+ /* Check for 'vga=mode-<mode>'. */
+3: push %ebx
+ pushl $sym_phys(.Lvga_mode)
+ call .Lstr_prefix
+ add $8,%esp
+ test %eax,%eax
+ jnz 1f
+
+ /* We have 'vga=mode-<mode>'. */
+ add $5,%ebx
+ push %ebx
+ call .Latoi
+ add $4,%esp
+ mov %ax,bootsym_phys(boot_vid_mode)
+
+1: popa
+ ret
+
+.Lvga_text_modes: /* rows, mode_number */
+ .word 25,VIDEO_80x25
+ .word 50,VIDEO_80x50
+ .word 43,VIDEO_80x43
+ .word 28,VIDEO_80x28
+ .word 30,VIDEO_80x30
+ .word 34,VIDEO_80x34
+ .word 60,VIDEO_80x60
+ .word 0
+
+.Lvga_opt:
+ .asciz "vga"
+.Lvga_text80:
+ .asciz "text-80x"
+.Lvga_gfx:
+ .asciz "gfx-"
+.Lvga_mode:
+ .asciz "mode-"
+.Lno_rm_opt:
+ .asciz "no-real-mode"
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/head.S
--- a/xen/arch/x86/boot/head.S Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/head.S Sun Jun 10 15:58:08 2007 +0100
@@ -73,6 +73,7 @@ __start:
mov $BOOT_DS,%ecx
mov %ecx,%ds
mov %ecx,%es
+ mov %ecx,%ss
/* Check for Multiboot bootloader */
cmp $0x2BADB002,%eax
@@ -166,8 +167,13 @@ 1: stosl /* low mappings cover up
mov $trampoline_end - trampoline_start,%ecx
rep movsb
+ mov $0x98000,%esp
+ call cmdline_parse_early
+
/* Jump into the relocated trampoline. */
jmp $BOOT_CS32,$bootsym_phys(trampoline_boot_cpu_entry)
+
+#include "cmdline.S"
.globl trampoline_start, trampoline_end
trampoline_start:
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/trampoline.S
--- a/xen/arch/x86/boot/trampoline.S Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/boot/trampoline.S Sun Jun 10 15:58:08 2007 +0100
@@ -6,7 +6,6 @@
.globl trampoline_realmode_entry
trampoline_realmode_entry:
- nop # We use this byte as a progress flag
movb $0xA5,bootsym(trampoline_cpu_started)
cld
cli
@@ -117,6 +116,9 @@ high_start:
.code32
trampoline_boot_cpu_entry:
+ cmpb $0,bootsym_phys(skip_realmode)
+ jnz .Lskip_realmode
+
/* Load pseudo-real-mode segments. */
mov $BOOT_PSEUDORM_DS,%eax
mov %eax,%ds
@@ -148,8 +150,10 @@ 1: mov $(BOOT_TRAMPOLINE>>4),%a
/*
* Do real-mode work:
* 1. Get memory map.
+ * 2. Set video mode.
*/
call get_memory_map
+ call video
/* Disable irqs before returning to protected mode. */
cli
@@ -170,12 +174,17 @@ 1: mov $BOOT_DS,%eax
mov %eax,%gs
mov %eax,%ss
+.Lskip_realmode:
/* EBX == 0 indicates we are the BP (Boot Processor). */
xor %ebx,%ebx
/* Jump to the common bootstrap entry point. */
jmp trampoline_protmode_entry
+skip_realmode:
+ .byte 0
+
rm_idt: .word 256*4-1, 0, 0
#include "mem.S"
+#include "video.S"
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/video.S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/video.S Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,994 @@
+/******************************************************************************
+ * video.S
+ *
+ * Display adapter & video mode setup, version 2.13 (14-May-99)
+ *
+ * Copyright (C) 1995 -- 1998 Martin Mares <mj@xxxxxx>
+ * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
+ *
+ * Rewritten to use GNU 'as' by Chris Noe <stiker@xxxxxxxxxxxxx> May 1999
+ *
+ * Updated and ported for Xen by Keir Fraser <keir@xxxxxxxxxxxxx> June 2007
+ */
+
+ .code16
+
+#include "video.h"
+
+#define modelist (0x2000)
+
+/* 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(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 prtstr
+vid2: call mode_menu
+vid1: call store_edid
+ call mode_params # Store mode parameters
+1: 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 VGA
+basret: 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)
+ ret
+
+mopar1: 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 parameters
+mopar_gr:
+ leaw modelist+1024, %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)
+
+# get video mem size
+ leaw modelist+1024, %di
+ movw $0x4f00, %ax
+ int $0x10
+ 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 size
+
+dac_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: ret
+
+# The video mode menu
+mode_menu:
+ leaw bootsym(keymsg), %si # "Return/Space/Timeout" message
+ call prtstr
+ call flush
+nokey: call getkt
+
+ cmpb $0x0d, %al # ENTER ?
+ je listm # yes - manual mode selection
+
+ cmpb $0x20, %al # SPACE ?
+ je defmd1 # no - repeat
+
+ call beep
+ jmp nokey
+
+defmd1: ret # No mode chosen? Default 80x25
+
+listm: call mode_table # List mode table
+listm0: 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 an1
+
+an2: call prtstr
+ leaw bootsym(svga_name), %si
+an1: call prtstr
+ leaw bootsym(listhdr), %si # Table header
+ call prtstr
+ movb $0x30, %dl # DL holds mode number
+ leaw modelist, %si
+lm1: 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 2f
+1: movb $0x78, %al # the letter 'x'
+ call prtchr
+ lodsw
+ call prtdec # Depth
+2: 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 lm2
+
+skip_bail:
+ cmpb $'i', %dl
+ jnz skip_pause
+ push %si
+ push %dx
+ leaw bootsym(menu_more_msg), %si # '<press space>'
+ call prtstr
+ call flush
+1: call getkey
+ cmpb $0x20, %al # SPACE ?
+ jne 1b # yes - manual mode selection
+ leaw bootsym(crlft), %si
+ call prtstr
+ pop %dx
+ pop %si
+
+skip_pause:
+ cmpb $'9'+1, %dl
+ jnz lm1
+ movb $'a', %dl
+ jmp lm1
+
+lm2: leaw bootsym(prompt), %si # Mode prompt
+ call prtstr
+ leaw bootsym(edit_buf), %di # Editor buffer
+lm3: 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 lm3
+
+lmbs: 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
+
+lmhx: xorw %bx, %bx # Else => mode ID in hex
+lmhex: lodsb
+ orb %al, %al
+ jz lmuse1
+
+ subb $0x30, %al
+ jc lmbad
+
+ cmpb $10, %al
+ jc lmhx1
+
+ subb $7, %al
+ andb $0xdf, %al
+ cmpb $10, %al
+ jc lmbad
+
+ cmpb $16, %al
+ jnc lmbad
+
+lmhx1: shlw $4, %bx
+ orb %al, %bl
+ jmp lmhex
+
+lmuse1: movw %bx, %ax
+ jmp lmuse
+
+mnusel: lodsb # Menu selection
+ xorb %ah, %ah
+ subb $0x30, %al
+ jc lmbad
+
+ cmpb $10, %al
+ jc lmuse
+
+ cmpb $0x61-0x30, %al
+ jc lmbad
+
+ subb $0x61-0x30-10, %al
+ cmpb $36, %al
+ jnc lmbad
+
+lmuse: call mode_set
+ jc lmdef
+
+lmbad: leaw bootsym(unknt), %si
+ call prtstr
+ jmp mode_menu
+lmdef: ret
+
+_setrec: jmp setrec # Ugly...
+_set_80x25: jmp set_80x25
+
+# Setting of user mode (AX=mode ID) => CF=success
+mode_set:
+ movw %ax, bootsym(boot_vid_mode)
+ movw %ax, %bx
+
+ cmpw $VIDEO_VESA_BY_SIZE, %ax
+ je setvesabysize
+
+ testb $VIDEO_RECALC>>8, %ah
+ jnz _setrec
+
+ cmpb $VIDEO_FIRST_SPECIAL>>8, %ah
+ jz setspc
+
+ cmpb $VIDEO_FIRST_VESA>>8, %ah
+ jnc check_vesa
+
+ orb %ah, %ah
+ jnz setbad
+
+ jmp setmenu
+
+setbad: clc
+ ret
+
+setspc: xorb %bh, %bh # Set special mode
+ cmpb $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
+ jnc setbad
+
+ addw %bx, %bx
+ jmp *bootsym(spec_inits)(%bx)
+
+setmenu:
+ orb %al, %al # 80x25 is an exception
+ jz _set_80x25
+
+ pushw %bx # Set mode chosen from menu
+ call mode_table # Build the mode table
+ popw %ax
+ shlw $3, %ax
+ addw %ax, %si
+ cmpw %di, %si
+ jnc setbad
+
+ movw (%si), %ax # Fetch mode ID
+ jmp mode_set
+
+check_vesa:
+#ifdef CONFIG_FIRMWARE_EDID
+ leaw modelist+1024, %di
+ movw $0x4f00, %ax
+ int $0x10
+ cmpw $0x004f, %ax
+ jnz setbad
+
+ movw 4(%di), %ax
+ movw %ax, bootsym(vbe_version)
+#endif
+ leaw modelist+1024, %di
+ subb $VIDEO_FIRST_VESA>>8, %bh
+ movw %bx, %cx # Get mode information structure
+ movw $0x4f01, %ax
+ int $0x10
+ addb $VIDEO_FIRST_VESA>>8, %bh
+ cmpw $0x004f, %ax
+ jnz setbad
+
+ movb (%di), %al # Check capabilities.
+ andb $0x99, %al
+ cmpb $0x99, %al
+ jnz _setbad # Doh! No linear frame buffer.
+
+ subb $VIDEO_FIRST_VESA>>8, %bh
+ orw $0x4000, %bx # Use linear frame buffer
+ movw $0x4f02, %ax # VESA BIOS mode set call
+ int $0x10
+ cmpw $0x004f, %ax # AL=4f if implemented
+ jnz _setbad # AH=0 if OK
+
+ movb $1, bootsym(graphic_mode) # flag graphic mode
+ stc
+ ret
+
+_setbad: jmp setbad # Ugly...
+
+# Recalculate vertical display end registers -- this fixes various
+# inconsistencies of extended modes on many adapters. Called when
+# the VIDEO_RECALC flag is set in the mode ID.
+
+setrec: subb $VIDEO_RECALC>>8, %ah # Set the base mode
+ call mode_set
+ jnc rct3
+
+ movw %gs:(0x485), %ax # Font size in pixels
+ movb %gs:(0x484), %bl # Number of rows
+ incb %bl
+ mulb %bl # Number of visible
+ decw %ax # scan lines - 1
+ movw $0x3d4, %dx
+ movw %ax, %bx
+ movb $0x12, %al # Lower 8 bits
+ movb %bl, %ah
+ outw %ax, %dx
+ movb $0x07, %al # Bits 8 and 9 in the overflow register
+ call inidx
+ xchgb %al, %ah
+ andb $0xbd, %ah
+ shrb %bh
+ jnc rct1
+ orb $0x02, %ah
+rct1: shrb %bh
+ jnc rct2
+ orb $0x40, %ah
+rct2: movb $0x07, %al
+ outw %ax, %dx
+ stc
+rct3: ret
+
+inidx: outb %al, %dx # Read from indexed VGA register
+ incw %dx # AL=index, DX=index reg port -> AL=data
+ inb %dx, %al
+ decw %dx
+ ret
+
+setvesabysize:
+ call mode_table
+ leaw modelist,%si
+1: add $8,%si
+ cmpw $ASK_VGA,-8(%si) # End?
+ je _setbad
+ movw -6(%si),%ax
+ cmpw %ax,bootsym(vesa_size)+0
+ jne 1b
+ movw -4(%si),%ax
+ cmpw %ax,bootsym(vesa_size)+2
+ jne 1b
+ movw -2(%si),%ax
+ cmpw %ax,bootsym(vesa_size)+4
+ jne 1b
+ movw -8(%si),%ax
+ movw %ax,%bx
+ movw %ax,bootsym(boot_vid_mode)
+ jmp check_vesa
+
+# Table of routines for setting of the special modes.
+spec_inits:
+ .word bootsym(set_80x25)
+ .word bootsym(set_8pixel)
+ .word bootsym(set_80x43)
+ .word bootsym(set_80x28)
+ .word bootsym(set_80x30)
+ .word bootsym(set_80x34)
+ .word bootsym(set_80x60)
+
+# Set the 80x25 mode. If already set, do nothing.
+set_80x25:
+ movw $0x5019, bootsym(force_size) # Override possibly broken BIOS
+use_80x25:
+ movw $0x1202, %ax # Force 400 scan lines
+ movb $0x30, %bl
+ int $0x10
+ movw $0x0003, %ax # Mode 3
+ int $0x10
+ stc
+ ret
+
+# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
+set_8pixel:
+ call use_80x25 # The base is 80x25
+set_8pt:
+ movw $0x1112, %ax # Use 8x8 font
+ xorb %bl, %bl
+ int $0x10
+ movw $0x1200, %ax # Use alternate print screen
+ movb $0x20, %bl
+ int $0x10
+ movw $0x1201, %ax # Turn off cursor emulation
+ movb $0x34, %bl
+ int $0x10
+ movb $0x01, %ah # Define cursor scan lines 6-7
+ movw $0x0607, %cx
+ int $0x10
+ stc
+ ret
+
+# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
+# 80x25 mode with 14-point fonts instead of 16-point.
+set_80x28:
+ call use_80x25 # The base is 80x25
+set14: movw $0x1111, %ax # Use 9x14 font
+ xorb %bl, %bl
+ int $0x10
+ movb $0x01, %ah # Define cursor scan lines 11-12
+ movw $0x0b0c, %cx
+ int $0x10
+ stc
+ ret
+
+# Set the 80x43 mode. This mode is works on all VGA's.
+# It's a 350-scanline mode with 8-pixel font.
+set_80x43:
+ movw $0x1201, %ax # Set 350 scans
+ movb $0x30, %bl
+ int $0x10
+ movw $0x0003, %ax # Reset video mode
+ int $0x10
+ jmp set_8pt # Use 8-pixel font
+
+# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
+set_80x30:
+ call use_80x25 # Start with real 80x25
+ movw $0x3cc, %dx # Get CRTC port
+ inb %dx, %al
+ movb $0xd4, %dl
+ rorb %al # Mono or color?
+ jc set48a
+
+ movb $0xb4, %dl
+set48a: movw $0x0c11, %ax # Vertical sync end (also unlocks
CR0-7)
+ call outidx
+ movw $0x0b06, %ax # Vertical total
+ call outidx
+ movw $0x3e07, %ax # (Vertical) overflow
+ call outidx
+ movw $0xea10, %ax # Vertical sync start
+ call outidx
+ movw $0xdf12, %ax # Vertical display end
+ call outidx
+ movw $0xe715, %ax # Vertical blank start
+ call outidx
+ movw $0x0416, %ax # Vertical blank end
+ call outidx
+ pushw %dx
+ movb $0xcc, %dl # Misc output register (read)
+ inb %dx, %al
+ movb $0xc2, %dl # (write)
+ andb $0x0d, %al # Preserve clock select bits and color
bit
+ orb $0xe2, %al # Set correct sync polarity
+ outb %al, %dx
+ popw %dx
+ movw $0x501e, bootsym(force_size)
+ stc # That's all.
+ ret
+
+# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
+set_80x34:
+ call set_80x30 # Set 480 scans
+ call set14 # And 14-pt font
+ movw $0xdb12, %ax # VGA vertical display end
+ movw $0x5022, bootsym(force_size)
+setvde: call outidx
+ stc
+ ret
+
+# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
+set_80x60:
+ call set_80x30 # Set 480 scans
+ call set_8pt # And 8-pt font
+ movw $0xdf12, %ax # VGA vertical display end
+ movw $0x503c, bootsym(force_size)
+ jmp setvde
+
+# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
+outidx: outb %al, %dx
+ pushw %ax
+ movb %ah, %al
+ incw %dx
+ outb %al, %dx
+ decw %dx
+ popw %ax
+ ret
+
+# Build the table of video modes (stored after the setup.S code at the
+# `modelist' label. Each video mode record looks like:
+# .word MODE-ID (our special mode ID (see above))
+# .byte rows (number of rows)
+# .byte columns (number of columns)
+# Returns address of the end of the table in DI, the end is marked
+# with a ASK_VGA ID.
+mode_table:
+ movw bootsym(mt_end), %di # Already filled?
+ orw %di, %di
+ jnz mtab1
+
+ leaw modelist, %di # Store standard modes:
+ movw $VIDEO_80x25,(%di) # The 80x25 mode (ALL)
+ movw $0x50,2(%di)
+ movw $0x19,4(%di)
+ movw $0x00,6(%di)
+ addw $8,%di
+
+ leaw bootsym(vga_modes), %si # All modes for std VGA
+ movw $vga_modes_end-vga_modes, %cx
+ rep movsb
+
+ call vesa_modes # Detect VESA VGA modes
+
+ movw $ASK_VGA, (%di) # End marker
+ movw %di, bootsym(mt_end)
+mtab1: leaw modelist, %si # SI=mode list, DI=list end
+ret0: ret
+
+# Modes usable on all standard VGAs
+vga_modes:
+ .word VIDEO_80x50, 0x50,0x32,0 # 80x50
+ .word VIDEO_80x43, 0x50,0x2b,0 # 80x43
+ .word VIDEO_80x28, 0x50,0x1c,0 # 80x28
+ .word VIDEO_80x30, 0x50,0x1e,0 # 80x30
+ .word VIDEO_80x34, 0x50,0x22,0 # 80x34
+ .word VIDEO_80x60, 0x50,0x3c,0 # 80x60
+vga_modes_end:
+
+# Detect VESA modes.
+vesa_modes:
+ movw %di, %bp # BP=original mode table end
+ addw $0x200, %di # Buffer space
+ movw $0x4f00, %ax # VESA Get card info call
+ int $0x10
+ movw %bp, %di
+ cmpw $0x004f, %ax # Successful?
+ jnz ret0
+
+ cmpw $0x4556, 0x200(%di) # 'VE'
+ jnz ret0
+
+ cmpw $0x4153, 0x202(%di) # 'SA'
+ jnz ret0
+
+ movw $bootsym(vesa_name), bootsym(card_name) # Set name to "VESA
VGA"
+ pushw %gs
+ lgsw 0x20e(%di), %si # GS:SI=mode list
+ movw $128, %cx # Iteration limit
+vesa1:
+ gs; lodsw
+ cmpw $0xffff, %ax # End of the table?
+ jz vesar
+
+ cmpw $0x0080, %ax # Check validity of mode ID
+ jc vesa2
+
+ orb %ah, %ah # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
+ jz vesan # Certain BIOSes report 0x80-0xff!
+
+ cmpw $0x0800, %ax
+ jnc vesae
+
+vesa2: pushw %cx
+ movw %ax, %cx # Get mode information structure
+ movw $0x4f01, %ax
+ int $0x10
+ movw %cx, %bx # BX=mode number
+ addb $VIDEO_FIRST_VESA>>8, %bh
+ popw %cx
+ cmpw $0x004f, %ax
+ jnz vesan # Don't report errors (buggy BIOSES)
+
+ movb (%di), %al # Check capabilities.
+ andb $0x9b, %al # LFB gfx mode in color?
+ cmpb $0x9b, %al
+ jnz vesan
+
+ movw %bx, (%di) # Store mode number
+ movw 0x12(%di), %bx # Width
+ movw %bx, 2(%di)
+ movw 0x14(%di), %bx # Height
+ movw %bx, 4(%di)
+ xorw %bx, %bx
+ movb 0x19(%di), %bl # Depth
+ movw %bx, 6(%di)
+
+ addw $8, %di # The mode is valid. Store it.
+vesan: loop vesa1 # Next mode. Limit exceeded => error
+vesae: leaw bootsym(vesaer), %si
+ call prtstr
+ movw %bp, %di # Discard already found modes.
+vesar: popw %gs
+ ret
+
+# Read a key and return the ASCII code in al, scan code in ah
+getkey: xorb %ah, %ah
+ int $0x16
+ ret
+
+# Read a key with a timeout of 30 seconds.
+# The hardware clock is used to get the time.
+getkt: call gettime
+ addb $30, %al # Wait 30 seconds
+ cmpb $60, %al
+ jl lminute
+
+ subb $60, %al
+lminute:
+ movb %al, %cl
+again: movb $0x01, %ah
+ int $0x16
+ jnz getkey # key pressed, so get it
+
+ call gettime
+ cmpb %cl, %al
+ jne again
+
+ movb $0x20, %al # timeout, return `space'
+ ret
+
+# Flush the keyboard buffer
+flush: movb $0x01, %ah
+ int $0x16
+ jz empty
+
+ xorb %ah, %ah
+ int $0x16
+ jmp flush
+
+empty: ret
+
+# Print hexadecimal number.
+prthw: pushw %ax
+ movb %ah, %al
+ call prthb
+ popw %ax
+prthb: pushw %ax
+ shrb $4, %al
+ call prthn
+ popw %ax
+ andb $0x0f, %al
+prthn: cmpb $0x0a, %al
+ jc prth1
+
+ addb $0x07, %al
+prth1: addb $0x30, %al
+ jmp prtchr
+
+# Print decimal number in ax
+prtdec: pushw %ax
+ pushw %cx
+ pushw %dx
+ xorw %dx, %dx
+ movw $0x0a, %cx
+ divw %cx
+ testw %ax, %ax
+ jz skip10
+ cmpw $0x09, %ax
+ jbe lt100
+
+ call prtdec
+ jmp skip10
+
+lt100: addb $0x30, %al
+ call prtchr
+skip10: movb %dl, %al
+ addb $0x30, %al
+ call prtchr
+ popw %dx
+ popw %cx
+ popw %ax
+ ret
+
+# Routine to print asciiz string at ds:si
+prtstr:
+ lodsb
+ andb %al, %al
+ jz fin
+
+ call prtchr
+ jmp prtstr
+
+fin: ret
+
+# Space printing
+prtsp2: call prtspc # Print double space
+prtspc: movb $0x20, %al # Print single space (note: fall-thru)
+
+# Part of above routine, this one just prints ascii al
+prtchr: pushw %ax
+ pushw %cx
+ movw $7,%bx
+ movw $0x01, %cx
+ movb $0x0e, %ah
+ int $0x10
+ popw %cx
+ popw %ax
+ ret
+
+beep: movb $0x07, %al
+ jmp prtchr
+
+# Read the cmos clock. Return the seconds in al
+gettime:
+ pushw %cx
+ movb $0x02, %ah
+ int $0x1a
+ movb %dh, %al # %dh contains the seconds
+ andb $0x0f, %al
+ movb %dh, %ah
+ movb $0x04, %cl
+ shrb %cl, %ah
+ aad
+ popw %cx
+ ret
+
+store_edid:
+#ifdef CONFIG_FIRMWARE_EDID
+ pushw %es # just save all registers
+ pushw %ax
+ pushw %bx
+ pushw %cx
+ pushw %dx
+ pushw %di
+
+ pushw %fs
+ popw %es
+
+ movl $0x13131313, %eax # memset block with 0x13
+ movw $32, %cx
+ movw $0x140, %di
+ cld
+ rep
+ stosl
+
+ cmpw $0x0200, bootsym(vbe_version) # only do EDID on >= VBE2.0
+ jl no_edid
+
+ pushw %es # save ES
+ xorw %di, %di # Report Capability
+ pushw %di
+ popw %es # ES:DI must be 0:0
+ movw $0x4f15, %ax
+ xorw %bx, %bx
+ xorw %cx, %cx
+ int $0x10
+ popw %es # restore ES
+
+ cmpb $0x00, %ah # call successful
+ jne no_edid
+
+ cmpb $0x4f, %al # function supported
+ jne no_edid
+
+ movw $0x4f15, %ax # do VBE/DDC
+ movw $0x01, %bx
+ movw $0x00, %cx
+ movw $0x00, %dx
+ movw $0x140, %di
+ int $0x10
+
+no_edid:
+ popw %di # restore all registers
+ popw %dx
+ popw %cx
+ popw %bx
+ popw %ax
+ popw %es
+#endif
+ ret
+
+mt_end: .word 0 # End of video mode table if built
+edit_buf: .space 6 # Line editor buffer
+card_name: .word 0 # Pointer to adapter name
+graphic_mode: .byte 0 # Graphic mode with a linear frame buffer
+dac_size: .byte 6 # DAC bit depth
+vbe_version: .word 0 # VBE bios version
+
+# Status messages
+keymsg: .ascii "Press <RETURN> to see video modes available,"
+ .byte 0x0d, 0x0a
+ .ascii "<SPACE> to continue or wait 30 secs"
+ .byte 0x0d, 0x0a, 0
+
+listhdr: .byte 0x0d, 0x0a
+ .ascii "MODE-KEY MODE-ID WIDTHxHEIGHTxDEPTH"
+
+crlft: .byte 0x0d, 0x0a, 0
+
+prompt: .byte 0x0d, 0x0a
+ .asciz "Enter mode number or 'menu': "
+
+unknt: .ascii "Unknown mode ID. Try again."
+ .byte 0x0d, 0x0a, 0
+
+badmdt: .ascii "You passed an undefined mode number."
+ .byte 0x0d, 0x0a, 0
+
+vesaer: .ascii "Error: Scanning of VESA modes failed. Please "
+ .ascii "report to <mj@xxxxxx>."
+ .byte 0x0d, 0x0a, 0
+
+textmode: .asciz " (text)"
+menu_more_msg: .asciz "<press SPACE for more>"
+menu_bail_msg: .ascii "<menu truncated>"
+ .byte 0x0d, 0x0a, 0
+
+svga_name: .ascii " "
+
+vga_name: .asciz "VGA"
+
+vesa_name: .asciz "VESA"
+
+name_bann: .asciz "Video adapter: "
+
+force_size: .word 0 # Use this size instead of the one in BIOS vars
+
+vesa_size: .word 0,0,0 # width x depth x height
+
+ .globl boot_vid_info
+/* If we don't run at all, assume basic video mode 3 at 80x25. */
+boot_vid_mode: .word VIDEO_80x25
+boot_vid_info: .byte 0, 0 /* orig_x, orig_y */
+ .byte 3 /* text mode 3 */
+ .byte 80, 25 /* 80x25 */
+ .byte 1 /* isVGA */
+ .word 16 /* 8x16 font */
+ .fill 0x28,1,0
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/boot/video.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/x86/boot/video.h Sun Jun 10 15:58:08 2007 +0100
@@ -0,0 +1,30 @@
+#ifndef __BOOT_VIDEO_H__
+#define __BOOT_VIDEO_H__
+
+/*
+ * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
+ * of compatibility when extending the table. These are between 0x00 and 0xff.
+ */
+#define VIDEO_FIRST_MENU 0x0000
+
+/* VESA BIOS video modes (VESA number + 0x0200) */
+#define VIDEO_FIRST_VESA 0x0200
+
+/* Special video modes */
+#define VIDEO_FIRST_SPECIAL 0x0f00
+#define VIDEO_80x25 0x0f00
+#define VIDEO_80x50 0x0f01
+#define VIDEO_80x43 0x0f02
+#define VIDEO_80x28 0x0f03
+#define VIDEO_80x30 0x0f04
+#define VIDEO_80x34 0x0f05
+#define VIDEO_80x60 0x0f06
+#define VIDEO_LAST_SPECIAL 0x0f07
+
+#define ASK_VGA 0xfffd
+#define VIDEO_VESA_BY_SIZE 0xffff
+
+/* The "recalculate timings" flag */
+#define VIDEO_RECALC 0x8000
+
+#endif /* __BOOT_VIDEO_H__ */
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/arch/x86/setup.c
--- a/xen/arch/x86/setup.c Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/arch/x86/setup.c Sun Jun 10 15:58:08 2007 +0100
@@ -18,6 +18,7 @@
#include <xen/keyhandler.h>
#include <xen/numa.h>
#include <xen/rcupdate.h>
+#include <xen/vga.h>
#include <public/version.h>
#ifdef CONFIG_COMPAT
#include <compat/platform.h>
@@ -313,6 +314,69 @@ static void __init reserve_in_boot_e820(
boot_e820.map[i].addr = e;
boot_e820.map[i].size = re - e;
}
+ }
+}
+
+struct boot_video_info {
+ u8 orig_x; /* 0x00 */
+ u8 orig_y; /* 0x01 */
+ u8 orig_video_mode; /* 0x02 */
+ u8 orig_video_cols; /* 0x03 */
+ u8 orig_video_lines; /* 0x04 */
+ u8 orig_video_isVGA; /* 0x05 */
+ u16 orig_video_points; /* 0x06 */
+
+ /* VESA graphic mode -- linear frame buffer */
+ u32 capabilities; /* 0x08 */
+ u16 lfb_linelength; /* 0x0c */
+ u16 lfb_width; /* 0x0e */
+ u16 lfb_height; /* 0x10 */
+ u16 lfb_depth; /* 0x12 */
+ u32 lfb_base; /* 0x14 */
+ u32 lfb_size; /* 0x18 */
+ u8 red_size; /* 0x1c */
+ u8 red_pos; /* 0x1d */
+ u8 green_size; /* 0x1e */
+ u8 green_pos; /* 0x1f */
+ u8 blue_size; /* 0x20 */
+ u8 blue_pos; /* 0x21 */
+ u8 rsvd_size; /* 0x22 */
+ u8 rsvd_pos; /* 0x23 */
+ u16 vesapm_seg; /* 0x24 */
+ u16 vesapm_off; /* 0x26 */
+};
+
+static void __init parse_video_info(void)
+{
+ extern struct boot_video_info boot_vid_info;
+ struct boot_video_info *bvi = &bootsym(boot_vid_info);
+
+ if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
+ {
+ vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
+ vga_console_info.u.text_mode_3.font_height = bvi->orig_video_points;
+ vga_console_info.u.text_mode_3.cursor_x = bvi->orig_x;
+ vga_console_info.u.text_mode_3.cursor_y = bvi->orig_y;
+ vga_console_info.u.text_mode_3.rows = bvi->orig_video_lines;
+ vga_console_info.u.text_mode_3.columns = bvi->orig_video_cols;
+ }
+ else if ( bvi->orig_video_isVGA == 0x23 )
+ {
+ vga_console_info.video_type = XEN_VGATYPE_VESA_LFB;
+ vga_console_info.u.vesa_lfb.width = bvi->lfb_width;
+ vga_console_info.u.vesa_lfb.height = bvi->lfb_height;
+ vga_console_info.u.vesa_lfb.bytes_per_line = bvi->lfb_linelength;
+ vga_console_info.u.vesa_lfb.bits_per_pixel = bvi->lfb_depth;
+ vga_console_info.u.vesa_lfb.lfb_base = bvi->lfb_base;
+ vga_console_info.u.vesa_lfb.lfb_size = bvi->lfb_size;
+ vga_console_info.u.vesa_lfb.red_pos = bvi->red_pos;
+ vga_console_info.u.vesa_lfb.red_size = bvi->red_size;
+ vga_console_info.u.vesa_lfb.green_pos = bvi->green_pos;
+ vga_console_info.u.vesa_lfb.green_size = bvi->green_size;
+ vga_console_info.u.vesa_lfb.blue_pos = bvi->blue_pos;
+ vga_console_info.u.vesa_lfb.blue_size = bvi->blue_size;
+ vga_console_info.u.vesa_lfb.rsvd_pos = bvi->rsvd_pos;
+ vga_console_info.u.vesa_lfb.rsvd_size = bvi->rsvd_size;
}
}
@@ -359,6 +423,8 @@ void __init __start_xen(multiboot_info_t
cmdline = __va(mbi->cmdline);
cmdline_parse(cmdline);
+ parse_video_info();
+
set_current((struct vcpu *)0xfffff000); /* debug sanity */
idle_vcpu[0] = current;
set_processor_id(0); /* needed early, for smp_processor_id() */
@@ -377,6 +443,22 @@ void __init __start_xen(multiboot_info_t
init_console();
printk("Command line: %s\n", cmdline);
+
+ switch ( vga_console_info.video_type )
+ {
+ case XEN_VGATYPE_TEXT_MODE_3:
+ printk("VGA is text mode %dx%d, font 8x%d\n",
+ vga_console_info.u.text_mode_3.columns,
+ vga_console_info.u.text_mode_3.rows,
+ vga_console_info.u.text_mode_3.font_height);
+ break;
+ case XEN_VGATYPE_VESA_LFB:
+ printk("VGA is graphics mode %dx%d, %d bpp\n",
+ vga_console_info.u.vesa_lfb.width,
+ vga_console_info.u.vesa_lfb.height,
+ vga_console_info.u.vesa_lfb.bits_per_pixel);
+ break;
+ }
/* Check that we have at least one Multiboot module. */
if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/drivers/video/vga.c
--- a/xen/drivers/video/vga.c Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/drivers/video/vga.c Sun Jun 10 15:58:08 2007 +0100
@@ -17,559 +17,43 @@
#include <asm/io.h>
#include "font.h"
-/* Some of the code below is taken from SVGAlib. The original,
- unmodified copyright notice for that code is below. */
-/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen */
-/* */
-/* This library is free software; you can redistribute it and/or */
-/* modify it without any restrictions. This library is distributed */
-/* in the hope that it will be useful, but without any warranty. */
-
-/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
-/* partially copyrighted (C) 1993 by Hartmut Schirmer */
-
-/* VGA data register ports */
-#define VGA_CRT_DC 0x3D5 /* CRT Controller Data Register - color
emulation */
-#define VGA_CRT_DM 0x3B5 /* CRT Controller Data Register - mono
emulation */
-#define VGA_ATT_R 0x3C1 /* Attribute Controller Data Read Register */
-#define VGA_ATT_W 0x3C0 /* Attribute Controller Data Write Register */
-#define VGA_GFX_D 0x3CF /* Graphics Controller Data Register */
-#define VGA_SEQ_D 0x3C5 /* Sequencer Data Register */
-#define VGA_MIS_R 0x3CC /* Misc Output Read Register */
-#define VGA_MIS_W 0x3C2 /* Misc Output Write Register */
-#define VGA_FTC_R 0x3CA /* Feature Control Read Register */
-#define VGA_IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
-#define VGA_IS1_RM 0x3BA /* Input Status Register 1 - mono emulation */
-#define VGA_PEL_D 0x3C9 /* PEL Data Register */
-#define VGA_PEL_MSK 0x3C6 /* PEL mask register */
-
-/* EGA-specific registers */
-#define EGA_GFX_E0 0x3CC /* Graphics enable processor 0 */
-#define EGA_GFX_E1 0x3CA /* Graphics enable processor 1 */
-
-/* VGA index register ports */
-#define VGA_CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
-#define VGA_CRT_IM 0x3B4 /* CRT Controller Index - mono emulation */
-#define VGA_ATT_IW 0x3C0 /* Attribute Controller Index & Data Write
Register */
-#define VGA_GFX_I 0x3CE /* Graphics Controller Index */
-#define VGA_SEQ_I 0x3C4 /* Sequencer Index */
-#define VGA_PEL_IW 0x3C8 /* PEL Write Index */
-#define VGA_PEL_IR 0x3C7 /* PEL Read Index */
-
-/* standard VGA indexes max counts */
-#define VGA_CRT_C 0x19 /* Number of CRT Controller Registers */
-#define VGA_ATT_C 0x15 /* Number of Attribute Controller Registers */
-#define VGA_GFX_C 0x09 /* Number of Graphics Controller Registers */
-#define VGA_SEQ_C 0x05 /* Number of Sequencer Registers */
-#define VGA_MIS_C 0x01 /* Number of Misc Output Register */
-
-/* VGA misc register bit masks */
-#define VGA_MIS_COLOR 0x01
-#define VGA_MIS_ENB_MEM_ACCESS 0x02
-#define VGA_MIS_DCLK_28322_720 0x04
-#define VGA_MIS_ENB_PLL_LOAD (0x04 | 0x08)
-#define VGA_MIS_SEL_HIGH_PAGE 0x20
-
-/* VGA CRT controller register indices */
-#define VGA_CRTC_H_TOTAL 0
-#define VGA_CRTC_H_DISP 1
-#define VGA_CRTC_H_BLANK_START 2
-#define VGA_CRTC_H_BLANK_END 3
-#define VGA_CRTC_H_SYNC_START 4
-#define VGA_CRTC_H_SYNC_END 5
-#define VGA_CRTC_V_TOTAL 6
-#define VGA_CRTC_OVERFLOW 7
-#define VGA_CRTC_PRESET_ROW 8
-#define VGA_CRTC_MAX_SCAN 9
-#define VGA_CRTC_CURSOR_START 0x0A
-#define VGA_CRTC_CURSOR_END 0x0B
-#define VGA_CRTC_START_HI 0x0C
-#define VGA_CRTC_START_LO 0x0D
-#define VGA_CRTC_CURSOR_HI 0x0E
-#define VGA_CRTC_CURSOR_LO 0x0F
-#define VGA_CRTC_V_SYNC_START 0x10
-#define VGA_CRTC_V_SYNC_END 0x11
-#define VGA_CRTC_V_DISP_END 0x12
-#define VGA_CRTC_OFFSET 0x13
-#define VGA_CRTC_UNDERLINE 0x14
-#define VGA_CRTC_V_BLANK_START 0x15
-#define VGA_CRTC_V_BLANK_END 0x16
-#define VGA_CRTC_MODE 0x17
-#define VGA_CRTC_LINE_COMPARE 0x18
-#define VGA_CRTC_REGS VGA_CRT_C
-
-/* VGA CRT controller bit masks */
-#define VGA_CR11_LOCK_CR0_CR7 0x80 /* lock writes to CR0 - CR7 */
-#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
-
-/* VGA attribute controller register indices */
-#define VGA_ATC_PALETTE0 0x00
-#define VGA_ATC_PALETTE1 0x01
-#define VGA_ATC_PALETTE2 0x02
-#define VGA_ATC_PALETTE3 0x03
-#define VGA_ATC_PALETTE4 0x04
-#define VGA_ATC_PALETTE5 0x05
-#define VGA_ATC_PALETTE6 0x06
-#define VGA_ATC_PALETTE7 0x07
-#define VGA_ATC_PALETTE8 0x08
-#define VGA_ATC_PALETTE9 0x09
-#define VGA_ATC_PALETTEA 0x0A
-#define VGA_ATC_PALETTEB 0x0B
-#define VGA_ATC_PALETTEC 0x0C
-#define VGA_ATC_PALETTED 0x0D
-#define VGA_ATC_PALETTEE 0x0E
-#define VGA_ATC_PALETTEF 0x0F
-#define VGA_ATC_MODE 0x10
-#define VGA_ATC_OVERSCAN 0x11
-#define VGA_ATC_PLANE_ENABLE 0x12
-#define VGA_ATC_PEL 0x13
-#define VGA_ATC_COLOR_PAGE 0x14
-
-#define VGA_AR_ENABLE_DISPLAY 0x20
-
-/* VGA sequencer register indices */
-#define VGA_SEQ_RESET 0x00
-#define VGA_SEQ_CLOCK_MODE 0x01
-#define VGA_SEQ_PLANE_WRITE 0x02
-#define VGA_SEQ_CHARACTER_MAP 0x03
-#define VGA_SEQ_MEMORY_MODE 0x04
-
-/* VGA sequencer register bit masks */
-#define VGA_SR01_CHAR_CLK_8DOTS 0x01 /* bit 0: character clocks 8 dots
wide are generated */
-#define VGA_SR01_SCREEN_OFF 0x20 /* bit 5: Screen is off */
-#define VGA_SR02_ALL_PLANES 0x0F /* bits 3-0: enable access to all planes */
-#define VGA_SR04_EXT_MEM 0x02 /* bit 1: allows complete mem access to
256K */
-#define VGA_SR04_SEQ_MODE 0x04 /* bit 2: directs system to use a
sequential addressing mode */
-#define VGA_SR04_CHN_4M 0x08 /* bit 3: selects modulo 4
addressing for CPU access to display memory */
-
-/* VGA graphics controller register indices */
-#define VGA_GFX_SR_VALUE 0x00
-#define VGA_GFX_SR_ENABLE 0x01
-#define VGA_GFX_COMPARE_VALUE 0x02
-#define VGA_GFX_DATA_ROTATE 0x03
-#define VGA_GFX_PLANE_READ 0x04
-#define VGA_GFX_MODE 0x05
-#define VGA_GFX_MISC 0x06
-#define VGA_GFX_COMPARE_MASK 0x07
-#define VGA_GFX_BIT_MASK 0x08
-
-/* VGA graphics controller bit masks */
-#define VGA_GR06_GRAPHICS_MODE 0x01
-
-/* macro for composing an 8-bit VGA register index and value
- * into a single 16-bit quantity */
-#define VGA_OUT16VAL(v, r) (((v) << 8) | (r))
-
-#define vgabase 0 /* use in/out port-access macros */
-#define VGA_OUTW_WRITE /* can use outw instead of 2xoutb */
-
-/*
- * generic VGA port read/write
- */
-
-static inline uint8_t vga_io_r(uint16_t port)
-{
- return inb(port);
-}
-
-static inline void vga_io_w(uint16_t port, uint8_t val)
-{
- outb(val, port);
-}
-
-static inline void vga_io_w_fast(uint16_t port, uint8_t reg, uint8_t val)
-{
- outw(VGA_OUT16VAL(val, reg), port);
-}
-
-static inline uint8_t vga_mm_r(void __iomem *regbase, uint16_t port)
-{
- return readb((char *)regbase + port);
-}
-
-static inline void vga_mm_w(void __iomem *regbase, uint16_t port, uint8_t val)
-{
- writeb(val, (char *)regbase + port);
-}
-
-static inline void vga_mm_w_fast(void __iomem *regbase, uint16_t port, uint8_t
reg, uint8_t val)
-{
- writew(VGA_OUT16VAL(val, reg), (char *)regbase + port);
-}
-
-static inline uint8_t vga_r(void __iomem *regbase, uint16_t port)
-{
- if (regbase)
- return vga_mm_r(regbase, port);
- else
- return vga_io_r(port);
-}
-
-static inline void vga_w(void __iomem *regbase, uint16_t port, uint8_t val)
-{
- if (regbase)
- vga_mm_w(regbase, port, val);
- else
- vga_io_w(port, val);
-}
-
-
-static inline void vga_w_fast(void __iomem *regbase, uint16_t port, uint8_t
reg, uint8_t val)
-{
- if (regbase)
- vga_mm_w_fast(regbase, port, reg, val);
- else
- vga_io_w_fast(port, reg, val);
-}
-
-
-/*
- * VGA CRTC register read/write
- */
-
-static inline uint8_t vga_rcrt(void __iomem *regbase, uint8_t reg)
-{
- vga_w(regbase, VGA_CRT_IC, reg);
- return vga_r(regbase, VGA_CRT_DC);
-}
-
-static inline void vga_wcrt(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
- vga_w_fast(regbase, VGA_CRT_IC, reg, val);
-#else
- vga_w(regbase, VGA_CRT_IC, reg);
- vga_w(regbase, VGA_CRT_DC, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA sequencer register read/write
- */
-
-static inline uint8_t vga_rseq(void __iomem *regbase, uint8_t reg)
-{
- vga_w(regbase, VGA_SEQ_I, reg);
- return vga_r(regbase, VGA_SEQ_D);
-}
-
-static inline void vga_wseq(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
- vga_w_fast(regbase, VGA_SEQ_I, reg, val);
-#else
- vga_w(regbase, VGA_SEQ_I, reg);
- vga_w(regbase, VGA_SEQ_D, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA graphics controller register read/write
- */
-
-static inline uint8_t vga_rgfx(void __iomem *regbase, uint8_t reg)
-{
- vga_w(regbase, VGA_GFX_I, reg);
- return vga_r(regbase, VGA_GFX_D);
-}
-
-static inline void vga_wgfx(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
-#ifdef VGA_OUTW_WRITE
- vga_w_fast(regbase, VGA_GFX_I, reg, val);
-#else
- vga_w(regbase, VGA_GFX_I, reg);
- vga_w(regbase, VGA_GFX_D, val);
-#endif /* VGA_OUTW_WRITE */
-}
-
-/*
- * VGA attribute controller register read/write
- */
-
-static inline uint8_t vga_rattr(void __iomem *regbase, uint8_t reg)
-{
- vga_w(regbase, VGA_ATT_IW, reg);
- return vga_r(regbase, VGA_ATT_R);
-}
-
-static inline void vga_wattr(void __iomem *regbase, uint8_t reg, uint8_t val)
-{
- vga_w(regbase, VGA_ATT_IW, reg);
- vga_w(regbase, VGA_ATT_W, val);
-}
-
-static int __init detect_video(void *video_base)
-{
- volatile u16 *p = (volatile u16 *)video_base;
- u16 saved1 = p[0], saved2 = p[1];
- int video_found = 1;
-
- p[0] = 0xAA55;
- p[1] = 0x55AA;
- if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
- video_found = 0;
-
- p[0] = 0x55AA;
- p[1] = 0xAA55;
- if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
- video_found = 0;
-
- p[0] = saved1;
- p[1] = saved2;
-
- return video_found;
-}
-
-/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
-static void * __init setup_vga(void)
-{
- /* The following VGA state was saved from a chip in text mode 3. */
- static unsigned char regs[] = {
- /* Sequencer registers */
- 0x03, 0x00, 0x03, 0x00, 0x02,
- /* CRTC registers */
- 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
- 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
- 0xb9, 0xa3, 0xff,
- /* Graphic registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
- /* Attribute registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
- 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
- };
-
- char *video;
- int i, j;
-
- if ( memory_is_conventional_ram(0xB8000) )
- goto no_vga;
-
- inb(VGA_IS1_RC);
- outb(0x00, VGA_ATT_IW);
-
- for ( i = j = 0; i < 5; i++ )
- vga_wseq(vgabase, i, regs[j++]);
-
- /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
- vga_wcrt(vgabase, 17, regs[5+17] & 0x7F);
-
- for ( i = 0; i < 25; i++ )
- vga_wcrt(vgabase, i, regs[j++]);
-
- for ( i = 0; i < 9; i++ )
- vga_wgfx(vgabase, i, regs[j++]);
-
- inb(VGA_IS1_RC);
- for ( i = 0; i < 21; i++ )
- vga_wattr(vgabase, i, regs[j++]);
-
- inb(VGA_IS1_RC);
- outb(0x20, VGA_ATT_IW);
-
- video = ioremap(0xB8000, 0x8000);
-
- if ( !detect_video(video) )
- {
- iounmap(video);
- goto no_vga;
- }
-
- return video;
-
- no_vga:
- printk("No VGA adaptor detected!\n");
- return NULL;
-}
-
-static int __init vga_set_scanlines(unsigned scanlines)
-{
- unsigned vtot, ovr, vss, vbs;
- uint8_t vse, vbe, misc = 0;
-
- switch (scanlines) {
- case 43*8:
- vtot = 0x1bf;
- vss = 0x183;
- vse = 0x05;
- vbs = 0x163;
- vbe = 0xba;
- break;
- case 25*16:
- case 28*14:
- vtot = 0x1bf;
- vss = 0x19c;
- vse = 0x0e;
- vbs = 0x196;
- vbe = 0xb9;
- break;
- case 30*16:
- case 34*14:
- vtot = 0x20b;
- vss = 0x1ea;
- vse = 0x0c;
- vbs = 0x1e7;
- vbe = 0x04;
- /* Preserve clock select bits and color bit, set correct sync
polarity. */
- misc = (inb(VGA_MIS_R) & 0x0d) | 0xe2;
- break;
- default:
- return -ENOSYS;
- }
-
- ovr = vga_rcrt(vgabase, VGA_CRTC_OVERFLOW);
- if(vga_rcrt(vgabase, VGA_CRTC_V_DISP_END) + ((ovr & 0x02) << 7) + ((ovr &
0x40) << 3) == scanlines - 1)
- return 0;
-
- ovr = (ovr & 0x10)
- | ((vtot >> 8) & 0x01)
- | ((vtot >> 4) & 0x20)
- | (((scanlines - 1) >> 7) & 0x02)
- | (((scanlines - 1) >> 3) & 0x40)
- | ((vss >> 6) & 0x04)
- | ((vss >> 2) & 0x80)
- | ((vbs >> 5) & 0x08);
- vse |= vga_rcrt(vgabase, VGA_CRTC_V_SYNC_END) & 0x70;
-
- vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse & 0x7f); /* Vertical sync end
(also unlocks CR0-7) */
- vga_wcrt(vgabase, VGA_CRTC_V_TOTAL, (uint8_t)vtot); /* Vertical total */
- vga_wcrt(vgabase, VGA_CRTC_OVERFLOW, (uint8_t)ovr); /* Overflow */
- vga_wcrt(vgabase, VGA_CRTC_V_SYNC_START, (uint8_t)vss); /* Vertical sync
start */
- vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse | 0x80); /* Vertical sync end
(also locks CR0-7) */
- vga_wcrt(vgabase, VGA_CRTC_V_DISP_END, (uint8_t)(scanlines - 1)); /*
Vertical display end */
- vga_wcrt(vgabase, VGA_CRTC_V_BLANK_START, (uint8_t)vbs); /* Vertical blank
start */
- vga_wcrt(vgabase, VGA_CRTC_V_BLANK_END, vbe); /* Vertical blank end */
-
- if (misc)
- outb(misc, VGA_MIS_W); /* Misc output register */
-
- return 0;
-}
-
-#define FONT_COUNT_MAX 256
-#define FONT_HEIGHT_MAX 32
-#define CHAR_MAP_SIZE (FONT_COUNT_MAX * FONT_HEIGHT_MAX)
-
-/*
- * We use font slot 0 because ATI cards do not honour changes to the
- * character map select register. The fontslot parameter can be used to
- * choose a non-default slot if the video card supports it and you wish to
- * preserve the BIOS-initialised font data.
- */
-static unsigned font_slot = 0;
-integer_param("fontslot", font_slot);
-
-static int __init vga_load_font(const struct font_desc *font, unsigned rows)
-{
- unsigned fontheight = font ? font->height : 16;
- uint8_t fsr = vga_rcrt(vgabase, VGA_CRTC_MAX_SCAN); /* Font size register
*/
- int ret;
-
- if (font_slot > 3 || (!font_slot && !font))
- return -ENOSYS;
-
- if (font
- && (font->count > FONT_COUNT_MAX
- || fontheight > FONT_HEIGHT_MAX
- || font->width != 8))
- return -EINVAL;
-
- ret = vga_set_scanlines(rows * fontheight);
- if (ret < 0)
- return ret;
-
- if ((fsr & 0x1f) == fontheight - 1)
- return 0;
-
- /* First, the Sequencer */
- vga_wseq(vgabase, VGA_SEQ_RESET, 0x1);
- /* CPU writes only to map 2 */
- vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
- /* Sequential addressing */
- vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
- /* Clear synchronous reset */
- vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
-
- /* Now, the graphics controller, select map 2 */
- vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x02);
- /* disable odd-even addressing */
- vga_wgfx(vgabase, VGA_GFX_MODE, 0x00);
- /* map start at A000:0000 */
- vga_wgfx(vgabase, VGA_GFX_MISC, 0x00);
-
- if ( font )
- {
- unsigned i, j;
- const uint8_t *data = font->data;
- uint8_t *map;
-
- map = ioremap(0xA0000 + font_slot*2*CHAR_MAP_SIZE, CHAR_MAP_SIZE);
-
- for ( i = j = 0; i < CHAR_MAP_SIZE; )
- {
- writeb(j < font->count * fontheight ? data[j++] : 0, map + i++);
- if ( !(j % fontheight) )
- while ( i & (FONT_HEIGHT_MAX - 1) )
- writeb(0, map + i++);
- }
-
- iounmap(map);
- }
-
- /* First, the sequencer, Synchronous reset */
- vga_wseq(vgabase, VGA_SEQ_RESET, 0x01);
- /* CPU writes to maps 0 and 1 */
- vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
- /* odd-even addressing */
- vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
- /* Character Map Select: The default font is kept in slot 0. */
- vga_wseq(vgabase, VGA_SEQ_CHARACTER_MAP,
- font ? font_slot | (font_slot << 2) : 0x00);
- /* clear synchronous reset */
- vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
-
- /* Now, the graphics controller, select map 0 for CPU */
- vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x00);
- /* enable even-odd addressing */
- vga_wgfx(vgabase, VGA_GFX_MODE, 0x10);
- /* map starts at b800:0 */
- vga_wgfx(vgabase, VGA_GFX_MISC, 0x0e);
-
- /* Font size register */
- fsr = (fsr & 0xe0) + (fontheight - 1);
- vga_wcrt(vgabase, VGA_CRTC_MAX_SCAN, fsr);
-
- /* Cursor shape registers */
- fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_END) & 0xe0;
- fsr |= fontheight - fontheight / 6;
- vga_wcrt(vgabase, VGA_CRTC_CURSOR_END, fsr);
- fsr = vga_rcrt(vgabase, VGA_CRTC_CURSOR_START) & 0xe0;
- fsr |= (fsr & 0x1f) - 1;
- vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, fsr);
-
- return 0;
-}
-
-
-/*
- * HIGH-LEVEL INITIALISATION AND TEXT OUTPUT.
- */
+/* Filled in by arch boot code. */
+struct xen_vga_console_info vga_console_info;
static int vgacon_enabled = 0;
static int vgacon_keep = 0;
-static int vgacon_lines = 50;
-static const struct font_desc *font;
+/*static const struct font_desc *font;*/
static int xpos, ypos;
static unsigned char *video;
-/* vga: comma-separated options. */
+/*
+ * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
+ *
+ * 'vga=ask':
+ * display a vga menu of available modes
+ *
+ * 'vga=text-80x<rows>':
+ * text mode, where <rows> is one of {25,28,30,34,43,50,60}
+ *
+ * 'vga=gfx-<width>x<height>x<depth>':
+ * graphics mode, e.g., vga=gfx-1024x768x16
+ *
+ * 'vga=mode-<mode>:
+ * specifies a mode as specified in 'vga=ask' menu
+ * (NB. menu modes are displayed in hex, so mode numbers here must
+ * be prefixed with '0x' (e.g., 'vga=mode-0x0318'))
+ *
+ * The option 'keep' causes Xen to continue to print to the VGA console even
+ * after domain 0 starts to boot. The default behaviour is to relinquish
+ * control of the console to domain 0.
+ */
static char opt_vga[30] = "";
string_param("vga", opt_vga);
/* VGA text-mode definitions. */
-#define COLUMNS 80
-#define LINES vgacon_lines
+#define COLUMNS vga_console_info.u.text_mode_3.columns
+#define LINES vga_console_info.u.text_mode_3.rows
#define ATTRIBUTE 7
#define VIDEO_SIZE (COLUMNS * LINES * 2)
@@ -577,49 +61,43 @@ void __init vga_init(void)
{
char *p;
+ /* Look for 'keep' in comma-separated options. */
for ( p = opt_vga; p != NULL; p = strchr(p, ',') )
{
if ( *p == ',' )
p++;
if ( strncmp(p, "keep", 4) == 0 )
vgacon_keep = 1;
- else if ( strncmp(p, "text-80x", 8) == 0 )
- vgacon_lines = simple_strtoul(p + 8, NULL, 10);
}
- video = setup_vga();
- if ( !video )
+ switch ( vga_console_info.video_type )
+ {
+ case XEN_VGATYPE_TEXT_MODE_3:
+ if ( memory_is_conventional_ram(0xB8000) )
+ return;
+ video = ioremap(0xB8000, 0x8000);
+ if ( video == NULL )
+ return;
+ /* Disable cursor. */
+ outw(0x200a, 0x3d4);
+ memset(video, 0, VIDEO_SIZE);
+ break;
+ case XEN_VGATYPE_VESA_LFB:
+#if 0
+ /* XXX Implement me! */
+ video = ioremap(vga_console_info.u.vesa_lfb.lfb_base,
+ vga_console_info.u.vesa_lfb.lfb_size);
+ if ( video == NULL )
+ return;
+ memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
+ break;
+#else
return;
-
- switch ( vgacon_lines )
- {
- case 25:
- case 30:
- font = &font_vga_8x16;
- break;
- case 28:
- case 34:
- font = &font_vga_8x14;
- break;
- case 43:
- case 50:
- case 60:
- font = &font_vga_8x8;
- break;
+#endif
+ default:
+ memset(&vga_console_info, 0, sizeof(vga_console_info));
+ return;
}
-
- if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) )
- {
- vgacon_lines = 25;
- font = NULL;
- }
-
- /* Clear the screen. */
- memset(video, 0, VIDEO_SIZE);
- xpos = ypos = 0;
-
- /* Disable cursor. */
- vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, 0x20);
vgacon_enabled = 1;
}
@@ -629,11 +107,10 @@ void __init vga_endboot(void)
if ( !vgacon_enabled )
return;
- if ( !vgacon_keep )
- vgacon_enabled = 0;
-
printk("Xen is %s VGA console.\n",
vgacon_keep ? "keeping" : "relinquishing");
+
+ vgacon_enabled = vgacon_keep;
}
@@ -672,17 +149,6 @@ void vga_putchar(int c)
int __init fill_console_start_info(struct dom0_vga_console_info *ci)
{
- memset(ci, 0, sizeof(*ci));
-
- if ( !vgacon_enabled )
- return 0;
-
- ci->video_type = XEN_VGATYPE_TEXT_MODE_3;
- ci->u.text_mode_3.rows = LINES;
- ci->u.text_mode_3.columns = COLUMNS;
- ci->u.text_mode_3.cursor_x = 0;
- ci->u.text_mode_3.cursor_y = LINES - 1;
- ci->u.text_mode_3.font_height = font ? font->height : 16;
-
+ memcpy(ci, &vga_console_info, sizeof(*ci));
return 1;
}
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/include/public/xen.h
--- a/xen/include/public/xen.h Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/include/public/xen.h Sun Jun 10 15:58:08 2007 +0100
@@ -568,6 +568,8 @@ typedef struct dom0_vga_console_info {
} vesa_lfb;
} u;
} dom0_vga_console_info_t;
+#define xen_vga_console_info dom0_vga_console_info
+#define xen_vga_console_info_t dom0_vga_console_info_t
typedef uint8_t xen_domain_handle_t[16];
diff -r 6d6b4b48773b -r 3cc79ef896a2 xen/include/xen/vga.h
--- a/xen/include/xen/vga.h Fri Jun 08 19:22:08 2007 +0100
+++ b/xen/include/xen/vga.h Sun Jun 10 15:58:08 2007 +0100
@@ -12,6 +12,7 @@
#include <xen/config.h>
#ifdef CONFIG_VGA
+extern struct xen_vga_console_info vga_console_info;
void vga_init(void);
void vga_endboot(void);
void vga_putchar(int c);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|