ia64/xen-unstable

view xen/drivers/video/vesa.c @ 19191:a55919061d79

blktap: Fix check_gcrypt

Signed-off-by: KUWAMURA Shin'ya <kuwa@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 11 10:44:42 2009 +0000 (2009-02-11)
parents 5e066dc410ac
children
line source
1 /******************************************************************************
2 * vesa.c
3 *
4 * VESA linear frame buffer handling.
5 */
7 #include <xen/config.h>
8 #include <xen/init.h>
9 #include <xen/lib.h>
10 #include <xen/mm.h>
11 #include <xen/errno.h>
12 #include <xen/console.h>
13 #include <xen/vga.h>
14 #include "font.h"
16 #define vlfb_info vga_console_info.u.vesa_lfb
17 #define text_columns (vlfb_info.width / font->width)
18 #define text_rows (vlfb_info.height / font->height)
20 static void vesa_redraw_puts(const char *s);
21 static void vesa_scroll_puts(const char *s);
23 static unsigned char *lfb, *lbuf, *text_buf;
24 static const struct font_desc *font;
25 static bool_t vga_compat;
26 static unsigned int pixel_on;
27 static unsigned int xpos, ypos;
29 static unsigned int vram_total;
30 integer_param("vesa-ram", vram_total);
32 static unsigned int vram_remap;
33 integer_param("vesa-map", vram_remap);
35 static int font_height;
36 static void __init parse_font_height(const char *s)
37 {
38 if ( simple_strtoul(s, &s, 10) == 8 && (*s++ == 'x') )
39 font_height = simple_strtoul(s, &s, 10);
40 if ( *s != '\0' )
41 font_height = 0;
42 }
43 custom_param("font", parse_font_height);
45 void __init vesa_early_init(void)
46 {
47 unsigned int vram_vmode;
49 vga_compat = !(vga_console_info.u.vesa_lfb.gbl_caps & 2);
51 if ( (vlfb_info.bits_per_pixel < 8) || (vlfb_info.bits_per_pixel > 32) )
52 return;
54 if ( font_height == 0 ) /* choose a sensible default */
55 font = ((vlfb_info.height <= 600) ? &font_vga_8x8 :
56 (vlfb_info.height <= 768) ? &font_vga_8x14 : &font_vga_8x16);
57 else if ( font_height <= 8 )
58 font = &font_vga_8x8;
59 else if ( font_height <= 14 )
60 font = &font_vga_8x14;
61 else
62 font = &font_vga_8x16;
64 /* vram_vmode -- that is the amount of memory needed for the
65 * used video mode, i.e. the minimum amount of
66 * memory we need. */
67 vram_vmode = vlfb_info.height * vlfb_info.bytes_per_line;
69 /* vram_total -- all video memory we have. Used for mtrr
70 * entries. */
71 vram_total = vram_total ? (vram_total << 20) : (vlfb_info.lfb_size << 16);
72 vram_total = max_t(unsigned int, vram_total, vram_vmode);
74 /* vram_remap -- the amount of video memory we are going to
75 * use for vesafb. With modern cards it is no
76 * option to simply use vram_total as that
77 * wastes plenty of kernel address space. */
78 vram_remap = (vram_remap ?
79 (vram_remap << 20) :
80 ((vram_vmode + (1 << L2_PAGETABLE_SHIFT) - 1) &
81 ~((1 << L2_PAGETABLE_SHIFT) - 1)));
82 vram_remap = max_t(unsigned int, vram_remap, vram_vmode);
83 vram_remap = min_t(unsigned int, vram_remap, vram_total);
84 }
86 void __init vesa_init(void)
87 {
88 if ( !font )
89 goto fail;
91 lbuf = xmalloc_bytes(vlfb_info.bytes_per_line);
92 if ( !lbuf )
93 goto fail;
95 text_buf = xmalloc_bytes(text_columns * text_rows);
96 if ( !text_buf )
97 goto fail;
99 if ( map_pages_to_xen(IOREMAP_VIRT_START,
100 vlfb_info.lfb_base >> PAGE_SHIFT,
101 vram_remap >> PAGE_SHIFT,
102 PAGE_HYPERVISOR_NOCACHE) )
103 goto fail;
105 lfb = memset((void *)IOREMAP_VIRT_START, 0, vram_remap);
106 memset(text_buf, 0, text_columns * text_rows);
108 vga_puts = vesa_redraw_puts;
110 printk(XENLOG_INFO "vesafb: framebuffer at 0x%x, mapped to 0x%p, "
111 "using %uk, total %uk\n",
112 vlfb_info.lfb_base, lfb,
113 vram_remap >> 10, vram_total >> 10);
114 printk(XENLOG_INFO "vesafb: mode is %dx%dx%u, linelength=%d, font %ux%u\n",
115 vlfb_info.width, vlfb_info.height,
116 vlfb_info.bits_per_pixel, vlfb_info.bytes_per_line,
117 font->width, font->height);
118 printk(XENLOG_INFO "vesafb: %scolor: size=%d:%d:%d:%d, "
119 "shift=%d:%d:%d:%d\n",
120 vlfb_info.bits_per_pixel > 8 ? "True" :
121 vga_compat ? "Pseudo" : "Static Pseudo",
122 vlfb_info.rsvd_size, vlfb_info.red_size,
123 vlfb_info.green_size, vlfb_info.blue_size,
124 vlfb_info.rsvd_pos, vlfb_info.red_pos,
125 vlfb_info.green_pos, vlfb_info.blue_pos);
127 if ( vlfb_info.bits_per_pixel > 8 )
128 {
129 /* Light grey in truecolor. */
130 unsigned int grey = 0xaaaaaaaa;
131 pixel_on =
132 ((grey >> (32 - vlfb_info. red_size)) << vlfb_info. red_pos) |
133 ((grey >> (32 - vlfb_info.green_size)) << vlfb_info.green_pos) |
134 ((grey >> (32 - vlfb_info. blue_size)) << vlfb_info. blue_pos);
135 }
136 else
137 {
138 /* White(ish) in default pseudocolor palette. */
139 pixel_on = 7;
140 }
142 return;
144 fail:
145 xfree(lbuf);
146 xfree(text_buf);
147 }
149 void __init vesa_endboot(bool_t keep)
150 {
151 if ( keep )
152 {
153 xpos = 0;
154 vga_puts = vesa_scroll_puts;
155 }
156 else
157 {
158 unsigned int i, bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
159 for ( i = 0; i < vlfb_info.height; i++ )
160 memset(lfb + i * vlfb_info.bytes_per_line, 0,
161 vlfb_info.width * bpp);
162 }
163 }
165 #if defined(CONFIG_X86)
167 #include <asm/mtrr.h>
169 static unsigned int vesa_mtrr;
170 integer_param("vesa-mtrr", vesa_mtrr);
172 void __init vesa_mtrr_init(void)
173 {
174 static const int mtrr_types[] = {
175 0, MTRR_TYPE_UNCACHABLE, MTRR_TYPE_WRBACK,
176 MTRR_TYPE_WRCOMB, MTRR_TYPE_WRTHROUGH };
177 unsigned int size_total;
178 int rc, type;
180 if ( !lfb || (vesa_mtrr == 0) || (vesa_mtrr >= ARRAY_SIZE(mtrr_types)) )
181 return;
183 type = mtrr_types[vesa_mtrr];
184 if ( !type )
185 return;
187 /* Find the largest power-of-two */
188 size_total = vram_total;
189 while ( size_total & (size_total - 1) )
190 size_total &= size_total - 1;
192 /* Try and find a power of two to add */
193 do {
194 rc = mtrr_add(vlfb_info.lfb_base, size_total, type, 1);
195 size_total >>= 1;
196 } while ( (size_total >= PAGE_SIZE) && (rc == -EINVAL) );
197 }
199 static void lfb_flush(void)
200 {
201 if ( vesa_mtrr == 3 )
202 __asm__ __volatile__ ("sfence" : : : "memory");
203 }
205 #else /* !defined(CONFIG_X86) */
207 #define lfb_flush() ((void)0)
209 #endif
211 /* Render one line of text to given linear framebuffer line. */
212 static void vesa_show_line(
213 const unsigned char *text_line,
214 unsigned char *video_line,
215 unsigned int nr_chars)
216 {
217 unsigned int i, j, b, bpp, pixel;
219 bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
221 for ( i = 0; i < font->height; i++ )
222 {
223 unsigned char *ptr = lbuf;
225 for ( j = 0; j < nr_chars; j++ )
226 {
227 const unsigned char *bits = font->data;
228 bits += ((text_line[j] * font->height + i) *
229 ((font->width + 7) >> 3));
230 for ( b = font->width; b--; )
231 {
232 pixel = (*bits & (1u<<b)) ? pixel_on : 0;
233 memcpy(ptr, &pixel, bpp);
234 ptr += bpp;
235 }
236 }
238 memset(ptr, 0, (vlfb_info.width - nr_chars * font->width) * bpp);
239 memcpy(video_line, lbuf, vlfb_info.width * bpp);
240 video_line += vlfb_info.bytes_per_line;
241 }
242 }
244 /* Fast mode which redraws all modified parts of a 2D text buffer. */
245 static void vesa_redraw_puts(const char *s)
246 {
247 unsigned int i, min_redraw_y = ypos;
248 char c;
250 /* Paste characters into text buffer. */
251 while ( (c = *s++) != '\0' )
252 {
253 if ( (c == '\n') || (xpos >= text_columns) )
254 {
255 if ( ++ypos >= text_rows )
256 {
257 min_redraw_y = 0;
258 ypos = text_rows - 1;
259 memmove(text_buf, text_buf + text_columns,
260 ypos * text_columns);
261 memset(text_buf + ypos * text_columns, 0, xpos);
262 }
263 xpos = 0;
264 }
266 if ( c != '\n' )
267 text_buf[xpos++ + ypos * text_columns] = c;
268 }
270 /* Render modified section of text buffer to VESA linear framebuffer. */
271 for ( i = min_redraw_y; i <= ypos; i++ )
272 vesa_show_line(text_buf + i * text_columns,
273 lfb + i * font->height * vlfb_info.bytes_per_line,
274 text_columns);
276 lfb_flush();
277 }
279 /* Slower line-based scroll mode which interacts better with dom0. */
280 static void vesa_scroll_puts(const char *s)
281 {
282 unsigned int i;
283 char c;
285 while ( (c = *s++) != '\0' )
286 {
287 if ( (c == '\n') || (xpos >= text_columns) )
288 {
289 unsigned int bytes = (vlfb_info.width *
290 ((vlfb_info.bits_per_pixel + 7) >> 3));
291 unsigned char *src = lfb + font->height * vlfb_info.bytes_per_line;
292 unsigned char *dst = lfb;
294 /* New line: scroll all previous rows up one line. */
295 for ( i = font->height; i < vlfb_info.height; i++ )
296 {
297 memcpy(dst, src, bytes);
298 src += vlfb_info.bytes_per_line;
299 dst += vlfb_info.bytes_per_line;
300 }
302 /* Render new line. */
303 vesa_show_line(
304 text_buf,
305 lfb + (text_rows-1) * font->height * vlfb_info.bytes_per_line,
306 xpos);
308 xpos = 0;
309 }
311 if ( c != '\n' )
312 text_buf[xpos++] = c;
313 }
315 lfb_flush();
316 }