Hi all,
these are the remaining unapplied patches of the ARM HDLCD patch series.
Changes in v7:
- rebased on b61ed421d2c85b5b106c63f2c14f8aa162b282f0;
- turn more printk and panic into early_printk and early_panic.
Changes in v6:
- rebased on 77d3a1db3196b1b5864469f8d3f41d496800c795;
- remove useless initializations to NULL in lfb_init;
- more compact checks in lfb_init.
Changes in v5:
- move the barriers outside the loop in flush_xen_data_tlb_range_va;
- move out of "introduce early_ioremap" any changes related to
flush_xen_data_tlb_range_va and PAGE masks;
- remove lfb_alloc and the now unused __initdata variables;
- fix indentation and long lines;
- reword commit message of "move setup_mm right after
setup_pagetables";
- turn printk in setup_mm into an early_printk in setup_mm;
- actually include the Makefile for xen/arch/arm/platforms.
Changes in v4:
- rename flush_xen_data_tlb_range to flush_xen_data_tlb_range_va;
- replace all the calls to flush_xen_data_tlb_va, with calls to
flush_xen_data_tlb_range_va;
- flush the entire 2MB mapping at BOOT_MISC_VIRT_START rather than just
the first 4k;
- remove flush_xen_data_tlb_va;
- fix indentation;
- rename EARLY_VMAP_START/END to EARLY_VMAP_VIRT_START/END;
- mark early_ioremap as __init;
- reduce the amount of casts in early_ioremap;
- 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;
- remove "preserve DTB mappings";
- introduce a new "move setup_mm right after setup_pagetables" patch;
- stop iterating over the DT nodes in device_tree_for_each_node if
func returns a value != 0;
- return 1 from _find_compatible_node when a node is found;
- move the wait loop and the syscfg cfgctrl write into a separate
function;
- fix comments;
- define all registers in write;
- move platform_vexpress.c to platforms/vexpress.c;
- move platform_vexpress.h to arm-arm/platforms/vexpress.h;
- use a lookup table to set the color masks;
- fix indentation;
- make sure mode_string is not NULL and is not bigger than 16 chars
before continuing;
- introduce 2 separate error messages for !hdlcd_start and
!framebuffer_start at the beginning of video_init;
- mark get_color_masks and set_pixclock as __init;
- check that we are running on a vexpress machine before calling
vexpress_syscfg.
Changes in v3:
- rename fb_cr to fb_carriage_return.
Changes in v2:
- rebase on latest xen-unstable;
- add support for multiple resolutions;
- add support to dynamically change the OSC5 motherboard timer;
- add the patch "preserve DTB mappings".
Stefano Stabellini (5):
xen: introduce a generic framebuffer driver
xen/arm: move setup_mm right after setup_pagetables
xen/device_tree: introduce find_compatible_node
xen/arm: introduce vexpress_syscfg
xen/arm: introduce a driver for the ARM HDLCD controller
xen/arch/arm/Makefile | 1 +
xen/arch/arm/Rules.mk | 1 +
xen/arch/arm/arm32/mode_switch.S | 2 +-
xen/arch/arm/platforms/Makefile | 1 +
xen/arch/arm/platforms/vexpress.c | 100 +++++++++++
xen/arch/arm/setup.c | 14 +-
xen/common/device_tree.c | 56 ++++++-
xen/common/page_alloc.c | 6 -
xen/drivers/video/Makefile | 2 +
xen/drivers/video/arm_hdlcd.c | 276 ++++++++++++++++++++++++++++++
xen/drivers/video/lfb.c | 183 ++++++++++++++++++++
xen/drivers/video/lfb.h | 46 +++++
xen/drivers/video/modelines.h | 77 +++++++++
xen/drivers/video/vesa.c | 177 +++-----------------
xen/include/asm-arm/config.h | 2 +
xen/include/asm-arm/platform_vexpress.h | 17 --
xen/include/asm-arm/platforms/vexpress.h | 40 +++++
xen/include/xen/device_tree.h | 3 +
18 files changed, 817 insertions(+), 187 deletions(-)
Cheers,
Stefano
Stefano Stabellini
2013-Feb-14 17:30 UTC
[PATCH v7 1/5] xen: introduce a generic framebuffer driver
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@eu.citrix.com>
Acked-by: Jan Beulich <JBeulich@suse.com>
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@eu.citrix.com>
+ * 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
Stefano Stabellini
2013-Feb-14 17:30 UTC
[PATCH v7 2/5] xen/arm: move setup_mm right after setup_pagetables
At the moment we destroy the DTB mappings we have in setup_pagetables
and we restore them only in setup_mm.
Move setup_mm right after setup_pagetables.
This ensures we have a valid DTB mapping while running the subsequent
initialization code.
Changes in v7:
- turn more printk''s into early_printk.
Changes in v5:
- reword commit message;
- turn printk in setup_mm into an early_printk.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
xen/arch/arm/setup.c | 7 +++----
xen/common/page_alloc.c | 6 ------
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index e1ab7f6..c568be5 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -246,11 +246,11 @@ static void __init setup_mm(unsigned long dtb_paddr,
size_t dtb_size)
} while ( xenheap_pages > 128<<(20-PAGE_SHIFT) );
if ( ! e )
- panic("Not not enough space for xenheap\n");
+ early_panic("Not not enough space for xenheap\n");
domheap_pages = heap_pages - xenheap_pages;
- printk("Xen heap: %lu pages Dom heap: %lu pages\n",
xenheap_pages, domheap_pages);
+ early_printk("Xen heap: %lu pages Dom heap: %lu pages\n",
xenheap_pages, domheap_pages);
setup_xenheap_mappings((e >> PAGE_SHIFT) - xenheap_pages,
xenheap_pages);
@@ -349,6 +349,7 @@ void __init start_xen(unsigned long boot_phys_offset,
cmdline_parse(device_tree_bootargs(fdt));
setup_pagetables(boot_phys_offset, get_xen_paddr());
+ setup_mm(atag_paddr, fdt_size);
#ifdef EARLY_UART_ADDRESS
/* TODO Need to get device tree or command line for UART address */
@@ -366,8 +367,6 @@ void __init start_xen(unsigned long boot_phys_offset,
set_current((struct vcpu *)0xfffff000); /* debug sanity */
idle_vcpu[0] = current;
- setup_mm(atag_paddr, fdt_size);
-
/* Setup Hyp vector base */
WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR);
printk("Set hyp vector base to %"PRIx32" (expected
%p)\n",
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 6b8bc39..6c2215b 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -182,12 +182,6 @@ void __init init_boot_pages(paddr_t ps, paddr_t pe)
else if ( *p != ''\0'' )
break;
- if ( bad_epfn == bad_spfn )
- printk("Marking page %lx as bad\n", bad_spfn);
- else
- printk("Marking pages %lx through %lx as bad\n",
- bad_spfn, bad_epfn);
-
bootmem_region_zap(bad_spfn, bad_epfn+1);
}
}
--
1.7.2.5
Stefano Stabellini
2013-Feb-14 17:30 UTC
[PATCH v7 3/5] xen/device_tree: introduce find_compatible_node
Introduce a find_compatible_node function that can be used by device
drivers to find the node corresponding to their device in the device
tree.
Initialize device_tree_flattened early in start_xen, so that it is
available before setup_mm. Get rid of fdt in the process.
Also add device_tree_node_compatible to device_tree.h, that is currently
missing.
Changes in v4:
- stop iterating over the DT nodes in device_tree_for_each_node if func
returns a value != 0;
- return 1 from _find_compatible_node when a node is found.
Changes in v2:
- remove fdt;
- return early from _find_compatible_node, if a node has already been
found.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
xen/arch/arm/setup.c | 7 ++---
xen/common/device_tree.c | 56 +++++++++++++++++++++++++++++++++++++++-
xen/include/xen/device_tree.h | 3 ++
3 files changed, 60 insertions(+), 6 deletions(-)
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index c568be5..52d2e7a 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -333,7 +333,6 @@ void __init start_xen(unsigned long boot_phys_offset,
unsigned long atag_paddr,
unsigned long cpuid)
{
- void *fdt;
size_t fdt_size;
int cpus, i;
@@ -341,12 +340,12 @@ void __init start_xen(unsigned long boot_phys_offset,
smp_clear_cpu_maps();
- fdt = (void *)BOOT_MISC_VIRT_START
+ device_tree_flattened = (void *)BOOT_MISC_VIRT_START
+ (atag_paddr & ((1 << SECOND_SHIFT) - 1));
- fdt_size = device_tree_early_init(fdt);
+ fdt_size = device_tree_early_init(device_tree_flattened);
cpus = smp_get_max_cpus();
- cmdline_parse(device_tree_bootargs(fdt));
+ cmdline_parse(device_tree_bootargs(device_tree_flattened));
setup_pagetables(boot_phys_offset, get_xen_paddr());
setup_mm(atag_paddr, fdt_size);
diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index 260c2d4..cef4b88 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -140,7 +140,7 @@ u32 device_tree_get_u32(const void *fdt, int node, const
char *prop_name)
* Any nodes nested at DEVICE_TREE_MAX_DEPTH or deeper are ignored.
*
* Returns 0 if all nodes were iterated over successfully. If @func
- * returns a negative value, that value is returned immediately.
+ * returns a value different from 0, that value is returned immediately.
*/
int device_tree_for_each_node(const void *fdt,
device_tree_node_func func, void *data)
@@ -169,12 +169,64 @@ int device_tree_for_each_node(const void *fdt,
ret = func(fdt, node, name, depth,
address_cells[depth-1], size_cells[depth-1], data);
- if ( ret < 0 )
+ if ( ret != 0 )
return ret;
}
return 0;
}
+struct find_compat {
+ const char *compatible;
+ int found;
+ int node;
+ int depth;
+ u32 address_cells;
+ u32 size_cells;
+};
+
+static int _find_compatible_node(const void *fdt,
+ int node, const char *name, int depth,
+ u32 address_cells, u32 size_cells,
+ void *data)
+{
+ struct find_compat *c = (struct find_compat *) data;
+
+ if ( c->found )
+ return 1;
+
+ if ( device_tree_node_compatible(fdt, node, c->compatible) )
+ {
+ c->found = 1;
+ c->node = node;
+ c->depth = depth;
+ c->address_cells = address_cells;
+ c->size_cells = size_cells;
+ return 1;
+ }
+ return 0;
+}
+
+int find_compatible_node(const char *compatible, int *node, int *depth,
+ u32 *address_cells, u32 *size_cells)
+{
+ int ret;
+ struct find_compat c;
+ c.compatible = compatible;
+ c.found = 0;
+
+ ret = device_tree_for_each_node(device_tree_flattened,
_find_compatible_node, &c);
+ if ( !c.found )
+ return ret;
+ else
+ {
+ *node = c.node;
+ *depth = c.depth;
+ *address_cells = c.address_cells;
+ *size_cells = c.size_cells;
+ return 1;
+ }
+}
+
/**
* device_tree_bootargs - return the bootargs (the Xen command line)
* @fdt flat device tree.
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 52ef258..1d04e4f 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -68,6 +68,9 @@ void device_tree_set_reg(u32 **cell, u32 address_cells, u32
size_cells,
u64 start, u64 size);
u32 device_tree_get_u32(const void *fdt, int node, const char *prop_name);
bool_t device_tree_node_matches(const void *fdt, int node, const char *match);
+bool_t device_tree_node_compatible(const void *fdt, int node, const char
*match);
+int find_compatible_node(const char *compatible, int *node, int *depth,
+ u32 *address_cells, u32 *size_cells);
int device_tree_for_each_node(const void *fdt,
device_tree_node_func func, void *data);
const char *device_tree_bootargs(const void *fdt);
--
1.7.2.5
Stefano Stabellini
2013-Feb-14 17:30 UTC
[PATCH v7 4/5] xen/arm: introduce vexpress_syscfg
Introduce a Versatile Express specific function to read/write
motherboard settings.
Changes in v5:
- actually include the Makefile.
Changes in v4:
- move the wait loop and the syscfg cfgctrl write into a separate
function;
- fix comments;
- define all registers in write;
- move platform_vexpress.c to platforms/vexpress.c;
- move platform_vexpress.h to arm-arm/platforms/vexpress.h.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
---
xen/arch/arm/Makefile | 1 +
xen/arch/arm/arm32/mode_switch.S | 2 +-
xen/arch/arm/platforms/Makefile | 1 +
xen/arch/arm/platforms/vexpress.c | 100 ++++++++++++++++++++++++++++++
xen/include/asm-arm/platform_vexpress.h | 17 -----
xen/include/asm-arm/platforms/vexpress.h | 40 ++++++++++++
6 files changed, 143 insertions(+), 18 deletions(-)
create mode 100644 xen/arch/arm/platforms/Makefile
create mode 100644 xen/arch/arm/platforms/vexpress.c
delete mode 100644 xen/include/asm-arm/platform_vexpress.h
create mode 100644 xen/include/asm-arm/platforms/vexpress.h
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index f2822f2..3954dbb 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -1,4 +1,5 @@
subdir-$(arm32) += arm32
+subdir-y += platforms
obj-y += early_printk.o
obj-y += domain.o
diff --git a/xen/arch/arm/arm32/mode_switch.S b/xen/arch/arm/arm32/mode_switch.S
index 411eb92..bc2be74 100644
--- a/xen/arch/arm/arm32/mode_switch.S
+++ b/xen/arch/arm/arm32/mode_switch.S
@@ -19,7 +19,7 @@
#include <asm/config.h>
#include <asm/page.h>
-#include <asm/platform_vexpress.h>
+#include <asm/platforms/vexpress.h>
#include <asm/asm_defns.h>
#include <asm/gic.h>
diff --git a/xen/arch/arm/platforms/Makefile b/xen/arch/arm/platforms/Makefile
new file mode 100644
index 0000000..4313e95
--- /dev/null
+++ b/xen/arch/arm/platforms/Makefile
@@ -0,0 +1 @@
+obj-y += vexpress.o
diff --git a/xen/arch/arm/platforms/vexpress.c
b/xen/arch/arm/platforms/vexpress.c
new file mode 100644
index 0000000..b57b62e
--- /dev/null
+++ b/xen/arch/arm/platforms/vexpress.c
@@ -0,0 +1,100 @@
+/*
+ * xen/arch/arm/platform_vexpress.c
+ *
+ * Versatile Express specific settings
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * 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.
+ */
+
+#include <asm/platforms/vexpress.h>
+#include <xen/mm.h>
+
+#define DCC_SHIFT 26
+#define FUNCTION_SHIFT 20
+#define SITE_SHIFT 16
+#define POSITION_SHIFT 12
+#define DEVICE_SHIFT 0
+
+static inline int vexpress_ctrl_start(uint32_t *syscfg, int write,
+ int function, int device)
+{
+ int dcc = 0; /* DCC to access */
+ int site = 0; /* motherboard */
+ int position = 0; /* daughterboard */
+ uint32_t stat;
+
+ /* set control register */
+ syscfg[V2M_SYS_CFGCTRL/4] = V2M_SYS_CFG_START |
+ (write ? V2M_SYS_CFG_WRITE : 0) |
+ (dcc << DCC_SHIFT) | (function << FUNCTION_SHIFT) |
+ (site << SITE_SHIFT) | (position << POSITION_SHIFT) |
+ (device << DEVICE_SHIFT);
+
+ /* wait for complete flag to be set */
+ do {
+ stat = syscfg[V2M_SYS_CFGSTAT/4];
+ dsb();
+ } while ( !(stat & V2M_SYS_CFG_COMPLETE) );
+
+ /* check error status and return error flag if set */
+ if ( stat & V2M_SYS_CFG_ERROR )
+ {
+ printk(KERN_ERR "V2M SYS_CFGSTAT reported a configuration
error\n");
+ return -1;
+ }
+ return 0;
+}
+
+int vexpress_syscfg(int write, int function, int device, uint32_t *data)
+{
+ uint32_t *syscfg = (uint32_t *) FIXMAP_ADDR(FIXMAP_MISC);
+ int ret = -1;
+
+ set_fixmap(FIXMAP_MISC, V2M_SYS_MMIO_BASE >> PAGE_SHIFT, DEV_SHARED);
+
+ if ( syscfg[V2M_SYS_CFGCTRL/4] & V2M_SYS_CFG_START )
+ goto out;
+
+ /* clear the complete bit in the V2M_SYS_CFGSTAT status register */
+ syscfg[V2M_SYS_CFGSTAT/4] = 0;
+
+ if ( write )
+ {
+ /* write data */
+ syscfg[V2M_SYS_CFGDATA/4] = *data;
+
+ if ( vexpress_ctrl_start(syscfg, write, function, device) < 0 )
+ goto out;
+ } else {
+ if ( vexpress_ctrl_start(syscfg, write, function, device) < 0 )
+ goto out;
+ else
+ /* read data */
+ *data = syscfg[V2M_SYS_CFGDATA/4];
+ }
+
+ ret = 0;
+out:
+ clear_fixmap(FIXMAP_MISC);
+ return ret;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/platform_vexpress.h
b/xen/include/asm-arm/platform_vexpress.h
deleted file mode 100644
index 3556af3..0000000
--- a/xen/include/asm-arm/platform_vexpress.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef __ASM_ARM_PLATFORM_H
-#define __ASM_ARM_PLATFORM_H
-
-/* V2M */
-#define V2M_SYS_MMIO_BASE (0x1c010000)
-#define V2M_SYS_FLAGSSET (0x30)
-#define V2M_SYS_FLAGSCLR (0x34)
-
-#endif /* __ASM_ARM_PLATFORM_H */
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-arm/platforms/vexpress.h
b/xen/include/asm-arm/platforms/vexpress.h
new file mode 100644
index 0000000..e464913
--- /dev/null
+++ b/xen/include/asm-arm/platforms/vexpress.h
@@ -0,0 +1,40 @@
+#ifndef __ASM_ARM_PLATFORMS_VEXPRESS_H
+#define __ASM_ARM_PLATFORMS_VEXPRESS_H
+
+/* V2M */
+#define V2M_SYS_MMIO_BASE (0x1c010000)
+#define V2M_SYS_FLAGSSET (0x30)
+#define V2M_SYS_FLAGSCLR (0x34)
+
+#define V2M_SYS_CFGDATA (0x00A0)
+#define V2M_SYS_CFGCTRL (0x00A4)
+#define V2M_SYS_CFGSTAT (0x00A8)
+
+#define V2M_SYS_CFG_START (1<<31)
+#define V2M_SYS_CFG_WRITE (1<<30)
+#define V2M_SYS_CFG_ERROR (1<<1)
+#define V2M_SYS_CFG_COMPLETE (1<<0)
+
+#define V2M_SYS_CFG_OSC_FUNC 1
+#define V2M_SYS_CFG_OSC0 0
+#define V2M_SYS_CFG_OSC1 1
+#define V2M_SYS_CFG_OSC2 2
+#define V2M_SYS_CFG_OSC3 3
+#define V2M_SYS_CFG_OSC4 4
+#define V2M_SYS_CFG_OSC5 5
+
+#ifndef __ASSEMBLY__
+#include <xen/inttypes.h>
+
+int vexpress_syscfg(int write, int function, int device, uint32_t *data);
+#endif
+
+#endif /* __ASM_ARM_PLATFORMS_VEXPRESS_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.7.2.5
Stefano Stabellini
2013-Feb-14 17:30 UTC
[PATCH v7 5/5] xen/arm: introduce a driver for the ARM HDLCD controller
Read the screen resolution setting from device tree, find the
corresponding modeline in a small table of standard video modes, set the
hardware accordingly.
Use vexpress_syscfg to configure the pixel clock.
Use the generic framebuffer functions to print on the screen.
Changes in v4:
- use a lookup table to set the color masks;
- fix indentation;
- make sure mode_string is not NULL and is not bigger than 16 chars
before continuing;
- introduce 2 separate error messages for !hdlcd_start and
!framebuffer_start at the beginning of video_init;
- mark get_color_masks and set_pixclock as __init;
- check that we are running on a vexpress machine before calling
vexpress_syscfg.
Changes in v2:
- read mode from DT;
- support multiple resolutions;
- use vexpress_syscfg to set the pixclock.
Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
xen/arch/arm/Rules.mk | 1 +
xen/drivers/video/Makefile | 1 +
xen/drivers/video/arm_hdlcd.c | 276 +++++++++++++++++++++++++++++++++++++++++
xen/drivers/video/modelines.h | 77 ++++++++++++
xen/include/asm-arm/config.h | 2 +
5 files changed, 357 insertions(+), 0 deletions(-)
create mode 100644 xen/drivers/video/arm_hdlcd.c
create mode 100644 xen/drivers/video/modelines.h
diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk
index 5b5768a..0843e50 100644
--- a/xen/arch/arm/Rules.mk
+++ b/xen/arch/arm/Rules.mk
@@ -8,6 +8,7 @@
HAS_DEVICE_TREE := y
HAS_VIDEO := y
+HAS_ARM_HDLCD := y
CFLAGS += -fno-builtin -fno-common -Wredundant-decls
CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe
diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile
index 77f9d5d..a756292 100644
--- a/xen/drivers/video/Makefile
+++ b/xen/drivers/video/Makefile
@@ -4,3 +4,4 @@ obj-$(HAS_VIDEO) += font_8x16.o
obj-$(HAS_VIDEO) += font_8x8.o
obj-$(HAS_VIDEO) += lfb.o
obj-$(HAS_VGA) += vesa.o
+obj-$(HAS_ARM_HDLCD) += arm_hdlcd.o
diff --git a/xen/drivers/video/arm_hdlcd.c b/xen/drivers/video/arm_hdlcd.c
new file mode 100644
index 0000000..45f9d64
--- /dev/null
+++ b/xen/drivers/video/arm_hdlcd.c
@@ -0,0 +1,276 @@
+/*
+ * xen/drivers/video/arm_hdlcd.c
+ *
+ * Driver for ARM HDLCD Controller
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>
+ * 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.
+ */
+
+#include <asm/delay.h>
+#include <asm/types.h>
+#include <asm/platforms/vexpress.h>
+#include <xen/config.h>
+#include <xen/device_tree.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include "font.h"
+#include "lfb.h"
+#include "modelines.h"
+
+#define HDLCD ((volatile uint32_t *) FIXMAP_ADDR(FIXMAP_MISC))
+
+#define HDLCD_INTMASK (0x18/4)
+#define HDLCD_FBBASE (0x100/4)
+#define HDLCD_LINELENGTH (0x104/4)
+#define HDLCD_LINECOUNT (0x108/4)
+#define HDLCD_LINEPITCH (0x10C/4)
+#define HDLCD_BUS (0x110/4)
+#define HDLCD_VSYNC (0x200/4)
+#define HDLCD_VBACK (0x204/4)
+#define HDLCD_VDATA (0x208/4)
+#define HDLCD_VFRONT (0x20C/4)
+#define HDLCD_HSYNC (0x210/4)
+#define HDLCD_HBACK (0x214/4)
+#define HDLCD_HDATA (0x218/4)
+#define HDLCD_HFRONT (0x21C/4)
+#define HDLCD_POLARITIES (0x220/4)
+#define HDLCD_COMMAND (0x230/4)
+#define HDLCD_PF (0x240/4)
+#define HDLCD_RED (0x244/4)
+#define HDLCD_GREEN (0x248/4)
+#define HDLCD_BLUE (0x24C/4)
+
+struct color_masks {
+ int red_shift;
+ int red_size;
+ int green_shift;
+ int green_size;
+ int blue_shift;
+ int blue_size;
+};
+
+struct pixel_colors {
+ const char* bpp;
+ struct color_masks colors;
+};
+
+struct pixel_colors __initdata colors[] = {
+ { "16", { 0, 5, 11, 5, 6, 5 } },
+ { "24", { 0, 8, 16, 8, 8, 8 } },
+ { "32", { 0, 8, 16, 8, 8, 8 } },
+};
+
+static void vga_noop_puts(const char *s) {}
+void (*video_puts)(const char *) = vga_noop_puts;
+
+static void hdlcd_flush(void)
+{
+ dsb();
+}
+
+static int __init get_color_masks(const char* bpp, struct color_masks **masks)
+{
+ int i;
+ for ( i = 0; i < ARRAY_SIZE(colors); i++ )
+ {
+ if ( !strncmp(colors[i].bpp, bpp, 2) )
+ {
+ *masks = &colors[i].colors;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+static void __init set_pixclock(uint32_t pixclock)
+{
+ if ( device_tree_node_compatible(device_tree_flattened, 0,
"arm,vexpress") )
+ vexpress_syscfg(1, V2M_SYS_CFG_OSC_FUNC,
+ V2M_SYS_CFG_OSC5, &pixclock);
+}
+
+void __init video_init(void)
+{
+ int node, depth;
+ u32 address_cells, size_cells;
+ struct lfb_prop lfbp;
+ unsigned char *lfb;
+ paddr_t hdlcd_start, hdlcd_size;
+ paddr_t framebuffer_start, framebuffer_size;
+ const struct fdt_property *prop;
+ const u32 *cell;
+ const char *mode_string;
+ char _mode_string[16];
+ int bytes_per_pixel = 4;
+ struct color_masks *c = NULL;
+ struct modeline *videomode = NULL;
+ int i;
+
+ if ( find_compatible_node("arm,hdlcd", &node, &depth,
+ &address_cells, &size_cells) <= 0 )
+ return;
+
+ prop = fdt_get_property(device_tree_flattened, node, "reg",
NULL);
+ if ( !prop )
+ return;
+
+ cell = (const u32 *)prop->data;
+ device_tree_get_reg(&cell, address_cells, size_cells,
+ &hdlcd_start, &hdlcd_size);
+
+ prop = fdt_get_property(device_tree_flattened, node,
"framebuffer", NULL);
+ if ( !prop )
+ return;
+
+ cell = (const u32 *)prop->data;
+ device_tree_get_reg(&cell, address_cells, size_cells,
+ &framebuffer_start, &framebuffer_size);
+
+ if ( !hdlcd_start )
+ {
+ printk(KERN_ERR "HDLCD address missing from device tree, disabling
driver\n");
+ return;
+ }
+
+ if ( !hdlcd_start || !framebuffer_start )
+ {
+ printk(KERN_ERR "HDLCD: framebuffer address missing from device
tree, disabling driver\n");
+ return;
+ }
+
+ mode_string = fdt_getprop(device_tree_flattened, node, "mode",
NULL);
+ if ( !mode_string )
+ {
+ get_color_masks("32", &c);
+ memcpy(_mode_string, "1280x1024@60",
strlen("1280x1024@60") + 1);
+ bytes_per_pixel = 4;
+ }
+ else if ( strlen(mode_string) < strlen("800x600@60") ||
+ strlen(mode_string) > sizeof(_mode_string) - 1 )
+ {
+ printk(KERN_ERR "HDLCD: invalid modeline=%s\n", mode_string);
+ return;
+ } else {
+ char *s = strchr(mode_string, ''-'');
+ if ( !s )
+ {
+ printk(KERN_INFO "HDLCD: bpp not found in modeline %s, assume
32 bpp\n",
+ mode_string);
+ get_color_masks("32", &c);
+ memcpy(_mode_string, mode_string, strlen(mode_string) + 1);
+ bytes_per_pixel = 4;
+ } else {
+ if ( strlen(s) < 6 )
+ {
+ printk(KERN_ERR "HDLCD: invalid mode %s\n",
mode_string);
+ return;
+ }
+ s++;
+ if ( get_color_masks(s, &c) < 0 )
+ {
+ printk(KERN_WARNING "HDLCD: unsupported bpp %s\n",
s);
+ return;
+ }
+ bytes_per_pixel = simple_strtoll(s, NULL, 10) / 8;
+ }
+ i = s - mode_string - 1;
+ memcpy(_mode_string, mode_string, i);
+ memcpy(_mode_string + i, mode_string + i + 3, 4);
+ }
+
+ for ( i = 0; i < ARRAY_SIZE(videomodes); i++ ) {
+ if ( !strcmp(_mode_string, videomodes[i].mode) )
+ {
+ videomode = &videomodes[i];
+ break;
+ }
+ }
+ if ( !videomode )
+ {
+ printk(KERN_WARNING "HDLCD: unsupported videomode %s\n",
_mode_string);
+ return;
+ }
+
+ if ( framebuffer_size < bytes_per_pixel * videomode->xres *
videomode->yres )
+ {
+ printk(KERN_ERR "HDLCD: the framebuffer is too small, disabling
the HDLCD driver\n");
+ return;
+ }
+
+ printk(KERN_INFO "Initializing HDLCD driver\n");
+
+ lfb = early_ioremap(framebuffer_start, framebuffer_size, DEV_WC);
+ if ( !lfb )
+ {
+ printk(KERN_ERR "Couldn''t map the framebuffer\n");
+ return;
+ }
+ memset(lfb, 0x00, bytes_per_pixel * videomode->xres *
videomode->yres);
+
+ /* uses FIXMAP_MISC */
+ set_pixclock(videomode->pixclock);
+
+ set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED);
+ HDLCD[HDLCD_COMMAND] = 0;
+
+ HDLCD[HDLCD_LINELENGTH] = videomode->xres * bytes_per_pixel;
+ HDLCD[HDLCD_LINECOUNT] = videomode->yres - 1;
+ HDLCD[HDLCD_LINEPITCH] = videomode->xres * bytes_per_pixel;
+ HDLCD[HDLCD_PF] = ((bytes_per_pixel - 1) << 3);
+ HDLCD[HDLCD_INTMASK] = 0;
+ HDLCD[HDLCD_FBBASE] = framebuffer_start;
+ HDLCD[HDLCD_BUS] = 0xf00 | (1 << 4);
+ HDLCD[HDLCD_VBACK] = videomode->vback - 1;
+ HDLCD[HDLCD_VSYNC] = videomode->vsync - 1;
+ HDLCD[HDLCD_VDATA] = videomode->yres - 1;
+ HDLCD[HDLCD_VFRONT] = videomode->vfront - 1;
+ HDLCD[HDLCD_HBACK] = videomode->hback - 1;
+ HDLCD[HDLCD_HSYNC] = videomode->hsync - 1;
+ HDLCD[HDLCD_HDATA] = videomode->xres - 1;
+ HDLCD[HDLCD_HFRONT] = videomode->hfront - 1;
+ HDLCD[HDLCD_POLARITIES] = (1 << 2) | (1 << 3);
+ HDLCD[HDLCD_RED] = (c->red_size << 8) | c->red_shift;
+ HDLCD[HDLCD_GREEN] = (c->green_size << 8) | c->green_shift;
+ HDLCD[HDLCD_BLUE] = (c->blue_size << 8) | c->blue_shift;
+ HDLCD[HDLCD_COMMAND] = 1;
+ clear_fixmap(FIXMAP_MISC);
+
+ lfbp.pixel_on = (((1 << c->red_size) - 1) <<
c->red_shift) |
+ (((1 << c->green_size) - 1) << c->green_shift) |
+ (((1 << c->blue_size) - 1) << c->blue_shift);
+ lfbp.lfb = lfb;
+ lfbp.font = &font_vga_8x16;
+ lfbp.bits_per_pixel = bytes_per_pixel*8;
+ lfbp.bytes_per_line = bytes_per_pixel*videomode->xres;
+ lfbp.width = videomode->xres;
+ lfbp.height = videomode->yres;
+ lfbp.flush = hdlcd_flush;
+ lfbp.text_columns = videomode->xres / 8;
+ lfbp.text_rows = videomode->yres / 16;
+ if ( lfb_init(&lfbp) < 0 )
+ return;
+ video_puts = lfb_scroll_puts;
+}
+
+void __init video_endboot(void) { }
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/drivers/video/modelines.h b/xen/drivers/video/modelines.h
new file mode 100644
index 0000000..9cb7cdd
--- /dev/null
+++ b/xen/drivers/video/modelines.h
@@ -0,0 +1,77 @@
+/*
+ * xen/drivers/video/modelines.h
+ *
+ * Timings for many popular monitor resolutions
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 1999 by The XFree86 Project, Inc.
+ * Copyright (c) 2013 Citrix Systems
+ */
+
+#ifndef _XEN_MODLINES_H
+#define _XEN_MODLINES_H
+
+struct modeline {
+ const char* mode; /* in the form 1280x1024@60 */
+ uint32_t pixclock; /* Khz */
+ uint32_t xres;
+ uint32_t hfront; /* horizontal front porch in pixels */
+ uint32_t hsync; /* horizontal sync pulse in pixels */
+ uint32_t hback; /* horizontal back porch in pixels */
+ uint32_t yres;
+ uint32_t vfront; /* vertical front porch in lines */
+ uint32_t vsync; /* vertical sync pulse in lines */
+ uint32_t vback; /* vertical back porch in lines */
+};
+
+struct modeline __initdata videomodes[] = {
+ { "640x480@60", 25175, 640, 16, 96, 48, 480, 11, 2,
31 },
+ { "640x480@72", 31500, 640, 24, 40, 128, 480, 9, 3,
28 },
+ { "640x480@75", 31500, 640, 16, 96, 48, 480, 11, 2,
32 },
+ { "640x480@85", 36000, 640, 32, 48, 112, 480, 1, 3,
25 },
+ { "800x600@56", 38100, 800, 32, 128, 128, 600, 1, 4,
14 },
+ { "800x600@60", 40000, 800, 40, 128, 88 , 600, 1, 4,
23 },
+ { "800x600@72", 50000, 800, 56, 120, 64 , 600, 37, 6,
23 },
+ { "800x600@75", 49500, 800, 16, 80, 160, 600, 1, 2,
21 },
+ { "800x600@85", 56250, 800, 32, 64, 152, 600, 1, 3,
27 },
+ { "1024x768@60", 65000, 1024, 24, 136, 160, 768, 3, 6,
29 },
+ { "1024x768@70", 75000, 1024, 24, 136, 144, 768, 3, 6,
29 },
+ { "1024x768@75", 78750, 1024, 16, 96, 176, 768, 1, 3,
28 },
+ { "1024x768@85", 94500, 1024, 48, 96, 208, 768, 1, 3,
36 },
+ { "1280x1024@60", 108000, 1280, 48, 112, 248, 1024, 1, 3,
38 },
+ { "1280x1024@75", 135000, 1280, 16, 144, 248, 1024, 1, 3,
38 },
+ { "1280x1024@85", 157500, 1280, 64, 160, 224, 1024, 1, 3,
44 },
+ { "1400x1050@60", 122610, 1400, 88, 152, 240, 1050, 1, 3,
33 },
+ { "1400x1050@75", 155850, 1400, 96, 152, 248, 1050, 1, 3,
42 },
+ { "1600x1200@60", 162000, 1600, 64, 192, 304, 1200, 1, 3,
46 },
+ { "1600x1200@65", 175500, 1600, 64, 192, 304, 1200, 1, 3,
46 },
+ { "1600x1200@70", 189000, 1600, 64, 192, 304, 1200, 1, 3,
46 },
+ { "1600x1200@75", 202500, 1600, 64, 192, 304, 1200, 1, 3,
46 },
+ { "1600x1200@85", 229500, 1600, 64, 192, 304, 1200, 1, 3,
46 },
+ { "1792x1344@60", 204800, 1792, 128, 200, 328, 1344, 1, 3,
46 },
+ { "1792x1344@75", 261000, 1792, 96, 216, 352, 1344, 1, 3,
69 },
+ { "1856x1392@60", 218300, 1856, 96, 224, 352, 1392, 1, 3,
43 },
+ { "1856x1392@75", 288000, 1856, 128, 224, 352, 1392, 1, 3,
104 },
+ { "1920x1200@75", 193160, 1920, 128, 208, 336, 1200, 1, 3,
38 },
+ { "1920x1440@60", 234000, 1920, 128, 208, 344, 1440, 1, 3,
56 },
+ { "1920x1440@75", 297000, 1920, 144, 224, 352, 1440, 1, 3,
56 },
+};
+
+#endif
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index e5dce5e..8e934a4 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -19,6 +19,8 @@
#define CONFIG_DOMAIN_PAGE 1
+#define CONFIG_VIDEO 1
+
#define OPT_CONSOLE_STR "com1"
#ifdef MAX_PHYS_CPUS
--
1.7.2.5
Stefano Stabellini
2013-Feb-14 17:32 UTC
Re: [PATCH v7 2/5] xen/arm: move setup_mm right after setup_pagetables
On Thu, 14 Feb 2013, Stefano Stabellini wrote:> At the moment we destroy the DTB mappings we have in setup_pagetables > and we restore them only in setup_mm. > > Move setup_mm right after setup_pagetables. > This ensures we have a valid DTB mapping while running the subsequent > initialization code. > > Changes in v7: > - turn more printk''s into early_printk.I forgot to mention in the changelog that I removed two printks from init_boot_pages.> Changes in v5: > - reword commit message; > - turn printk in setup_mm into an early_printk. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/setup.c | 7 +++---- > xen/common/page_alloc.c | 6 ------ > 2 files changed, 3 insertions(+), 10 deletions(-) > > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index e1ab7f6..c568be5 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -246,11 +246,11 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) > } while ( xenheap_pages > 128<<(20-PAGE_SHIFT) ); > > if ( ! e ) > - panic("Not not enough space for xenheap\n"); > + early_panic("Not not enough space for xenheap\n"); > > domheap_pages = heap_pages - xenheap_pages; > > - printk("Xen heap: %lu pages Dom heap: %lu pages\n", xenheap_pages, domheap_pages); > + early_printk("Xen heap: %lu pages Dom heap: %lu pages\n", xenheap_pages, domheap_pages); > > setup_xenheap_mappings((e >> PAGE_SHIFT) - xenheap_pages, xenheap_pages); > > @@ -349,6 +349,7 @@ void __init start_xen(unsigned long boot_phys_offset, > cmdline_parse(device_tree_bootargs(fdt)); > > setup_pagetables(boot_phys_offset, get_xen_paddr()); > + setup_mm(atag_paddr, fdt_size); > > #ifdef EARLY_UART_ADDRESS > /* TODO Need to get device tree or command line for UART address */ > @@ -366,8 +367,6 @@ void __init start_xen(unsigned long boot_phys_offset, > set_current((struct vcpu *)0xfffff000); /* debug sanity */ > idle_vcpu[0] = current; > > - setup_mm(atag_paddr, fdt_size); > - > /* Setup Hyp vector base */ > WRITE_CP32((uint32_t) hyp_traps_vector, HVBAR); > printk("Set hyp vector base to %"PRIx32" (expected %p)\n", > diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c > index 6b8bc39..6c2215b 100644 > --- a/xen/common/page_alloc.c > +++ b/xen/common/page_alloc.c > @@ -182,12 +182,6 @@ void __init init_boot_pages(paddr_t ps, paddr_t pe) > else if ( *p != ''\0'' ) > break; > > - if ( bad_epfn == bad_spfn ) > - printk("Marking page %lx as bad\n", bad_spfn); > - else > - printk("Marking pages %lx through %lx as bad\n", > - bad_spfn, bad_epfn); > - > bootmem_region_zap(bad_spfn, bad_epfn+1); > } > } > -- > 1.7.2.5 >
Ian Campbell
2013-Feb-15 12:41 UTC
Re: [PATCH v7 1/5] xen: introduce a generic framebuffer driver
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@eu.citrix.com> > Acked-by: Jan Beulich <JBeulich@suse.com> > > 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@eu.citrix.com> > + * 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 >
Keir Fraser
2013-Feb-15 13:15 UTC
Re: [PATCH v7 1/5] xen: introduce a generic framebuffer driver
Yep Acked-by: Keir Fraser <keir@xen.org> On 15/02/2013 12:41, "Ian Campbell" <Ian.Campbell@citrix.com> 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@eu.citrix.com> >> Acked-by: Jan Beulich <JBeulich@suse.com> >> >> 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@eu.citrix.com> >> + * 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 >> > >
On Thu, 2013-02-14 at 17:30 +0000, Stefano Stabellini wrote:> Stefano Stabellini (5): > xen: introduce a generic framebuffer driverNeeded ack from Keir when I first went through my queue. He has given it now so I''ll go back to this one.> xen/arm: move setup_mm right after setup_pagetables > xen/device_tree: introduce find_compatible_node > xen/arm: introduce vexpress_syscfgAcked + applied these with s/atag_paddr/fdt_paddr/ since it was on top of " xen: arm: rename atag_paddr argument fdt_paddr"> xen/arm: introduce a driver for the ARM HDLCD controllerNeeds the first one. Ian.
Ian Campbell
2013-Feb-15 14:07 UTC
Re: [PATCH v7 1/5] xen: introduce a generic framebuffer driver
On Thu, 2013-02-14 at 17:30 +0000, Stefano Stabellini wrote:> xen/drivers/video/Makefile | 1 + > xen/drivers/video/lfb.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ > xen/drivers/video/lfb.h | 46 +++++++++++ > xen/drivers/video/vesa.c | 177 ++++++------------------------------------On x86_64; vesa.c: In function ‘vesa_init’: vesa.c:126: error: ‘fbp’ undeclared (first use in this function) vesa.c:126: error: (Each undeclared identifier is reported only once vesa.c:126: error: for each function it appears in.) I think this fixes it, if it does then I'm happy to role in as I apply. diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c index 1fbe959..575db62 100644 --- a/xen/drivers/video/vesa.c +++ b/xen/drivers/video/vesa.c @@ -123,7 +123,7 @@ void __init vesa_init(void) { /* Light grey in truecolor. */ unsigned int grey = 0xaaaaaaaa; - fbp.pixel_on + lfbp.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); @@ -131,7 +131,7 @@ void __init vesa_init(void) else { /* White(ish) in default pseudocolor palette. */ - fbp.pixel_on = 7; + lfbp.pixel_on = 7; } if ( lfb_init(&lfbp) < 0 ) _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Stefano Stabellini
2013-Feb-15 14:09 UTC
Re: [PATCH v7 1/5] xen: introduce a generic framebuffer driver
On Fri, 15 Feb 2013, Ian Campbell wrote:> On Thu, 2013-02-14 at 17:30 +0000, Stefano Stabellini wrote: > > xen/drivers/video/Makefile | 1 + > > xen/drivers/video/lfb.c | 183 ++++++++++++++++++++++++++++++++++++++++++++ > > xen/drivers/video/lfb.h | 46 +++++++++++ > > xen/drivers/video/vesa.c | 177 ++++++------------------------------------ > > On x86_64; > > vesa.c: In function ‘vesa_init’: > vesa.c:126: error: ‘fbp’ undeclared (first use in this function) > vesa.c:126: error: (Each undeclared identifier is reported only once > vesa.c:126: error: for each function it appears in.) > > I think this fixes it, if it does then I''m happy to role in as I apply.Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>> diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c > index 1fbe959..575db62 100644 > --- a/xen/drivers/video/vesa.c > +++ b/xen/drivers/video/vesa.c > @@ -123,7 +123,7 @@ void __init vesa_init(void) > { > /* Light grey in truecolor. */ > unsigned int grey = 0xaaaaaaaa; > - fbp.pixel_on > + lfbp.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); > @@ -131,7 +131,7 @@ void __init vesa_init(void) > else > { > /* White(ish) in default pseudocolor palette. */ > - fbp.pixel_on = 7; > + lfbp.pixel_on = 7; > } > > if ( lfb_init(&lfbp) < 0 ) > > >_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
On Thu, 2013-02-14 at 17:30 +0000, Stefano Stabellini wrote:> Stefano Stabellini (5): > xen: introduce a generic framebuffer driver > xen/arm: introduce a driver for the ARM HDLCD controllerI''ve now applied these as well, with the fixes to the first as previously discussed.
Seemingly Similar Threads
- [Bug 63263] New: X server crash in nouveau_xv.c:NVPutImage (NVCopyNV12ColorPlanes)
- [PATCH 1/2] exa: Pre-G80 tiling support.
- Bug report about Windows 7 pro 64 bit domU on xen-unstable dom0 with qemu traditional
- Device model failure: no longer running with HVM-Guest
- pci passthrough error "unknown command"pci-ins"