ia64/xen-unstable

changeset 15747:f2649861d594

x86-64: enable hypervisor output on VESA frame buffer

This is x86-64 only for now due to the virtual address space
constraints on x86-32.

New options 'vesa-ram', 'vesa-map', 'vesa-mtrr' are close equivalents
to the vesafb Linux options 'vtotal', 'vremap', 'mtrr'.

Also the font can be specified: font=8x{8,14,16}.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Mon Aug 13 10:09:06 2007 +0100 (2007-08-13)
parents c362bcee8047
children 01c721fddb90
files xen/arch/x86/setup.c xen/drivers/char/console.c xen/drivers/video/Makefile xen/drivers/video/vesa.c xen/drivers/video/vga.c xen/include/xen/vga.h
line diff
     1.1 --- a/xen/arch/x86/setup.c	Sun Aug 12 16:09:13 2007 +0100
     1.2 +++ b/xen/arch/x86/setup.c	Mon Aug 13 10:09:06 2007 +0100
     1.3 @@ -106,6 +106,8 @@ extern void init_IRQ(void);
     1.4  extern void trap_init(void);
     1.5  extern void early_time_init(void);
     1.6  extern void early_cpu_init(void);
     1.7 +extern void vesa_init(void);
     1.8 +extern void vesa_mtrr_init(void);
     1.9  
    1.10  struct tss_struct init_tss[NR_CPUS];
    1.11  
    1.12 @@ -901,6 +903,7 @@ void __init __start_xen(unsigned long mb
    1.13  #ifdef __x86_64__
    1.14      init_xenheap_pages(xen_phys_start, __pa(&_start));
    1.15      nr_pages += (__pa(&_start) - xen_phys_start) >> PAGE_SHIFT;
    1.16 +    vesa_init();
    1.17  #endif
    1.18      xenheap_phys_start = xen_phys_start;
    1.19      printk("Xen heap: %luMB (%lukB)\n", 
    1.20 @@ -966,6 +969,9 @@ void __init __start_xen(unsigned long mb
    1.21          set_in_cr4(X86_CR4_OSFXSR);
    1.22      if ( cpu_has_xmm )
    1.23          set_in_cr4(X86_CR4_OSXMMEXCPT);
    1.24 +#ifdef CONFIG_X86_64
    1.25 +    vesa_mtrr_init();
    1.26 +#endif
    1.27  
    1.28      if ( opt_nosmp )
    1.29          max_cpus = 0;
     2.1 --- a/xen/drivers/char/console.c	Sun Aug 12 16:09:13 2007 +0100
     2.2 +++ b/xen/drivers/char/console.c	Mon Aug 13 10:09:06 2007 +0100
     2.3 @@ -331,13 +331,11 @@ static long guest_console_write(XEN_GUES
     2.4          kbuf[kcount] = '\0';
     2.5  
     2.6          sercon_puts(kbuf);
     2.7 +        vga_puts(kbuf);
     2.8  
     2.9 -        for ( kptr = kbuf; *kptr != '\0'; kptr++ )
    2.10 -        {
    2.11 -            vga_putchar(*kptr);
    2.12 -            if ( opt_console_to_ring )
    2.13 +        if ( opt_console_to_ring )
    2.14 +            for ( kptr = kbuf; *kptr != '\0'; kptr++ )
    2.15                  putchar_console_ring(*kptr);
    2.16 -        }
    2.17  
    2.18          if ( opt_console_to_ring )
    2.19              send_guest_global_virq(dom0, VIRQ_CON_RING);
    2.20 @@ -404,12 +402,10 @@ static void __putstr(const char *str)
    2.21      int c;
    2.22  
    2.23      sercon_puts(str);
    2.24 +    vga_puts(str);
    2.25  
    2.26      while ( (c = *str++) != '\0' )
    2.27 -    {
    2.28 -        vga_putchar(c);
    2.29          putchar_console_ring(c);
    2.30 -    }
    2.31  
    2.32      send_guest_global_virq(dom0, VIRQ_CON_RING);
    2.33  }
     3.1 --- a/xen/drivers/video/Makefile	Sun Aug 12 16:09:13 2007 +0100
     3.2 +++ b/xen/drivers/video/Makefile	Mon Aug 13 10:09:06 2007 +0100
     3.3 @@ -1,4 +1,8 @@
     3.4 -obj-y += font_8x14.o
     3.5 -obj-y += font_8x16.o
     3.6 -obj-y += font_8x8.o
     3.7 -obj-y += vga.o
     3.8 +obj-y                := vga.o
     3.9 +obj-$(CONFIG_X86_64) += font_8x14.o
    3.10 +obj-$(CONFIG_X86_64) += font_8x16.o
    3.11 +obj-$(CONFIG_X86_64) += font_8x8.o
    3.12 +obj-$(CONFIG_X86_64) += vesa.o
    3.13 +
    3.14 +# extra dependencies
    3.15 +vesa.o: font.h
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/drivers/video/vesa.c	Mon Aug 13 10:09:06 2007 +0100
     4.3 @@ -0,0 +1,307 @@
     4.4 +/******************************************************************************
     4.5 + * vesa.c
     4.6 + *
     4.7 + * VESA linear frame buffer handling.
     4.8 + */
     4.9 +
    4.10 +#include <xen/config.h>
    4.11 +#include <xen/compile.h>
    4.12 +#include <xen/init.h>
    4.13 +#include <xen/lib.h>
    4.14 +#include <xen/mm.h>
    4.15 +#include <xen/errno.h>
    4.16 +#include <xen/console.h>
    4.17 +#include <xen/vga.h>
    4.18 +#include "font.h"
    4.19 +
    4.20 +#define vlfb_info    vga_console_info.u.vesa_lfb
    4.21 +#define text_columns (vlfb_info.width / font->width)
    4.22 +#define text_rows    (vlfb_info.height / font->height)
    4.23 +
    4.24 +static void vesa_redraw_puts(const char *s);
    4.25 +static void vesa_scroll_puts(const char *s);
    4.26 +
    4.27 +static unsigned char *lfb, *lbuf, *text_buf;
    4.28 +static const struct font_desc *font;
    4.29 +static bool_t vga_compat;
    4.30 +static unsigned int pixel_on;
    4.31 +static unsigned int xpos, ypos;
    4.32 +
    4.33 +static unsigned int vram_total;
    4.34 +integer_param("vesa-ram", vram_total);
    4.35 +
    4.36 +static unsigned int vram_remap;
    4.37 +integer_param("vesa-map", vram_remap);
    4.38 +
    4.39 +static int font_height;
    4.40 +static void __init parse_font_height(const char *s)
    4.41 +{
    4.42 +    if ( simple_strtoul(s, &s, 10) == 8 && (*s++ == 'x') )
    4.43 +        font_height = simple_strtoul(s, &s, 10);
    4.44 +    if ( *s != '\0' )
    4.45 +        font_height = 0;
    4.46 +}
    4.47 +custom_param("font", parse_font_height);
    4.48 +
    4.49 +void __init vesa_early_init(void)
    4.50 +{
    4.51 +    unsigned int vram_vmode;
    4.52 +
    4.53 +    /* XXX vga_compat = !(boot_video_info.capabilities & 2); */
    4.54 +
    4.55 +    if ( (vlfb_info.bits_per_pixel < 8) || (vlfb_info.bits_per_pixel > 32) )
    4.56 +        return;
    4.57 +
    4.58 +    if ( font_height == 0 ) /* choose a sensible default */
    4.59 +        font = ((vlfb_info.height <= 600) ? &font_vga_8x8 :
    4.60 +                (vlfb_info.height <= 768) ? &font_vga_8x14 : &font_vga_8x16);
    4.61 +    else if ( font_height <= 8 )
    4.62 +        font = &font_vga_8x8;
    4.63 +    else if ( font_height <= 14 )
    4.64 +        font = &font_vga_8x14;
    4.65 +    else
    4.66 +        font = &font_vga_8x16;
    4.67 +
    4.68 +    /*   vram_vmode -- that is the amount of memory needed for the
    4.69 +     *                 used video mode, i.e. the minimum amount of
    4.70 +     *                 memory we need. */
    4.71 +    vram_vmode = vlfb_info.height * vlfb_info.bytes_per_line;
    4.72 +
    4.73 +    /*   vram_total -- all video memory we have. Used for mtrr
    4.74 +     *                 entries. */
    4.75 +    vram_total = vram_total ? (vram_total << 20) : (vlfb_info.lfb_size << 16);
    4.76 +    vram_total = max_t(unsigned int, vram_total, vram_vmode);
    4.77 +
    4.78 +    /*   vram_remap -- the amount of video memory we are going to
    4.79 +     *                 use for vesafb.  With modern cards it is no
    4.80 +     *                 option to simply use vram_total as that
    4.81 +     *                 wastes plenty of kernel address space. */
    4.82 +    vram_remap = (vram_remap ?
    4.83 +                  (vram_remap << 20) :
    4.84 +                  ((vram_vmode + (1 << L2_PAGETABLE_SHIFT) - 1) &
    4.85 +                   ~((1 << L2_PAGETABLE_SHIFT) - 1)));
    4.86 +    vram_remap = max_t(unsigned int, vram_remap, vram_vmode);
    4.87 +    vram_remap = min_t(unsigned int, vram_remap, vram_total);
    4.88 +}
    4.89 +
    4.90 +void __init vesa_init(void)
    4.91 +{
    4.92 +    if ( !font )
    4.93 +        goto fail;
    4.94 +
    4.95 +    lbuf = xmalloc_bytes(vlfb_info.bytes_per_line);
    4.96 +    if ( !lbuf )
    4.97 +        goto fail;
    4.98 +
    4.99 +    text_buf = xmalloc_bytes(text_columns * text_rows);
   4.100 +    if ( !text_buf )
   4.101 +        goto fail;
   4.102 +
   4.103 +    if ( map_pages_to_xen(IOREMAP_VIRT_START,
   4.104 +                          vlfb_info.lfb_base >> PAGE_SHIFT,
   4.105 +                          vram_remap >> PAGE_SHIFT,
   4.106 +                          PAGE_HYPERVISOR_NOCACHE) )
   4.107 +        goto fail;
   4.108 +
   4.109 +    lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap);
   4.110 +    memset(text_buf, 0, text_columns * text_rows);
   4.111 +
   4.112 +    vga_puts = vesa_redraw_puts;
   4.113 +
   4.114 +    printk(XENLOG_INFO "vesafb: framebuffer at 0x%x, mapped to 0x%p, "
   4.115 +           "using %uk, total %uk\n",
   4.116 +           vlfb_info.lfb_base, lfb,
   4.117 +           vram_remap >> 10, vram_total >> 10);
   4.118 +    printk(XENLOG_INFO "vesafb: mode is %dx%dx%u, linelength=%d, font %ux%u\n",
   4.119 +           vlfb_info.width, vlfb_info.height,
   4.120 +           vlfb_info.bits_per_pixel, vlfb_info.bytes_per_line,
   4.121 +           font->width, font->height);
   4.122 +    printk(XENLOG_INFO "vesafb: %scolor: size=%d:%d:%d:%d, "
   4.123 +           "shift=%d:%d:%d:%d\n",
   4.124 +           vlfb_info.bits_per_pixel > 8 ? "True" :
   4.125 +           vga_compat ? "Pseudo" : "Static Pseudo",
   4.126 +           vlfb_info.rsvd_size, vlfb_info.red_size,
   4.127 +           vlfb_info.green_size, vlfb_info.blue_size,
   4.128 +           vlfb_info.rsvd_pos, vlfb_info.red_pos,
   4.129 +           vlfb_info.green_pos, vlfb_info.blue_pos);
   4.130 +
   4.131 +    if ( vlfb_info.bits_per_pixel > 8 )
   4.132 +    {
   4.133 +        /* Light grey in truecolor. */
   4.134 +        unsigned int grey = 0xaaaaaaaa;
   4.135 +        pixel_on = 
   4.136 +            ((grey >> (32 - vlfb_info.  red_size)) << vlfb_info.  red_pos) |
   4.137 +            ((grey >> (32 - vlfb_info.green_size)) << vlfb_info.green_pos) |
   4.138 +            ((grey >> (32 - vlfb_info. blue_size)) << vlfb_info. blue_pos);
   4.139 +    }
   4.140 +    else
   4.141 +    {
   4.142 +        /* White(ish) in default pseudocolor palette. */
   4.143 +        pixel_on = 7;
   4.144 +    }
   4.145 +
   4.146 +    return;
   4.147 +
   4.148 + fail:
   4.149 +    xfree(lbuf);
   4.150 +    xfree(text_buf);
   4.151 +}
   4.152 +
   4.153 +void __init vesa_endboot(void)
   4.154 +{
   4.155 +    xpos = 0;
   4.156 +    vga_puts = vesa_scroll_puts;
   4.157 +}
   4.158 +
   4.159 +#if defined(CONFIG_X86)
   4.160 +
   4.161 +#include <asm/mtrr.h>
   4.162 +
   4.163 +static unsigned int vesa_mtrr;
   4.164 +integer_param("vesa-mtrr", vesa_mtrr);
   4.165 +
   4.166 +void __init vesa_mtrr_init(void)
   4.167 +{
   4.168 +    static const int mtrr_types[] = {
   4.169 +        0, MTRR_TYPE_UNCACHABLE, MTRR_TYPE_WRBACK,
   4.170 +        MTRR_TYPE_WRCOMB, MTRR_TYPE_WRTHROUGH };
   4.171 +    unsigned int size_total;
   4.172 +    int rc, type;
   4.173 +
   4.174 +    if ( !lfb || (vesa_mtrr == 0) || (vesa_mtrr >= ARRAY_SIZE(mtrr_types)) )
   4.175 +        return;
   4.176 +
   4.177 +    type = mtrr_types[vesa_mtrr];
   4.178 +    if ( !type )
   4.179 +        return;
   4.180 +
   4.181 +    /* Find the largest power-of-two */
   4.182 +    size_total = vram_total;
   4.183 +    while ( size_total & (size_total - 1) )
   4.184 +        size_total &= size_total - 1;
   4.185 +
   4.186 +    /* Try and find a power of two to add */
   4.187 +    do {
   4.188 +        rc = mtrr_add(vlfb_info.lfb_base, size_total, type, 1);
   4.189 +        size_total >>= 1;
   4.190 +    } while ( (size_total >= PAGE_SIZE) && (rc == -EINVAL) );
   4.191 +}
   4.192 +
   4.193 +static void lfb_flush(void)
   4.194 +{
   4.195 +    if ( vesa_mtrr == 3 )
   4.196 +        __asm__ __volatile__ ("sfence" : : : "memory");
   4.197 +}
   4.198 +
   4.199 +#else /* !defined(CONFIG_X86) */
   4.200 +
   4.201 +#define lfb_flush() ((void)0)
   4.202 +
   4.203 +#endif
   4.204 +
   4.205 +/* Render one line of text to given linear framebuffer line. */
   4.206 +static void vesa_show_line(
   4.207 +    const unsigned char *text_line,
   4.208 +    unsigned char *video_line,
   4.209 +    unsigned int nr_chars)
   4.210 +{
   4.211 +    unsigned int i, j, b, bpp, pixel;
   4.212 +
   4.213 +    bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
   4.214 +
   4.215 +    for ( i = 0; i < font->height; i++ )
   4.216 +    {
   4.217 +        unsigned char *ptr = lbuf;
   4.218 +
   4.219 +        for ( j = 0; j < nr_chars; j++ )
   4.220 +        {
   4.221 +            const unsigned char *bits = font->data;
   4.222 +            bits += ((text_line[j] * font->height + i) *
   4.223 +                     ((font->width + 7) >> 3));
   4.224 +            for ( b = font->width; b--; )
   4.225 +            {
   4.226 +                pixel = test_bit(b, bits) ? pixel_on : 0;
   4.227 +                memcpy(ptr, &pixel, bpp);
   4.228 +                ptr += bpp;
   4.229 +            }
   4.230 +        }
   4.231 +
   4.232 +        memset(ptr, 0, (vlfb_info.width - nr_chars * font->width) * bpp);
   4.233 +        memcpy(video_line, lbuf, vlfb_info.width * bpp);
   4.234 +        video_line += vlfb_info.bytes_per_line;
   4.235 +    }
   4.236 +}
   4.237 +
   4.238 +/* Fast mode which redraws all modified parts of a 2D text buffer. */
   4.239 +static void vesa_redraw_puts(const char *s)
   4.240 +{
   4.241 +    unsigned int i, min_redraw_y = ypos;
   4.242 +    char c;
   4.243 +
   4.244 +    /* Paste characters into text buffer. */
   4.245 +    while ( (c = *s++) != '\0' )
   4.246 +    {
   4.247 +        if ( (c == '\n') || (xpos >= text_columns) )
   4.248 +        {
   4.249 +            if ( ++ypos >= text_rows )
   4.250 +            {
   4.251 +                min_redraw_y = 0;
   4.252 +                ypos = text_rows - 1;
   4.253 +                memmove(text_buf, text_buf + text_columns,
   4.254 +                        ypos * text_columns);
   4.255 +                memset(text_buf + ypos * text_columns, 0, xpos);
   4.256 +            }
   4.257 +            xpos = 0;
   4.258 +        }
   4.259 +
   4.260 +        if ( c != '\n' )
   4.261 +            text_buf[xpos++ + ypos * text_columns] = c;
   4.262 +    }
   4.263 +
   4.264 +    /* Render modified section of text buffer to VESA linear framebuffer. */
   4.265 +    for ( i = min_redraw_y; i <= ypos; i++ )
   4.266 +        vesa_show_line(text_buf + i * text_columns,
   4.267 +                       lfb + i * font->height * vlfb_info.bytes_per_line,
   4.268 +                       text_columns);
   4.269 +
   4.270 +    lfb_flush();
   4.271 +}
   4.272 +
   4.273 +/* Slower line-based scroll mode which interacts better with dom0. */
   4.274 +static void vesa_scroll_puts(const char *s)
   4.275 +{
   4.276 +    unsigned int i;
   4.277 +    char c;
   4.278 +
   4.279 +    while ( (c = *s++) != '\0' )
   4.280 +    {
   4.281 +        if ( (c == '\n') || (xpos >= text_columns) )
   4.282 +        {
   4.283 +            unsigned int bytes = (vlfb_info.width *
   4.284 +                                  ((vlfb_info.bits_per_pixel + 7) >> 3));
   4.285 +            unsigned char *src = lfb + font->height * vlfb_info.bytes_per_line;
   4.286 +            unsigned char *dst = lfb;
   4.287 +            
   4.288 +            /* New line: scroll all previous rows up one line. */
   4.289 +            for ( i = font->height; i < vlfb_info.height; i++ )
   4.290 +            {
   4.291 +                memcpy(dst, src, bytes);
   4.292 +                src += vlfb_info.bytes_per_line;
   4.293 +                dst += vlfb_info.bytes_per_line;
   4.294 +            }
   4.295 +
   4.296 +            /* Render new line. */
   4.297 +            vesa_show_line(
   4.298 +                text_buf,
   4.299 +                lfb + (text_rows-1) * font->height * vlfb_info.bytes_per_line,
   4.300 +                xpos);
   4.301 +
   4.302 +            xpos = 0;
   4.303 +        }
   4.304 +
   4.305 +        if ( c != '\n' )
   4.306 +            text_buf[xpos++] = c;
   4.307 +    }
   4.308 +
   4.309 +    lfb_flush();
   4.310 +}
     5.1 --- a/xen/drivers/video/vga.c	Sun Aug 12 16:09:13 2007 +0100
     5.2 +++ b/xen/drivers/video/vga.c	Mon Aug 13 10:09:06 2007 +0100
     5.3 @@ -10,22 +10,20 @@
     5.4  #include <xen/lib.h>
     5.5  #include <xen/mm.h>
     5.6  #include <xen/errno.h>
     5.7 -#include <xen/event.h>
     5.8 -#include <xen/spinlock.h>
     5.9  #include <xen/console.h>
    5.10  #include <xen/vga.h>
    5.11  #include <asm/io.h>
    5.12 -#include "font.h"
    5.13  
    5.14  /* Filled in by arch boot code. */
    5.15  struct xen_vga_console_info vga_console_info;
    5.16  
    5.17 -static int vgacon_enabled = 0;
    5.18 -static int vgacon_keep    = 0;
    5.19 -/*static const struct font_desc *font;*/
    5.20 +static int vgacon_keep;
    5.21 +static unsigned int xpos, ypos;
    5.22 +static unsigned char *video;
    5.23  
    5.24 -static int xpos, ypos;
    5.25 -static unsigned char *video;
    5.26 +static void vga_text_puts(const char *s);
    5.27 +static void vga_noop_puts(const char *s) {}
    5.28 +void (*vga_puts)(const char *) = vga_noop_puts;
    5.29  
    5.30  /*
    5.31   * 'vga=<mode-specifier>[,keep]' where <mode-specifier> is one of:
    5.32 @@ -55,10 +53,16 @@ static char opt_vga[30] = "";
    5.33  string_param("vga", opt_vga);
    5.34  
    5.35  /* VGA text-mode definitions. */
    5.36 -#define COLUMNS vga_console_info.u.text_mode_3.columns
    5.37 -#define LINES   vga_console_info.u.text_mode_3.rows
    5.38 +static unsigned int columns, lines;
    5.39  #define ATTRIBUTE   7
    5.40 -#define VIDEO_SIZE  (COLUMNS * LINES * 2)
    5.41 +
    5.42 +#ifdef CONFIG_X86_64
    5.43 +void vesa_early_init(void);
    5.44 +void vesa_endboot(void);
    5.45 +#else
    5.46 +#define vesa_early_init() ((void)0)
    5.47 +#define vesa_endboot()    ((void)0)
    5.48 +#endif
    5.49  
    5.50  void __init vga_init(void)
    5.51  {
    5.52 @@ -76,77 +80,61 @@ void __init vga_init(void)
    5.53      switch ( vga_console_info.video_type )
    5.54      {
    5.55      case XEN_VGATYPE_TEXT_MODE_3:
    5.56 -        if ( memory_is_conventional_ram(0xB8000) )
    5.57 +        if ( memory_is_conventional_ram(0xB8000) ||
    5.58 +             ((video = ioremap(0xB8000, 0x8000)) == NULL) )
    5.59              return;
    5.60 -        video = ioremap(0xB8000, 0x8000);
    5.61 -        if ( video == NULL )
    5.62 -            return;
    5.63 -        /* Disable cursor. */
    5.64 -        outw(0x200a, 0x3d4);
    5.65 -        memset(video, 0, VIDEO_SIZE);
    5.66 +        outw(0x200a, 0x3d4); /* disable cursor */
    5.67 +        columns = vga_console_info.u.text_mode_3.columns;
    5.68 +        lines   = vga_console_info.u.text_mode_3.rows;
    5.69 +        memset(video, 0, columns * lines * 2);
    5.70 +        vga_puts = vga_text_puts;
    5.71          break;
    5.72      case XEN_VGATYPE_VESA_LFB:
    5.73 -#if 0
    5.74 -        /* XXX Implement me! */
    5.75 -        video = ioremap(vga_console_info.u.vesa_lfb.lfb_base,
    5.76 -                        vga_console_info.u.vesa_lfb.lfb_size);
    5.77 -        if ( video == NULL )
    5.78 -            return;
    5.79 -        memset(video, 0, vga_console_info.u.vesa_lfb.lfb_size);
    5.80 +        vesa_early_init();
    5.81          break;
    5.82 -#else
    5.83 -        return;
    5.84 -#endif
    5.85      default:
    5.86          memset(&vga_console_info, 0, sizeof(vga_console_info));
    5.87 -        return;
    5.88 +        break;
    5.89      }
    5.90 -
    5.91 -    vgacon_enabled = 1;
    5.92  }
    5.93  
    5.94  void __init vga_endboot(void)
    5.95  {
    5.96 -    if ( !vgacon_enabled )
    5.97 +    if ( vga_puts == vga_noop_puts )
    5.98          return;
    5.99  
   5.100      printk("Xen is %s VGA console.\n",
   5.101             vgacon_keep ? "keeping" : "relinquishing");
   5.102  
   5.103 -    vgacon_enabled = vgacon_keep;
   5.104 +    vesa_endboot();
   5.105 +
   5.106 +    if ( !vgacon_keep )
   5.107 +        vga_puts = vga_noop_puts;
   5.108  }
   5.109  
   5.110 -
   5.111 -static void put_newline(void)
   5.112 +static void vga_text_puts(const char *s)
   5.113  {
   5.114 -    xpos = 0;
   5.115 -    ypos++;
   5.116 -
   5.117 -    if ( ypos >= LINES )
   5.118 -    {
   5.119 -        ypos = LINES-1;
   5.120 -        memmove((char*)video, 
   5.121 -                (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
   5.122 -        memset((char*)video + (LINES-1)*2*COLUMNS, 0, 2*COLUMNS);
   5.123 -    }
   5.124 -}
   5.125 +    char c;
   5.126  
   5.127 -void vga_putchar(int c)
   5.128 -{
   5.129 -    if ( !vgacon_enabled )
   5.130 -        return;
   5.131 -
   5.132 -    if ( c == '\n' )
   5.133 +    while ( (c = *s++) != '\0' )
   5.134      {
   5.135 -        put_newline();
   5.136 -    }
   5.137 -    else
   5.138 -    {
   5.139 -        if ( xpos >= COLUMNS )
   5.140 -            put_newline();
   5.141 -        video[(xpos + ypos * COLUMNS) * 2]     = c & 0xFF;
   5.142 -        video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
   5.143 -        ++xpos;
   5.144 +        if ( (c == '\n') || (xpos >= columns) )
   5.145 +        {
   5.146 +            if ( ++ypos >= lines )
   5.147 +            {
   5.148 +                ypos = lines - 1;
   5.149 +                memmove(video, video + 2 * columns, ypos * 2 * columns);
   5.150 +                memset(video + ypos * 2 * columns, 0, 2 * xpos);
   5.151 +            }
   5.152 +            xpos = 0;
   5.153 +        }
   5.154 +
   5.155 +        if ( c != '\n' )
   5.156 +        {
   5.157 +            video[(xpos + ypos * columns) * 2]     = c;
   5.158 +            video[(xpos + ypos * columns) * 2 + 1] = ATTRIBUTE;
   5.159 +            xpos++;
   5.160 +        }
   5.161      }
   5.162  }
   5.163  
     6.1 --- a/xen/include/xen/vga.h	Sun Aug 12 16:09:13 2007 +0100
     6.2 +++ b/xen/include/xen/vga.h	Mon Aug 13 10:09:06 2007 +0100
     6.3 @@ -15,11 +15,11 @@
     6.4  extern struct xen_vga_console_info vga_console_info;
     6.5  void vga_init(void);
     6.6  void vga_endboot(void);
     6.7 -void vga_putchar(int c);
     6.8 +extern void (*vga_puts)(const char *);
     6.9  #else
    6.10 -#define vga_init()     ((void)0)
    6.11 -#define vga_endboot()  ((void)0)
    6.12 -#define vga_putchar(c) ((void)0)
    6.13 +#define vga_init()    ((void)0)
    6.14 +#define vga_endboot() ((void)0)
    6.15 +#define vga_puts(s)   ((void)0)
    6.16  #endif
    6.17  
    6.18  #endif /* _XEN_VGA_H */