2 * Copyright (c) 2004-2005 Fabrice Bellard
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License V2
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* VGA init. We use the Bochs VESA VBE extensions */
22 #define VBE_DISPI_INDEX_ID 0x0
23 #define VBE_DISPI_INDEX_XRES 0x1
24 #define VBE_DISPI_INDEX_YRES 0x2
25 #define VBE_DISPI_INDEX_BPP 0x3
26 #define VBE_DISPI_INDEX_ENABLE 0x4
27 #define VBE_DISPI_INDEX_BANK 0x5
28 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
29 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
30 #define VBE_DISPI_INDEX_X_OFFSET 0x8
31 #define VBE_DISPI_INDEX_Y_OFFSET 0x9
32 #define VBE_DISPI_INDEX_NB 0xa
34 #define VBE_DISPI_ID0 0xB0C0
35 #define VBE_DISPI_ID1 0xB0C1
36 #define VBE_DISPI_ID2 0xB0C2
38 #define VBE_DISPI_DISABLED 0x00
39 #define VBE_DISPI_ENABLED 0x01
40 #define VBE_DISPI_LFB_ENABLED 0x40
41 #define VBE_DISPI_NOCLEARMEM 0x80
43 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
45 static void vga_text_init(void);
47 unsigned long vga_fb_phys_addr;
53 uint8_t rgb_to_index[256];
55 static void vbe_outw(int index, int val)
61 /* init VGA in standard state for PREP boot */
62 void vga_prep_init(void)
64 outb(0x3c0, 0x00); /* set blanking */
65 vbe_outw(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
68 /* build standard RGB palette */
69 void vga_build_rgb_palette(void)
71 static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
75 for(r = 0; r < 6; r++) {
76 for(g = 0; g < 6; g++) {
77 for(b = 0; b < 6; b++) {
78 vga_set_palette(i, RGB(pal_value[r], pal_value[g],
84 for(i = 0; i < 256; i++) {
85 rgb_to_index[i] = ((i * 5) + 128) / 255;
89 void vga_set_address (uint32_t address)
91 vga_fb_phys_addr = address;
94 /* depth = 8, 15, 16 or 32 */
95 void vga_set_mode(int width, int height, int depth)
97 vbe_outw(VBE_DISPI_INDEX_XRES, width);
98 vbe_outw(VBE_DISPI_INDEX_YRES, height);
99 vbe_outw(VBE_DISPI_INDEX_BPP, depth);
100 vbe_outw(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED);
101 outb(0x3c0, 0x20); /* disable blanking */
103 if (vga_fb_phys_addr == 0x00000000)
104 vga_fb_phys_addr = VBE_DISPI_LFB_PHYSICAL_ADDRESS;
105 vga_fb_width = width;
106 vga_fb_height = height;
107 vga_fb_depth = depth;
108 vga_fb_bpp = (depth + 7) >> 3;
109 vga_fb_linesize = width * vga_fb_bpp;
112 vga_build_rgb_palette();
116 /* for depth = 8 mode, set a hardware palette entry */
117 void vga_set_palette(int i, unsigned int rgba)
119 unsigned int r, g, b;
121 r = (rgba >> 16) & 0xff;
122 g = (rgba >> 8) & 0xff;
130 /* convert a RGBA color to a color index usable in graphic primitives */
131 unsigned int vga_get_color(unsigned int rgba)
133 unsigned int r, g, b, color;
135 switch(vga_fb_depth) {
137 r = (rgba >> 16) & 0xff;
138 g = (rgba >> 8) & 0xff;
140 color = (rgb_to_index[r] * 6 * 6) +
141 (rgb_to_index[g] * 6) +
145 r = (rgba >> 16) & 0xff;
146 g = (rgba >> 8) & 0xff;
148 color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
151 r = (rgba >> 16) & 0xff;
152 g = (rgba >> 8) & 0xff;
154 color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
164 void vga_draw_buf (const void *buf, int buf_linesize,
165 int posx, int posy, int width, int height)
172 d = (uint8_t *)vga_fb_phys_addr +
173 vga_fb_linesize * posy + vga_fb_bpp * posx;
174 wb = width * vga_fb_bpp;
175 for (y = 0; y < height; y++) {
178 d += vga_fb_linesize;
182 void vga_fill_rect (int posx, int posy, int width, int height, uint32_t color)
187 d1 = (uint8_t *)vga_fb_phys_addr +
188 vga_fb_linesize * posy + vga_fb_bpp * posx;
189 for (y = 0; y < height; y++) {
193 for (x = 0; x < width; x++) {
194 *((uint8_t *)d) = color;
199 for (x = 0; x < width; x++) {
200 *((uint16_t *)d) = color;
205 for (x = 0; x < width; x++) {
206 *((uint32_t *)d) = color;
211 d1 += vga_fb_linesize;
215 /* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
216 void vga_bitblt(int xs, int ys, int xd, int yd, int w, int h)
224 s = (uint8_t *)vga_fb_phys_addr +
225 vga_fb_linesize * ys + vga_fb_bpp * xs;
226 d = (uint8_t *)vga_fb_phys_addr +
227 vga_fb_linesize * yd + vga_fb_bpp * xd;
228 for (y = 0; y < h; y++) {
230 d += vga_fb_linesize;
231 s += vga_fb_linesize;
234 s = (uint8_t *)vga_fb_phys_addr +
235 vga_fb_linesize * (ys + h - 1) + vga_fb_bpp * xs;
236 d = (uint8_t *)vga_fb_phys_addr +
237 vga_fb_linesize * (yd + h - 1) + vga_fb_bpp * xd;
238 for (y = 0; y < h; y++) {
240 d -= vga_fb_linesize;
241 s -= vga_fb_linesize;
246 /***********************************************************/
247 /* basic char display */
249 #define FONT_HEIGHT 16
254 #define cbswap_32(__x) \
256 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
257 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
258 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
259 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
261 /* XXX: endianness */
263 #define PAT(x) cbswap_32(x)
268 static const uint32_t dmask16[16] = {
287 static const uint32_t dmask4[4] = {
294 int text_width, text_height, text_fgcol, text_bgcol, text_x, text_y;
296 static void vga_text_init(void)
298 text_width = vga_fb_width / FONT_WIDTH;
299 text_height = vga_fb_height / FONT_HEIGHT;
302 vga_text_set_fgcol(RGB(0xff, 0xff, 0xff));
303 vga_text_set_bgcol(RGB(0x00, 0x00, 0x00));
306 static inline unsigned int col_expand(unsigned int col)
317 text_fgcol = 0xffffff;
324 void vga_text_set_fgcol(unsigned int rgba)
326 text_fgcol = col_expand(vga_get_color(rgba));
329 void vga_text_set_bgcol(unsigned int rgba)
331 text_bgcol = col_expand(vga_get_color(rgba));
334 void vga_putcharxy(int x, int y, int ch,
335 unsigned int fgcol, unsigned int bgcol)
338 const uint8_t *font_ptr;
339 unsigned int font_data, linesize, xorcol;
342 d = (uint8_t *)vga_fb_phys_addr +
343 vga_fb_linesize * y * FONT_HEIGHT + vga_fb_bpp * x * FONT_WIDTH;
344 linesize = vga_fb_linesize;
345 font_ptr = vgafont16 + FONT_HEIGHT * ch;
346 xorcol = bgcol ^ fgcol;
347 switch(vga_fb_depth) {
349 for(i = 0; i < FONT_HEIGHT; i++) {
350 font_data = *font_ptr++;
351 ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
352 ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
358 for(i = 0; i < FONT_HEIGHT; i++) {
359 font_data = *font_ptr++;
360 ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
361 ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
362 ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
363 ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
368 for(i = 0; i < FONT_HEIGHT; i++) {
369 font_data = *font_ptr++;
370 ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
371 ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
372 ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
373 ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
374 ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
375 ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
376 ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
377 ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
384 static void vga_put_lf(void)
388 if (text_y >= text_height) {
389 text_y = text_height - 1;
390 vga_bitblt(0, FONT_HEIGHT, 0, 0,
391 text_width * FONT_WIDTH,
392 (text_height - 1) * FONT_HEIGHT);
393 vga_fill_rect(0, (text_height - 1) * FONT_HEIGHT,
394 text_width * FONT_WIDTH, FONT_HEIGHT, text_bgcol);
398 void vga_putchar(int ch)
402 } else if (ch == '\n') {
404 } else if (ch == '\b') {
413 vga_putcharxy(--text_x, text_y, ' ', text_fgcol, text_bgcol);
416 vga_putcharxy(text_x, text_y, ch, text_fgcol, text_bgcol);
418 if (text_x >= text_width)
423 void vga_puts(const char *s)
426 vga_putchar(*(uint8_t *)s);