ia64/xen-unstable

changeset 15298:3cc79ef896a2

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@xensource.com>
author Keir Fraser <keir@xensource.com>
date Sun Jun 10 15:58:08 2007 +0100 (2007-06-10)
parents 6d6b4b48773b
children 91aeaf000ca2
files xen/arch/x86/boot/Makefile xen/arch/x86/boot/cmdline.S xen/arch/x86/boot/head.S xen/arch/x86/boot/trampoline.S xen/arch/x86/boot/video.S xen/arch/x86/boot/video.h xen/arch/x86/setup.c xen/drivers/video/vga.c xen/include/public/xen.h xen/include/xen/vga.h
line diff
     1.1 --- a/xen/arch/x86/boot/Makefile	Fri Jun 08 19:22:08 2007 +0100
     1.2 +++ b/xen/arch/x86/boot/Makefile	Sun Jun 10 15:58:08 2007 +0100
     1.3 @@ -1,3 +1,3 @@
     1.4  obj-y += head.o
     1.5  
     1.6 -head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S
     1.7 +head.o: head.S $(TARGET_SUBARCH).S trampoline.S mem.S video.S cmdline.S
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/arch/x86/boot/cmdline.S	Sun Jun 10 15:58:08 2007 +0100
     2.3 @@ -0,0 +1,285 @@
     2.4 +/******************************************************************************
     2.5 + * cmdline.S
     2.6 + *
     2.7 + * Early command-line parsing.
     2.8 + */
     2.9 +
    2.10 +        .code32
    2.11 +
    2.12 +#include "video.h"
    2.13 +
    2.14 +# NB. String pointer on stack is modified to point past parsed digits.
    2.15 +.Latoi:
    2.16 +        push    %ebx
    2.17 +        push    %ecx
    2.18 +        push    %edx
    2.19 +        push    %esi
    2.20 +        xor     %ebx,%ebx       /* %ebx = accumulator */
    2.21 +        mov     $10,%ecx        /* %ecx = base (default base 10) */
    2.22 +        mov     16+4(%esp),%esi /* %esi = pointer into ascii string. */
    2.23 +        lodsb
    2.24 +        cmpb    $'0',%al
    2.25 +        jne     2f
    2.26 +        mov     $8,%ecx         /* Prefix '0' => octal (base 8) */
    2.27 +        lodsb
    2.28 +        cmpb    $'x',%al
    2.29 +        jne     2f
    2.30 +        mov     $16,%ecx        /* Prefix '0x' => hex (base 16) */
    2.31 +1:      lodsb
    2.32 +2:      sub     $'0',%al
    2.33 +        jb      4f
    2.34 +        cmp     $9,%al
    2.35 +        jbe     3f
    2.36 +        sub     $'A'-'0'-10,%al
    2.37 +        jb      4f
    2.38 +        cmp     $15,%al
    2.39 +        jbe     3f
    2.40 +        sub     $'a'-'A',%al
    2.41 +        jb      4f
    2.42 +3:      cmp     %cl,%al
    2.43 +        jae     4f
    2.44 +        movzbl  %al,%eax
    2.45 +        xchg    %eax,%ebx
    2.46 +        mul     %ecx
    2.47 +        xchg    %eax,%ebx
    2.48 +        add     %eax,%ebx
    2.49 +        jmp     1b
    2.50 +4:      mov     %ebx,%eax
    2.51 +        dec     %esi
    2.52 +        mov     %esi,16+4(%esp)
    2.53 +        pop     %esi
    2.54 +        pop     %edx
    2.55 +        pop     %ecx
    2.56 +        pop     %ebx
    2.57 +        ret
    2.58 +
    2.59 +.Lstrstr:
    2.60 +        push    %ecx
    2.61 +        push    %edx
    2.62 +        push    %esi
    2.63 +        push    %edi
    2.64 +        xor     %eax,%eax
    2.65 +        xor     %ecx,%ecx
    2.66 +        not     %ecx
    2.67 +        mov     16+4(%esp),%esi
    2.68 +        mov     16+8(%esp),%edi
    2.69 +        repne   scasb
    2.70 +        not     %ecx
    2.71 +        dec     %ecx
    2.72 +        mov     %ecx,%edx
    2.73 +1:      mov     16+8(%esp),%edi
    2.74 +        mov     %esi,%eax
    2.75 +        mov     %edx,%ecx
    2.76 +        repe    cmpsb
    2.77 +        je      2f
    2.78 +        xchg    %eax,%esi
    2.79 +        inc     %esi
    2.80 +        cmpb    $0,-1(%eax)
    2.81 +        jne     1b
    2.82 +        xor     %eax,%eax
    2.83 +2:      pop     %edi
    2.84 +        pop     %esi
    2.85 +        pop     %edx
    2.86 +        pop     %ecx
    2.87 +        ret
    2.88 +
    2.89 +.Lstr_prefix:
    2.90 +        push    %esi
    2.91 +        push    %edi
    2.92 +        mov     8+4(%esp),%esi /* 1st arg is prefix string */
    2.93 +        mov     8+8(%esp),%edi /* 2nd arg is main string */
    2.94 +1:      lodsb
    2.95 +        test    %al,%al
    2.96 +        jz      2f
    2.97 +        scasb
    2.98 +        je      1b
    2.99 +        sbb     %eax,%eax
   2.100 +        or      $1,%al
   2.101 +        jmp     3f
   2.102 +2:      xor     %eax,%eax
   2.103 +3:      pop     %edi
   2.104 +        pop     %esi
   2.105 +        ret
   2.106 +
   2.107 +.Lstrlen:
   2.108 +        push    %ecx
   2.109 +        push    %esi
   2.110 +        push    %edi
   2.111 +        xor     %eax,%eax
   2.112 +        xor     %ecx,%ecx
   2.113 +        not     %ecx
   2.114 +        mov     12+4(%esp),%edi
   2.115 +        repne   scasb
   2.116 +        not     %ecx
   2.117 +        dec     %ecx
   2.118 +        mov     %ecx,%eax
   2.119 +        pop     %edi
   2.120 +        pop     %esi
   2.121 +        pop     %ecx
   2.122 +        ret
   2.123 +
   2.124 +.Lfind_option:
   2.125 +        push    %ebx
   2.126 +        push    4+8(%esp)
   2.127 +        push    4+8(%esp)
   2.128 +        call    .Lstrstr
   2.129 +        add     $8,%esp
   2.130 +        test    %eax,%eax
   2.131 +        jz      3f
   2.132 +        cmp     %eax,4+4(%esp)
   2.133 +        je      1f
   2.134 +        cmpb    $' ',-1(%eax)
   2.135 +        jne     2f
   2.136 +1:      mov     %eax,%ebx
   2.137 +        push    4+8(%esp)
   2.138 +        call    .Lstrlen
   2.139 +        add     $4,%esp
   2.140 +        xchg    %eax,%ebx
   2.141 +        add     %eax,%ebx
   2.142 +        cmpb    $'\0',(%ebx)
   2.143 +        je      3f
   2.144 +        cmpb    $' ',(%ebx)
   2.145 +        je      3f
   2.146 +        cmpb    $'=',(%ebx)
   2.147 +        je      3f
   2.148 +2:      xor     %eax,%eax
   2.149 +3:      pop     %ebx
   2.150 +        ret
   2.151 +
   2.152 +/* multiboot_info structure offsets. */
   2.153 +#define MB_flags   0
   2.154 +#define MB_cmdline 16
   2.155 +
   2.156 +cmdline_parse_early:
   2.157 +        pusha
   2.158 +
   2.159 +        /* Bail if there is no command line to parse. */
   2.160 +        mov     sym_phys(multiboot_ptr),%ebx
   2.161 +        mov     MB_flags(%ebx),%eax
   2.162 +        test    $4,%al
   2.163 +        jz      1f
   2.164 +        mov     MB_cmdline(%ebx),%eax
   2.165 +        test    %eax,%eax
   2.166 +        jz      1f
   2.167 +
   2.168 +        /* Check for 'no-real-mode' command-line option. */
   2.169 +        pushl   $sym_phys(.Lno_rm_opt)
   2.170 +        pushl   MB_cmdline(%ebx)
   2.171 +        call    .Lfind_option
   2.172 +        test    %eax,%eax
   2.173 +        setnz   bootsym_phys(skip_realmode)
   2.174 +
   2.175 +        /* Check for 'vga=' command-line option. */
   2.176 +        movl    $sym_phys(.Lvga_opt),4(%esp)
   2.177 +        call    .Lfind_option
   2.178 +        add     $8,%esp
   2.179 +        test    %eax,%eax
   2.180 +        jz      1f
   2.181 +        cmpb    $'=',3(%eax)
   2.182 +        jne     1f
   2.183 +        add     $4,%eax
   2.184 +
   2.185 +        /* Found the 'vga=' option. Default option is to display vga menu. */
   2.186 +        movw    $ASK_VGA,bootsym_phys(boot_vid_mode)
   2.187 +
   2.188 +        /* Check for 'vga=text-80x<rows>. */
   2.189 +        mov     %eax,%ebx
   2.190 +        push    %ebx
   2.191 +        pushl   $sym_phys(.Lvga_text80)
   2.192 +        call    .Lstr_prefix
   2.193 +        add     $8,%esp
   2.194 +        test    %eax,%eax
   2.195 +        jnz     3f
   2.196 +
   2.197 +        /* We have 'vga=text-80x<rows>'. */
   2.198 +        add     $8,%ebx
   2.199 +        push    %ebx
   2.200 +        call    .Latoi
   2.201 +        add     $4,%esp
   2.202 +        mov     %ax,%bx
   2.203 +        lea     sym_phys(.Lvga_text_modes),%esi
   2.204 +2:      lodsw
   2.205 +        test    %ax,%ax
   2.206 +        jz      1f
   2.207 +        cmp     %ax,%bx
   2.208 +        lodsw
   2.209 +        jne     2b
   2.210 +        mov     %ax,bootsym_phys(boot_vid_mode)
   2.211 +        jmp     1f
   2.212 +
   2.213 +        /* Check for 'vga=gfx-<width>x<height>x<depth>'. */
   2.214 +3:      push    %ebx
   2.215 +        pushl   $sym_phys(.Lvga_gfx)
   2.216 +        call    .Lstr_prefix
   2.217 +        add     $8,%esp
   2.218 +        test    %eax,%eax
   2.219 +        jnz     3f
   2.220 +
   2.221 +        /* We have 'vga=gfx-<width>x<height>x<depth>'. */
   2.222 +        /* skip 'gfx-' */
   2.223 +        add     $4,%ebx
   2.224 +        /* parse <width> */
   2.225 +        push    %ebx
   2.226 +        call    .Latoi
   2.227 +        pop     %esi
   2.228 +        mov     %ax,bootsym_phys(vesa_size)+0
   2.229 +        /* skip 'x' */
   2.230 +        lodsb
   2.231 +        cmpb    $'x',%al
   2.232 +        jne     1f
   2.233 +        /* parse <height> */
   2.234 +        push    %esi
   2.235 +        call    .Latoi
   2.236 +        pop     %esi
   2.237 +        mov     %ax,bootsym_phys(vesa_size)+2
   2.238 +        /* skip 'x' */
   2.239 +        lodsb
   2.240 +        cmpb    $'x',%al
   2.241 +        jne     1f
   2.242 +        /* parse <depth> */
   2.243 +        push    %esi
   2.244 +        call    .Latoi
   2.245 +        pop     %esi
   2.246 +        mov     %ax,bootsym_phys(vesa_size)+4
   2.247 +        /* commit to vesa mode */
   2.248 +        movw    $VIDEO_VESA_BY_SIZE,bootsym_phys(boot_vid_mode)
   2.249 +        jmp     1f
   2.250 +
   2.251 +        /* Check for 'vga=mode-<mode>'. */
   2.252 +3:      push    %ebx
   2.253 +        pushl   $sym_phys(.Lvga_mode)
   2.254 +        call    .Lstr_prefix
   2.255 +        add     $8,%esp
   2.256 +        test    %eax,%eax
   2.257 +        jnz     1f
   2.258 +
   2.259 +        /* We have 'vga=mode-<mode>'. */
   2.260 +        add     $5,%ebx
   2.261 +        push    %ebx
   2.262 +        call    .Latoi
   2.263 +        add     $4,%esp
   2.264 +        mov     %ax,bootsym_phys(boot_vid_mode)
   2.265 +
   2.266 +1:      popa
   2.267 +        ret
   2.268 +
   2.269 +.Lvga_text_modes: /* rows, mode_number */
   2.270 +        .word   25,VIDEO_80x25
   2.271 +        .word   50,VIDEO_80x50
   2.272 +        .word   43,VIDEO_80x43
   2.273 +        .word   28,VIDEO_80x28
   2.274 +        .word   30,VIDEO_80x30
   2.275 +        .word   34,VIDEO_80x34
   2.276 +        .word   60,VIDEO_80x60
   2.277 +        .word   0
   2.278 +
   2.279 +.Lvga_opt:
   2.280 +        .asciz  "vga"
   2.281 +.Lvga_text80:
   2.282 +        .asciz  "text-80x"
   2.283 +.Lvga_gfx:
   2.284 +        .asciz  "gfx-"
   2.285 +.Lvga_mode:
   2.286 +        .asciz  "mode-"
   2.287 +.Lno_rm_opt:
   2.288 +        .asciz  "no-real-mode"
     3.1 --- a/xen/arch/x86/boot/head.S	Fri Jun 08 19:22:08 2007 +0100
     3.2 +++ b/xen/arch/x86/boot/head.S	Sun Jun 10 15:58:08 2007 +0100
     3.3 @@ -73,6 +73,7 @@ gdt_boot_descr:
     3.4          mov     $BOOT_DS,%ecx
     3.5          mov     %ecx,%ds
     3.6          mov     %ecx,%es
     3.7 +        mov     %ecx,%ss
     3.8  
     3.9          /* Check for Multiboot bootloader */
    3.10          cmp     $0x2BADB002,%eax
    3.11 @@ -166,9 +167,14 @@ 1:      stosl   /* low mappings cover up
    3.12          mov     $trampoline_end - trampoline_start,%ecx
    3.13          rep     movsb
    3.14  
    3.15 +        mov     $0x98000,%esp
    3.16 +        call    cmdline_parse_early
    3.17 +
    3.18          /* Jump into the relocated trampoline. */
    3.19          jmp     $BOOT_CS32,$bootsym_phys(trampoline_boot_cpu_entry)
    3.20  
    3.21 +#include "cmdline.S"
    3.22 +
    3.23          .globl trampoline_start, trampoline_end
    3.24  trampoline_start:
    3.25  #include "trampoline.S"
     4.1 --- a/xen/arch/x86/boot/trampoline.S	Fri Jun 08 19:22:08 2007 +0100
     4.2 +++ b/xen/arch/x86/boot/trampoline.S	Sun Jun 10 15:58:08 2007 +0100
     4.3 @@ -6,7 +6,6 @@
     4.4  
     4.5          .globl trampoline_realmode_entry
     4.6  trampoline_realmode_entry:
     4.7 -        nop                               # We use this byte as a progress flag
     4.8          movb    $0xA5,bootsym(trampoline_cpu_started)
     4.9          cld
    4.10          cli
    4.11 @@ -117,6 +116,9 @@ high_start:
    4.12  
    4.13          .code32
    4.14  trampoline_boot_cpu_entry:
    4.15 +        cmpb    $0,bootsym_phys(skip_realmode)
    4.16 +        jnz     .Lskip_realmode
    4.17 +
    4.18          /* Load pseudo-real-mode segments. */
    4.19          mov     $BOOT_PSEUDORM_DS,%eax
    4.20          mov     %eax,%ds
    4.21 @@ -148,8 +150,10 @@ 1:      mov     $(BOOT_TRAMPOLINE>>4),%a
    4.22          /*
    4.23           * Do real-mode work:
    4.24           *  1. Get memory map.
    4.25 +         *  2. Set video mode.
    4.26           */
    4.27          call    get_memory_map
    4.28 +        call    video
    4.29  
    4.30          /* Disable irqs before returning to protected mode. */
    4.31          cli
    4.32 @@ -170,12 +174,17 @@ 1:      mov     $BOOT_DS,%eax
    4.33          mov     %eax,%gs
    4.34          mov     %eax,%ss
    4.35  
    4.36 +.Lskip_realmode:
    4.37          /* EBX == 0 indicates we are the BP (Boot Processor). */
    4.38          xor     %ebx,%ebx
    4.39  
    4.40          /* Jump to the common bootstrap entry point. */
    4.41          jmp     trampoline_protmode_entry
    4.42  
    4.43 +skip_realmode:
    4.44 +        .byte   0
    4.45 +
    4.46  rm_idt: .word   256*4-1, 0, 0
    4.47  
    4.48  #include "mem.S"
    4.49 +#include "video.S"
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen/arch/x86/boot/video.S	Sun Jun 10 15:58:08 2007 +0100
     5.3 @@ -0,0 +1,994 @@
     5.4 +/******************************************************************************
     5.5 + * video.S
     5.6 + *
     5.7 + * Display adapter & video mode setup, version 2.13 (14-May-99)
     5.8 + *
     5.9 + * Copyright (C) 1995 -- 1998 Martin Mares <mj@ucw.cz>
    5.10 + * Based on the original setup.S code (C) Linus Torvalds and Mats Anderson
    5.11 + *
    5.12 + * Rewritten to use GNU 'as' by Chris Noe <stiker@northlink.com> May 1999
    5.13 + *
    5.14 + * Updated and ported for Xen by Keir Fraser <keir@xensource.com> June 2007
    5.15 + */
    5.16 +
    5.17 +        .code16
    5.18 +
    5.19 +#include "video.h"
    5.20 +
    5.21 +#define modelist (0x2000)
    5.22 +
    5.23 +/* Retrieve Extended Display Identification Data. */
    5.24 +#define CONFIG_FIRMWARE_EDID
    5.25 +
    5.26 +/* Force 400 scan lines for standard modes (hack to fix bad BIOS behaviour */
    5.27 +#undef CONFIG_VIDEO_400_HACK
    5.28 +
    5.29 +/* Positions of various video parameters passed to the kernel */
    5.30 +/* (see also include/linux/tty.h) */
    5.31 +#define PARAM_CURSOR_POS        0x00
    5.32 +#define PARAM_VIDEO_MODE        0x02
    5.33 +#define PARAM_VIDEO_COLS        0x03
    5.34 +#define PARAM_VIDEO_LINES       0x04
    5.35 +#define PARAM_HAVE_VGA          0x05
    5.36 +#define PARAM_FONT_POINTS       0x06
    5.37 +#define PARAM_CAPABILITIES      0x08
    5.38 +#define PARAM_LFB_LINELENGTH    0x0c
    5.39 +#define PARAM_LFB_WIDTH         0x0e
    5.40 +#define PARAM_LFB_HEIGHT        0x10
    5.41 +#define PARAM_LFB_DEPTH         0x12
    5.42 +#define PARAM_LFB_BASE          0x14
    5.43 +#define PARAM_LFB_SIZE          0x18
    5.44 +#define PARAM_LFB_COLORS        0x1c
    5.45 +#define PARAM_VESAPM_SEG        0x24
    5.46 +#define PARAM_VESAPM_OFF        0x26
    5.47 +#define _param(param) bootsym(boot_vid_info)+(param)
    5.48 +
    5.49 +video:  xorw    %ax, %ax
    5.50 +        movw    %ax, %gs        # GS is zero
    5.51 +        cld
    5.52 +        call    basic_detect    # Basic adapter type testing (EGA/VGA/MDA/CGA)
    5.53 +        cmpb    $0,_param(PARAM_HAVE_VGA)
    5.54 +        je      1f                # Bail if there's no VGA
    5.55 +        movw    bootsym(boot_vid_mode), %ax     # User selected video mode
    5.56 +        cmpw    $ASK_VGA, %ax                   # Bring up the menu
    5.57 +        jz      vid2
    5.58 +
    5.59 +        call    mode_set                        # Set the mode
    5.60 +        jc      vid1
    5.61 +
    5.62 +        leaw    bootsym(badmdt), %si            # Invalid mode ID
    5.63 +        call    prtstr
    5.64 +vid2:   call    mode_menu
    5.65 +vid1:   call    store_edid
    5.66 +        call    mode_params                     # Store mode parameters
    5.67 +1:      ret
    5.68 +
    5.69 +# Detect if we have CGA, MDA, EGA or VGA and pass it to the kernel.
    5.70 +basic_detect:
    5.71 +        movb    $0, _param(PARAM_HAVE_VGA)
    5.72 +        movb    $0x12, %ah                      # Check EGA/VGA
    5.73 +        movb    $0x10, %bl
    5.74 +        int     $0x10
    5.75 +        cmpb    $0x10, %bl                      # No, it's a CGA/MDA/HGA card.
    5.76 +        je      basret
    5.77 +        movw    $0x1a00, %ax                    # Check EGA or VGA?
    5.78 +        int     $0x10
    5.79 +        cmpb    $0x1a, %al                      # 1a means VGA...
    5.80 +        jne     basret                          # anything else is EGA.
    5.81 +        incb    _param(PARAM_HAVE_VGA)          # We've detected a VGA
    5.82 +basret: ret
    5.83 +
    5.84 +# Store the video mode parameters for later usage by the kernel.
    5.85 +# This is done by asking the BIOS except for the rows/columns
    5.86 +# parameters in the default 80x25 mode -- these are set directly,
    5.87 +# because some very obscure BIOSes supply insane values.
    5.88 +mode_params:
    5.89 +        cmpb    $0, bootsym(graphic_mode)
    5.90 +        jnz     mopar_gr
    5.91 +        movb    $0x03, %ah                      # Read cursor position
    5.92 +        xorb    %bh, %bh
    5.93 +        int     $0x10
    5.94 +        movw    %dx, _param(PARAM_CURSOR_POS)
    5.95 +        movb    $0x0f, %ah                      # Read page/mode/width
    5.96 +        int     $0x10
    5.97 +        movw    %ax, _param(PARAM_VIDEO_MODE)   # Video mode and screen width
    5.98 +        movw    %gs:(0x485), %ax                # Font size
    5.99 +        movw    %ax, _param(PARAM_FONT_POINTS)  # (valid only on EGA/VGA)
   5.100 +        movw    bootsym(force_size), %ax        # Forced size?
   5.101 +        orw     %ax, %ax
   5.102 +        jz      mopar1
   5.103 +
   5.104 +        movb    %ah, _param(PARAM_VIDEO_COLS)
   5.105 +        movb    %al, _param(PARAM_VIDEO_LINES)
   5.106 +        ret
   5.107 +
   5.108 +mopar1: movb    %gs:(0x484), %al                # On EGA/VGA, use the EGA+ BIOS
   5.109 +        incb    %al                             # location of max lines.
   5.110 +mopar2: movb    %al, _param(PARAM_VIDEO_LINES)
   5.111 +        ret
   5.112 +
   5.113 +# Fetching of VESA frame buffer parameters
   5.114 +mopar_gr:
   5.115 +        leaw    modelist+1024, %di
   5.116 +        movb    $0x23, _param(PARAM_HAVE_VGA)
   5.117 +        movw    16(%di), %ax
   5.118 +        movw    %ax, _param(PARAM_LFB_LINELENGTH)
   5.119 +        movw    18(%di), %ax
   5.120 +        movw    %ax, _param(PARAM_LFB_WIDTH)
   5.121 +        movw    20(%di), %ax
   5.122 +        movw    %ax, _param(PARAM_LFB_HEIGHT)
   5.123 +        movb    25(%di), %al
   5.124 +        movb    $0, %ah
   5.125 +        movw    %ax, _param(PARAM_LFB_DEPTH)
   5.126 +        movl    40(%di), %eax
   5.127 +        movl    %eax, _param(PARAM_LFB_BASE)
   5.128 +        movl    31(%di), %eax
   5.129 +        movl    %eax, _param(PARAM_LFB_COLORS)
   5.130 +        movl    35(%di), %eax
   5.131 +        movl    %eax, _param(PARAM_LFB_COLORS+4)
   5.132 +
   5.133 +# get video mem size
   5.134 +        leaw    modelist+1024, %di
   5.135 +        movw    $0x4f00, %ax
   5.136 +        int     $0x10
   5.137 +        xorl    %eax, %eax
   5.138 +        movw    18(%di), %ax
   5.139 +        movl    %eax, _param(PARAM_LFB_SIZE)
   5.140 +
   5.141 +# store mode capabilities
   5.142 +        movl    10(%di), %eax
   5.143 +        movl    %eax, _param(PARAM_CAPABILITIES)
   5.144 +
   5.145 +# switching the DAC to 8-bit is for <= 8 bpp only
   5.146 +        movw    _param(PARAM_LFB_DEPTH), %ax
   5.147 +        cmpw    $8, %ax
   5.148 +        jg      dac_done
   5.149 +
   5.150 +# get DAC switching capability
   5.151 +        xorl    %eax, %eax
   5.152 +        movb    10(%di), %al
   5.153 +        testb   $1, %al
   5.154 +        jz      dac_set
   5.155 +
   5.156 +# attempt to switch DAC to 8-bit
   5.157 +        movw    $0x4f08, %ax
   5.158 +        movw    $0x0800, %bx
   5.159 +        int     $0x10
   5.160 +        cmpw    $0x004f, %ax
   5.161 +        jne     dac_set
   5.162 +        movb    %bh, bootsym(dac_size)          # store actual DAC size
   5.163 +
   5.164 +dac_set:
   5.165 +# set color size to DAC size
   5.166 +        movb    bootsym(dac_size), %al
   5.167 +        movb    %al, _param(PARAM_LFB_COLORS+0)
   5.168 +        movb    %al, _param(PARAM_LFB_COLORS+2)
   5.169 +        movb    %al, _param(PARAM_LFB_COLORS+4)
   5.170 +        movb    %al, _param(PARAM_LFB_COLORS+6)
   5.171 +
   5.172 +# set color offsets to 0
   5.173 +        movb    $0, _param(PARAM_LFB_COLORS+1)
   5.174 +        movb    $0, _param(PARAM_LFB_COLORS+3)
   5.175 +        movb    $0, _param(PARAM_LFB_COLORS+5)
   5.176 +        movb    $0, _param(PARAM_LFB_COLORS+7)
   5.177 +
   5.178 +dac_done:
   5.179 +# get protected mode interface informations
   5.180 +        movw    $0x4f0a, %ax
   5.181 +        xorw    %bx, %bx
   5.182 +        xorw    %di, %di
   5.183 +        int     $0x10
   5.184 +        cmp     $0x004f, %ax
   5.185 +        jnz     no_pm
   5.186 +
   5.187 +        movw    %es, _param(PARAM_VESAPM_SEG)
   5.188 +        movw    %di, _param(PARAM_VESAPM_OFF)
   5.189 +no_pm:  ret
   5.190 +
   5.191 +# The video mode menu
   5.192 +mode_menu:
   5.193 +        leaw    bootsym(keymsg), %si    # "Return/Space/Timeout" message
   5.194 +        call    prtstr
   5.195 +        call    flush
   5.196 +nokey:  call    getkt
   5.197 +
   5.198 +        cmpb    $0x0d, %al              # ENTER ?
   5.199 +        je      listm                   # yes - manual mode selection
   5.200 +
   5.201 +        cmpb    $0x20, %al              # SPACE ?
   5.202 +        je      defmd1                  # no - repeat
   5.203 +
   5.204 +        call    beep
   5.205 +        jmp     nokey
   5.206 +
   5.207 +defmd1: ret                             # No mode chosen? Default 80x25
   5.208 +
   5.209 +listm:  call    mode_table              # List mode table
   5.210 +listm0: leaw    bootsym(name_bann), %si # Print adapter name
   5.211 +        call    prtstr
   5.212 +        movw    bootsym(card_name), %si
   5.213 +        orw     %si, %si
   5.214 +        jnz     an2
   5.215 +
   5.216 +        leaw    bootsym(vga_name), %si
   5.217 +        jmp     an1
   5.218 +
   5.219 +an2:    call    prtstr
   5.220 +        leaw    bootsym(svga_name), %si
   5.221 +an1:    call    prtstr
   5.222 +        leaw    bootsym(listhdr), %si   # Table header
   5.223 +        call    prtstr
   5.224 +        movb    $0x30, %dl              # DL holds mode number
   5.225 +        leaw    modelist, %si
   5.226 +lm1:    cmpw    $ASK_VGA, (%si)         # End?
   5.227 +        jz      lm2
   5.228 +
   5.229 +        movb    %dl, %al                # Menu selection number
   5.230 +        call    prtchr
   5.231 +        call    prtsp2
   5.232 +        lodsw
   5.233 +        call    prthw                   # Mode ID
   5.234 +        call    prtsp2
   5.235 +        lodsw
   5.236 +        call    prtdec                  # Width
   5.237 +        movb    $0x78, %al              # the letter 'x'
   5.238 +        call    prtchr
   5.239 +        lodsw
   5.240 +        call    prtdec                  # Height
   5.241 +        testb   $0xff,(%si)
   5.242 +        jnz     1f
   5.243 +        push    %si
   5.244 +        leaw    bootsym(textmode), %si
   5.245 +        call    prtstr
   5.246 +        pop     %si
   5.247 +        lodsw
   5.248 +        jmp     2f
   5.249 +1:      movb    $0x78, %al              # the letter 'x'
   5.250 +        call    prtchr
   5.251 +        lodsw
   5.252 +        call    prtdec                  # Depth
   5.253 +2:      movb    $0x0d, %al              # New line
   5.254 +        call    prtchr
   5.255 +        movb    $0x0a, %al
   5.256 +        call    prtchr
   5.257 +        incb    %dl                     # Next character
   5.258 +
   5.259 +        cmpb    $'z'+1, %dl
   5.260 +        jnz     skip_bail
   5.261 +        leaw    bootsym(menu_bail_msg), %si
   5.262 +        call    prtstr
   5.263 +        jmp     lm2
   5.264 +
   5.265 +skip_bail:
   5.266 +        cmpb    $'i', %dl
   5.267 +        jnz     skip_pause
   5.268 +        push    %si
   5.269 +        push    %dx
   5.270 +        leaw    bootsym(menu_more_msg), %si  # '<press space>'
   5.271 +        call    prtstr
   5.272 +        call    flush
   5.273 +1:      call    getkey
   5.274 +        cmpb    $0x20, %al              # SPACE ?
   5.275 +        jne     1b                      # yes - manual mode selection
   5.276 +        leaw    bootsym(crlft), %si
   5.277 +        call    prtstr
   5.278 +        pop     %dx
   5.279 +        pop     %si
   5.280 +
   5.281 +skip_pause:
   5.282 +        cmpb    $'9'+1, %dl
   5.283 +        jnz     lm1
   5.284 +        movb    $'a', %dl
   5.285 +        jmp     lm1
   5.286 +
   5.287 +lm2:    leaw    bootsym(prompt), %si    # Mode prompt
   5.288 +        call    prtstr
   5.289 +        leaw    bootsym(edit_buf), %di  # Editor buffer
   5.290 +lm3:    call    getkey
   5.291 +        cmpb    $0x0d, %al              # Enter?
   5.292 +        jz      lment
   5.293 +
   5.294 +        cmpb    $0x08, %al              # Backspace?
   5.295 +        jz      lmbs
   5.296 +
   5.297 +        cmpb    $0x20, %al              # Printable?
   5.298 +        jc      lm3
   5.299 +
   5.300 +        cmpw    $bootsym(edit_buf)+4, %di  # Enough space?
   5.301 +        jz      lm3
   5.302 +
   5.303 +        stosb
   5.304 +        call    prtchr
   5.305 +        jmp     lm3
   5.306 +
   5.307 +lmbs:   cmpw    $bootsym(edit_buf), %di # Backspace
   5.308 +        jz      lm3
   5.309 +
   5.310 +        decw    %di
   5.311 +        movb    $0x08, %al
   5.312 +        call    prtchr
   5.313 +        call    prtspc
   5.314 +        movb    $0x08, %al
   5.315 +        call    prtchr
   5.316 +        jmp     lm3
   5.317 +        
   5.318 +lment:  movb    $0, (%di)
   5.319 +        leaw    bootsym(crlft), %si
   5.320 +        call    prtstr
   5.321 +        leaw    bootsym(edit_buf), %si
   5.322 +        cmpb    $0, (%si)               # Empty string = default mode
   5.323 +        jz      lmdef
   5.324 +
   5.325 +        cmpb    $0, 1(%si)              # One character = menu selection
   5.326 +        jz      mnusel
   5.327 +
   5.328 +        cmpw    $0x656d, (%si)          # 'me'
   5.329 +        jnz     lmhx
   5.330 +        cmpw    $0x756e, 2(%si)         # 'nu'
   5.331 +        jnz     lmhx
   5.332 +        jmp     listm
   5.333 +
   5.334 +lmhx:   xorw    %bx, %bx                # Else => mode ID in hex
   5.335 +lmhex:  lodsb
   5.336 +        orb     %al, %al
   5.337 +        jz      lmuse1
   5.338 +
   5.339 +        subb    $0x30, %al
   5.340 +        jc      lmbad
   5.341 +
   5.342 +        cmpb    $10, %al
   5.343 +        jc      lmhx1
   5.344 +
   5.345 +        subb    $7, %al
   5.346 +        andb    $0xdf, %al
   5.347 +        cmpb    $10, %al
   5.348 +        jc      lmbad
   5.349 +
   5.350 +        cmpb    $16, %al
   5.351 +        jnc     lmbad
   5.352 +
   5.353 +lmhx1:  shlw    $4, %bx
   5.354 +        orb     %al, %bl
   5.355 +        jmp     lmhex
   5.356 +
   5.357 +lmuse1: movw    %bx, %ax
   5.358 +        jmp     lmuse
   5.359 +
   5.360 +mnusel: lodsb                           # Menu selection
   5.361 +        xorb    %ah, %ah
   5.362 +        subb    $0x30, %al
   5.363 +        jc      lmbad
   5.364 +
   5.365 +        cmpb    $10, %al
   5.366 +        jc      lmuse
   5.367 +        
   5.368 +        cmpb    $0x61-0x30, %al
   5.369 +        jc      lmbad
   5.370 +        
   5.371 +        subb    $0x61-0x30-10, %al
   5.372 +        cmpb    $36, %al
   5.373 +        jnc     lmbad
   5.374 +
   5.375 +lmuse:  call    mode_set
   5.376 +        jc      lmdef
   5.377 +
   5.378 +lmbad:  leaw    bootsym(unknt), %si
   5.379 +        call    prtstr
   5.380 +        jmp     mode_menu
   5.381 +lmdef:  ret
   5.382 +
   5.383 +_setrec:    jmp setrec                  # Ugly...
   5.384 +_set_80x25: jmp set_80x25
   5.385 +
   5.386 +# Setting of user mode (AX=mode ID) => CF=success
   5.387 +mode_set:
   5.388 +        movw    %ax, bootsym(boot_vid_mode)
   5.389 +        movw    %ax, %bx
   5.390 +
   5.391 +        cmpw    $VIDEO_VESA_BY_SIZE, %ax
   5.392 +        je      setvesabysize
   5.393 +
   5.394 +        testb   $VIDEO_RECALC>>8, %ah
   5.395 +        jnz     _setrec
   5.396 +
   5.397 +        cmpb    $VIDEO_FIRST_SPECIAL>>8, %ah
   5.398 +        jz      setspc
   5.399 +
   5.400 +        cmpb    $VIDEO_FIRST_VESA>>8, %ah
   5.401 +        jnc     check_vesa
   5.402 +
   5.403 +        orb     %ah, %ah
   5.404 +        jnz     setbad
   5.405 +
   5.406 +        jmp     setmenu
   5.407 +
   5.408 +setbad: clc
   5.409 +        ret
   5.410 +
   5.411 +setspc: xorb    %bh, %bh                # Set special mode
   5.412 +        cmpb    $VIDEO_LAST_SPECIAL-VIDEO_FIRST_SPECIAL, %bl
   5.413 +        jnc     setbad
   5.414 +        
   5.415 +        addw    %bx, %bx
   5.416 +        jmp     *bootsym(spec_inits)(%bx)
   5.417 +
   5.418 +setmenu:
   5.419 +        orb     %al, %al                # 80x25 is an exception
   5.420 +        jz      _set_80x25
   5.421 +        
   5.422 +        pushw   %bx                     # Set mode chosen from menu
   5.423 +        call    mode_table              # Build the mode table
   5.424 +        popw    %ax
   5.425 +        shlw    $3, %ax
   5.426 +        addw    %ax, %si
   5.427 +        cmpw    %di, %si
   5.428 +        jnc     setbad
   5.429 +        
   5.430 +        movw    (%si), %ax              # Fetch mode ID
   5.431 +        jmp     mode_set
   5.432 +
   5.433 +check_vesa:
   5.434 +#ifdef CONFIG_FIRMWARE_EDID
   5.435 +        leaw    modelist+1024, %di
   5.436 +        movw    $0x4f00, %ax
   5.437 +        int     $0x10
   5.438 +        cmpw    $0x004f, %ax
   5.439 +        jnz     setbad
   5.440 +
   5.441 +        movw    4(%di), %ax
   5.442 +        movw    %ax, bootsym(vbe_version)
   5.443 +#endif
   5.444 +        leaw    modelist+1024, %di
   5.445 +        subb    $VIDEO_FIRST_VESA>>8, %bh
   5.446 +        movw    %bx, %cx                # Get mode information structure
   5.447 +        movw    $0x4f01, %ax
   5.448 +        int     $0x10
   5.449 +        addb    $VIDEO_FIRST_VESA>>8, %bh
   5.450 +        cmpw    $0x004f, %ax
   5.451 +        jnz     setbad
   5.452 +
   5.453 +        movb    (%di), %al              # Check capabilities.
   5.454 +        andb    $0x99, %al
   5.455 +        cmpb    $0x99, %al
   5.456 +        jnz     _setbad                 # Doh! No linear frame buffer.
   5.457 +
   5.458 +        subb    $VIDEO_FIRST_VESA>>8, %bh
   5.459 +        orw     $0x4000, %bx            # Use linear frame buffer
   5.460 +        movw    $0x4f02, %ax            # VESA BIOS mode set call
   5.461 +        int     $0x10
   5.462 +        cmpw    $0x004f, %ax            # AL=4f if implemented
   5.463 +        jnz     _setbad                 # AH=0 if OK
   5.464 +
   5.465 +        movb    $1, bootsym(graphic_mode)  # flag graphic mode
   5.466 +        stc
   5.467 +        ret
   5.468 +
   5.469 +_setbad: jmp    setbad                  # Ugly...
   5.470 +
   5.471 +# Recalculate vertical display end registers -- this fixes various
   5.472 +# inconsistencies of extended modes on many adapters. Called when
   5.473 +# the VIDEO_RECALC flag is set in the mode ID.
   5.474 +
   5.475 +setrec: subb    $VIDEO_RECALC>>8, %ah   # Set the base mode
   5.476 +        call    mode_set
   5.477 +        jnc     rct3
   5.478 +
   5.479 +        movw    %gs:(0x485), %ax        # Font size in pixels
   5.480 +        movb    %gs:(0x484), %bl        # Number of rows
   5.481 +        incb    %bl
   5.482 +        mulb    %bl                     # Number of visible
   5.483 +        decw    %ax                     # scan lines - 1
   5.484 +        movw    $0x3d4, %dx
   5.485 +        movw    %ax, %bx
   5.486 +        movb    $0x12, %al              # Lower 8 bits
   5.487 +        movb    %bl, %ah
   5.488 +        outw    %ax, %dx
   5.489 +        movb    $0x07, %al              # Bits 8 and 9 in the overflow register
   5.490 +        call    inidx
   5.491 +        xchgb   %al, %ah
   5.492 +        andb    $0xbd, %ah
   5.493 +        shrb    %bh
   5.494 +        jnc     rct1
   5.495 +        orb     $0x02, %ah
   5.496 +rct1:   shrb    %bh
   5.497 +        jnc     rct2
   5.498 +        orb     $0x40, %ah
   5.499 +rct2:   movb    $0x07, %al
   5.500 +        outw    %ax, %dx
   5.501 +        stc
   5.502 +rct3:   ret
   5.503 +
   5.504 +inidx:  outb    %al, %dx                # Read from indexed VGA register
   5.505 +        incw    %dx                    # AL=index, DX=index reg port -> AL=data
   5.506 +        inb     %dx, %al
   5.507 +        decw    %dx
   5.508 +        ret
   5.509 +
   5.510 +setvesabysize:
   5.511 +        call    mode_table
   5.512 +        leaw    modelist,%si
   5.513 +1:      add     $8,%si
   5.514 +        cmpw    $ASK_VGA,-8(%si)        # End?
   5.515 +        je      _setbad
   5.516 +        movw    -6(%si),%ax
   5.517 +        cmpw    %ax,bootsym(vesa_size)+0
   5.518 +        jne     1b
   5.519 +        movw    -4(%si),%ax
   5.520 +        cmpw    %ax,bootsym(vesa_size)+2
   5.521 +        jne     1b
   5.522 +        movw    -2(%si),%ax
   5.523 +        cmpw    %ax,bootsym(vesa_size)+4
   5.524 +        jne     1b
   5.525 +        movw    -8(%si),%ax
   5.526 +        movw    %ax,%bx
   5.527 +        movw    %ax,bootsym(boot_vid_mode)
   5.528 +        jmp     check_vesa
   5.529 +
   5.530 +# Table of routines for setting of the special modes.
   5.531 +spec_inits:
   5.532 +        .word   bootsym(set_80x25)
   5.533 +        .word   bootsym(set_8pixel)
   5.534 +        .word   bootsym(set_80x43)
   5.535 +        .word   bootsym(set_80x28)
   5.536 +        .word   bootsym(set_80x30)
   5.537 +        .word   bootsym(set_80x34)
   5.538 +        .word   bootsym(set_80x60)
   5.539 +
   5.540 +# Set the 80x25 mode. If already set, do nothing.
   5.541 +set_80x25:
   5.542 +        movw    $0x5019, bootsym(force_size)  # Override possibly broken BIOS
   5.543 +use_80x25:
   5.544 +        movw    $0x1202, %ax            # Force 400 scan lines
   5.545 +        movb    $0x30, %bl
   5.546 +        int     $0x10
   5.547 +        movw    $0x0003, %ax            # Mode 3
   5.548 +        int     $0x10
   5.549 +        stc
   5.550 +        ret
   5.551 +
   5.552 +# Set the 80x50/80x43 8-pixel mode. Simple BIOS calls.
   5.553 +set_8pixel:
   5.554 +        call    use_80x25               # The base is 80x25
   5.555 +set_8pt:
   5.556 +        movw    $0x1112, %ax            # Use 8x8 font
   5.557 +        xorb    %bl, %bl
   5.558 +        int     $0x10
   5.559 +        movw    $0x1200, %ax            # Use alternate print screen
   5.560 +        movb    $0x20, %bl
   5.561 +        int     $0x10
   5.562 +        movw    $0x1201, %ax            # Turn off cursor emulation
   5.563 +        movb    $0x34, %bl
   5.564 +        int     $0x10
   5.565 +        movb    $0x01, %ah              # Define cursor scan lines 6-7
   5.566 +        movw    $0x0607, %cx
   5.567 +        int     $0x10
   5.568 +        stc
   5.569 +        ret
   5.570 +
   5.571 +# Set the 80x28 mode. This mode works on all VGA's, because it's a standard
   5.572 +# 80x25 mode with 14-point fonts instead of 16-point.
   5.573 +set_80x28:
   5.574 +        call    use_80x25               # The base is 80x25
   5.575 +set14:  movw    $0x1111, %ax            # Use 9x14 font
   5.576 +        xorb    %bl, %bl
   5.577 +        int     $0x10
   5.578 +        movb    $0x01, %ah              # Define cursor scan lines 11-12
   5.579 +        movw    $0x0b0c, %cx
   5.580 +        int     $0x10
   5.581 +        stc
   5.582 +        ret
   5.583 +
   5.584 +# Set the 80x43 mode. This mode is works on all VGA's.
   5.585 +# It's a 350-scanline mode with 8-pixel font.
   5.586 +set_80x43:
   5.587 +        movw    $0x1201, %ax            # Set 350 scans
   5.588 +        movb    $0x30, %bl
   5.589 +        int     $0x10
   5.590 +        movw    $0x0003, %ax            # Reset video mode
   5.591 +        int     $0x10
   5.592 +        jmp     set_8pt                 # Use 8-pixel font
   5.593 +
   5.594 +# Set the 80x30 mode (all VGA's). 480 scanlines, 16-pixel font.
   5.595 +set_80x30:
   5.596 +        call    use_80x25               # Start with real 80x25
   5.597 +        movw    $0x3cc, %dx             # Get CRTC port
   5.598 +        inb     %dx, %al
   5.599 +        movb    $0xd4, %dl
   5.600 +        rorb    %al                     # Mono or color?
   5.601 +        jc      set48a
   5.602 +
   5.603 +        movb    $0xb4, %dl
   5.604 +set48a: movw    $0x0c11, %ax            # Vertical sync end (also unlocks CR0-7)
   5.605 +        call    outidx
   5.606 +        movw    $0x0b06, %ax            # Vertical total
   5.607 +        call    outidx
   5.608 +        movw    $0x3e07, %ax            # (Vertical) overflow
   5.609 +        call    outidx
   5.610 +        movw    $0xea10, %ax            # Vertical sync start
   5.611 +        call    outidx
   5.612 +        movw    $0xdf12, %ax            # Vertical display end
   5.613 +        call    outidx
   5.614 +        movw    $0xe715, %ax            # Vertical blank start
   5.615 +        call    outidx
   5.616 +        movw    $0x0416, %ax            # Vertical blank end
   5.617 +        call    outidx
   5.618 +        pushw   %dx
   5.619 +        movb    $0xcc, %dl              # Misc output register (read)
   5.620 +        inb     %dx, %al
   5.621 +        movb    $0xc2, %dl              # (write)
   5.622 +        andb    $0x0d, %al              # Preserve clock select bits and color bit
   5.623 +        orb     $0xe2, %al              # Set correct sync polarity
   5.624 +        outb    %al, %dx
   5.625 +        popw    %dx
   5.626 +        movw    $0x501e, bootsym(force_size)
   5.627 +        stc                             # That's all.
   5.628 +        ret
   5.629 +
   5.630 +# Set the 80x34 mode (all VGA's). 480 scans, 14-pixel font.
   5.631 +set_80x34:
   5.632 +        call    set_80x30               # Set 480 scans
   5.633 +        call    set14                   # And 14-pt font
   5.634 +        movw    $0xdb12, %ax            # VGA vertical display end
   5.635 +        movw    $0x5022, bootsym(force_size)
   5.636 +setvde: call    outidx
   5.637 +        stc
   5.638 +        ret
   5.639 +
   5.640 +# Set the 80x60 mode (all VGA's). 480 scans, 8-pixel font.
   5.641 +set_80x60:
   5.642 +        call    set_80x30               # Set 480 scans
   5.643 +        call    set_8pt                 # And 8-pt font
   5.644 +        movw    $0xdf12, %ax            # VGA vertical display end
   5.645 +        movw    $0x503c, bootsym(force_size)
   5.646 +        jmp     setvde
   5.647 +
   5.648 +# Write to indexed VGA register (AL=index, AH=data, DX=index reg. port)
   5.649 +outidx: outb    %al, %dx
   5.650 +        pushw   %ax
   5.651 +        movb    %ah, %al
   5.652 +        incw    %dx
   5.653 +        outb    %al, %dx
   5.654 +        decw    %dx
   5.655 +        popw    %ax
   5.656 +        ret
   5.657 +
   5.658 +# Build the table of video modes (stored after the setup.S code at the
   5.659 +# `modelist' label. Each video mode record looks like:
   5.660 +#        .word        MODE-ID             (our special mode ID (see above))
   5.661 +#        .byte        rows                (number of rows)
   5.662 +#        .byte        columns             (number of columns)
   5.663 +# Returns address of the end of the table in DI, the end is marked
   5.664 +# with a ASK_VGA ID.
   5.665 +mode_table:
   5.666 +        movw    bootsym(mt_end), %di    # Already filled?
   5.667 +        orw     %di, %di
   5.668 +        jnz     mtab1
   5.669 +
   5.670 +        leaw    modelist, %di           # Store standard modes:
   5.671 +        movw    $VIDEO_80x25,(%di)      # The 80x25 mode (ALL)
   5.672 +        movw    $0x50,2(%di)
   5.673 +        movw    $0x19,4(%di)
   5.674 +        movw    $0x00,6(%di)
   5.675 +        addw    $8,%di
   5.676 +
   5.677 +        leaw    bootsym(vga_modes), %si # All modes for std VGA
   5.678 +        movw    $vga_modes_end-vga_modes, %cx
   5.679 +        rep     movsb
   5.680 +
   5.681 +        call    vesa_modes              # Detect VESA VGA modes
   5.682 +
   5.683 +        movw    $ASK_VGA, (%di)         # End marker
   5.684 +        movw    %di, bootsym(mt_end)
   5.685 +mtab1:  leaw    modelist, %si           # SI=mode list, DI=list end
   5.686 +ret0:   ret
   5.687 +
   5.688 +# Modes usable on all standard VGAs
   5.689 +vga_modes:
   5.690 +        .word   VIDEO_80x50, 0x50,0x32,0        # 80x50
   5.691 +        .word   VIDEO_80x43, 0x50,0x2b,0        # 80x43
   5.692 +        .word   VIDEO_80x28, 0x50,0x1c,0        # 80x28
   5.693 +        .word   VIDEO_80x30, 0x50,0x1e,0        # 80x30
   5.694 +        .word   VIDEO_80x34, 0x50,0x22,0        # 80x34
   5.695 +        .word   VIDEO_80x60, 0x50,0x3c,0        # 80x60
   5.696 +vga_modes_end:
   5.697 +
   5.698 +# Detect VESA modes.
   5.699 +vesa_modes:
   5.700 +        movw    %di, %bp                # BP=original mode table end
   5.701 +        addw    $0x200, %di             # Buffer space
   5.702 +        movw    $0x4f00, %ax            # VESA Get card info call
   5.703 +        int     $0x10
   5.704 +        movw    %bp, %di
   5.705 +        cmpw    $0x004f, %ax            # Successful?
   5.706 +        jnz     ret0
   5.707 +        
   5.708 +        cmpw    $0x4556, 0x200(%di)     # 'VE'
   5.709 +        jnz     ret0
   5.710 +        
   5.711 +        cmpw    $0x4153, 0x202(%di)     # 'SA'
   5.712 +        jnz     ret0
   5.713 +        
   5.714 +        movw    $bootsym(vesa_name), bootsym(card_name) # Set name to "VESA VGA"
   5.715 +        pushw   %gs
   5.716 +        lgsw    0x20e(%di), %si         # GS:SI=mode list
   5.717 +        movw    $128, %cx               # Iteration limit
   5.718 +vesa1:
   5.719 +        gs;     lodsw
   5.720 +        cmpw    $0xffff, %ax                        # End of the table?
   5.721 +        jz      vesar
   5.722 +        
   5.723 +        cmpw    $0x0080, %ax                        # Check validity of mode ID
   5.724 +        jc      vesa2
   5.725 +        
   5.726 +        orb     %ah, %ah        # Valid IDs: 0x0000-0x007f/0x0100-0x07ff
   5.727 +        jz      vesan                # Certain BIOSes report 0x80-0xff!
   5.728 +
   5.729 +        cmpw    $0x0800, %ax
   5.730 +        jnc     vesae
   5.731 +
   5.732 +vesa2:  pushw   %cx
   5.733 +        movw    %ax, %cx                # Get mode information structure
   5.734 +        movw    $0x4f01, %ax
   5.735 +        int     $0x10
   5.736 +        movw    %cx, %bx                # BX=mode number
   5.737 +        addb    $VIDEO_FIRST_VESA>>8, %bh
   5.738 +        popw    %cx
   5.739 +        cmpw    $0x004f, %ax
   5.740 +        jnz     vesan                   # Don't report errors (buggy BIOSES)
   5.741 +
   5.742 +        movb    (%di), %al              # Check capabilities.
   5.743 +        andb    $0x9b, %al              # LFB gfx mode in color?
   5.744 +        cmpb    $0x9b, %al
   5.745 +        jnz     vesan
   5.746 +
   5.747 +        movw    %bx, (%di)              # Store mode number
   5.748 +        movw    0x12(%di), %bx          # Width
   5.749 +        movw    %bx, 2(%di)
   5.750 +        movw    0x14(%di), %bx          # Height
   5.751 +        movw    %bx, 4(%di)
   5.752 +        xorw    %bx, %bx
   5.753 +        movb    0x19(%di), %bl          # Depth
   5.754 +        movw    %bx, 6(%di)
   5.755 +
   5.756 +        addw    $8, %di                 # The mode is valid. Store it.
   5.757 +vesan:  loop    vesa1                   # Next mode. Limit exceeded => error
   5.758 +vesae:  leaw    bootsym(vesaer), %si
   5.759 +        call    prtstr
   5.760 +        movw    %bp, %di                # Discard already found modes.
   5.761 +vesar:  popw    %gs
   5.762 +        ret
   5.763 +
   5.764 +# Read a key and return the ASCII code in al, scan code in ah
   5.765 +getkey: xorb    %ah, %ah
   5.766 +        int     $0x16
   5.767 +        ret
   5.768 +
   5.769 +# Read a key with a timeout of 30 seconds.
   5.770 +# The hardware clock is used to get the time.
   5.771 +getkt:  call    gettime
   5.772 +        addb    $30, %al                # Wait 30 seconds
   5.773 +        cmpb    $60, %al
   5.774 +        jl      lminute
   5.775 +
   5.776 +        subb    $60, %al
   5.777 +lminute:
   5.778 +        movb    %al, %cl
   5.779 +again:  movb    $0x01, %ah
   5.780 +        int     $0x16
   5.781 +        jnz     getkey                  # key pressed, so get it
   5.782 +
   5.783 +        call    gettime
   5.784 +        cmpb    %cl, %al
   5.785 +        jne     again
   5.786 +
   5.787 +        movb    $0x20, %al              # timeout, return `space'
   5.788 +        ret
   5.789 +
   5.790 +# Flush the keyboard buffer
   5.791 +flush:  movb    $0x01, %ah
   5.792 +        int     $0x16
   5.793 +        jz      empty
   5.794 +        
   5.795 +        xorb    %ah, %ah
   5.796 +        int     $0x16
   5.797 +        jmp     flush
   5.798 +
   5.799 +empty:  ret
   5.800 +
   5.801 +# Print hexadecimal number.
   5.802 +prthw:  pushw   %ax
   5.803 +        movb    %ah, %al
   5.804 +        call    prthb
   5.805 +        popw    %ax
   5.806 +prthb:  pushw   %ax
   5.807 +        shrb    $4, %al
   5.808 +        call    prthn
   5.809 +        popw    %ax
   5.810 +        andb    $0x0f, %al
   5.811 +prthn:  cmpb    $0x0a, %al
   5.812 +        jc      prth1
   5.813 +
   5.814 +        addb    $0x07, %al
   5.815 +prth1:  addb    $0x30, %al
   5.816 +        jmp     prtchr
   5.817 +
   5.818 +# Print decimal number in ax
   5.819 +prtdec: pushw   %ax
   5.820 +        pushw   %cx
   5.821 +        pushw   %dx
   5.822 +        xorw    %dx, %dx
   5.823 +        movw    $0x0a, %cx
   5.824 +        divw    %cx
   5.825 +        testw   %ax, %ax
   5.826 +        jz      skip10
   5.827 +        cmpw    $0x09, %ax
   5.828 +        jbe     lt100
   5.829 +
   5.830 +        call    prtdec
   5.831 +        jmp     skip10
   5.832 +
   5.833 +lt100:  addb    $0x30, %al
   5.834 +        call    prtchr
   5.835 +skip10: movb    %dl, %al
   5.836 +        addb    $0x30, %al
   5.837 +        call    prtchr        
   5.838 +        popw    %dx
   5.839 +        popw    %cx
   5.840 +        popw    %ax
   5.841 +        ret
   5.842 +
   5.843 +# Routine to print asciiz string at ds:si
   5.844 +prtstr:
   5.845 +        lodsb
   5.846 +        andb    %al, %al
   5.847 +        jz      fin
   5.848 +
   5.849 +        call    prtchr
   5.850 +        jmp     prtstr
   5.851 +
   5.852 +fin:    ret
   5.853 +
   5.854 +# Space printing
   5.855 +prtsp2: call    prtspc                  # Print double space
   5.856 +prtspc: movb    $0x20, %al              # Print single space (note: fall-thru)
   5.857 +
   5.858 +# Part of above routine, this one just prints ascii al
   5.859 +prtchr: pushw   %ax
   5.860 +        pushw   %cx
   5.861 +        movw    $7,%bx
   5.862 +        movw    $0x01, %cx
   5.863 +        movb    $0x0e, %ah
   5.864 +        int     $0x10
   5.865 +        popw    %cx
   5.866 +        popw    %ax
   5.867 +        ret
   5.868 +
   5.869 +beep:   movb    $0x07, %al
   5.870 +        jmp     prtchr
   5.871 +
   5.872 +# Read the cmos clock. Return the seconds in al
   5.873 +gettime:
   5.874 +        pushw   %cx
   5.875 +        movb    $0x02, %ah
   5.876 +        int     $0x1a
   5.877 +        movb    %dh, %al                # %dh contains the seconds
   5.878 +        andb    $0x0f, %al
   5.879 +        movb    %dh, %ah
   5.880 +        movb    $0x04, %cl
   5.881 +        shrb    %cl, %ah
   5.882 +        aad
   5.883 +        popw    %cx
   5.884 +        ret
   5.885 +
   5.886 +store_edid:
   5.887 +#ifdef CONFIG_FIRMWARE_EDID
   5.888 +        pushw   %es                     # just save all registers
   5.889 +        pushw   %ax
   5.890 +        pushw   %bx
   5.891 +        pushw   %cx
   5.892 +        pushw   %dx
   5.893 +        pushw   %di
   5.894 +
   5.895 +        pushw   %fs
   5.896 +        popw    %es
   5.897 +
   5.898 +        movl    $0x13131313, %eax       # memset block with 0x13
   5.899 +        movw    $32, %cx
   5.900 +        movw    $0x140, %di
   5.901 +        cld
   5.902 +        rep
   5.903 +        stosl
   5.904 +
   5.905 +        cmpw    $0x0200, bootsym(vbe_version)  # only do EDID on >= VBE2.0
   5.906 +        jl      no_edid
   5.907 +
   5.908 +        pushw   %es                     # save ES
   5.909 +        xorw    %di, %di                # Report Capability
   5.910 +        pushw   %di
   5.911 +        popw    %es                     # ES:DI must be 0:0
   5.912 +        movw    $0x4f15, %ax
   5.913 +        xorw    %bx, %bx
   5.914 +        xorw    %cx, %cx
   5.915 +        int     $0x10
   5.916 +        popw    %es                     # restore ES
   5.917 +
   5.918 +        cmpb    $0x00, %ah              # call successful
   5.919 +        jne     no_edid
   5.920 +
   5.921 +        cmpb    $0x4f, %al              # function supported
   5.922 +        jne     no_edid
   5.923 +
   5.924 +        movw    $0x4f15, %ax            # do VBE/DDC
   5.925 +        movw    $0x01, %bx
   5.926 +        movw    $0x00, %cx
   5.927 +        movw    $0x00, %dx
   5.928 +        movw    $0x140, %di
   5.929 +        int     $0x10
   5.930 +
   5.931 +no_edid:
   5.932 +        popw    %di                     # restore all registers
   5.933 +        popw    %dx
   5.934 +        popw    %cx
   5.935 +        popw    %bx
   5.936 +        popw    %ax
   5.937 +        popw    %es
   5.938 +#endif
   5.939 +        ret
   5.940 +
   5.941 +mt_end:         .word   0       # End of video mode table if built
   5.942 +edit_buf:       .space  6       # Line editor buffer
   5.943 +card_name:      .word   0       # Pointer to adapter name
   5.944 +graphic_mode:   .byte   0       # Graphic mode with a linear frame buffer
   5.945 +dac_size:       .byte   6       # DAC bit depth
   5.946 +vbe_version:    .word   0       # VBE bios version
   5.947 +
   5.948 +# Status messages
   5.949 +keymsg:         .ascii  "Press <RETURN> to see video modes available,"
   5.950 +                .byte   0x0d, 0x0a
   5.951 +                .ascii  "<SPACE> to continue or wait 30 secs"
   5.952 +                .byte   0x0d, 0x0a, 0
   5.953 +
   5.954 +listhdr:        .byte   0x0d, 0x0a
   5.955 +                .ascii  "MODE-KEY  MODE-ID  WIDTHxHEIGHTxDEPTH"
   5.956 +
   5.957 +crlft:          .byte   0x0d, 0x0a, 0
   5.958 +
   5.959 +prompt:         .byte   0x0d, 0x0a
   5.960 +                .asciz  "Enter mode number or 'menu': "
   5.961 +
   5.962 +unknt:          .ascii  "Unknown mode ID. Try again."
   5.963 +                .byte   0x0d, 0x0a, 0
   5.964 +
   5.965 +badmdt:         .ascii  "You passed an undefined mode number."
   5.966 +                .byte   0x0d, 0x0a, 0
   5.967 +
   5.968 +vesaer:         .ascii  "Error: Scanning of VESA modes failed. Please "
   5.969 +                .ascii  "report to <mj@ucw.cz>."
   5.970 +                .byte   0x0d, 0x0a, 0
   5.971 +
   5.972 +textmode:       .asciz  " (text)"
   5.973 +menu_more_msg:  .asciz  "<press SPACE for more>"
   5.974 +menu_bail_msg:  .ascii  "<menu truncated>"
   5.975 +                .byte   0x0d, 0x0a, 0
   5.976 +
   5.977 +svga_name:      .ascii  " "
   5.978 +
   5.979 +vga_name:       .asciz  "VGA"
   5.980 +
   5.981 +vesa_name:      .asciz  "VESA"
   5.982 +
   5.983 +name_bann:      .asciz  "Video adapter: "
   5.984 +
   5.985 +force_size:     .word   0       # Use this size instead of the one in BIOS vars
   5.986 +
   5.987 +vesa_size:      .word   0,0,0   # width x depth x height
   5.988 +
   5.989 +                .globl  boot_vid_info
   5.990 +/* If we don't run at all, assume basic video mode 3 at 80x25. */
   5.991 +boot_vid_mode:  .word   VIDEO_80x25
   5.992 +boot_vid_info:  .byte   0, 0    /* orig_x, orig_y */
   5.993 +                .byte   3       /* text mode 3    */
   5.994 +                .byte   80, 25  /* 80x25          */
   5.995 +                .byte   1       /* isVGA          */
   5.996 +                .word   16      /* 8x16 font      */
   5.997 +                .fill   0x28,1,0
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen/arch/x86/boot/video.h	Sun Jun 10 15:58:08 2007 +0100
     6.3 @@ -0,0 +1,30 @@
     6.4 +#ifndef __BOOT_VIDEO_H__
     6.5 +#define __BOOT_VIDEO_H__
     6.6 +
     6.7 +/*
     6.8 + * Video modes numbered by menu position -- NOT RECOMMENDED because of lack
     6.9 + * of compatibility when extending the table. These are between 0x00 and 0xff.
    6.10 + */
    6.11 +#define VIDEO_FIRST_MENU    0x0000
    6.12 +
    6.13 +/* VESA BIOS video modes (VESA number + 0x0200) */
    6.14 +#define VIDEO_FIRST_VESA    0x0200
    6.15 +
    6.16 +/* Special video modes */
    6.17 +#define VIDEO_FIRST_SPECIAL 0x0f00
    6.18 +#define VIDEO_80x25         0x0f00
    6.19 +#define VIDEO_80x50         0x0f01
    6.20 +#define VIDEO_80x43         0x0f02
    6.21 +#define VIDEO_80x28         0x0f03
    6.22 +#define VIDEO_80x30         0x0f04
    6.23 +#define VIDEO_80x34         0x0f05
    6.24 +#define VIDEO_80x60         0x0f06
    6.25 +#define VIDEO_LAST_SPECIAL  0x0f07
    6.26 +
    6.27 +#define ASK_VGA             0xfffd
    6.28 +#define VIDEO_VESA_BY_SIZE  0xffff
    6.29 +
    6.30 +/* The "recalculate timings" flag */
    6.31 +#define VIDEO_RECALC        0x8000
    6.32 +
    6.33 +#endif /* __BOOT_VIDEO_H__ */
     7.1 --- a/xen/arch/x86/setup.c	Fri Jun 08 19:22:08 2007 +0100
     7.2 +++ b/xen/arch/x86/setup.c	Sun Jun 10 15:58:08 2007 +0100
     7.3 @@ -18,6 +18,7 @@
     7.4  #include <xen/keyhandler.h>
     7.5  #include <xen/numa.h>
     7.6  #include <xen/rcupdate.h>
     7.7 +#include <xen/vga.h>
     7.8  #include <public/version.h>
     7.9  #ifdef CONFIG_COMPAT
    7.10  #include <compat/platform.h>
    7.11 @@ -316,6 +317,69 @@ static void __init reserve_in_boot_e820(
    7.12      }
    7.13  }
    7.14  
    7.15 +struct boot_video_info {
    7.16 +    u8  orig_x;             /* 0x00 */
    7.17 +    u8  orig_y;             /* 0x01 */
    7.18 +    u8  orig_video_mode;    /* 0x02 */
    7.19 +    u8  orig_video_cols;    /* 0x03 */
    7.20 +    u8  orig_video_lines;   /* 0x04 */
    7.21 +    u8  orig_video_isVGA;   /* 0x05 */
    7.22 +    u16 orig_video_points;  /* 0x06 */
    7.23 +
    7.24 +    /* VESA graphic mode -- linear frame buffer */
    7.25 +    u32 capabilities;       /* 0x08 */
    7.26 +    u16 lfb_linelength;     /* 0x0c */
    7.27 +    u16 lfb_width;          /* 0x0e */
    7.28 +    u16 lfb_height;         /* 0x10 */
    7.29 +    u16 lfb_depth;          /* 0x12 */
    7.30 +    u32 lfb_base;           /* 0x14 */
    7.31 +    u32 lfb_size;           /* 0x18 */
    7.32 +    u8  red_size;           /* 0x1c */
    7.33 +    u8  red_pos;            /* 0x1d */
    7.34 +    u8  green_size;         /* 0x1e */
    7.35 +    u8  green_pos;          /* 0x1f */
    7.36 +    u8  blue_size;          /* 0x20 */
    7.37 +    u8  blue_pos;           /* 0x21 */
    7.38 +    u8  rsvd_size;          /* 0x22 */
    7.39 +    u8  rsvd_pos;           /* 0x23 */
    7.40 +    u16 vesapm_seg;         /* 0x24 */
    7.41 +    u16 vesapm_off;         /* 0x26 */
    7.42 +};
    7.43 +
    7.44 +static void __init parse_video_info(void)
    7.45 +{
    7.46 +    extern struct boot_video_info boot_vid_info;
    7.47 +    struct boot_video_info *bvi = &bootsym(boot_vid_info);
    7.48 +
    7.49 +    if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
    7.50 +    {
    7.51 +        vga_console_info.video_type = XEN_VGATYPE_TEXT_MODE_3;
    7.52 +        vga_console_info.u.text_mode_3.font_height = bvi->orig_video_points;
    7.53 +        vga_console_info.u.text_mode_3.cursor_x = bvi->orig_x;
    7.54 +        vga_console_info.u.text_mode_3.cursor_y = bvi->orig_y;
    7.55 +        vga_console_info.u.text_mode_3.rows = bvi->orig_video_lines;
    7.56 +        vga_console_info.u.text_mode_3.columns = bvi->orig_video_cols;
    7.57 +    }
    7.58 +    else if ( bvi->orig_video_isVGA == 0x23 )
    7.59 +    {
    7.60 +        vga_console_info.video_type = XEN_VGATYPE_VESA_LFB;
    7.61 +        vga_console_info.u.vesa_lfb.width = bvi->lfb_width;
    7.62 +        vga_console_info.u.vesa_lfb.height = bvi->lfb_height;
    7.63 +        vga_console_info.u.vesa_lfb.bytes_per_line = bvi->lfb_linelength;
    7.64 +        vga_console_info.u.vesa_lfb.bits_per_pixel = bvi->lfb_depth;
    7.65 +        vga_console_info.u.vesa_lfb.lfb_base = bvi->lfb_base;
    7.66 +        vga_console_info.u.vesa_lfb.lfb_size = bvi->lfb_size;
    7.67 +        vga_console_info.u.vesa_lfb.red_pos = bvi->red_pos;
    7.68 +        vga_console_info.u.vesa_lfb.red_size = bvi->red_size;
    7.69 +        vga_console_info.u.vesa_lfb.green_pos = bvi->green_pos;
    7.70 +        vga_console_info.u.vesa_lfb.green_size = bvi->green_size;
    7.71 +        vga_console_info.u.vesa_lfb.blue_pos = bvi->blue_pos;
    7.72 +        vga_console_info.u.vesa_lfb.blue_size = bvi->blue_size;
    7.73 +        vga_console_info.u.vesa_lfb.rsvd_pos = bvi->rsvd_pos;
    7.74 +        vga_console_info.u.vesa_lfb.rsvd_size = bvi->rsvd_size;
    7.75 +    }
    7.76 +}
    7.77 +
    7.78  void init_done(void)
    7.79  {
    7.80      extern char __init_begin[], __init_end[];
    7.81 @@ -359,6 +423,8 @@ void __init __start_xen(multiboot_info_t
    7.82          cmdline = __va(mbi->cmdline);
    7.83      cmdline_parse(cmdline);
    7.84  
    7.85 +    parse_video_info();
    7.86 +
    7.87      set_current((struct vcpu *)0xfffff000); /* debug sanity */
    7.88      idle_vcpu[0] = current;
    7.89      set_processor_id(0); /* needed early, for smp_processor_id() */
    7.90 @@ -378,6 +444,22 @@ void __init __start_xen(multiboot_info_t
    7.91  
    7.92      printk("Command line: %s\n", cmdline);
    7.93  
    7.94 +    switch ( vga_console_info.video_type )
    7.95 +    {
    7.96 +    case XEN_VGATYPE_TEXT_MODE_3:
    7.97 +        printk("VGA is text mode %dx%d, font 8x%d\n",
    7.98 +               vga_console_info.u.text_mode_3.columns,
    7.99 +               vga_console_info.u.text_mode_3.rows,
   7.100 +               vga_console_info.u.text_mode_3.font_height);
   7.101 +        break;
   7.102 +    case XEN_VGATYPE_VESA_LFB:
   7.103 +        printk("VGA is graphics mode %dx%d, %d bpp\n",
   7.104 +               vga_console_info.u.vesa_lfb.width,
   7.105 +               vga_console_info.u.vesa_lfb.height,
   7.106 +               vga_console_info.u.vesa_lfb.bits_per_pixel);
   7.107 +        break;
   7.108 +    }
   7.109 +
   7.110      /* Check that we have at least one Multiboot module. */
   7.111      if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
   7.112          EARLY_FAIL("dom0 kernel not specified. "
     8.1 --- a/xen/drivers/video/vga.c	Fri Jun 08 19:22:08 2007 +0100
     8.2 +++ b/xen/drivers/video/vga.c	Sun Jun 10 15:58:08 2007 +0100
     8.3 @@ -17,559 +17,43 @@
     8.4  #include <asm/io.h>
     8.5  #include "font.h"
     8.6  
     8.7 -/* Some of the code below is taken from SVGAlib.  The original,
     8.8 -   unmodified copyright notice for that code is below. */
     8.9 -/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen                    */
    8.10 -/*                                                                 */
    8.11 -/* This library is free software; you can redistribute it and/or   */
    8.12 -/* modify it without any restrictions. This library is distributed */
    8.13 -/* in the hope that it will be useful, but without any warranty.   */
    8.14 -
    8.15 -/* Multi-chipset support Copyright 1993 Harm Hanemaayer */
    8.16 -/* partially copyrighted (C) 1993 by Hartmut Schirmer */
    8.17 -
    8.18 -/* VGA data register ports */
    8.19 -#define VGA_CRT_DC  	0x3D5	/* CRT Controller Data Register - color emulation */
    8.20 -#define VGA_CRT_DM  	0x3B5	/* CRT Controller Data Register - mono emulation */
    8.21 -#define VGA_ATT_R   	0x3C1	/* Attribute Controller Data Read Register */
    8.22 -#define VGA_ATT_W   	0x3C0	/* Attribute Controller Data Write Register */
    8.23 -#define VGA_GFX_D   	0x3CF	/* Graphics Controller Data Register */
    8.24 -#define VGA_SEQ_D   	0x3C5	/* Sequencer Data Register */
    8.25 -#define VGA_MIS_R   	0x3CC	/* Misc Output Read Register */
    8.26 -#define VGA_MIS_W   	0x3C2	/* Misc Output Write Register */
    8.27 -#define VGA_FTC_R	0x3CA	/* Feature Control Read Register */
    8.28 -#define VGA_IS1_RC  	0x3DA	/* Input Status Register 1 - color emulation */
    8.29 -#define VGA_IS1_RM  	0x3BA	/* Input Status Register 1 - mono emulation */
    8.30 -#define VGA_PEL_D   	0x3C9	/* PEL Data Register */
    8.31 -#define VGA_PEL_MSK 	0x3C6	/* PEL mask register */
    8.32 -
    8.33 -/* EGA-specific registers */
    8.34 -#define EGA_GFX_E0	0x3CC	/* Graphics enable processor 0 */
    8.35 -#define EGA_GFX_E1	0x3CA	/* Graphics enable processor 1 */
    8.36 -
    8.37 -/* VGA index register ports */
    8.38 -#define VGA_CRT_IC  	0x3D4	/* CRT Controller Index - color emulation */
    8.39 -#define VGA_CRT_IM  	0x3B4	/* CRT Controller Index - mono emulation */
    8.40 -#define VGA_ATT_IW  	0x3C0	/* Attribute Controller Index & Data Write Register */
    8.41 -#define VGA_GFX_I   	0x3CE	/* Graphics Controller Index */
    8.42 -#define VGA_SEQ_I   	0x3C4	/* Sequencer Index */
    8.43 -#define VGA_PEL_IW  	0x3C8	/* PEL Write Index */
    8.44 -#define VGA_PEL_IR  	0x3C7	/* PEL Read Index */
    8.45 -
    8.46 -/* standard VGA indexes max counts */
    8.47 -#define VGA_CRT_C   	0x19	/* Number of CRT Controller Registers */
    8.48 -#define VGA_ATT_C   	0x15	/* Number of Attribute Controller Registers */
    8.49 -#define VGA_GFX_C   	0x09	/* Number of Graphics Controller Registers */
    8.50 -#define VGA_SEQ_C   	0x05	/* Number of Sequencer Registers */
    8.51 -#define VGA_MIS_C   	0x01	/* Number of Misc Output Register */
    8.52 -
    8.53 -/* VGA misc register bit masks */
    8.54 -#define VGA_MIS_COLOR		0x01
    8.55 -#define VGA_MIS_ENB_MEM_ACCESS	0x02
    8.56 -#define VGA_MIS_DCLK_28322_720	0x04
    8.57 -#define VGA_MIS_ENB_PLL_LOAD	(0x04 | 0x08)
    8.58 -#define VGA_MIS_SEL_HIGH_PAGE	0x20
    8.59 -
    8.60 -/* VGA CRT controller register indices */
    8.61 -#define VGA_CRTC_H_TOTAL	0
    8.62 -#define VGA_CRTC_H_DISP		1
    8.63 -#define VGA_CRTC_H_BLANK_START	2
    8.64 -#define VGA_CRTC_H_BLANK_END	3
    8.65 -#define VGA_CRTC_H_SYNC_START	4
    8.66 -#define VGA_CRTC_H_SYNC_END	5
    8.67 -#define VGA_CRTC_V_TOTAL	6
    8.68 -#define VGA_CRTC_OVERFLOW	7
    8.69 -#define VGA_CRTC_PRESET_ROW	8
    8.70 -#define VGA_CRTC_MAX_SCAN	9
    8.71 -#define VGA_CRTC_CURSOR_START	0x0A
    8.72 -#define VGA_CRTC_CURSOR_END	0x0B
    8.73 -#define VGA_CRTC_START_HI	0x0C
    8.74 -#define VGA_CRTC_START_LO	0x0D
    8.75 -#define VGA_CRTC_CURSOR_HI	0x0E
    8.76 -#define VGA_CRTC_CURSOR_LO	0x0F
    8.77 -#define VGA_CRTC_V_SYNC_START	0x10
    8.78 -#define VGA_CRTC_V_SYNC_END	0x11
    8.79 -#define VGA_CRTC_V_DISP_END	0x12
    8.80 -#define VGA_CRTC_OFFSET		0x13
    8.81 -#define VGA_CRTC_UNDERLINE	0x14
    8.82 -#define VGA_CRTC_V_BLANK_START	0x15
    8.83 -#define VGA_CRTC_V_BLANK_END	0x16
    8.84 -#define VGA_CRTC_MODE		0x17
    8.85 -#define VGA_CRTC_LINE_COMPARE	0x18
    8.86 -#define VGA_CRTC_REGS		VGA_CRT_C
    8.87 -
    8.88 -/* VGA CRT controller bit masks */
    8.89 -#define VGA_CR11_LOCK_CR0_CR7	0x80 /* lock writes to CR0 - CR7 */
    8.90 -#define VGA_CR17_H_V_SIGNALS_ENABLED 0x80
    8.91 -
    8.92 -/* VGA attribute controller register indices */
    8.93 -#define VGA_ATC_PALETTE0	0x00
    8.94 -#define VGA_ATC_PALETTE1	0x01
    8.95 -#define VGA_ATC_PALETTE2	0x02
    8.96 -#define VGA_ATC_PALETTE3	0x03
    8.97 -#define VGA_ATC_PALETTE4	0x04
    8.98 -#define VGA_ATC_PALETTE5	0x05
    8.99 -#define VGA_ATC_PALETTE6	0x06
   8.100 -#define VGA_ATC_PALETTE7	0x07
   8.101 -#define VGA_ATC_PALETTE8	0x08
   8.102 -#define VGA_ATC_PALETTE9	0x09
   8.103 -#define VGA_ATC_PALETTEA	0x0A
   8.104 -#define VGA_ATC_PALETTEB	0x0B
   8.105 -#define VGA_ATC_PALETTEC	0x0C
   8.106 -#define VGA_ATC_PALETTED	0x0D
   8.107 -#define VGA_ATC_PALETTEE	0x0E
   8.108 -#define VGA_ATC_PALETTEF	0x0F
   8.109 -#define VGA_ATC_MODE		0x10
   8.110 -#define VGA_ATC_OVERSCAN	0x11
   8.111 -#define VGA_ATC_PLANE_ENABLE	0x12
   8.112 -#define VGA_ATC_PEL		0x13
   8.113 -#define VGA_ATC_COLOR_PAGE	0x14
   8.114 -
   8.115 -#define VGA_AR_ENABLE_DISPLAY	0x20
   8.116 -
   8.117 -/* VGA sequencer register indices */
   8.118 -#define VGA_SEQ_RESET		0x00
   8.119 -#define VGA_SEQ_CLOCK_MODE	0x01
   8.120 -#define VGA_SEQ_PLANE_WRITE	0x02
   8.121 -#define VGA_SEQ_CHARACTER_MAP	0x03
   8.122 -#define VGA_SEQ_MEMORY_MODE	0x04
   8.123 -
   8.124 -/* VGA sequencer register bit masks */
   8.125 -#define VGA_SR01_CHAR_CLK_8DOTS	0x01 /* bit 0: character clocks 8 dots wide are generated */
   8.126 -#define VGA_SR01_SCREEN_OFF	0x20 /* bit 5: Screen is off */
   8.127 -#define VGA_SR02_ALL_PLANES	0x0F /* bits 3-0: enable access to all planes */
   8.128 -#define VGA_SR04_EXT_MEM	0x02 /* bit 1: allows complete mem access to 256K */
   8.129 -#define VGA_SR04_SEQ_MODE	0x04 /* bit 2: directs system to use a sequential addressing mode */
   8.130 -#define VGA_SR04_CHN_4M		0x08 /* bit 3: selects modulo 4 addressing for CPU access to display memory */
   8.131 -
   8.132 -/* VGA graphics controller register indices */
   8.133 -#define VGA_GFX_SR_VALUE	0x00
   8.134 -#define VGA_GFX_SR_ENABLE	0x01
   8.135 -#define VGA_GFX_COMPARE_VALUE	0x02
   8.136 -#define VGA_GFX_DATA_ROTATE	0x03
   8.137 -#define VGA_GFX_PLANE_READ	0x04
   8.138 -#define VGA_GFX_MODE		0x05
   8.139 -#define VGA_GFX_MISC		0x06
   8.140 -#define VGA_GFX_COMPARE_MASK	0x07
   8.141 -#define VGA_GFX_BIT_MASK	0x08
   8.142 -
   8.143 -/* VGA graphics controller bit masks */
   8.144 -#define VGA_GR06_GRAPHICS_MODE	0x01
   8.145 -
   8.146 -/* macro for composing an 8-bit VGA register index and value
   8.147 - * into a single 16-bit quantity */
   8.148 -#define VGA_OUT16VAL(v, r)       (((v) << 8) | (r))
   8.149 -
   8.150 -#define vgabase 0         /* use in/out port-access macros  */
   8.151 -#define VGA_OUTW_WRITE    /* can use outw instead of 2xoutb */
   8.152 -
   8.153 -/*
   8.154 - * generic VGA port read/write
   8.155 - */
   8.156 - 
   8.157 -static inline uint8_t vga_io_r(uint16_t port)
   8.158 -{
   8.159 -    return inb(port);
   8.160 -}
   8.161 -
   8.162 -static inline void vga_io_w(uint16_t port, uint8_t val)
   8.163 -{
   8.164 -    outb(val, port);
   8.165 -}
   8.166 -
   8.167 -static inline void vga_io_w_fast(uint16_t port, uint8_t reg, uint8_t val)
   8.168 -{
   8.169 -    outw(VGA_OUT16VAL(val, reg), port);
   8.170 -}
   8.171 -
   8.172 -static inline uint8_t vga_mm_r(void __iomem *regbase, uint16_t port)
   8.173 -{
   8.174 -    return readb((char *)regbase + port);
   8.175 -}
   8.176 -
   8.177 -static inline void vga_mm_w(void __iomem *regbase, uint16_t port, uint8_t val)
   8.178 -{
   8.179 -    writeb(val, (char *)regbase + port);
   8.180 -}
   8.181 -
   8.182 -static inline void vga_mm_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val)
   8.183 -{
   8.184 -    writew(VGA_OUT16VAL(val, reg), (char *)regbase + port);
   8.185 -}
   8.186 -
   8.187 -static inline uint8_t vga_r(void __iomem *regbase, uint16_t port)
   8.188 -{
   8.189 -    if (regbase)
   8.190 -        return vga_mm_r(regbase, port);
   8.191 -    else
   8.192 -        return vga_io_r(port);
   8.193 -}
   8.194 -
   8.195 -static inline void vga_w(void __iomem *regbase, uint16_t port, uint8_t val)
   8.196 -{
   8.197 -    if (regbase)
   8.198 -        vga_mm_w(regbase, port, val);
   8.199 -    else
   8.200 -        vga_io_w(port, val);
   8.201 -}
   8.202 -
   8.203 -
   8.204 -static inline void vga_w_fast(void __iomem *regbase, uint16_t port, uint8_t reg, uint8_t val)
   8.205 -{
   8.206 -    if (regbase)
   8.207 -        vga_mm_w_fast(regbase, port, reg, val);
   8.208 -    else
   8.209 -        vga_io_w_fast(port, reg, val);
   8.210 -}
   8.211 -
   8.212 -
   8.213 -/*
   8.214 - * VGA CRTC register read/write
   8.215 - */
   8.216 - 
   8.217 -static inline uint8_t vga_rcrt(void __iomem *regbase, uint8_t reg)
   8.218 -{
   8.219 -    vga_w(regbase, VGA_CRT_IC, reg);
   8.220 -    return vga_r(regbase, VGA_CRT_DC);
   8.221 -}
   8.222 -
   8.223 -static inline void vga_wcrt(void __iomem *regbase, uint8_t reg, uint8_t val)
   8.224 -{
   8.225 -#ifdef VGA_OUTW_WRITE
   8.226 -    vga_w_fast(regbase, VGA_CRT_IC, reg, val);
   8.227 -#else
   8.228 -    vga_w(regbase, VGA_CRT_IC, reg);
   8.229 -    vga_w(regbase, VGA_CRT_DC, val);
   8.230 -#endif /* VGA_OUTW_WRITE */
   8.231 -}
   8.232 -
   8.233 -/*
   8.234 - * VGA sequencer register read/write
   8.235 - */
   8.236 - 
   8.237 -static inline uint8_t vga_rseq(void __iomem *regbase, uint8_t reg)
   8.238 -{
   8.239 -    vga_w(regbase, VGA_SEQ_I, reg);
   8.240 -    return vga_r(regbase, VGA_SEQ_D);
   8.241 -}
   8.242 -
   8.243 -static inline void vga_wseq(void __iomem *regbase, uint8_t reg, uint8_t val)
   8.244 -{
   8.245 -#ifdef VGA_OUTW_WRITE
   8.246 -    vga_w_fast(regbase, VGA_SEQ_I, reg, val);
   8.247 -#else
   8.248 -    vga_w(regbase, VGA_SEQ_I, reg);
   8.249 -    vga_w(regbase, VGA_SEQ_D, val);
   8.250 -#endif /* VGA_OUTW_WRITE */
   8.251 -}
   8.252 -
   8.253 -/*
   8.254 - * VGA graphics controller register read/write
   8.255 - */
   8.256 - 
   8.257 -static inline uint8_t vga_rgfx(void __iomem *regbase, uint8_t reg)
   8.258 -{
   8.259 -    vga_w(regbase, VGA_GFX_I, reg);
   8.260 -    return vga_r(regbase, VGA_GFX_D);
   8.261 -}
   8.262 -
   8.263 -static inline void vga_wgfx(void __iomem *regbase, uint8_t reg, uint8_t val)
   8.264 -{
   8.265 -#ifdef VGA_OUTW_WRITE
   8.266 -    vga_w_fast(regbase, VGA_GFX_I, reg, val);
   8.267 -#else
   8.268 -    vga_w(regbase, VGA_GFX_I, reg);
   8.269 -    vga_w(regbase, VGA_GFX_D, val);
   8.270 -#endif /* VGA_OUTW_WRITE */
   8.271 -}
   8.272 -
   8.273 -/*
   8.274 - * VGA attribute controller register read/write
   8.275 - */
   8.276 - 
   8.277 -static inline uint8_t vga_rattr(void __iomem *regbase, uint8_t reg)
   8.278 -{
   8.279 -    vga_w(regbase, VGA_ATT_IW, reg);
   8.280 -    return vga_r(regbase, VGA_ATT_R);
   8.281 -}
   8.282 -
   8.283 -static inline void vga_wattr(void __iomem *regbase, uint8_t reg, uint8_t val)
   8.284 -{
   8.285 -    vga_w(regbase, VGA_ATT_IW, reg);
   8.286 -    vga_w(regbase, VGA_ATT_W, val);
   8.287 -}
   8.288 -
   8.289 -static int __init detect_video(void *video_base)
   8.290 -{
   8.291 -    volatile u16 *p = (volatile u16 *)video_base;
   8.292 -    u16 saved1 = p[0], saved2 = p[1];
   8.293 -    int video_found = 1;
   8.294 -
   8.295 -    p[0] = 0xAA55;
   8.296 -    p[1] = 0x55AA;
   8.297 -    if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
   8.298 -        video_found = 0;
   8.299 -
   8.300 -    p[0] = 0x55AA;
   8.301 -    p[1] = 0xAA55;
   8.302 -    if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
   8.303 -        video_found = 0;
   8.304 -
   8.305 -    p[0] = saved1;
   8.306 -    p[1] = saved2;
   8.307 -
   8.308 -    return video_found;
   8.309 -}
   8.310 -
   8.311 -/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
   8.312 -static void * __init setup_vga(void)
   8.313 -{
   8.314 -    /* The following VGA state was saved from a chip in text mode 3. */
   8.315 -    static unsigned char regs[] = {
   8.316 -        /* Sequencer registers */
   8.317 -        0x03, 0x00, 0x03, 0x00, 0x02,
   8.318 -        /* CRTC registers */
   8.319 -        0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
   8.320 -        0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
   8.321 -        0xb9, 0xa3, 0xff,
   8.322 -        /* Graphic registers */
   8.323 -        0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
   8.324 -        /* Attribute registers */
   8.325 -        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
   8.326 -        0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
   8.327 -    };
   8.328 -
   8.329 -    char *video;
   8.330 -    int i, j;
   8.331 -
   8.332 -    if ( memory_is_conventional_ram(0xB8000) )
   8.333 -        goto no_vga;
   8.334 -
   8.335 -    inb(VGA_IS1_RC);
   8.336 -    outb(0x00, VGA_ATT_IW);
   8.337 -    
   8.338 -    for ( i = j = 0; i < 5;  i++ )
   8.339 -        vga_wseq(vgabase, i, regs[j++]);
   8.340 -    
   8.341 -    /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
   8.342 -    vga_wcrt(vgabase, 17, regs[5+17] & 0x7F);
   8.343 -    
   8.344 -    for ( i = 0; i < 25; i++ ) 
   8.345 -        vga_wcrt(vgabase, i, regs[j++]);
   8.346 -    
   8.347 -    for ( i = 0; i < 9;  i++ )
   8.348 -        vga_wgfx(vgabase, i, regs[j++]);
   8.349 -    
   8.350 -    inb(VGA_IS1_RC);
   8.351 -    for ( i = 0; i < 21; i++ )
   8.352 -        vga_wattr(vgabase, i, regs[j++]);
   8.353 -    
   8.354 -    inb(VGA_IS1_RC);
   8.355 -    outb(0x20, VGA_ATT_IW);
   8.356 -
   8.357 -    video = ioremap(0xB8000, 0x8000);
   8.358 -
   8.359 -    if ( !detect_video(video) )
   8.360 -    {
   8.361 -        iounmap(video);
   8.362 -        goto no_vga;
   8.363 -    }
   8.364 -
   8.365 -    return video;
   8.366 -
   8.367 - no_vga:
   8.368 -    printk("No VGA adaptor detected!\n");
   8.369 -    return NULL;
   8.370 -}
   8.371 -
   8.372 -static int __init vga_set_scanlines(unsigned scanlines)
   8.373 -{
   8.374 -    unsigned vtot, ovr, vss, vbs;
   8.375 -    uint8_t vse, vbe, misc = 0;
   8.376 -
   8.377 -    switch (scanlines) {
   8.378 -    case 43*8:
   8.379 -        vtot = 0x1bf;
   8.380 -        vss = 0x183;
   8.381 -        vse = 0x05;
   8.382 -        vbs = 0x163;
   8.383 -        vbe = 0xba;
   8.384 -        break;
   8.385 -    case 25*16:
   8.386 -    case 28*14:
   8.387 -        vtot = 0x1bf;
   8.388 -        vss = 0x19c;
   8.389 -        vse = 0x0e;
   8.390 -        vbs = 0x196;
   8.391 -        vbe = 0xb9;
   8.392 -        break;
   8.393 -    case 30*16:
   8.394 -    case 34*14:
   8.395 -        vtot = 0x20b;
   8.396 -        vss = 0x1ea;
   8.397 -        vse = 0x0c;
   8.398 -        vbs = 0x1e7;
   8.399 -        vbe = 0x04;
   8.400 -        /* Preserve clock select bits and color bit, set correct sync polarity. */
   8.401 -        misc = (inb(VGA_MIS_R) & 0x0d) | 0xe2;
   8.402 -        break;
   8.403 -    default:
   8.404 -        return -ENOSYS;
   8.405 -    }
   8.406 -
   8.407 -    ovr = vga_rcrt(vgabase, VGA_CRTC_OVERFLOW);
   8.408 -    if(vga_rcrt(vgabase, VGA_CRTC_V_DISP_END) + ((ovr & 0x02) << 7) + ((ovr & 0x40) << 3) == scanlines - 1)
   8.409 -        return 0;
   8.410 -
   8.411 -    ovr = (ovr & 0x10)
   8.412 -        | ((vtot >> 8) & 0x01)
   8.413 -        | ((vtot >> 4) & 0x20)
   8.414 -        | (((scanlines - 1) >> 7) & 0x02)
   8.415 -        | (((scanlines - 1) >> 3) & 0x40)
   8.416 -        | ((vss >> 6) & 0x04)
   8.417 -        | ((vss >> 2) & 0x80)
   8.418 -        | ((vbs >> 5) & 0x08);
   8.419 -    vse |= vga_rcrt(vgabase, VGA_CRTC_V_SYNC_END) & 0x70;
   8.420 -
   8.421 -    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse & 0x7f); /* Vertical sync end (also unlocks CR0-7) */
   8.422 -    vga_wcrt(vgabase, VGA_CRTC_V_TOTAL, (uint8_t)vtot); /* Vertical total */
   8.423 -    vga_wcrt(vgabase, VGA_CRTC_OVERFLOW, (uint8_t)ovr); /* Overflow */
   8.424 -    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_START, (uint8_t)vss); /* Vertical sync start */
   8.425 -    vga_wcrt(vgabase, VGA_CRTC_V_SYNC_END, vse | 0x80); /* Vertical sync end (also locks CR0-7) */
   8.426 -    vga_wcrt(vgabase, VGA_CRTC_V_DISP_END, (uint8_t)(scanlines - 1)); /* Vertical display end */
   8.427 -    vga_wcrt(vgabase, VGA_CRTC_V_BLANK_START, (uint8_t)vbs); /* Vertical blank start */
   8.428 -    vga_wcrt(vgabase, VGA_CRTC_V_BLANK_END, vbe); /* Vertical blank end */
   8.429 -
   8.430 -    if (misc)
   8.431 -        outb(misc, VGA_MIS_W); /* Misc output register */
   8.432 -
   8.433 -    return 0;
   8.434 -}
   8.435 -
   8.436 -#define FONT_COUNT_MAX 256
   8.437 -#define FONT_HEIGHT_MAX 32
   8.438 -#define CHAR_MAP_SIZE (FONT_COUNT_MAX * FONT_HEIGHT_MAX)
   8.439 -
   8.440 -/*
   8.441 - * We use font slot 0 because ATI cards do not honour changes to the
   8.442 - * character map select register. The fontslot parameter can be used to
   8.443 - * choose a non-default slot if the video card supports it and you wish to
   8.444 - * preserve the BIOS-initialised font data.
   8.445 - */
   8.446 -static unsigned font_slot = 0;
   8.447 -integer_param("fontslot", font_slot);
   8.448 -
   8.449 -static int __init vga_load_font(const struct font_desc *font, unsigned rows)
   8.450 -{
   8.451 -    unsigned fontheight = font ? font->height : 16;
   8.452 -    uint8_t fsr = vga_rcrt(vgabase, VGA_CRTC_MAX_SCAN); /* Font size register */
   8.453 -    int ret;
   8.454 -
   8.455 -    if (font_slot > 3 || (!font_slot && !font))
   8.456 -        return -ENOSYS;
   8.457 -
   8.458 -    if (font
   8.459 -        && (font->count > FONT_COUNT_MAX
   8.460 -            || fontheight > FONT_HEIGHT_MAX
   8.461 -            || font->width != 8))
   8.462 -        return -EINVAL;
   8.463 -
   8.464 -    ret = vga_set_scanlines(rows * fontheight);
   8.465 -    if (ret < 0)
   8.466 -        return ret;
   8.467 -
   8.468 -    if ((fsr & 0x1f) == fontheight - 1)
   8.469 -        return 0;
   8.470 -
   8.471 -    /* First, the Sequencer */
   8.472 -    vga_wseq(vgabase, VGA_SEQ_RESET, 0x1);
   8.473 -    /* CPU writes only to map 2 */
   8.474 -    vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x04);
   8.475 -    /* Sequential addressing */
   8.476 -    vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x07);
   8.477 -    /* Clear synchronous reset */
   8.478 -    vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
   8.479 -
   8.480 -    /* Now, the graphics controller, select map 2 */
   8.481 -    vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x02);
   8.482 -    /* disable odd-even addressing */
   8.483 -    vga_wgfx(vgabase, VGA_GFX_MODE, 0x00);
   8.484 -    /* map start at A000:0000 */
   8.485 -    vga_wgfx(vgabase, VGA_GFX_MISC, 0x00);
   8.486 -
   8.487 -    if ( font )
   8.488 -    {
   8.489 -        unsigned i, j;
   8.490 -        const uint8_t *data = font->data;
   8.491 -        uint8_t *map;
   8.492 -
   8.493 -        map = ioremap(0xA0000 + font_slot*2*CHAR_MAP_SIZE, CHAR_MAP_SIZE);
   8.494 -
   8.495 -        for ( i = j = 0; i < CHAR_MAP_SIZE; )
   8.496 -        {
   8.497 -            writeb(j < font->count * fontheight ? data[j++] : 0, map + i++);
   8.498 -            if ( !(j % fontheight) )
   8.499 -                while ( i & (FONT_HEIGHT_MAX - 1) )
   8.500 -                    writeb(0, map + i++);
   8.501 -        }
   8.502 -
   8.503 -        iounmap(map);
   8.504 -    }
   8.505 -
   8.506 -    /* First, the sequencer, Synchronous reset */
   8.507 -    vga_wseq(vgabase, VGA_SEQ_RESET, 0x01);
   8.508 -    /* CPU writes to maps 0 and 1 */
   8.509 -    vga_wseq(vgabase, VGA_SEQ_PLANE_WRITE, 0x03);
   8.510 -    /* odd-even addressing */
   8.511 -    vga_wseq(vgabase, VGA_SEQ_MEMORY_MODE, 0x03);
   8.512 -    /* Character Map Select: The default font is kept in slot 0. */
   8.513 -    vga_wseq(vgabase, VGA_SEQ_CHARACTER_MAP,
   8.514 -             font ? font_slot | (font_slot << 2) : 0x00);
   8.515 -    /* clear synchronous reset */
   8.516 -    vga_wseq(vgabase, VGA_SEQ_RESET, 0x03);
   8.517 -
   8.518 -    /* Now, the graphics controller, select map 0 for CPU */
   8.519 -    vga_wgfx(vgabase, VGA_GFX_PLANE_READ, 0x00);
   8.520 -    /* enable even-odd addressing */
   8.521 -    vga_wgfx(vgabase, VGA_GFX_MODE, 0x10);
   8.522 -    /* map starts at b800:0 */
   8.523 -    vga_wgfx(vgabase, VGA_GFX_MISC, 0x0e);
   8.524 -
   8.525 -    /* Font size register */
   8.526 -    fsr = (fsr & 0xe0) + (fontheight - 1);
   8.527 -    vga_wcrt(vgabase, VGA_CRTC_MAX_SCAN, fsr);
   8.528 -
   8.529 -    /* Cursor shape registers */
   8.530 -    fsr  = vga_rcrt(vgabase, VGA_CRTC_CURSOR_END) & 0xe0;
   8.531 -    fsr |= fontheight - fontheight / 6;
   8.532 -    vga_wcrt(vgabase, VGA_CRTC_CURSOR_END, fsr);
   8.533 -    fsr  = vga_rcrt(vgabase, VGA_CRTC_CURSOR_START) & 0xe0;
   8.534 -    fsr |= (fsr & 0x1f) - 1;
   8.535 -    vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, fsr);
   8.536 -
   8.537 -    return 0;
   8.538 -}
   8.539 -
   8.540 -
   8.541 -/*
   8.542 - * HIGH-LEVEL INITIALISATION AND TEXT OUTPUT.
   8.543 - */
   8.544 +/* Filled in by arch boot code. */
   8.545 +struct xen_vga_console_info vga_console_info;
   8.546  
   8.547  static int vgacon_enabled = 0;
   8.548  static int vgacon_keep    = 0;
   8.549 -static int vgacon_lines   = 50;
   8.550 -static const struct font_desc *font;
   8.551 +/*static const struct font_desc *font;*/
   8.552  
   8.553  static int xpos, ypos;
   8.554  static unsigned char *video;
   8.555  
   8.556 -/* vga: comma-separated options. */
   8.557 +/*
   8.558 + * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
   8.559 + * 
   8.560 + *   'vga=ask':
   8.561 + *      display a vga menu of available modes
   8.562 + * 
   8.563 + *   'vga=text-80x<rows>':
   8.564 + *      text mode, where <rows> is one of {25,28,30,34,43,50,60}
   8.565 + * 
   8.566 + *   'vga=gfx-<width>x<height>x<depth>':
   8.567 + *      graphics mode, e.g., vga=gfx-1024x768x16
   8.568 + * 
   8.569 + *   'vga=mode-<mode>:
   8.570 + *      specifies a mode as specified in 'vga=ask' menu
   8.571 + *      (NB. menu modes are displayed in hex, so mode numbers here must
   8.572 + *           be prefixed with '0x' (e.g., 'vga=mode-0x0318'))
   8.573 + * 
   8.574 + * The option 'keep' causes Xen to continue to print to the VGA console even 
   8.575 + * after domain 0 starts to boot. The default behaviour is to relinquish
   8.576 + * control of the console to domain 0.
   8.577 + */
   8.578  static char opt_vga[30] = "";
   8.579  string_param("vga", opt_vga);
   8.580  
   8.581  /* VGA text-mode definitions. */
   8.582 -#define COLUMNS     80
   8.583 -#define LINES       vgacon_lines
   8.584 +#define COLUMNS vga_console_info.u.text_mode_3.columns
   8.585 +#define LINES   vga_console_info.u.text_mode_3.rows
   8.586  #define ATTRIBUTE   7
   8.587  #define VIDEO_SIZE  (COLUMNS * LINES * 2)
   8.588  
   8.589 @@ -577,50 +61,44 @@ void __init vga_init(void)
   8.590  {
   8.591      char *p;
   8.592  
   8.593 +    /* Look for 'keep' in comma-separated options. */
   8.594      for ( p = opt_vga; p != NULL; p = strchr(p, ',') )
   8.595      {
   8.596          if ( *p == ',' )
   8.597              p++;
   8.598          if ( strncmp(p, "keep", 4) == 0 )
   8.599              vgacon_keep = 1;
   8.600 -        else if ( strncmp(p, "text-80x", 8) == 0 )
   8.601 -            vgacon_lines = simple_strtoul(p + 8, NULL, 10);
   8.602      }
   8.603  
   8.604 -    video = setup_vga();
   8.605 -    if ( !video )
   8.606 -        return;
   8.607 -
   8.608 -    switch ( vgacon_lines )
   8.609 +    switch ( vga_console_info.video_type )
   8.610      {
   8.611 -    case 25:
   8.612 -    case 30:
   8.613 -        font = &font_vga_8x16;
   8.614 -        break;
   8.615 -    case 28:
   8.616 -    case 34:
   8.617 -        font = &font_vga_8x14;
   8.618 +    case XEN_VGATYPE_TEXT_MODE_3:
   8.619 +        if ( memory_is_conventional_ram(0xB8000) )
   8.620 +            return;
   8.621 +        video = ioremap(0xB8000, 0x8000);
   8.622 +        if ( video == NULL )
   8.623 +            return;
   8.624 +        /* Disable cursor. */
   8.625 +        outw(0x200a, 0x3d4);
   8.626 +        memset(video, 0, VIDEO_SIZE);
   8.627          break;
   8.628 -    case 43:
   8.629 -    case 50:
   8.630 -    case 60:
   8.631 -        font = &font_vga_8x8;
   8.632 +    case XEN_VGATYPE_VESA_LFB:
   8.633 +#if 0
   8.634 +        /* XXX Implement me! */
   8.635 +        video = ioremap(vga_console_info.u.vesa_lfb.lfb_base,
   8.636 +                        vga_console_info.u.vesa_lfb.lfb_size);
   8.637 +        if ( video == NULL )
   8.638 +            return;
   8.639 +        memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
   8.640          break;
   8.641 +#else
   8.642 +        return;
   8.643 +#endif
   8.644 +    default:
   8.645 +        memset(&vga_console_info, 0, sizeof(vga_console_info));
   8.646 +        return;
   8.647      }
   8.648  
   8.649 -    if ( (font == NULL) || (vga_load_font(font, vgacon_lines) < 0) )
   8.650 -    {
   8.651 -        vgacon_lines = 25;
   8.652 -        font = NULL;
   8.653 -    }
   8.654 -    
   8.655 -    /* Clear the screen. */
   8.656 -    memset(video, 0, VIDEO_SIZE);
   8.657 -    xpos = ypos = 0;
   8.658 -
   8.659 -    /* Disable cursor. */
   8.660 -    vga_wcrt(vgabase, VGA_CRTC_CURSOR_START, 0x20);
   8.661 -
   8.662      vgacon_enabled = 1;
   8.663  }
   8.664  
   8.665 @@ -629,11 +107,10 @@ void __init vga_endboot(void)
   8.666      if ( !vgacon_enabled )
   8.667          return;
   8.668  
   8.669 -    if ( !vgacon_keep )
   8.670 -        vgacon_enabled = 0;
   8.671 -        
   8.672      printk("Xen is %s VGA console.\n",
   8.673             vgacon_keep ? "keeping" : "relinquishing");
   8.674 +
   8.675 +    vgacon_enabled = vgacon_keep;
   8.676  }
   8.677  
   8.678  
   8.679 @@ -672,17 +149,6 @@ void vga_putchar(int c)
   8.680  
   8.681  int __init fill_console_start_info(struct dom0_vga_console_info *ci)
   8.682  {
   8.683 -    memset(ci, 0, sizeof(*ci));
   8.684 -
   8.685 -    if ( !vgacon_enabled )
   8.686 -        return 0;
   8.687 -
   8.688 -    ci->video_type = XEN_VGATYPE_TEXT_MODE_3;
   8.689 -    ci->u.text_mode_3.rows     = LINES;
   8.690 -    ci->u.text_mode_3.columns  = COLUMNS;
   8.691 -    ci->u.text_mode_3.cursor_x = 0;
   8.692 -    ci->u.text_mode_3.cursor_y = LINES - 1;
   8.693 -    ci->u.text_mode_3.font_height = font ? font->height : 16;
   8.694 -
   8.695 +    memcpy(ci, &vga_console_info, sizeof(*ci));
   8.696      return 1;
   8.697  }
     9.1 --- a/xen/include/public/xen.h	Fri Jun 08 19:22:08 2007 +0100
     9.2 +++ b/xen/include/public/xen.h	Sun Jun 10 15:58:08 2007 +0100
     9.3 @@ -568,6 +568,8 @@ typedef struct dom0_vga_console_info {
     9.4          } vesa_lfb;
     9.5      } u;
     9.6  } dom0_vga_console_info_t;
     9.7 +#define xen_vga_console_info dom0_vga_console_info
     9.8 +#define xen_vga_console_info_t dom0_vga_console_info_t
     9.9  
    9.10  typedef uint8_t xen_domain_handle_t[16];
    9.11  
    10.1 --- a/xen/include/xen/vga.h	Fri Jun 08 19:22:08 2007 +0100
    10.2 +++ b/xen/include/xen/vga.h	Sun Jun 10 15:58:08 2007 +0100
    10.3 @@ -12,6 +12,7 @@
    10.4  #include <xen/config.h>
    10.5  
    10.6  #ifdef CONFIG_VGA
    10.7 +extern struct xen_vga_console_info vga_console_info;
    10.8  void vga_init(void);
    10.9  void vga_endboot(void);
   10.10  void vga_putchar(int c);