ia64/xen-unstable

view xen/drivers/video/vesa.c @ 16126:1c4203730ff6

x86/64: Fix the build.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Fri Oct 12 13:06:16 2007 +0100 (2007-10-12)
parents ef4119637f52
children af33f2054f47
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(void)
150 {
151 xpos = 0;
152 vga_puts = vesa_scroll_puts;
153 }
155 #if defined(CONFIG_X86)
157 #include <asm/mtrr.h>
159 static unsigned int vesa_mtrr;
160 integer_param("vesa-mtrr", vesa_mtrr);
162 void __init vesa_mtrr_init(void)
163 {
164 static const int mtrr_types[] = {
165 0, MTRR_TYPE_UNCACHABLE, MTRR_TYPE_WRBACK,
166 MTRR_TYPE_WRCOMB, MTRR_TYPE_WRTHROUGH };
167 unsigned int size_total;
168 int rc, type;
170 if ( !lfb || (vesa_mtrr == 0) || (vesa_mtrr >= ARRAY_SIZE(mtrr_types)) )
171 return;
173 type = mtrr_types[vesa_mtrr];
174 if ( !type )
175 return;
177 /* Find the largest power-of-two */
178 size_total = vram_total;
179 while ( size_total & (size_total - 1) )
180 size_total &= size_total - 1;
182 /* Try and find a power of two to add */
183 do {
184 rc = mtrr_add(vlfb_info.lfb_base, size_total, type, 1);
185 size_total >>= 1;
186 } while ( (size_total >= PAGE_SIZE) && (rc == -EINVAL) );
187 }
189 static void lfb_flush(void)
190 {
191 if ( vesa_mtrr == 3 )
192 __asm__ __volatile__ ("sfence" : : : "memory");
193 }
195 #else /* !defined(CONFIG_X86) */
197 #define lfb_flush() ((void)0)
199 #endif
201 /* Render one line of text to given linear framebuffer line. */
202 static void vesa_show_line(
203 const unsigned char *text_line,
204 unsigned char *video_line,
205 unsigned int nr_chars)
206 {
207 unsigned int i, j, b, bpp, pixel;
209 bpp = (vlfb_info.bits_per_pixel + 7) >> 3;
211 for ( i = 0; i < font->height; i++ )
212 {
213 unsigned char *ptr = lbuf;
215 for ( j = 0; j < nr_chars; j++ )
216 {
217 const unsigned char *bits = font->data;
218 bits += ((text_line[j] * font->height + i) *
219 ((font->width + 7) >> 3));
220 for ( b = font->width; b--; )
221 {
222 pixel = test_bit(b, bits) ? pixel_on : 0;
223 memcpy(ptr, &pixel, bpp);
224 ptr += bpp;
225 }
226 }
228 memset(ptr, 0, (vlfb_info.width - nr_chars * font->width) * bpp);
229 memcpy(video_line, lbuf, vlfb_info.width * bpp);
230 video_line += vlfb_info.bytes_per_line;
231 }
232 }
234 /* Fast mode which redraws all modified parts of a 2D text buffer. */
235 static void vesa_redraw_puts(const char *s)
236 {
237 unsigned int i, min_redraw_y = ypos;
238 char c;
240 /* Paste characters into text buffer. */
241 while ( (c = *s++) != '\0' )
242 {
243 if ( (c == '\n') || (xpos >= text_columns) )
244 {
245 if ( ++ypos >= text_rows )
246 {
247 min_redraw_y = 0;
248 ypos = text_rows - 1;
249 memmove(text_buf, text_buf + text_columns,
250 ypos * text_columns);
251 memset(text_buf + ypos * text_columns, 0, xpos);
252 }
253 xpos = 0;
254 }
256 if ( c != '\n' )
257 text_buf[xpos++ + ypos * text_columns] = c;
258 }
260 /* Render modified section of text buffer to VESA linear framebuffer. */
261 for ( i = min_redraw_y; i <= ypos; i++ )
262 vesa_show_line(text_buf + i * text_columns,
263 lfb + i * font->height * vlfb_info.bytes_per_line,
264 text_columns);
266 lfb_flush();
267 }
269 /* Slower line-based scroll mode which interacts better with dom0. */
270 static void vesa_scroll_puts(const char *s)
271 {
272 unsigned int i;
273 char c;
275 while ( (c = *s++) != '\0' )
276 {
277 if ( (c == '\n') || (xpos >= text_columns) )
278 {
279 unsigned int bytes = (vlfb_info.width *
280 ((vlfb_info.bits_per_pixel + 7) >> 3));
281 unsigned char *src = lfb + font->height * vlfb_info.bytes_per_line;
282 unsigned char *dst = lfb;
284 /* New line: scroll all previous rows up one line. */
285 for ( i = font->height; i < vlfb_info.height; i++ )
286 {
287 memcpy(dst, src, bytes);
288 src += vlfb_info.bytes_per_line;
289 dst += vlfb_info.bytes_per_line;
290 }
292 /* Render new line. */
293 vesa_show_line(
294 text_buf,
295 lfb + (text_rows-1) * font->height * vlfb_info.bytes_per_line,
296 xpos);
298 xpos = 0;
299 }
301 if ( c != '\n' )
302 text_buf[xpos++] = c;
303 }
305 lfb_flush();
306 }