[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v7 1/5] xen: introduce a generic framebuffer driver
Yep Acked-by: Keir Fraser <keir@xxxxxxx> On 15/02/2013 12:41, "Ian Campbell" <Ian.Campbell@xxxxxxxxxx> wrote: > Keir, are you OK with this change? > > On Thu, 2013-02-14 at 17:30 +0000, Stefano Stabellini wrote: >> Abstract away from vesa.c the funcions to handle a linear framebuffer >> and print characters to it. >> Make use of the new functions in vesa.c. >> >> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> >> Acked-by: Jan Beulich <JBeulich@xxxxxxxx> >> >> Changes in v6: >> - remove useless initializations to NULL in lfb_init; >> - more compact checks in lfb_init. >> >> Changes in v5: >> - remove lfb_alloc and the now unused __initdata variables; >> - fix indentation and long lines. >> >> Changes in v4: >> - squash the vesa.c changes into this patch; >> - rename fb* to lfb*; >> - pass a pointer to fb_init; >> - use %u for screen dimensions; >> - specify loglevel in printk; >> - call fb_free on error in fb_alloc; >> - no __init on declarations; >> - do not break messages to fit 80 columns. >> --- >> xen/drivers/video/Makefile | 1 + >> xen/drivers/video/lfb.c | 183 >> ++++++++++++++++++++++++++++++++++++++++++++ >> xen/drivers/video/lfb.h | 46 +++++++++++ >> xen/drivers/video/vesa.c | 177 ++++++------------------------------------ >> 4 files changed, 254 insertions(+), 153 deletions(-) >> create mode 100644 xen/drivers/video/lfb.c >> create mode 100644 xen/drivers/video/lfb.h >> >> diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile >> index 2993c39..77f9d5d 100644 >> --- a/xen/drivers/video/Makefile >> +++ b/xen/drivers/video/Makefile >> @@ -2,4 +2,5 @@ obj-$(HAS_VGA) := vga.o >> obj-$(HAS_VIDEO) += font_8x14.o >> obj-$(HAS_VIDEO) += font_8x16.o >> obj-$(HAS_VIDEO) += font_8x8.o >> +obj-$(HAS_VIDEO) += lfb.o >> obj-$(HAS_VGA) += vesa.o >> diff --git a/xen/drivers/video/lfb.c b/xen/drivers/video/lfb.c >> new file mode 100644 >> index 0000000..cc7f7ac >> --- /dev/null >> +++ b/xen/drivers/video/lfb.c >> @@ -0,0 +1,183 @@ >> +/*************************************************************************** >> *** >> + * lfb.c >> + * >> + * linear frame buffer handling. >> + */ >> + >> +#include <xen/config.h> >> +#include <xen/kernel.h> >> +#include <xen/lib.h> >> +#include <xen/errno.h> >> +#include "lfb.h" >> +#include "font.h" >> + >> +#define MAX_XRES 1900 >> +#define MAX_YRES 1200 >> +#define MAX_BPP 4 >> +#define MAX_FONT_W 8 >> +#define MAX_FONT_H 16 >> + >> +struct lfb_status { >> + struct lfb_prop lfbp; >> + >> + unsigned char *lbuf, *text_buf; >> + unsigned int *line_len; >> + unsigned int xpos, ypos; >> +}; >> +static struct lfb_status lfb; >> + >> +static void lfb_show_line( >> + const unsigned char *text_line, >> + unsigned char *video_line, >> + unsigned int nr_chars, >> + unsigned int nr_cells) >> +{ >> + unsigned int i, j, b, bpp, pixel; >> + >> + bpp = (lfb.lfbp.bits_per_pixel + 7) >> 3; >> + >> + for ( i = 0; i < lfb.lfbp.font->height; i++ ) >> + { >> + unsigned char *ptr = lfb.lbuf; >> + >> + for ( j = 0; j < nr_chars; j++ ) >> + { >> + const unsigned char *bits = lfb.lfbp.font->data; >> + bits += ((text_line[j] * lfb.lfbp.font->height + i) * >> + ((lfb.lfbp.font->width + 7) >> 3)); >> + for ( b = lfb.lfbp.font->width; b--; ) >> + { >> + pixel = (*bits & (1u<<b)) ? lfb.lfbp.pixel_on : 0; >> + memcpy(ptr, &pixel, bpp); >> + ptr += bpp; >> + } >> + } >> + >> + memset(ptr, 0, (lfb.lfbp.width - nr_chars * lfb.lfbp.font->width) * >> bpp); >> + memcpy(video_line, lfb.lbuf, nr_cells * lfb.lfbp.font->width * bpp); >> + video_line += lfb.lfbp.bytes_per_line; >> + } >> +} >> + >> +/* Fast mode which redraws all modified parts of a 2D text buffer. */ >> +void lfb_redraw_puts(const char *s) >> +{ >> + unsigned int i, min_redraw_y = lfb.ypos; >> + char c; >> + >> + /* Paste characters into text buffer. */ >> + while ( (c = *s++) != '\0' ) >> + { >> + if ( (c == '\n') || (lfb.xpos >= lfb.lfbp.text_columns) ) >> + { >> + if ( ++lfb.ypos >= lfb.lfbp.text_rows ) >> + { >> + min_redraw_y = 0; >> + lfb.ypos = lfb.lfbp.text_rows - 1; >> + memmove(lfb.text_buf, lfb.text_buf + lfb.lfbp.text_columns, >> + lfb.ypos * lfb.lfbp.text_columns); >> + memset(lfb.text_buf + lfb.ypos * lfb.lfbp.text_columns, 0, >> lfb.xpos); >> + } >> + lfb.xpos = 0; >> + } >> + >> + if ( c != '\n' ) >> + lfb.text_buf[lfb.xpos++ + lfb.ypos * lfb.lfbp.text_columns] = c; >> + } >> + >> + /* Render modified section of text buffer to VESA linear framebuffer. */ >> + for ( i = min_redraw_y; i <= lfb.ypos; i++ ) >> + { >> + const unsigned char *line = lfb.text_buf + i * >> lfb.lfbp.text_columns; >> + unsigned int width; >> + >> + for ( width = lfb.lfbp.text_columns; width; --width ) >> + if ( line[width - 1] ) >> + break; >> + lfb_show_line(line, >> + lfb.lfbp.lfb + i * lfb.lfbp.font->height * >> lfb.lfbp.bytes_per_line, >> + width, max(lfb.line_len[i], width)); >> + lfb.line_len[i] = width; >> + } >> + >> + lfb.lfbp.flush(); >> +} >> + >> +/* Slower line-based scroll mode which interacts better with dom0. */ >> +void lfb_scroll_puts(const char *s) >> +{ >> + unsigned int i; >> + char c; >> + >> + while ( (c = *s++) != '\0' ) >> + { >> + if ( (c == '\n') || (lfb.xpos >= lfb.lfbp.text_columns) ) >> + { >> + unsigned int bytes = (lfb.lfbp.width * >> + ((lfb.lfbp.bits_per_pixel + 7) >> 3)); >> + unsigned char *src = lfb.lfbp.lfb + lfb.lfbp.font->height * >> lfb.lfbp.bytes_per_line; >> + unsigned char *dst = lfb.lfbp.lfb; >> + >> + /* New line: scroll all previous rows up one line. */ >> + for ( i = lfb.lfbp.font->height; i < lfb.lfbp.height; i++ ) >> + { >> + memcpy(dst, src, bytes); >> + src += lfb.lfbp.bytes_per_line; >> + dst += lfb.lfbp.bytes_per_line; >> + } >> + >> + /* Render new line. */ >> + lfb_show_line( >> + lfb.text_buf, >> + lfb.lfbp.lfb + (lfb.lfbp.text_rows-1) * >> lfb.lfbp.font->height * >> + lfb.lfbp.bytes_per_line, >> + lfb.xpos, lfb.lfbp.text_columns); >> + >> + lfb.xpos = 0; >> + } >> + >> + if ( c != '\n' ) >> + lfb.text_buf[lfb.xpos++] = c; >> + } >> + >> + lfb.lfbp.flush(); >> +} >> + >> +void lfb_carriage_return(void) >> +{ >> + lfb.xpos = 0; >> +} >> + >> +int __init lfb_init(struct lfb_prop *lfbp) >> +{ >> + if ( lfbp->width > MAX_XRES || lfbp->height > MAX_YRES ) >> + { >> + printk(XENLOG_WARNING "Couldn't initialize a %ux%u framebuffer >> early.\n", >> + lfbp->width, lfbp->height); >> + return -EINVAL; >> + } >> + >> + lfb.lfbp = *lfbp; >> + >> + lfb.lbuf = xmalloc_bytes(lfb.lfbp.bytes_per_line); >> + lfb.text_buf = xzalloc_bytes(lfb.lfbp.text_columns * >> lfb.lfbp.text_rows); >> + lfb.line_len = xzalloc_array(unsigned int, lfb.lfbp.text_columns); >> + >> + if ( !lfb.lbuf || !lfb.text_buf || !lfb.line_len ) >> + goto fail; >> + >> + return 0; >> + >> +fail: >> + printk(XENLOG_ERR "Couldn't allocate enough memory to drive the >> framebuffer\n"); >> + lfb_free(); >> + >> + return -ENOMEM; >> +} >> + >> +void lfb_free(void) >> +{ >> + xfree(lfb.lbuf); >> + xfree(lfb.text_buf); >> + xfree(lfb.line_len); >> +} >> diff --git a/xen/drivers/video/lfb.h b/xen/drivers/video/lfb.h >> new file mode 100644 >> index 0000000..ac40a66 >> --- /dev/null >> +++ b/xen/drivers/video/lfb.h >> @@ -0,0 +1,46 @@ >> +/* >> + * xen/drivers/video/lfb.h >> + * >> + * Cross-platform framebuffer library >> + * >> + * Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> >> + * Copyright (c) 2013 Citrix Systems. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + */ >> + >> +#ifndef _XEN_LFB_H >> +#define _XEN_LFB_H >> + >> +#include <xen/init.h> >> + >> +struct lfb_prop { >> + const struct font_desc *font; >> + unsigned char *lfb; >> + unsigned int pixel_on; >> + uint16_t width, height; >> + uint16_t bytes_per_line; >> + uint16_t bits_per_pixel; >> + void (*flush)(void); >> + >> + unsigned int text_columns; >> + unsigned int text_rows; >> +}; >> + >> +void lfb_redraw_puts(const char *s); >> +void lfb_scroll_puts(const char *s); >> +void lfb_carriage_return(void); >> +void lfb_free(void); >> + >> +/* initialize the framebuffer */ >> +int lfb_init(struct lfb_prop *lfbp); >> + >> +#endif >> diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c >> index aaf8b23..1144f76 100644 >> --- a/xen/drivers/video/vesa.c >> +++ b/xen/drivers/video/vesa.c >> @@ -13,20 +13,15 @@ >> #include <asm/io.h> >> #include <asm/page.h> >> #include "font.h" >> +#include "lfb.h" >> >> #define vlfb_info vga_console_info.u.vesa_lfb >> -#define text_columns (vlfb_info.width / font->width) >> -#define text_rows (vlfb_info.height / font->height) >> >> -static void vesa_redraw_puts(const char *s); >> -static void vesa_scroll_puts(const char *s); >> +static void lfb_flush(void); >> >> -static unsigned char *lfb, *lbuf, *text_buf; >> -static unsigned int *__initdata line_len; >> +static unsigned char *lfb; >> static const struct font_desc *font; >> static bool_t vga_compat; >> -static unsigned int pixel_on; >> -static unsigned int xpos, ypos; >> >> static unsigned int vram_total; >> integer_param("vesa-ram", vram_total); >> @@ -87,29 +82,26 @@ void __init vesa_early_init(void) >> >> void __init vesa_init(void) >> { >> - if ( !font ) >> - goto fail; >> - >> - lbuf = xmalloc_bytes(vlfb_info.bytes_per_line); >> - if ( !lbuf ) >> - goto fail; >> + struct lfb_prop lfbp; >> >> - text_buf = xzalloc_bytes(text_columns * text_rows); >> - if ( !text_buf ) >> - goto fail; >> + if ( !font ) >> + return; >> >> - line_len = xzalloc_array(unsigned int, text_columns); >> - if ( !line_len ) >> - goto fail; >> + lfbp.font = font; >> + lfbp.bits_per_pixel = vlfb_info.bits_per_pixel; >> + lfbp.bytes_per_line = vlfb_info.bytes_per_line; >> + lfbp.width = vlfb_info.width; >> + lfbp.height = vlfb_info.height; >> + lfbp.flush = lfb_flush; >> + lfbp.text_columns = vlfb_info.width / font->width; >> + lfbp.text_rows = vlfb_info.height / font->height; >> >> - lfb = ioremap(vlfb_info.lfb_base, vram_remap); >> + lfbp.lfb = lfb = ioremap(vlfb_info.lfb_base, vram_remap); >> if ( !lfb ) >> - goto fail; >> + return; >> >> memset(lfb, 0, vram_remap); >> >> - video_puts = vesa_redraw_puts; >> - >> printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " >> "using %uk, total %uk\n", >> vlfb_info.lfb_base, lfb, >> @@ -131,7 +123,7 @@ void __init vesa_init(void) >> { >> /* Light grey in truecolor. */ >> unsigned int grey = 0xaaaaaaaa; >> - pixel_on = >> + fbp.pixel_on = >> ((grey >> (32 - vlfb_info. red_size)) << vlfb_info. red_pos) | >> ((grey >> (32 - vlfb_info.green_size)) << vlfb_info.green_pos) | >> ((grey >> (32 - vlfb_info. blue_size)) << vlfb_info. blue_pos); >> @@ -139,15 +131,12 @@ void __init vesa_init(void) >> else >> { >> /* White(ish) in default pseudocolor palette. */ >> - pixel_on = 7; >> + fbp.pixel_on = 7; >> } >> >> - return; >> - >> - fail: >> - xfree(lbuf); >> - xfree(text_buf); >> - xfree(line_len); >> + if ( lfb_init(&lfbp) < 0 ) >> + return; >> + video_puts = lfb_redraw_puts; >> } >> >> #include <asm/mtrr.h> >> @@ -192,8 +181,8 @@ void __init vesa_endboot(bool_t keep) >> { >> if ( keep ) >> { >> - xpos = 0; >> - video_puts = vesa_scroll_puts; >> + video_puts = lfb_scroll_puts; >> + lfb_carriage_return(); >> } >> else >> { >> @@ -202,124 +191,6 @@ void __init vesa_endboot(bool_t keep) >> memset(lfb + i * vlfb_info.bytes_per_line, 0, >> vlfb_info.width * bpp); >> lfb_flush(); >> + lfb_free(); >> } >> - >> - xfree(line_len); >> -} >> - >> -/* Render one line of text to given linear framebuffer line. */ >> -static void vesa_show_line( >> - const unsigned char *text_line, >> - unsigned char *video_line, >> - unsigned int nr_chars, >> - unsigned int nr_cells) >> -{ >> - unsigned int i, j, b, bpp, pixel; >> - >> - bpp = (vlfb_info.bits_per_pixel + 7) >> 3; >> - >> - for ( i = 0; i < font->height; i++ ) >> - { >> - unsigned char *ptr = lbuf; >> - >> - for ( j = 0; j < nr_chars; j++ ) >> - { >> - const unsigned char *bits = font->data; >> - bits += ((text_line[j] * font->height + i) * >> - ((font->width + 7) >> 3)); >> - for ( b = font->width; b--; ) >> - { >> - pixel = (*bits & (1u<<b)) ? pixel_on : 0; >> - memcpy(ptr, &pixel, bpp); >> - ptr += bpp; >> - } >> - } >> - >> - memset(ptr, 0, (vlfb_info.width - nr_chars * font->width) * bpp); >> - memcpy(video_line, lbuf, nr_cells * font->width * bpp); >> - video_line += vlfb_info.bytes_per_line; >> - } >> -} >> - >> -/* Fast mode which redraws all modified parts of a 2D text buffer. */ >> -static void __init vesa_redraw_puts(const char *s) >> -{ >> - unsigned int i, min_redraw_y = ypos; >> - char c; >> - >> - /* Paste characters into text buffer. */ >> - while ( (c = *s++) != '\0' ) >> - { >> - if ( (c == '\n') || (xpos >= text_columns) ) >> - { >> - if ( ++ypos >= text_rows ) >> - { >> - min_redraw_y = 0; >> - ypos = text_rows - 1; >> - memmove(text_buf, text_buf + text_columns, >> - ypos * text_columns); >> - memset(text_buf + ypos * text_columns, 0, xpos); >> - } >> - xpos = 0; >> - } >> - >> - if ( c != '\n' ) >> - text_buf[xpos++ + ypos * text_columns] = c; >> - } >> - >> - /* Render modified section of text buffer to VESA linear framebuffer. */ >> - for ( i = min_redraw_y; i <= ypos; i++ ) >> - { >> - const unsigned char *line = text_buf + i * text_columns; >> - unsigned int width; >> - >> - for ( width = text_columns; width; --width ) >> - if ( line[width - 1] ) >> - break; >> - vesa_show_line(line, >> - lfb + i * font->height * vlfb_info.bytes_per_line, >> - width, max(line_len[i], width)); >> - line_len[i] = width; >> - } >> - >> - lfb_flush(); >> -} >> - >> -/* Slower line-based scroll mode which interacts better with dom0. */ >> -static void vesa_scroll_puts(const char *s) >> -{ >> - unsigned int i; >> - char c; >> - >> - while ( (c = *s++) != '\0' ) >> - { >> - if ( (c == '\n') || (xpos >= text_columns) ) >> - { >> - unsigned int bytes = (vlfb_info.width * >> - ((vlfb_info.bits_per_pixel + 7) >> 3)); >> - unsigned char *src = lfb + font->height * >> vlfb_info.bytes_per_line; >> - unsigned char *dst = lfb; >> - >> - /* New line: scroll all previous rows up one line. */ >> - for ( i = font->height; i < vlfb_info.height; i++ ) >> - { >> - memcpy(dst, src, bytes); >> - src += vlfb_info.bytes_per_line; >> - dst += vlfb_info.bytes_per_line; >> - } >> - >> - /* Render new line. */ >> - vesa_show_line( >> - text_buf, >> - lfb + (text_rows-1) * font->height * >> vlfb_info.bytes_per_line, >> - xpos, text_columns); >> - >> - xpos = 0; >> - } >> - >> - if ( c != '\n' ) >> - text_buf[xpos++] = c; >> - } >> - >> - lfb_flush(); >> } >> -- >> 1.7.2.5 >> > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |