Hi all, this patch series introduces a very simple driver for the ARM HDLCD Controller, that means that we can finally have something on the screen while Xen is booting on ARM :) The driver is very limited at the moment and it is only capable of setting one resolution that is 1280x1024. Also it requires the OSC5 timer to be set to 108Mhz in the Versatile Express config file. In order to reduce code duplication with x86, I tried to generalize the existing vesa character rendering functions into a architecture agnostic framebuffer driver that can be used by vesa and the hdlcd drivers. I would very much appreciate if you could give a close look at the vesa changes because I don''t have any x86 test machines that boot in vesa mode, therefore I couldn''t test it. Stefano Stabellini (6): xen/arm: introduce map_phys_range xen: infrastructure to have cross-platform video drivers xen: introduce a generic framebuffer driver xen/vesa: use the new fb_* functions xen/device_tree: introduce find_compatible_node xen/arm: introduce a driver for the ARM HDLCD controller xen/arch/arm/Rules.mk | 2 + xen/arch/arm/mm.c | 23 +++++ xen/arch/arm/setup.c | 2 +- xen/arch/x86/Rules.mk | 1 + xen/common/device_tree.c | 47 +++++++++ xen/drivers/Makefile | 2 +- xen/drivers/char/console.c | 12 +- xen/drivers/video/Makefile | 12 ++- xen/drivers/video/arm_hdlcd.c | 165 ++++++++++++++++++++++++++++++++ xen/drivers/video/fb.c | 209 +++++++++++++++++++++++++++++++++++++++++ xen/drivers/video/fb.h | 44 +++++++++ xen/drivers/video/vesa.c | 179 +++++------------------------------ xen/drivers/video/vga.c | 12 +- xen/include/asm-arm/config.h | 3 + xen/include/asm-arm/mm.h | 3 + xen/include/asm-x86/config.h | 1 + xen/include/xen/device_tree.h | 3 + xen/include/xen/vga.h | 9 +-- xen/include/xen/video.h | 24 +++++ 19 files changed, 573 insertions(+), 180 deletions(-) Cheers, Stefano
Introduce a function to map a physical memory into virtual memory. It is going to be used later to map the videoram. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/mm.c | 23 +++++++++++++++++++++++ xen/include/asm-arm/mm.h | 3 +++ 2 files changed, 26 insertions(+), 0 deletions(-) diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index 68ee9da..418a414 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -376,6 +376,29 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); } +/* Map the physical memory range start - end at the virtual address + * virt_start in 2MB chunks. start and virt_start have to be 2MB + * aligned. + */ +void map_phys_range(paddr_t start, paddr_t end, + unsigned long virt_start, unsigned attributes) +{ + ASSERT(!(start & ((1 << 21) - 1))); + ASSERT(!(virt_start & ((1 << 21) - 1))); + + while ( start < end ) + { + lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT); + e.pt.ai = attributes; + write_pte(xen_second + second_table_offset(virt_start), e); + + start += (1<<21); + virt_start += (1<<21); + } + + flush_xen_data_tlb(); +} + enum mg { mg_clear, mg_ro, mg_rw, mg_rx }; static void set_pte_flags_on_range(const char *p, unsigned long l, enum mg mg) { diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h index 3549c83..a11f20b 100644 --- a/xen/include/asm-arm/mm.h +++ b/xen/include/asm-arm/mm.h @@ -152,6 +152,9 @@ extern void setup_frametable_mappings(paddr_t ps, paddr_t pe); extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes); /* Remove a mapping from a fixmap entry */ extern void clear_fixmap(unsigned map); +/* map a 2MB aligned physical range in virtual memory. */ +extern void map_phys_range(paddr_t start, paddr_t end, + unsigned long virt_start, unsigned attributes); #define mfn_valid(mfn) ({ \ -- 1.7.2.5
Stefano Stabellini
2012-Dec-05 18:19 UTC
[PATCH 2/6] xen: infrastructure to have cross-platform video drivers
- introduce a new HAS_VIDEO config variable; - build xen/drivers/video/font* if HAS_VIDEO; - rename vga_puts to video_puts; - rename vga_init to video_init; - rename vga_endboot to video_endboot. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/Rules.mk | 1 + xen/arch/x86/Rules.mk | 1 + xen/drivers/Makefile | 2 +- xen/drivers/char/console.c | 12 ++++++------ xen/drivers/video/Makefile | 10 +++++----- xen/drivers/video/vesa.c | 4 ++-- xen/drivers/video/vga.c | 12 ++++++------ xen/include/asm-x86/config.h | 1 + xen/include/xen/vga.h | 9 +-------- xen/include/xen/video.h | 24 ++++++++++++++++++++++++ 10 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 xen/include/xen/video.h diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk index a45c654..fa9f9c1 100644 --- a/xen/arch/arm/Rules.mk +++ b/xen/arch/arm/Rules.mk @@ -7,6 +7,7 @@ # HAS_DEVICE_TREE := y +HAS_VIDEO := y CFLAGS += -fno-builtin -fno-common -Wredundant-decls CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk index 963850f..0a9d68d 100644 --- a/xen/arch/x86/Rules.mk +++ b/xen/arch/x86/Rules.mk @@ -3,6 +3,7 @@ HAS_ACPI := y HAS_VGA := y +HAS_VIDEO := y HAS_CPUFREQ := y HAS_PCI := y HAS_PASSTHROUGH := y diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile index 7239375..9c70f20 100644 --- a/xen/drivers/Makefile +++ b/xen/drivers/Makefile @@ -3,4 +3,4 @@ subdir-$(HAS_CPUFREQ) += cpufreq subdir-$(HAS_PCI) += pci subdir-$(HAS_PASSTHROUGH) += passthrough subdir-$(HAS_ACPI) += acpi -subdir-$(HAS_VGA) += video +subdir-$(HAS_VIDEO) += video diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 9e1adb5..683271e 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -21,7 +21,7 @@ #include <xen/delay.h> #include <xen/guest_access.h> #include <xen/shutdown.h> -#include <xen/vga.h> +#include <xen/video.h> #include <xen/kexec.h> #include <asm/debugger.h> #include <asm/div64.h> @@ -297,7 +297,7 @@ static void dump_console_ring_key(unsigned char key) buf[sofar] = ''\0''; sercon_puts(buf); - vga_puts(buf); + video_puts(buf); free_xenheap_pages(buf, order); } @@ -383,7 +383,7 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count) spin_lock_irq(&console_lock); sercon_puts(kbuf); - vga_puts(kbuf); + video_puts(kbuf); if ( opt_console_to_ring ) { @@ -464,7 +464,7 @@ static void __putstr(const char *str) ASSERT(spin_is_locked(&console_lock)); sercon_puts(str); - vga_puts(str); + video_puts(str); if ( !console_locks_busted ) { @@ -592,7 +592,7 @@ void __init console_init_preirq(void) if ( *p == '','' ) p++; if ( !strncmp(p, "vga", 3) ) - vga_init(); + video_init(); else if ( !strncmp(p, "none", 4) ) continue; else if ( (sh = serial_parse_handle(p)) >= 0 ) @@ -694,7 +694,7 @@ void __init console_endboot(void) printk("\n"); } - vga_endboot(); + video_endboot(); /* * If user specifies so, we fool the switch routine to redirect input diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile index 6c3e5b4..2993c39 100644 --- a/xen/drivers/video/Makefile +++ b/xen/drivers/video/Makefile @@ -1,5 +1,5 @@ -obj-y := vga.o -obj-$(CONFIG_X86) += font_8x14.o -obj-$(CONFIG_X86) += font_8x16.o -obj-$(CONFIG_X86) += font_8x8.o -obj-$(CONFIG_X86) += vesa.o +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_VGA) += vesa.o diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c index 47cd3ed..759355f 100644 --- a/xen/drivers/video/vesa.c +++ b/xen/drivers/video/vesa.c @@ -109,7 +109,7 @@ void __init vesa_init(void) lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); - vga_puts = vesa_redraw_puts; + video_puts = vesa_redraw_puts; printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " "using %uk, total %uk\n", @@ -194,7 +194,7 @@ void __init vesa_endboot(bool_t keep) if ( keep ) { xpos = 0; - vga_puts = vesa_scroll_puts; + video_puts = vesa_scroll_puts; } else { diff --git a/xen/drivers/video/vga.c b/xen/drivers/video/vga.c index a98bd00..40e5963 100644 --- a/xen/drivers/video/vga.c +++ b/xen/drivers/video/vga.c @@ -21,7 +21,7 @@ static unsigned char *video; static void vga_text_puts(const char *s); static void vga_noop_puts(const char *s) {} -void (*vga_puts)(const char *) = vga_noop_puts; +void (*video_puts)(const char *) = vga_noop_puts; /* * ''vga=<mode-specifier>[,keep]'' where <mode-specifier> is one of: @@ -62,7 +62,7 @@ void vesa_endboot(bool_t keep); #define vesa_endboot(x) ((void)0) #endif -void __init vga_init(void) +void __init video_init(void) { char *p; @@ -85,7 +85,7 @@ void __init vga_init(void) columns = vga_console_info.u.text_mode_3.columns; lines = vga_console_info.u.text_mode_3.rows; memset(video, 0, columns * lines * 2); - vga_puts = vga_text_puts; + video_puts = vga_text_puts; break; case XEN_VGATYPE_VESA_LFB: case XEN_VGATYPE_EFI_LFB: @@ -97,16 +97,16 @@ void __init vga_init(void) } } -void __init vga_endboot(void) +void __init video_endboot(void) { - if ( vga_puts == vga_noop_puts ) + if ( video_puts == vga_noop_puts ) return; printk("Xen is %s VGA console.\n", vgacon_keep ? "keeping" : "relinquishing"); if ( !vgacon_keep ) - vga_puts = vga_noop_puts; + video_puts = vga_noop_puts; else { int bus, devfn; diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index b69dbe6..2169627 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -38,6 +38,7 @@ #define CONFIG_ACPI_CSTATE 1 #define CONFIG_VGA 1 +#define CONFIG_VIDEO 1 #define CONFIG_HOTPLUG 1 #define CONFIG_HOTPLUG_CPU 1 diff --git a/xen/include/xen/vga.h b/xen/include/xen/vga.h index cc690b9..f72b63d 100644 --- a/xen/include/xen/vga.h +++ b/xen/include/xen/vga.h @@ -9,17 +9,10 @@ #ifndef _XEN_VGA_H #define _XEN_VGA_H -#include <public/xen.h> +#include <xen/video.h> #ifdef CONFIG_VGA extern struct xen_vga_console_info vga_console_info; -void vga_init(void); -void vga_endboot(void); -extern void (*vga_puts)(const char *); -#else -#define vga_init() ((void)0) -#define vga_endboot() ((void)0) -#define vga_puts(s) ((void)0) #endif #endif /* _XEN_VGA_H */ diff --git a/xen/include/xen/video.h b/xen/include/xen/video.h new file mode 100644 index 0000000..e9bc92e --- /dev/null +++ b/xen/include/xen/video.h @@ -0,0 +1,24 @@ +/* + * vga.h + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#ifndef _XEN_VIDEO_H +#define _XEN_VIDEO_H + +#include <public/xen.h> + +#ifdef CONFIG_VIDEO +void video_init(void); +extern void (*video_puts)(const char *); +void video_endboot(void); +#else +#define video_init() ((void)0) +#define video_puts(s) ((void)0) +#define video_endboot() ((void)0) +#endif + +#endif /* _XEN_VIDEO_H */ -- 1.7.2.5
Stefano Stabellini
2012-Dec-05 18:19 UTC
[PATCH 3/6] xen: introduce a generic framebuffer driver
Abstract away from vesa.c the funcions to handle a linear framebuffer and print characters to it. The corresponding functions are going to be removed from vesa.c in the next patch. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/drivers/video/Makefile | 1 + xen/drivers/video/fb.c | 209 ++++++++++++++++++++++++++++++++++++++++++++ xen/drivers/video/fb.h | 44 +++++++++ 3 files changed, 254 insertions(+), 0 deletions(-) create mode 100644 xen/drivers/video/fb.c create mode 100644 xen/drivers/video/fb.h diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile index 2993c39..3b3eb43 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) += fb.o obj-$(HAS_VGA) += vesa.o diff --git a/xen/drivers/video/fb.c b/xen/drivers/video/fb.c new file mode 100644 index 0000000..282f97e --- /dev/null +++ b/xen/drivers/video/fb.c @@ -0,0 +1,209 @@ +/****************************************************************************** + * fb.c + * + * linear frame buffer handling. + */ + +#include <xen/config.h> +#include <xen/kernel.h> +#include <xen/lib.h> +#include <xen/errno.h> +#include "fb.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 +static __initdata unsigned int line_len[MAX_XRES / MAX_FONT_W]; +static __initdata unsigned char lbuf[MAX_XRES * MAX_BPP]; +static __initdata unsigned char text_buf[(MAX_XRES / MAX_FONT_W) * \ + (MAX_YRES / MAX_FONT_H)]; + +struct fb_status { + struct fb_prop fbp; + + unsigned char *lbuf, *text_buf; + unsigned int *line_len; + unsigned int xpos, ypos; +}; +static struct fb_status fb; + +static void fb_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 = (fb.fbp.bits_per_pixel + 7) >> 3; + + for ( i = 0; i < fb.fbp.font->height; i++ ) + { + unsigned char *ptr = fb.lbuf; + + for ( j = 0; j < nr_chars; j++ ) + { + const unsigned char *bits = fb.fbp.font->data; + bits += ((text_line[j] * fb.fbp.font->height + i) * + ((fb.fbp.font->width + 7) >> 3)); + for ( b = fb.fbp.font->width; b--; ) + { + pixel = (*bits & (1u<<b)) ? fb.fbp.pixel_on : 0; + memcpy(ptr, &pixel, bpp); + ptr += bpp; + } + } + + memset(ptr, 0, (fb.fbp.width - nr_chars * fb.fbp.font->width) * bpp); + memcpy(video_line, fb.lbuf, nr_cells * fb.fbp.font->width * bpp); + video_line += fb.fbp.bytes_per_line; + } +} + +/* Fast mode which redraws all modified parts of a 2D text buffer. */ +void fb_redraw_puts(const char *s) +{ + unsigned int i, min_redraw_y = fb.ypos; + char c; + + /* Paste characters into text buffer. */ + while ( (c = *s++) != ''\0'' ) + { + if ( (c == ''\n'') || (fb.xpos >= fb.fbp.text_columns) ) + { + if ( ++fb.ypos >= fb.fbp.text_rows ) + { + min_redraw_y = 0; + fb.ypos = fb.fbp.text_rows - 1; + memmove(fb.text_buf, fb.text_buf + fb.fbp.text_columns, + fb.ypos * fb.fbp.text_columns); + memset(fb.text_buf + fb.ypos * fb.fbp.text_columns, 0, fb.xpos); + } + fb.xpos = 0; + } + + if ( c != ''\n'' ) + fb.text_buf[fb.xpos++ + fb.ypos * fb.fbp.text_columns] = c; + } + + /* Render modified section of text buffer to VESA linear framebuffer. */ + for ( i = min_redraw_y; i <= fb.ypos; i++ ) + { + const unsigned char *line = fb.text_buf + i * fb.fbp.text_columns; + unsigned int width; + + for ( width = fb.fbp.text_columns; width; --width ) + if ( line[width - 1] ) + break; + fb_show_line(line, + fb.fbp.lfb + i * fb.fbp.font->height * fb.fbp.bytes_per_line, + width, max(fb.line_len[i], width)); + fb.line_len[i] = width; + } + + fb.fbp.flush(); +} + +/* Slower line-based scroll mode which interacts better with dom0. */ +void fb_scroll_puts(const char *s) +{ + unsigned int i; + char c; + + while ( (c = *s++) != ''\0'' ) + { + if ( (c == ''\n'') || (fb.xpos >= fb.fbp.text_columns) ) + { + unsigned int bytes = (fb.fbp.width * + ((fb.fbp.bits_per_pixel + 7) >> 3)); + unsigned char *src = fb.fbp.lfb + fb.fbp.font->height * fb.fbp.bytes_per_line; + unsigned char *dst = fb.fbp.lfb; + + /* New line: scroll all previous rows up one line. */ + for ( i = fb.fbp.font->height; i < fb.fbp.height; i++ ) + { + memcpy(dst, src, bytes); + src += fb.fbp.bytes_per_line; + dst += fb.fbp.bytes_per_line; + } + + /* Render new line. */ + fb_show_line( + fb.text_buf, + fb.fbp.lfb + (fb.fbp.text_rows-1) * fb.fbp.font->height * fb.fbp.bytes_per_line, + fb.xpos, fb.fbp.text_columns); + + fb.xpos = 0; + } + + if ( c != ''\n'' ) + fb.text_buf[fb.xpos++] = c; + } + + fb.fbp.flush(); +} + +void fb_cr(void) +{ + fb.xpos = 0; +} + +int __init fb_init(struct fb_prop fbp) +{ + if ( fbp.width > MAX_XRES || fbp.height > MAX_YRES ) + { + printk("Couldn''t initialize a %xx%x framebuffer early.\n", + fbp.width, fbp.height); + return -EINVAL; + } + + fb.fbp = fbp; + fb.lbuf = lbuf; + fb.text_buf = text_buf; + fb.line_len = line_len; + return 0; +} + +int __init fb_alloc(void) +{ + fb.lbuf = NULL; + fb.text_buf = NULL; + fb.line_len = NULL; + + fb.lbuf = xmalloc_bytes(fb.fbp.bytes_per_line); + if ( !fb.lbuf ) + goto fail; + + fb.text_buf = xzalloc_bytes(fb.fbp.text_columns * fb.fbp.text_rows); + if ( !fb.text_buf ) + goto fail; + + fb.line_len = xzalloc_array(unsigned int, fb.fbp.text_columns); + if ( !fb.line_len ) + goto fail; + + memcpy(fb.lbuf, lbuf, fb.fbp.bytes_per_line); + memcpy(fb.text_buf, text_buf, fb.fbp.text_columns * fb.fbp.text_rows); + memcpy(fb.line_len, line_len, fb.fbp.text_columns); + + return 0; + +fail: + printk(XENLOG_ERR "Couldn''t allocate enough memory to drive " + "the framebuffer\n"); + xfree(fb.lbuf); + xfree(fb.text_buf); + xfree(fb.line_len); + + return -ENOMEM; +} + +void fb_free(void) +{ + xfree(fb.lbuf); + xfree(fb.text_buf); + xfree(fb.line_len); +} diff --git a/xen/drivers/video/fb.h b/xen/drivers/video/fb.h new file mode 100644 index 0000000..a432e19 --- /dev/null +++ b/xen/drivers/video/fb.h @@ -0,0 +1,44 @@ +/* + * xen/drivers/video/fb.h + * + * Cross-platform framebuffer library + * + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> + * Copyright (c) 2012 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 <xen/init.h> + +struct fb_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 fb_redraw_puts(const char *s); +void fb_scroll_puts(const char *s); +void fb_cr(void); +void fb_free(void); + +/* initialize the framebuffer, can be called early (before xmalloc is + * available) */ +int __init fb_init(struct fb_prop fbp); +/* fb_alloc allocates internal structures using xmalloc */ +int __init fb_alloc(void); -- 1.7.2.5
Make use of the framebuffer functions previously introduced. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/drivers/video/vesa.c | 179 +++++++--------------------------------------- 1 files changed, 26 insertions(+), 153 deletions(-) diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c index 759355f..4dbaecf 100644 --- a/xen/drivers/video/vesa.c +++ b/xen/drivers/video/vesa.c @@ -12,20 +12,15 @@ #include <xen/vga.h> #include <asm/page.h> #include "font.h" +#include "fb.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); @@ -86,30 +81,27 @@ 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 fb_prop fbp; - 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; + fbp.font = font; + fbp.bits_per_pixel = vlfb_info.bits_per_pixel; + fbp.bytes_per_line = vlfb_info.bytes_per_line; + fbp.width = vlfb_info.width; + fbp.height = vlfb_info.height; + fbp.flush = lfb_flush; + fbp.text_columns = vlfb_info.width / font->width; + fbp.text_rows = vlfb_info.height / font->height; if ( map_pages_to_xen(IOREMAP_VIRT_START, vlfb_info.lfb_base >> PAGE_SHIFT, vram_remap >> PAGE_SHIFT, PAGE_HYPERVISOR_NOCACHE) ) - goto fail; - - lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); + return; - video_puts = vesa_redraw_puts; + fbp.lfb = lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " "using %uk, total %uk\n", @@ -132,7 +124,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); @@ -140,15 +132,14 @@ 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 ( fb_init(fbp) < 0 ) + return; + if ( fb_alloc() < 0 ) + return; + video_puts = fb_redraw_puts; } #include <asm/mtrr.h> @@ -193,8 +184,8 @@ void __init vesa_endboot(bool_t keep) { if ( keep ) { - xpos = 0; - video_puts = vesa_scroll_puts; + video_puts = fb_scroll_puts; + fb_cr(); } else { @@ -203,124 +194,6 @@ void __init vesa_endboot(bool_t keep) memset(lfb + i * vlfb_info.bytes_per_line, 0, vlfb_info.width * bpp); lfb_flush(); + fb_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
2012-Dec-05 18:19 UTC
[PATCH 5/6] 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. Also add device_tree_node_compatible to device_tree.h, that is currently missing. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> --- xen/arch/arm/setup.c | 2 +- xen/common/device_tree.c | 47 +++++++++++++++++++++++++++++++++++++++++ xen/include/xen/device_tree.h | 3 ++ 3 files changed, 51 insertions(+), 1 deletions(-) diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 5f4e318..d978938 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -187,7 +187,7 @@ void __init start_xen(unsigned long boot_phys_offset, smp_clear_cpu_maps(); - fdt = (void *)BOOT_MISC_VIRT_START + device_tree_flattened = fdt = (void *)BOOT_MISC_VIRT_START + (atag_paddr & ((1 << SECOND_SHIFT) - 1)); fdt_size = device_tree_early_init(fdt); diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c index 8d5b6b0..ca0aba7 100644 --- a/xen/common/device_tree.c +++ b/xen/common/device_tree.c @@ -173,6 +173,53 @@ int device_tree_for_each_node(const void *fdt, 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 ( 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 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 a0e3a97..5a75f0e 100644 --- a/xen/include/xen/device_tree.h +++ b/xen/include/xen/device_tree.h @@ -54,6 +54,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
2012-Dec-05 18:19 UTC
[PATCH 6/6] xen/arm: introduce a driver for the ARM HDLCD controller
For the moment the resolution is hardcoded to 1280x1024@60. Use the generic framebuffer functions to print on the screen. 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 | 165 +++++++++++++++++++++++++++++++++++++++++ xen/include/asm-arm/config.h | 3 + 4 files changed, 170 insertions(+), 0 deletions(-) create mode 100644 xen/drivers/video/arm_hdlcd.c diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk index fa9f9c1..9580e6b 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 3b3eb43..8a6f5da 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) += fb.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..68f588c --- /dev/null +++ b/xen/drivers/video/arm_hdlcd.c @@ -0,0 +1,165 @@ +/* + * xen/drivers/video/arm_hdlcd.c + * + * Driver for ARM HDLCD Controller + * + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> + * Copyright (c) 2012 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 <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 "fb.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) + +#define BPP 4 +#define XRES 1280 +#define YRES 1024 +#define refresh 60 +#define pixclock 108 /* in Mhz, needs to be set in the board config for OSC5 */ +#define left_margin 80 +#define hback left_margin +#define right_margin 48 +#define hfront right_margin +#define upper_margin 21 +#define vback upper_margin +#define lower_margin 3 +#define vfront lower_margin +#define hsync_len 32 +#define vsync_len 6 + +#define HDLCD_SIZE (XRES*YRES*BPP) + +static void vga_noop_puts(const char *s) {} +void (*video_puts)(const char *) = vga_noop_puts; + +static void hdlcd_flush(void) +{ + dsb(); +} + +void __init video_init(void) +{ + int node, depth; + u32 address_cells, size_cells; + struct fb_prop fbp; + unsigned char *lfb = (unsigned char *) VRAM_VIRT_START; + paddr_t hdlcd_start, hdlcd_size; + paddr_t framebuffer_start, framebuffer_size; + const struct fdt_property *prop; + const u32 *cell; + + 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 || !framebuffer_start ) + return; + + printk("Initializing HDLCD driver\n"); + + map_phys_range(framebuffer_start, + framebuffer_start + framebuffer_size, + VRAM_VIRT_START, DEV_WC); + memset(lfb, 0x00, HDLCD_SIZE); + + set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED); + HDLCD[HDLCD_COMMAND] = 0; + + HDLCD[HDLCD_LINELENGTH] = XRES * BPP; + HDLCD[HDLCD_LINECOUNT] = YRES - 1; + HDLCD[HDLCD_LINEPITCH] = XRES * BPP; + HDLCD[HDLCD_PF] = ((BPP - 1) << 3); + HDLCD[HDLCD_INTMASK] = 0; + HDLCD[HDLCD_FBBASE] = framebuffer_start; + HDLCD[HDLCD_BUS] = 0xf00|(1<<4); + HDLCD[HDLCD_VBACK] = upper_margin - 1; + HDLCD[HDLCD_VSYNC] = vsync_len - 1; + HDLCD[HDLCD_VDATA] = YRES - 1; + HDLCD[HDLCD_VFRONT] = lower_margin - 1; + HDLCD[HDLCD_HBACK] = left_margin - 1; + HDLCD[HDLCD_HSYNC] = hsync_len - 1; + HDLCD[HDLCD_HDATA] = XRES - 1; + HDLCD[HDLCD_HFRONT] = right_margin - 1; + HDLCD[HDLCD_POLARITIES] = (1<<2)|(1<<3); + HDLCD[HDLCD_RED] = (8<<8)|0; + HDLCD[HDLCD_GREEN] = (8<<8)|8; + HDLCD[HDLCD_BLUE] = (8<<8)|16; + + HDLCD[HDLCD_COMMAND] = 1; + clear_fixmap(FIXMAP_MISC); + + fbp.lfb = lfb; + fbp.font = &font_vga_8x16; + fbp.pixel_on = 0xffffff; + fbp.bits_per_pixel = BPP*8; + fbp.bytes_per_line = BPP*XRES; + fbp.width = XRES; + fbp.height = YRES; + fbp.flush = hdlcd_flush; + fbp.text_columns = XRES / 8; + fbp.text_rows = YRES / 16; + if ( fb_init(fbp) < 0 ) + return; + video_puts = fb_scroll_puts; +} + +void video_endboot(void) +{ + if ( video_puts != vga_noop_puts ) + fb_alloc(); +} diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index 2a05539..9727562 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 @@ -73,6 +75,7 @@ #define FIXMAP_ADDR(n) (mk_unsigned_long(0x00400000) + (n) * PAGE_SIZE) #define BOOT_MISC_VIRT_START mk_unsigned_long(0x00600000) #define FRAMETABLE_VIRT_START mk_unsigned_long(0x02000000) +#define VRAM_VIRT_START mk_unsigned_long(0x10000000) #define XENHEAP_VIRT_START mk_unsigned_long(0x40000000) #define DOMHEAP_VIRT_START mk_unsigned_long(0x80000000) -- 1.7.2.5
On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote:> Introduce a function to map a physical memory into virtual memory. > It is going to be used later to map the videoram. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/mm.c | 23 +++++++++++++++++++++++ > xen/include/asm-arm/mm.h | 3 +++ > 2 files changed, 26 insertions(+), 0 deletions(-) > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 68ee9da..418a414 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -376,6 +376,29 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) > frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); > } > > +/* Map the physical memory range start - end at the virtual address > + * virt_start in 2MB chunks. start and virt_start have to be 2MB > + * aligned. > + */ > +void map_phys_range(paddr_t start, paddr_t end, > + unsigned long virt_start, unsigned attributes) > +{ > + ASSERT(!(start & ((1 << 21) - 1))); > + ASSERT(!(virt_start & ((1 << 21) - 1))); > + > + while ( start < end ) > + { > + lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT); > + e.pt.ai = attributes; > + write_pte(xen_second + second_table_offset(virt_start), e); > + > + start += (1<<21); > + virt_start += (1<<21); > + } > + > + flush_xen_data_tlb();What does this flush? The ptes are flushed by the write_pte aren''t they? Should this be a range over virt_start + len?> +} > + > enum mg { mg_clear, mg_ro, mg_rw, mg_rx }; > static void set_pte_flags_on_range(const char *p, unsigned long l, enum mg mg) > { > diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h > index 3549c83..a11f20b 100644 > --- a/xen/include/asm-arm/mm.h > +++ b/xen/include/asm-arm/mm.h > @@ -152,6 +152,9 @@ extern void setup_frametable_mappings(paddr_t ps, paddr_t pe); > extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes); > /* Remove a mapping from a fixmap entry */ > extern void clear_fixmap(unsigned map); > +/* map a 2MB aligned physical range in virtual memory. */ > +extern void map_phys_range(paddr_t start, paddr_t end, > + unsigned long virt_start, unsigned attributes);Hard tabs I''m afraid. Ian.
Ian Campbell
2012-Dec-06 09:57 UTC
Re: [PATCH 2/6] xen: infrastructure to have cross-platform video drivers
On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote:> - introduce a new HAS_VIDEO config variable; > - build xen/drivers/video/font* if HAS_VIDEO; > - rename vga_puts to video_puts; > - rename vga_init to video_init; > - rename vga_endboot to video_endboot. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Acked-by: Ian Campbell <ian.campbell@citrix.com> For the general concept + arm specific bits (such as they are..)> --- > xen/arch/arm/Rules.mk | 1 + > xen/arch/x86/Rules.mk | 1 + > xen/drivers/Makefile | 2 +- > xen/drivers/char/console.c | 12 ++++++------ > xen/drivers/video/Makefile | 10 +++++----- > xen/drivers/video/vesa.c | 4 ++-- > xen/drivers/video/vga.c | 12 ++++++------ > xen/include/asm-x86/config.h | 1 + > xen/include/xen/vga.h | 9 +-------- > xen/include/xen/video.h | 24 ++++++++++++++++++++++++ > 10 files changed, 48 insertions(+), 28 deletions(-) > create mode 100644 xen/include/xen/video.h > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > index a45c654..fa9f9c1 100644 > --- a/xen/arch/arm/Rules.mk > +++ b/xen/arch/arm/Rules.mk > @@ -7,6 +7,7 @@ > # > > HAS_DEVICE_TREE := y > +HAS_VIDEO := y > > CFLAGS += -fno-builtin -fno-common -Wredundant-decls > CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe > diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk > index 963850f..0a9d68d 100644 > --- a/xen/arch/x86/Rules.mk > +++ b/xen/arch/x86/Rules.mk > @@ -3,6 +3,7 @@ > > HAS_ACPI := y > HAS_VGA := y > +HAS_VIDEO := y > HAS_CPUFREQ := y > HAS_PCI := y > HAS_PASSTHROUGH := y > diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile > index 7239375..9c70f20 100644 > --- a/xen/drivers/Makefile > +++ b/xen/drivers/Makefile > @@ -3,4 +3,4 @@ subdir-$(HAS_CPUFREQ) += cpufreq > subdir-$(HAS_PCI) += pci > subdir-$(HAS_PASSTHROUGH) += passthrough > subdir-$(HAS_ACPI) += acpi > -subdir-$(HAS_VGA) += video > +subdir-$(HAS_VIDEO) += video > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c > index 9e1adb5..683271e 100644 > --- a/xen/drivers/char/console.c > +++ b/xen/drivers/char/console.c > @@ -21,7 +21,7 @@ > #include <xen/delay.h> > #include <xen/guest_access.h> > #include <xen/shutdown.h> > -#include <xen/vga.h> > +#include <xen/video.h> > #include <xen/kexec.h> > #include <asm/debugger.h> > #include <asm/div64.h> > @@ -297,7 +297,7 @@ static void dump_console_ring_key(unsigned char key) > buf[sofar] = ''\0''; > > sercon_puts(buf); > - vga_puts(buf); > + video_puts(buf); > > free_xenheap_pages(buf, order); > } > @@ -383,7 +383,7 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) buffer, int count) > spin_lock_irq(&console_lock); > > sercon_puts(kbuf); > - vga_puts(kbuf); > + video_puts(kbuf); > > if ( opt_console_to_ring ) > { > @@ -464,7 +464,7 @@ static void __putstr(const char *str) > ASSERT(spin_is_locked(&console_lock)); > > sercon_puts(str); > - vga_puts(str); > + video_puts(str); > > if ( !console_locks_busted ) > { > @@ -592,7 +592,7 @@ void __init console_init_preirq(void) > if ( *p == '','' ) > p++; > if ( !strncmp(p, "vga", 3) ) > - vga_init(); > + video_init(); > else if ( !strncmp(p, "none", 4) ) > continue; > else if ( (sh = serial_parse_handle(p)) >= 0 ) > @@ -694,7 +694,7 @@ void __init console_endboot(void) > printk("\n"); > } > > - vga_endboot(); > + video_endboot(); > > /* > * If user specifies so, we fool the switch routine to redirect input > diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile > index 6c3e5b4..2993c39 100644 > --- a/xen/drivers/video/Makefile > +++ b/xen/drivers/video/Makefile > @@ -1,5 +1,5 @@ > -obj-y := vga.o > -obj-$(CONFIG_X86) += font_8x14.o > -obj-$(CONFIG_X86) += font_8x16.o > -obj-$(CONFIG_X86) += font_8x8.o > -obj-$(CONFIG_X86) += vesa.o > +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_VGA) += vesa.o > diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c > index 47cd3ed..759355f 100644 > --- a/xen/drivers/video/vesa.c > +++ b/xen/drivers/video/vesa.c > @@ -109,7 +109,7 @@ void __init vesa_init(void) > > lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > > - vga_puts = vesa_redraw_puts; > + video_puts = vesa_redraw_puts; > > printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " > "using %uk, total %uk\n", > @@ -194,7 +194,7 @@ void __init vesa_endboot(bool_t keep) > if ( keep ) > { > xpos = 0; > - vga_puts = vesa_scroll_puts; > + video_puts = vesa_scroll_puts; > } > else > { > diff --git a/xen/drivers/video/vga.c b/xen/drivers/video/vga.c > index a98bd00..40e5963 100644 > --- a/xen/drivers/video/vga.c > +++ b/xen/drivers/video/vga.c > @@ -21,7 +21,7 @@ static unsigned char *video; > > static void vga_text_puts(const char *s); > static void vga_noop_puts(const char *s) {} > -void (*vga_puts)(const char *) = vga_noop_puts; > +void (*video_puts)(const char *) = vga_noop_puts; > > /* > * ''vga=<mode-specifier>[,keep]'' where <mode-specifier> is one of: > @@ -62,7 +62,7 @@ void vesa_endboot(bool_t keep); > #define vesa_endboot(x) ((void)0) > #endif > > -void __init vga_init(void) > +void __init video_init(void) > { > char *p; > > @@ -85,7 +85,7 @@ void __init vga_init(void) > columns = vga_console_info.u.text_mode_3.columns; > lines = vga_console_info.u.text_mode_3.rows; > memset(video, 0, columns * lines * 2); > - vga_puts = vga_text_puts; > + video_puts = vga_text_puts; > break; > case XEN_VGATYPE_VESA_LFB: > case XEN_VGATYPE_EFI_LFB: > @@ -97,16 +97,16 @@ void __init vga_init(void) > } > } > > -void __init vga_endboot(void) > +void __init video_endboot(void) > { > - if ( vga_puts == vga_noop_puts ) > + if ( video_puts == vga_noop_puts ) > return; > > printk("Xen is %s VGA console.\n", > vgacon_keep ? "keeping" : "relinquishing"); > > if ( !vgacon_keep ) > - vga_puts = vga_noop_puts; > + video_puts = vga_noop_puts; > else > { > int bus, devfn; > diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h > index b69dbe6..2169627 100644 > --- a/xen/include/asm-x86/config.h > +++ b/xen/include/asm-x86/config.h > @@ -38,6 +38,7 @@ > #define CONFIG_ACPI_CSTATE 1 > > #define CONFIG_VGA 1 > +#define CONFIG_VIDEO 1 > > #define CONFIG_HOTPLUG 1 > #define CONFIG_HOTPLUG_CPU 1 > diff --git a/xen/include/xen/vga.h b/xen/include/xen/vga.h > index cc690b9..f72b63d 100644 > --- a/xen/include/xen/vga.h > +++ b/xen/include/xen/vga.h > @@ -9,17 +9,10 @@ > #ifndef _XEN_VGA_H > #define _XEN_VGA_H > > -#include <public/xen.h> > +#include <xen/video.h> > > #ifdef CONFIG_VGA > extern struct xen_vga_console_info vga_console_info; > -void vga_init(void); > -void vga_endboot(void); > -extern void (*vga_puts)(const char *); > -#else > -#define vga_init() ((void)0) > -#define vga_endboot() ((void)0) > -#define vga_puts(s) ((void)0) > #endif > > #endif /* _XEN_VGA_H */ > diff --git a/xen/include/xen/video.h b/xen/include/xen/video.h > new file mode 100644 > index 0000000..e9bc92e > --- /dev/null > +++ b/xen/include/xen/video.h > @@ -0,0 +1,24 @@ > +/* > + * vga.h > + * > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file COPYING in the main directory of this archive > + * for more details. > + */ > + > +#ifndef _XEN_VIDEO_H > +#define _XEN_VIDEO_H > + > +#include <public/xen.h> > + > +#ifdef CONFIG_VIDEO > +void video_init(void); > +extern void (*video_puts)(const char *); > +void video_endboot(void); > +#else > +#define video_init() ((void)0) > +#define video_puts(s) ((void)0) > +#define video_endboot() ((void)0) > +#endif > + > +#endif /* _XEN_VIDEO_H */
Ian Campbell
2012-Dec-06 10:14 UTC
Re: [PATCH 5/6] xen/device_tree: introduce find_compatible_node
On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote:> 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. > > Also add device_tree_node_compatible to device_tree.h, that is currently > missing. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/setup.c | 2 +- > xen/common/device_tree.c | 47 +++++++++++++++++++++++++++++++++++++++++ > xen/include/xen/device_tree.h | 3 ++ > 3 files changed, 51 insertions(+), 1 deletions(-) > > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > index 5f4e318..d978938 100644 > --- a/xen/arch/arm/setup.c > +++ b/xen/arch/arm/setup.c > @@ -187,7 +187,7 @@ void __init start_xen(unsigned long boot_phys_offset, > > smp_clear_cpu_maps(); > > - fdt = (void *)BOOT_MISC_VIRT_START > + device_tree_flattened = fdt = (void *)BOOT_MISC_VIRT_STARTThis seems unrelated to the commit log? Is this to avoid declaring an early variant? It seems like this could mean we can drop the fdt variable from a bunch of the existing early_* functions.> + (atag_paddr & ((1 << SECOND_SHIFT) - 1)); > fdt_size = device_tree_early_init(fdt); > > diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c > index 8d5b6b0..ca0aba7 100644 > --- a/xen/common/device_tree.c > +++ b/xen/common/device_tree.c > @@ -173,6 +173,53 @@ int device_tree_for_each_node(const void *fdt, > 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;Do you want if ( c->found ) return ?> + 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 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 a0e3a97..5a75f0e 100644 > --- a/xen/include/xen/device_tree.h > +++ b/xen/include/xen/device_tree.h > @@ -54,6 +54,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);
Ian Campbell
2012-Dec-06 10:28 UTC
Re: [PATCH 6/6] xen/arm: introduce a driver for the ARM HDLCD controller
On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote:> For the moment the resolution is hardcoded to 1280x1024@60.Is there a longer term alternative? Something in the DTB perhaps. Also there are hardcoded dependencies on the vexpress (clock stuff) which aren''t mentioned here, but just in /* in Mhz, needs to be set in the board config for OSC5 */. Would be good to have some instruction on how to use this stuff somewhere.> Use the generic framebuffer functions to print on the screen. > > 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 | 165 +++++++++++++++++++++++++++++++++++++++++ > xen/include/asm-arm/config.h | 3 + > 4 files changed, 170 insertions(+), 0 deletions(-) > create mode 100644 xen/drivers/video/arm_hdlcd.c > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > index fa9f9c1..9580e6b 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 3b3eb43..8a6f5da 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) += fb.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..68f588c > --- /dev/null > +++ b/xen/drivers/video/arm_hdlcd.c > @@ -0,0 +1,165 @@ > +/* > + * xen/drivers/video/arm_hdlcd.c > + * > + * Driver for ARM HDLCD Controller > + * > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> > + * Copyright (c) 2012 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 <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 "fb.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) > + > +#define BPP 4 > +#define XRES 1280 > +#define YRES 1024 > +#define refresh 60 > +#define pixclock 108 /* in Mhz, needs to be set in the board config for OSC5 */ > +#define left_margin 80 > +#define hback left_margin > +#define right_margin 48 > +#define hfront right_margin > +#define upper_margin 21 > +#define vback upper_margin > +#define lower_margin 3 > +#define vfront lower_margin > +#define hsync_len 32 > +#define vsync_len 6 > + > +#define HDLCD_SIZE (XRES*YRES*BPP) > + > +static void vga_noop_puts(const char *s) {} > +void (*video_puts)(const char *) = vga_noop_puts; > + > +static void hdlcd_flush(void) > +{ > + dsb(); > +} > + > +void __init video_init(void) > +{ > + int node, depth; > + u32 address_cells, size_cells; > + struct fb_prop fbp; > + unsigned char *lfb = (unsigned char *) VRAM_VIRT_START; > + paddr_t hdlcd_start, hdlcd_size; > + paddr_t framebuffer_start, framebuffer_size; > + const struct fdt_property *prop; > + const u32 *cell; > + > + 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);I wonder why we don''t have a function to get the reg given a prop, because we have this pattern everywhere AFAICT.> + > + 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 || !framebuffer_start ) > + return; > + > + printk("Initializing HDLCD driver\n"); > + > + map_phys_range(framebuffer_start, > + framebuffer_start + framebuffer_size, > + VRAM_VIRT_START, DEV_WC); > + memset(lfb, 0x00, HDLCD_SIZE); > + > + set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED); > + HDLCD[HDLCD_COMMAND] = 0; > + > + HDLCD[HDLCD_LINELENGTH] = XRES * BPP; > + HDLCD[HDLCD_LINECOUNT] = YRES - 1; > + HDLCD[HDLCD_LINEPITCH] = XRES * BPP; > + HDLCD[HDLCD_PF] = ((BPP - 1) << 3); > + HDLCD[HDLCD_INTMASK] = 0; > + HDLCD[HDLCD_FBBASE] = framebuffer_start; > + HDLCD[HDLCD_BUS] = 0xf00|(1<<4); > + HDLCD[HDLCD_VBACK] = upper_margin - 1; > + HDLCD[HDLCD_VSYNC] = vsync_len - 1; > + HDLCD[HDLCD_VDATA] = YRES - 1; > + HDLCD[HDLCD_VFRONT] = lower_margin - 1; > + HDLCD[HDLCD_HBACK] = left_margin - 1; > + HDLCD[HDLCD_HSYNC] = hsync_len - 1; > + HDLCD[HDLCD_HDATA] = XRES - 1; > + HDLCD[HDLCD_HFRONT] = right_margin - 1; > + HDLCD[HDLCD_POLARITIES] = (1<<2)|(1<<3); > + HDLCD[HDLCD_RED] = (8<<8)|0; > + HDLCD[HDLCD_GREEN] = (8<<8)|8; > + HDLCD[HDLCD_BLUE] = (8<<8)|16; > + > + HDLCD[HDLCD_COMMAND] = 1; > + clear_fixmap(FIXMAP_MISC); > + > + fbp.lfb = lfb; > + fbp.font = &font_vga_8x16; > + fbp.pixel_on = 0xffffff; > + fbp.bits_per_pixel = BPP*8; > + fbp.bytes_per_line = BPP*XRES; > + fbp.width = XRES; > + fbp.height = YRES; > + fbp.flush = hdlcd_flush; > + fbp.text_columns = XRES / 8; > + fbp.text_rows = YRES / 16; > + if ( fb_init(fbp) < 0 ) > + return; > + video_puts = fb_scroll_puts; > +} > + > +void video_endboot(void) > +{ > + if ( video_puts != vga_noop_puts ) > + fb_alloc(); > +}Can you stick the standard magic block here please.> diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h > index 2a05539..9727562 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 > @@ -73,6 +75,7 @@ > #define FIXMAP_ADDR(n) (mk_unsigned_long(0x00400000) + (n) * PAGE_SIZE) > #define BOOT_MISC_VIRT_START mk_unsigned_long(0x00600000) > #define FRAMETABLE_VIRT_START mk_unsigned_long(0x02000000) > +#define VRAM_VIRT_START mk_unsigned_long(0x10000000) > #define XENHEAP_VIRT_START mk_unsigned_long(0x40000000) > #define DOMHEAP_VIRT_START mk_unsigned_long(0x80000000) >
Jan Beulich
2012-Dec-06 11:25 UTC
Re: [PATCH 2/6] xen: infrastructure to have cross-platform video drivers
>>> On 05.12.12 at 19:19, Stefano Stabellini <stefano.stabellini@eu.citrix.com>wrote:> - introduce a new HAS_VIDEO config variable; > - build xen/drivers/video/font* if HAS_VIDEO; > - rename vga_puts to video_puts; > - rename vga_init to video_init; > - rename vga_endboot to video_endboot. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Acked-by: Jan Beulich <jbeulich@suse.com>> --- > xen/arch/arm/Rules.mk | 1 + > xen/arch/x86/Rules.mk | 1 + > xen/drivers/Makefile | 2 +- > xen/drivers/char/console.c | 12 ++++++------ > xen/drivers/video/Makefile | 10 +++++----- > xen/drivers/video/vesa.c | 4 ++-- > xen/drivers/video/vga.c | 12 ++++++------ > xen/include/asm-x86/config.h | 1 + > xen/include/xen/vga.h | 9 +-------- > xen/include/xen/video.h | 24 ++++++++++++++++++++++++ > 10 files changed, 48 insertions(+), 28 deletions(-) > create mode 100644 xen/include/xen/video.h > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > index a45c654..fa9f9c1 100644 > --- a/xen/arch/arm/Rules.mk > +++ b/xen/arch/arm/Rules.mk > @@ -7,6 +7,7 @@ > # > > HAS_DEVICE_TREE := y > +HAS_VIDEO := y > > CFLAGS += -fno-builtin -fno-common -Wredundant-decls > CFLAGS += -iwithprefix include -Werror -Wno-pointer-arith -pipe > diff --git a/xen/arch/x86/Rules.mk b/xen/arch/x86/Rules.mk > index 963850f..0a9d68d 100644 > --- a/xen/arch/x86/Rules.mk > +++ b/xen/arch/x86/Rules.mk > @@ -3,6 +3,7 @@ > > HAS_ACPI := y > HAS_VGA := y > +HAS_VIDEO := y > HAS_CPUFREQ := y > HAS_PCI := y > HAS_PASSTHROUGH := y > diff --git a/xen/drivers/Makefile b/xen/drivers/Makefile > index 7239375..9c70f20 100644 > --- a/xen/drivers/Makefile > +++ b/xen/drivers/Makefile > @@ -3,4 +3,4 @@ subdir-$(HAS_CPUFREQ) += cpufreq > subdir-$(HAS_PCI) += pci > subdir-$(HAS_PASSTHROUGH) += passthrough > subdir-$(HAS_ACPI) += acpi > -subdir-$(HAS_VGA) += video > +subdir-$(HAS_VIDEO) += video > diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c > index 9e1adb5..683271e 100644 > --- a/xen/drivers/char/console.c > +++ b/xen/drivers/char/console.c > @@ -21,7 +21,7 @@ > #include <xen/delay.h> > #include <xen/guest_access.h> > #include <xen/shutdown.h> > -#include <xen/vga.h> > +#include <xen/video.h> > #include <xen/kexec.h> > #include <asm/debugger.h> > #include <asm/div64.h> > @@ -297,7 +297,7 @@ static void dump_console_ring_key(unsigned char key) > buf[sofar] = ''\0''; > > sercon_puts(buf); > - vga_puts(buf); > + video_puts(buf); > > free_xenheap_pages(buf, order); > } > @@ -383,7 +383,7 @@ static long guest_console_write(XEN_GUEST_HANDLE(char) > buffer, int count) > spin_lock_irq(&console_lock); > > sercon_puts(kbuf); > - vga_puts(kbuf); > + video_puts(kbuf); > > if ( opt_console_to_ring ) > { > @@ -464,7 +464,7 @@ static void __putstr(const char *str) > ASSERT(spin_is_locked(&console_lock)); > > sercon_puts(str); > - vga_puts(str); > + video_puts(str); > > if ( !console_locks_busted ) > { > @@ -592,7 +592,7 @@ void __init console_init_preirq(void) > if ( *p == '','' ) > p++; > if ( !strncmp(p, "vga", 3) ) > - vga_init(); > + video_init(); > else if ( !strncmp(p, "none", 4) ) > continue; > else if ( (sh = serial_parse_handle(p)) >= 0 ) > @@ -694,7 +694,7 @@ void __init console_endboot(void) > printk("\n"); > } > > - vga_endboot(); > + video_endboot(); > > /* > * If user specifies so, we fool the switch routine to redirect input > diff --git a/xen/drivers/video/Makefile b/xen/drivers/video/Makefile > index 6c3e5b4..2993c39 100644 > --- a/xen/drivers/video/Makefile > +++ b/xen/drivers/video/Makefile > @@ -1,5 +1,5 @@ > -obj-y := vga.o > -obj-$(CONFIG_X86) += font_8x14.o > -obj-$(CONFIG_X86) += font_8x16.o > -obj-$(CONFIG_X86) += font_8x8.o > -obj-$(CONFIG_X86) += vesa.o > +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_VGA) += vesa.o > diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c > index 47cd3ed..759355f 100644 > --- a/xen/drivers/video/vesa.c > +++ b/xen/drivers/video/vesa.c > @@ -109,7 +109,7 @@ void __init vesa_init(void) > > lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > > - vga_puts = vesa_redraw_puts; > + video_puts = vesa_redraw_puts; > > printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " > "using %uk, total %uk\n", > @@ -194,7 +194,7 @@ void __init vesa_endboot(bool_t keep) > if ( keep ) > { > xpos = 0; > - vga_puts = vesa_scroll_puts; > + video_puts = vesa_scroll_puts; > } > else > { > diff --git a/xen/drivers/video/vga.c b/xen/drivers/video/vga.c > index a98bd00..40e5963 100644 > --- a/xen/drivers/video/vga.c > +++ b/xen/drivers/video/vga.c > @@ -21,7 +21,7 @@ static unsigned char *video; > > static void vga_text_puts(const char *s); > static void vga_noop_puts(const char *s) {} > -void (*vga_puts)(const char *) = vga_noop_puts; > +void (*video_puts)(const char *) = vga_noop_puts; > > /* > * ''vga=<mode-specifier>[,keep]'' where <mode-specifier> is one of: > @@ -62,7 +62,7 @@ void vesa_endboot(bool_t keep); > #define vesa_endboot(x) ((void)0) > #endif > > -void __init vga_init(void) > +void __init video_init(void) > { > char *p; > > @@ -85,7 +85,7 @@ void __init vga_init(void) > columns = vga_console_info.u.text_mode_3.columns; > lines = vga_console_info.u.text_mode_3.rows; > memset(video, 0, columns * lines * 2); > - vga_puts = vga_text_puts; > + video_puts = vga_text_puts; > break; > case XEN_VGATYPE_VESA_LFB: > case XEN_VGATYPE_EFI_LFB: > @@ -97,16 +97,16 @@ void __init vga_init(void) > } > } > > -void __init vga_endboot(void) > +void __init video_endboot(void) > { > - if ( vga_puts == vga_noop_puts ) > + if ( video_puts == vga_noop_puts ) > return; > > printk("Xen is %s VGA console.\n", > vgacon_keep ? "keeping" : "relinquishing"); > > if ( !vgacon_keep ) > - vga_puts = vga_noop_puts; > + video_puts = vga_noop_puts; > else > { > int bus, devfn; > diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h > index b69dbe6..2169627 100644 > --- a/xen/include/asm-x86/config.h > +++ b/xen/include/asm-x86/config.h > @@ -38,6 +38,7 @@ > #define CONFIG_ACPI_CSTATE 1 > > #define CONFIG_VGA 1 > +#define CONFIG_VIDEO 1 > > #define CONFIG_HOTPLUG 1 > #define CONFIG_HOTPLUG_CPU 1 > diff --git a/xen/include/xen/vga.h b/xen/include/xen/vga.h > index cc690b9..f72b63d 100644 > --- a/xen/include/xen/vga.h > +++ b/xen/include/xen/vga.h > @@ -9,17 +9,10 @@ > #ifndef _XEN_VGA_H > #define _XEN_VGA_H > > -#include <public/xen.h> > +#include <xen/video.h> > > #ifdef CONFIG_VGA > extern struct xen_vga_console_info vga_console_info; > -void vga_init(void); > -void vga_endboot(void); > -extern void (*vga_puts)(const char *); > -#else > -#define vga_init() ((void)0) > -#define vga_endboot() ((void)0) > -#define vga_puts(s) ((void)0) > #endif > > #endif /* _XEN_VGA_H */ > diff --git a/xen/include/xen/video.h b/xen/include/xen/video.h > new file mode 100644 > index 0000000..e9bc92e > --- /dev/null > +++ b/xen/include/xen/video.h > @@ -0,0 +1,24 @@ > +/* > + * vga.h > + * > + * This file is subject to the terms and conditions of the GNU General > Public > + * License. See the file COPYING in the main directory of this archive > + * for more details. > + */ > + > +#ifndef _XEN_VIDEO_H > +#define _XEN_VIDEO_H > + > +#include <public/xen.h> > + > +#ifdef CONFIG_VIDEO > +void video_init(void); > +extern void (*video_puts)(const char *); > +void video_endboot(void); > +#else > +#define video_init() ((void)0) > +#define video_puts(s) ((void)0) > +#define video_endboot() ((void)0) > +#endif > + > +#endif /* _XEN_VIDEO_H */ > -- > 1.7.2.5
>>> On 05.12.12 at 19:19, Stefano Stabellini <stefano.stabellini@eu.citrix.com>wrote:> Make use of the framebuffer functions previously introduced. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>Conceptually this and the prior patch look fine, but the one here definitely is against a stale tree (namely lacking the merge with 26184:7b4449bdb980). Jan> --- > xen/drivers/video/vesa.c | 179 +++++++--------------------------------------- > 1 files changed, 26 insertions(+), 153 deletions(-) > > diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c > index 759355f..4dbaecf 100644 > --- a/xen/drivers/video/vesa.c > +++ b/xen/drivers/video/vesa.c > @@ -12,20 +12,15 @@ > #include <xen/vga.h> > #include <asm/page.h> > #include "font.h" > +#include "fb.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); > @@ -86,30 +81,27 @@ 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 fb_prop fbp; > > - 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; > + fbp.font = font; > + fbp.bits_per_pixel = vlfb_info.bits_per_pixel; > + fbp.bytes_per_line = vlfb_info.bytes_per_line; > + fbp.width = vlfb_info.width; > + fbp.height = vlfb_info.height; > + fbp.flush = lfb_flush; > + fbp.text_columns = vlfb_info.width / font->width; > + fbp.text_rows = vlfb_info.height / font->height; > > if ( map_pages_to_xen(IOREMAP_VIRT_START, > vlfb_info.lfb_base >> PAGE_SHIFT, > vram_remap >> PAGE_SHIFT, > PAGE_HYPERVISOR_NOCACHE) ) > - goto fail; > - > - lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > + return; > > - video_puts = vesa_redraw_puts; > + fbp.lfb = lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > > printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " > "using %uk, total %uk\n", > @@ -132,7 +124,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); > @@ -140,15 +132,14 @@ 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 ( fb_init(fbp) < 0 ) > + return; > + if ( fb_alloc() < 0 ) > + return; > + video_puts = fb_redraw_puts; > } > > #include <asm/mtrr.h> > @@ -193,8 +184,8 @@ void __init vesa_endboot(bool_t keep) > { > if ( keep ) > { > - xpos = 0; > - video_puts = vesa_scroll_puts; > + video_puts = fb_scroll_puts; > + fb_cr(); > } > else > { > @@ -203,124 +194,6 @@ void __init vesa_endboot(bool_t keep) > memset(lfb + i * vlfb_info.bytes_per_line, 0, > vlfb_info.width * bpp); > lfb_flush(); > + fb_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, 2012-12-06 at 11:28 +0000, Jan Beulich wrote:> >>> On 05.12.12 at 19:19, Stefano Stabellini <stefano.stabellini@eu.citrix.com> > wrote: > > Make use of the framebuffer functions previously introduced. > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > Conceptually this and the prior patch look fine, but the one here > definitely is against a stale tree (namely lacking the merge with > 26184:7b4449bdb980).Need to be careful with the code motion then, from that PoV these two patches would be better combined. Also, this vmap/ioremap thing seems like something we should replicate on ARM instead of the map_phys_range introduced in a previous patch (even if it is just a name change). No reason to gratuitously differ on these things. Ian.> > Jan > > > --- > > xen/drivers/video/vesa.c | 179 +++++++--------------------------------------- > > 1 files changed, 26 insertions(+), 153 deletions(-) > > > > diff --git a/xen/drivers/video/vesa.c b/xen/drivers/video/vesa.c > > index 759355f..4dbaecf 100644 > > --- a/xen/drivers/video/vesa.c > > +++ b/xen/drivers/video/vesa.c > > @@ -12,20 +12,15 @@ > > #include <xen/vga.h> > > #include <asm/page.h> > > #include "font.h" > > +#include "fb.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); > > @@ -86,30 +81,27 @@ 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 fb_prop fbp; > > > > - 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; > > + fbp.font = font; > > + fbp.bits_per_pixel = vlfb_info.bits_per_pixel; > > + fbp.bytes_per_line = vlfb_info.bytes_per_line; > > + fbp.width = vlfb_info.width; > > + fbp.height = vlfb_info.height; > > + fbp.flush = lfb_flush; > > + fbp.text_columns = vlfb_info.width / font->width; > > + fbp.text_rows = vlfb_info.height / font->height; > > > > if ( map_pages_to_xen(IOREMAP_VIRT_START, > > vlfb_info.lfb_base >> PAGE_SHIFT, > > vram_remap >> PAGE_SHIFT, > > PAGE_HYPERVISOR_NOCACHE) ) > > - goto fail; > > - > > - lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > > + return; > > > > - video_puts = vesa_redraw_puts; > > + fbp.lfb = lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap); > > > > printk(XENLOG_INFO "vesafb: framebuffer at %#x, mapped to 0x%p, " > > "using %uk, total %uk\n", > > @@ -132,7 +124,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); > > @@ -140,15 +132,14 @@ 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 ( fb_init(fbp) < 0 ) > > + return; > > + if ( fb_alloc() < 0 ) > > + return; > > + video_puts = fb_redraw_puts; > > } > > > > #include <asm/mtrr.h> > > @@ -193,8 +184,8 @@ void __init vesa_endboot(bool_t keep) > > { > > if ( keep ) > > { > > - xpos = 0; > > - video_puts = vesa_scroll_puts; > > + video_puts = fb_scroll_puts; > > + fb_cr(); > > } > > else > > { > > @@ -203,124 +194,6 @@ void __init vesa_endboot(bool_t keep) > > memset(lfb + i * vlfb_info.bytes_per_line, 0, > > vlfb_info.width * bpp); > > lfb_flush(); > > + fb_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 > >
At 18:19 +0000 on 05 Dec (1354731583), Stefano Stabellini wrote:> Introduce a function to map a physical memory into virtual memory. > It is going to be used later to map the videoram. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > --- > xen/arch/arm/mm.c | 23 +++++++++++++++++++++++ > xen/include/asm-arm/mm.h | 3 +++ > 2 files changed, 26 insertions(+), 0 deletions(-) > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > index 68ee9da..418a414 100644 > --- a/xen/arch/arm/mm.c > +++ b/xen/arch/arm/mm.c > @@ -376,6 +376,29 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) > frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); > } > > +/* Map the physical memory range start - end at the virtual address > + * virt_start in 2MB chunks. start and virt_start have to be 2MB > + * aligned. > + */ > +void map_phys_range(paddr_t start, paddr_t end, > + unsigned long virt_start, unsigned attributes) > +{ > + ASSERT(!(start & ((1 << 21) - 1))); > + ASSERT(!(virt_start & ((1 << 21) - 1)));Please use SECOND_SHIFT rather than 21, and maybe even add a SECOND_MASK &c to page.h rather than open-coding the <<s here. Also, can you add some assertions that the VAs here are in some well-defined region (with annotations in config.h)?> + while ( start < end ) > + { > + lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT); > + e.pt.ai = attributes; > + write_pte(xen_second + second_table_offset(virt_start), e); > + > + start += (1<<21); > + virt_start += (1<<21);Maybe add SECOND_SIZE &c too?> + } > + > + flush_xen_data_tlb();What''s this for? Cheers, Tim.> +} > + > enum mg { mg_clear, mg_ro, mg_rw, mg_rx }; > static void set_pte_flags_on_range(const char *p, unsigned long l, enum mg mg) > { > diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h > index 3549c83..a11f20b 100644 > --- a/xen/include/asm-arm/mm.h > +++ b/xen/include/asm-arm/mm.h > @@ -152,6 +152,9 @@ extern void setup_frametable_mappings(paddr_t ps, paddr_t pe); > extern void set_fixmap(unsigned map, unsigned long mfn, unsigned attributes); > /* Remove a mapping from a fixmap entry */ > extern void clear_fixmap(unsigned map); > +/* map a 2MB aligned physical range in virtual memory. */ > +extern void map_phys_range(paddr_t start, paddr_t end, > + unsigned long virt_start, unsigned attributes); > > > #define mfn_valid(mfn) ({ \ > -- > 1.7.2.5 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Tim Deegan
2012-Dec-06 12:46 UTC
Re: [PATCH 2/6] xen: infrastructure to have cross-platform video drivers
At 18:19 +0000 on 05 Dec (1354731584), Stefano Stabellini wrote:> diff --git a/xen/include/xen/video.h b/xen/include/xen/video.h > new file mode 100644 > index 0000000..e9bc92e > --- /dev/null > +++ b/xen/include/xen/video.h > @@ -0,0 +1,24 @@ > +/* > + * vga.hvideo.h ? :)> + * > + * This file is subject to the terms and conditions of the GNU General Public > + * License. See the file COPYING in the main directory of this archive > + * for more details. > + */ > + > +#ifndef _XEN_VIDEO_H > +#define _XEN_VIDEO_H > + > +#include <public/xen.h> > + > +#ifdef CONFIG_VIDEO > +void video_init(void); > +extern void (*video_puts)(const char *); > +void video_endboot(void); > +#else > +#define video_init() ((void)0) > +#define video_puts(s) ((void)0) > +#define video_endboot() ((void)0) > +#endif > + > +#endif /* _XEN_VIDEO_H */ > -- > 1.7.2.5
Tim Deegan
2012-Dec-06 12:53 UTC
Re: [PATCH 6/6] xen/arm: introduce a driver for the ARM HDLCD controller
At 18:19 +0000 on 05 Dec (1354731588), Stefano Stabellini wrote:> For the moment the resolution is hardcoded to 1280x1024@60. > Use the generic framebuffer functions to print on the screen. > > 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 | 165 +++++++++++++++++++++++++++++++++++++++++ > xen/include/asm-arm/config.h | 3 + > 4 files changed, 170 insertions(+), 0 deletions(-) > create mode 100644 xen/drivers/video/arm_hdlcd.c > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > index fa9f9c1..9580e6b 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 3b3eb43..8a6f5da 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) += fb.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..68f588c > --- /dev/null > +++ b/xen/drivers/video/arm_hdlcd.c > @@ -0,0 +1,165 @@ > +/* > + * xen/drivers/video/arm_hdlcd.c > + * > + * Driver for ARM HDLCD Controller > + * > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> > + * Copyright (c) 2012 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 <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 "fb.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) > + > +#define BPP 4 > +#define XRES 1280 > +#define YRES 1024 > +#define refresh 60 > +#define pixclock 108 /* in Mhz, needs to be set in the board config for OSC5 */ > +#define left_margin 80 > +#define hback left_margin > +#define right_margin 48 > +#define hfront right_margin > +#define upper_margin 21 > +#define vback upper_margin > +#define lower_margin 3 > +#define vfront lower_margin > +#define hsync_len 32 > +#define vsync_len 6 > + > +#define HDLCD_SIZE (XRES*YRES*BPP) > + > +static void vga_noop_puts(const char *s) {} > +void (*video_puts)(const char *) = vga_noop_puts; > + > +static void hdlcd_flush(void) > +{ > + dsb(); > +} > + > +void __init video_init(void) > +{ > + int node, depth; > + u32 address_cells, size_cells; > + struct fb_prop fbp; > + unsigned char *lfb = (unsigned char *) VRAM_VIRT_START; > + paddr_t hdlcd_start, hdlcd_size; > + paddr_t framebuffer_start, framebuffer_size; > + const struct fdt_property *prop; > + const u32 *cell; > + > + 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 || !framebuffer_start ) > + return; > + > + printk("Initializing HDLCD driver\n"); > + > + map_phys_range(framebuffer_start, > + framebuffer_start + framebuffer_size, > + VRAM_VIRT_START, DEV_WC); > + memset(lfb, 0x00, HDLCD_SIZE);This needs some checks that framebuffer_size >= HDLCD_SIZE, and that framebuffer_size <= XENHEAP_VIRT_START - VRAM_VIRT_START.> + set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED); > + HDLCD[HDLCD_COMMAND] = 0; > + > + HDLCD[HDLCD_LINELENGTH] = XRES * BPP; > + HDLCD[HDLCD_LINECOUNT] = YRES - 1; > + HDLCD[HDLCD_LINEPITCH] = XRES * BPP; > + HDLCD[HDLCD_PF] = ((BPP - 1) << 3); > + HDLCD[HDLCD_INTMASK] = 0; > + HDLCD[HDLCD_FBBASE] = framebuffer_start; > + HDLCD[HDLCD_BUS] = 0xf00|(1<<4); > + HDLCD[HDLCD_VBACK] = upper_margin - 1; > + HDLCD[HDLCD_VSYNC] = vsync_len - 1; > + HDLCD[HDLCD_VDATA] = YRES - 1; > + HDLCD[HDLCD_VFRONT] = lower_margin - 1; > + HDLCD[HDLCD_HBACK] = left_margin - 1; > + HDLCD[HDLCD_HSYNC] = hsync_len - 1; > + HDLCD[HDLCD_HDATA] = XRES - 1; > + HDLCD[HDLCD_HFRONT] = right_margin - 1; > + HDLCD[HDLCD_POLARITIES] = (1<<2)|(1<<3); > + HDLCD[HDLCD_RED] = (8<<8)|0; > + HDLCD[HDLCD_GREEN] = (8<<8)|8; > + HDLCD[HDLCD_BLUE] = (8<<8)|16; > + > + HDLCD[HDLCD_COMMAND] = 1; > + clear_fixmap(FIXMAP_MISC); > + > + fbp.lfb = lfb; > + fbp.font = &font_vga_8x16; > + fbp.pixel_on = 0xffffff; > + fbp.bits_per_pixel = BPP*8; > + fbp.bytes_per_line = BPP*XRES; > + fbp.width = XRES; > + fbp.height = YRES; > + fbp.flush = hdlcd_flush; > + fbp.text_columns = XRES / 8; > + fbp.text_rows = YRES / 16; > + if ( fb_init(fbp) < 0 ) > + return; > + video_puts = fb_scroll_puts; > +} > + > +void video_endboot(void) > +{ > + if ( video_puts != vga_noop_puts ) > + fb_alloc(); > +} > diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h > index 2a05539..9727562 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 > @@ -73,6 +75,7 @@ > #define FIXMAP_ADDR(n) (mk_unsigned_long(0x00400000) + (n) * PAGE_SIZE) > #define BOOT_MISC_VIRT_START mk_unsigned_long(0x00600000) > #define FRAMETABLE_VIRT_START mk_unsigned_long(0x02000000) > +#define VRAM_VIRT_START mk_unsigned_long(0x10000000)Please update the comments above to reflect this change. Cheers, Tim.> #define XENHEAP_VIRT_START mk_unsigned_long(0x40000000) > #define DOMHEAP_VIRT_START mk_unsigned_long(0x80000000) > > -- > 1.7.2.5 > > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xen.org > http://lists.xen.org/xen-devel
Stefano Stabellini
2012-Dec-06 12:55 UTC
Re: [PATCH 5/6] xen/device_tree: introduce find_compatible_node
On Thu, 6 Dec 2012, Ian Campbell wrote:> On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote: > > 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. > > > > Also add device_tree_node_compatible to device_tree.h, that is currently > > missing. > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > --- > > xen/arch/arm/setup.c | 2 +- > > xen/common/device_tree.c | 47 +++++++++++++++++++++++++++++++++++++++++ > > xen/include/xen/device_tree.h | 3 ++ > > 3 files changed, 51 insertions(+), 1 deletions(-) > > > > diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c > > index 5f4e318..d978938 100644 > > --- a/xen/arch/arm/setup.c > > +++ b/xen/arch/arm/setup.c > > @@ -187,7 +187,7 @@ void __init start_xen(unsigned long boot_phys_offset, > > > > smp_clear_cpu_maps(); > > > > - fdt = (void *)BOOT_MISC_VIRT_START > > + device_tree_flattened = fdt = (void *)BOOT_MISC_VIRT_START > > This seems unrelated to the commit log? > > Is this to avoid declaring an early variant? It seems like this could > mean we can drop the fdt variable from a bunch of the existing early_* > functions.Yes, it is needed to make device_tree_flattened available earlier than setup_mm. I''ll get rid of fdt.> > + (atag_paddr & ((1 << SECOND_SHIFT) - 1)); > > fdt_size = device_tree_early_init(fdt); > > > > diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c > > index 8d5b6b0..ca0aba7 100644 > > --- a/xen/common/device_tree.c > > +++ b/xen/common/device_tree.c > > @@ -173,6 +173,53 @@ int device_tree_for_each_node(const void *fdt, > > 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; > > Do you want > if ( c->found ) > return ?Good idea
Stefano Stabellini
2012-Dec-06 15:18 UTC
Re: [PATCH 4/6] xen/vesa: use the new fb_* functions
On Thu, 6 Dec 2012, Jan Beulich wrote:> >>> On 05.12.12 at 19:19, Stefano Stabellini <stefano.stabellini@eu.citrix.com> > wrote: > > Make use of the framebuffer functions previously introduced. > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > Conceptually this and the prior patch look fine, but the one here > definitely is against a stale tree (namely lacking the merge with > 26184:7b4449bdb980).Thanks for the pointer, I''ll rebase
Stefano Stabellini
2012-Dec-06 15:39 UTC
Re: [PATCH 4/6] xen/vesa: use the new fb_* functions
On Thu, 6 Dec 2012, Ian Campbell wrote:> On Thu, 2012-12-06 at 11:28 +0000, Jan Beulich wrote: > > >>> On 05.12.12 at 19:19, Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > wrote: > > > Make use of the framebuffer functions previously introduced. > > > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > > > Conceptually this and the prior patch look fine, but the one here > > definitely is against a stale tree (namely lacking the merge with > > 26184:7b4449bdb980). > > Need to be careful with the code motion then, from that PoV these two > patches would be better combined.That is true. If you prefer I can merge the two patches.> Also, this vmap/ioremap thing seems like something we should replicate > on ARM instead of the map_phys_range introduced in a previous patch > (even if it is just a name change). No reason to gratuitously differ on > these things.Of course we should have ioremap working on ARM, however in this case I would rather not use ioremap, because in its current form relies on the xen domheap being already setup, while I would prefer being able to initialize the HDLCD controller earlier than that. On the other hand we could have a much simpler implementation of ioremap only based on map_phys_range rather than vmap. I wouldn''t be against that. We could call it early_ioremap to make it clear that it differs from the x86 counterpart.
Stefano Stabellini
2012-Dec-06 16:06 UTC
Re: [PATCH 1/6] xen/arm: introduce map_phys_range
On Thu, 6 Dec 2012, Ian Campbell wrote:> On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote: > > Introduce a function to map a physical memory into virtual memory. > > It is going to be used later to map the videoram. > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > --- > > xen/arch/arm/mm.c | 23 +++++++++++++++++++++++ > > xen/include/asm-arm/mm.h | 3 +++ > > 2 files changed, 26 insertions(+), 0 deletions(-) > > > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > > index 68ee9da..418a414 100644 > > --- a/xen/arch/arm/mm.c > > +++ b/xen/arch/arm/mm.c > > @@ -376,6 +376,29 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) > > frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); > > } > > > > +/* Map the physical memory range start - end at the virtual address > > + * virt_start in 2MB chunks. start and virt_start have to be 2MB > > + * aligned. > > + */ > > +void map_phys_range(paddr_t start, paddr_t end, > > + unsigned long virt_start, unsigned attributes) > > +{ > > + ASSERT(!(start & ((1 << 21) - 1))); > > + ASSERT(!(virt_start & ((1 << 21) - 1))); > > + > > + while ( start < end ) > > + { > > + lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT); > > + e.pt.ai = attributes; > > + write_pte(xen_second + second_table_offset(virt_start), e); > > + > > + start += (1<<21); > > + virt_start += (1<<21); > > + } > > + > > + flush_xen_data_tlb(); > > What does this flush? The ptes are flushed by the write_pte aren''t they?write_pte doesn''t flush the tlb at the moment.> Should this be a range over virt_start + len?Yes, ideally it would flush only the range virt_start-virt_start+size. In practice I think I could remove the flush entirely because we don''t have any previous mappings at virt_start but I presume that it is not a good idea to rely on that?
Stefano Stabellini
2012-Dec-06 16:35 UTC
Re: [PATCH 6/6] xen/arm: introduce a driver for the ARM HDLCD controller
On Thu, 6 Dec 2012, Tim Deegan wrote:> At 18:19 +0000 on 05 Dec (1354731588), Stefano Stabellini wrote: > > For the moment the resolution is hardcoded to 1280x1024@60. > > Use the generic framebuffer functions to print on the screen. > > > > 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 | 165 +++++++++++++++++++++++++++++++++++++++++ > > xen/include/asm-arm/config.h | 3 + > > 4 files changed, 170 insertions(+), 0 deletions(-) > > create mode 100644 xen/drivers/video/arm_hdlcd.c > > > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > > index fa9f9c1..9580e6b 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 3b3eb43..8a6f5da 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) += fb.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..68f588c > > --- /dev/null > > +++ b/xen/drivers/video/arm_hdlcd.c > > @@ -0,0 +1,165 @@ > > +/* > > + * xen/drivers/video/arm_hdlcd.c > > + * > > + * Driver for ARM HDLCD Controller > > + * > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > + * Copyright (c) 2012 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 <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 "fb.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) > > + > > +#define BPP 4 > > +#define XRES 1280 > > +#define YRES 1024 > > +#define refresh 60 > > +#define pixclock 108 /* in Mhz, needs to be set in the board config for OSC5 */ > > +#define left_margin 80 > > +#define hback left_margin > > +#define right_margin 48 > > +#define hfront right_margin > > +#define upper_margin 21 > > +#define vback upper_margin > > +#define lower_margin 3 > > +#define vfront lower_margin > > +#define hsync_len 32 > > +#define vsync_len 6 > > + > > +#define HDLCD_SIZE (XRES*YRES*BPP) > > + > > +static void vga_noop_puts(const char *s) {} > > +void (*video_puts)(const char *) = vga_noop_puts; > > + > > +static void hdlcd_flush(void) > > +{ > > + dsb(); > > +} > > + > > +void __init video_init(void) > > +{ > > + int node, depth; > > + u32 address_cells, size_cells; > > + struct fb_prop fbp; > > + unsigned char *lfb = (unsigned char *) VRAM_VIRT_START; > > + paddr_t hdlcd_start, hdlcd_size; > > + paddr_t framebuffer_start, framebuffer_size; > > + const struct fdt_property *prop; > > + const u32 *cell; > > + > > + 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 || !framebuffer_start ) > > + return; > > + > > + printk("Initializing HDLCD driver\n"); > > + > > + map_phys_range(framebuffer_start, > > + framebuffer_start + framebuffer_size, > > + VRAM_VIRT_START, DEV_WC); > > + memset(lfb, 0x00, HDLCD_SIZE); > > This needs some checks that framebuffer_size >= HDLCD_SIZE, and that > framebuffer_size <= XENHEAP_VIRT_START - VRAM_VIRT_START.You are right, I''ll add those checks. I think I''ll turn map_phys_range into early_ioremap and have early_ioremap return NULL if the range passed as an argument is too big.
On Thu, 2012-12-06 at 16:06 +0000, Stefano Stabellini wrote:> On Thu, 6 Dec 2012, Ian Campbell wrote: > > On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote: > > > Introduce a function to map a physical memory into virtual memory. > > > It is going to be used later to map the videoram. > > > > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > > --- > > > xen/arch/arm/mm.c | 23 +++++++++++++++++++++++ > > > xen/include/asm-arm/mm.h | 3 +++ > > > 2 files changed, 26 insertions(+), 0 deletions(-) > > > > > > diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c > > > index 68ee9da..418a414 100644 > > > --- a/xen/arch/arm/mm.c > > > +++ b/xen/arch/arm/mm.c > > > @@ -376,6 +376,29 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) > > > frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); > > > } > > > > > > +/* Map the physical memory range start - end at the virtual address > > > + * virt_start in 2MB chunks. start and virt_start have to be 2MB > > > + * aligned. > > > + */ > > > +void map_phys_range(paddr_t start, paddr_t end, > > > + unsigned long virt_start, unsigned attributes) > > > +{ > > > + ASSERT(!(start & ((1 << 21) - 1))); > > > + ASSERT(!(virt_start & ((1 << 21) - 1))); > > > + > > > + while ( start < end ) > > > + { > > > + lpae_t e = mfn_to_xen_entry(start >> PAGE_SHIFT); > > > + e.pt.ai = attributes; > > > + write_pte(xen_second + second_table_offset(virt_start), e); > > > + > > > + start += (1<<21); > > > + virt_start += (1<<21); > > > + } > > > + > > > + flush_xen_data_tlb(); > > > > What does this flush? The ptes are flushed by the write_pte aren''t they? > > write_pte doesn''t flush the tlb at the moment.Oh right, it just flushes the dcache.> > Should this be a range over virt_start + len? > > Yes, ideally it would flush only the range virt_start-virt_start+size.Why doesn''t it?> In practice I think I could remove the flush entirely because we don''t > have any previous mappings at virt_start but I presume that it is not a > good idea to rely on that?Better safe than sorry I guess.
Stefano Stabellini
2012-Dec-07 15:50 UTC
Re: [PATCH 6/6] xen/arm: introduce a driver for the ARM HDLCD controller
On Thu, 6 Dec 2012, Ian Campbell wrote:> On Wed, 2012-12-05 at 18:19 +0000, Stefano Stabellini wrote: > > For the moment the resolution is hardcoded to 1280x1024@60. > > Is there a longer term alternative? Something in the DTB perhaps. > > Also there are hardcoded dependencies on the vexpress (clock stuff) > which aren''t mentioned here, but just in /* in Mhz, needs to be set in > the board config for OSC5 */. Would be good to have some instruction on > how to use this stuff somewhere.I managed to get rid of those.> > Use the generic framebuffer functions to print on the screen. > > > > 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 | 165 +++++++++++++++++++++++++++++++++++++++++ > > xen/include/asm-arm/config.h | 3 + > > 4 files changed, 170 insertions(+), 0 deletions(-) > > create mode 100644 xen/drivers/video/arm_hdlcd.c > > > > diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk > > index fa9f9c1..9580e6b 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 3b3eb43..8a6f5da 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) += fb.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..68f588c > > --- /dev/null > > +++ b/xen/drivers/video/arm_hdlcd.c > > @@ -0,0 +1,165 @@ > > +/* > > + * xen/drivers/video/arm_hdlcd.c > > + * > > + * Driver for ARM HDLCD Controller > > + * > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com> > > + * Copyright (c) 2012 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 <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 "fb.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) > > + > > +#define BPP 4 > > +#define XRES 1280 > > +#define YRES 1024 > > +#define refresh 60 > > +#define pixclock 108 /* in Mhz, needs to be set in the board config for OSC5 */ > > +#define left_margin 80 > > +#define hback left_margin > > +#define right_margin 48 > > +#define hfront right_margin > > +#define upper_margin 21 > > +#define vback upper_margin > > +#define lower_margin 3 > > +#define vfront lower_margin > > +#define hsync_len 32 > > +#define vsync_len 6 > > + > > +#define HDLCD_SIZE (XRES*YRES*BPP) > > + > > +static void vga_noop_puts(const char *s) {} > > +void (*video_puts)(const char *) = vga_noop_puts; > > + > > +static void hdlcd_flush(void) > > +{ > > + dsb(); > > +} > > + > > +void __init video_init(void) > > +{ > > + int node, depth; > > + u32 address_cells, size_cells; > > + struct fb_prop fbp; > > + unsigned char *lfb = (unsigned char *) VRAM_VIRT_START; > > + paddr_t hdlcd_start, hdlcd_size; > > + paddr_t framebuffer_start, framebuffer_size; > > + const struct fdt_property *prop; > > + const u32 *cell; > > + > > + 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); > > I wonder why we don''t have a function to get the reg given a prop, > because we have this pattern everywhere AFAICT.It is not possible only from a prop because we also need to know address_cells and size_cells. They are only known at depth - 1, that''s why it is non-trivial to write such a function.> > + 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 || !framebuffer_start ) > > + return; > > + > > + printk("Initializing HDLCD driver\n"); > > + > > + map_phys_range(framebuffer_start, > > + framebuffer_start + framebuffer_size, > > + VRAM_VIRT_START, DEV_WC); > > + memset(lfb, 0x00, HDLCD_SIZE); > > + > > + set_fixmap(FIXMAP_MISC, hdlcd_start >> PAGE_SHIFT, DEV_SHARED); > > + HDLCD[HDLCD_COMMAND] = 0; > > + > > + HDLCD[HDLCD_LINELENGTH] = XRES * BPP; > > + HDLCD[HDLCD_LINECOUNT] = YRES - 1; > > + HDLCD[HDLCD_LINEPITCH] = XRES * BPP; > > + HDLCD[HDLCD_PF] = ((BPP - 1) << 3); > > + HDLCD[HDLCD_INTMASK] = 0; > > + HDLCD[HDLCD_FBBASE] = framebuffer_start; > > + HDLCD[HDLCD_BUS] = 0xf00|(1<<4); > > + HDLCD[HDLCD_VBACK] = upper_margin - 1; > > + HDLCD[HDLCD_VSYNC] = vsync_len - 1; > > + HDLCD[HDLCD_VDATA] = YRES - 1; > > + HDLCD[HDLCD_VFRONT] = lower_margin - 1; > > + HDLCD[HDLCD_HBACK] = left_margin - 1; > > + HDLCD[HDLCD_HSYNC] = hsync_len - 1; > > + HDLCD[HDLCD_HDATA] = XRES - 1; > > + HDLCD[HDLCD_HFRONT] = right_margin - 1; > > + HDLCD[HDLCD_POLARITIES] = (1<<2)|(1<<3); > > + HDLCD[HDLCD_RED] = (8<<8)|0; > > + HDLCD[HDLCD_GREEN] = (8<<8)|8; > > + HDLCD[HDLCD_BLUE] = (8<<8)|16; > > + > > + HDLCD[HDLCD_COMMAND] = 1; > > + clear_fixmap(FIXMAP_MISC); > > + > > + fbp.lfb = lfb; > > + fbp.font = &font_vga_8x16; > > + fbp.pixel_on = 0xffffff; > > + fbp.bits_per_pixel = BPP*8; > > + fbp.bytes_per_line = BPP*XRES; > > + fbp.width = XRES; > > + fbp.height = YRES; > > + fbp.flush = hdlcd_flush; > > + fbp.text_columns = XRES / 8; > > + fbp.text_rows = YRES / 16; > > + if ( fb_init(fbp) < 0 ) > > + return; > > + video_puts = fb_scroll_puts; > > +} > > + > > +void video_endboot(void) > > +{ > > + if ( video_puts != vga_noop_puts ) > > + fb_alloc(); > > +} > > Can you stick the standard magic block here please.OK