Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / openhackware / src / vga.c
1 /*
2  *  Copyright (c) 2004-2005 Fabrice Bellard
3  *
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
7  *
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.
12  *
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
16  */
17
18 #include <stdlib.h>
19 #include "bios.h"
20
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
33       
34 #define VBE_DISPI_ID0                   0xB0C0
35 #define VBE_DISPI_ID1                   0xB0C1
36 #define VBE_DISPI_ID2                   0xB0C2
37   
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
42   
43 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
44
45 static void vga_text_init(void);
46
47 unsigned long vga_fb_phys_addr;
48 int vga_fb_width;
49 int vga_fb_height;
50 int vga_fb_linesize;
51 int vga_fb_bpp;
52 int vga_fb_depth;
53 uint8_t rgb_to_index[256];
54
55 static void vbe_outw(int index, int val)
56 {
57     outw(0x1ce, index);
58     outw(0x1d0, val);
59 }
60
61 /* init VGA in standard state for PREP boot */
62 void vga_prep_init(void)
63 {
64     outb(0x3c0, 0x00); /* set blanking */
65     vbe_outw(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
66 }
67
68 /* build standard RGB palette */
69 void vga_build_rgb_palette(void)
70 {
71     static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff };
72     int i, r, g, b;
73
74     i = 0;
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], 
79                                        pal_value[b]));
80                 i++;
81             }
82         }
83     }
84     for(i = 0; i < 256; i++) {
85         rgb_to_index[i] = ((i * 5) + 128) / 255;
86     }
87 }
88
89 void vga_set_address (uint32_t address)
90 {
91     vga_fb_phys_addr = address;
92 }
93
94 /* depth = 8, 15, 16 or 32 */
95 void vga_set_mode(int width, int height, int depth)
96 {
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 */
102
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;
110     
111     if (depth == 8)
112         vga_build_rgb_palette();
113     vga_text_init();
114 }
115
116 /* for depth = 8 mode, set a hardware palette entry */
117 void vga_set_palette(int i, unsigned int rgba)
118 {
119     unsigned int r, g, b;
120
121     r = (rgba >> 16) & 0xff;
122     g = (rgba >> 8) & 0xff;
123     b = (rgba) & 0xff;
124     outb(0x3c8, i);
125     outb(0x3c9, r >> 2);
126     outb(0x3c9, g >> 2);
127     outb(0x3c9, b >> 2);
128 }
129
130 /* convert a RGBA color to a color index usable in graphic primitives */
131 unsigned int vga_get_color(unsigned int rgba)
132 {
133     unsigned int r, g, b, color;
134
135     switch(vga_fb_depth) {
136     case 8:
137         r = (rgba >> 16) & 0xff;
138         g = (rgba >> 8) & 0xff;
139         b = (rgba) & 0xff;
140         color = (rgb_to_index[r] * 6 * 6) + 
141             (rgb_to_index[g] * 6) + 
142             (rgb_to_index[b]);
143         break;
144     case 15:
145         r = (rgba >> 16) & 0xff;
146         g = (rgba >> 8) & 0xff;
147         b = (rgba) & 0xff;
148         color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
149         break;
150     case 16:
151         r = (rgba >> 16) & 0xff;
152         g = (rgba >> 8) & 0xff;
153         b = (rgba) & 0xff;
154         color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
155         break;
156     case 32:
157     default:
158         color = rgba;
159         break;
160     }
161     return color;
162 }
163
164 void vga_draw_buf (const void *buf, int buf_linesize,
165                    int posx, int posy, int width, int height)
166 {
167     const uint8_t *s;
168     uint8_t *d;
169     int y, wb;
170     
171     s = buf;
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++) {
176         memcpy(d, s, wb);
177         s += buf_linesize;
178         d += vga_fb_linesize;
179     }
180 }
181
182 void vga_fill_rect (int posx, int posy, int width, int height, uint32_t color)
183 {
184     uint8_t *d, *d1;
185     int x, y;
186     
187     d1 = (uint8_t *)vga_fb_phys_addr + 
188         vga_fb_linesize * posy + vga_fb_bpp * posx;
189     for (y = 0; y < height; y++) {
190         d = d1;
191         switch(vga_fb_bpp) {
192         case 1:
193             for (x = 0; x < width; x++) {
194                 *((uint8_t *)d) = color;
195                 d++;
196             }
197             break;
198         case 2:
199             for (x = 0; x < width; x++) {
200                 *((uint16_t *)d) = color;
201                 d += 2;
202             }
203             break;
204         case 4:
205             for (x = 0; x < width; x++) {
206                 *((uint32_t *)d) = color;
207                 d += 4;
208             }
209             break;
210         }
211         d1 += vga_fb_linesize;
212     }
213 }
214
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)
217 {
218     const uint8_t *s;
219     uint8_t *d;
220     int wb, y;
221
222     wb = w * vga_fb_bpp;
223     if (yd <= ys) {
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++) {
229             memmove(d, s, wb);
230             d += vga_fb_linesize;
231             s += vga_fb_linesize;
232         }
233     } else {
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++) {
239             memmove(d, s, wb);
240             d -= vga_fb_linesize;
241             s -= vga_fb_linesize;
242         }
243     }
244 }
245
246 /***********************************************************/
247 /* basic char display */
248
249 #define FONT_HEIGHT 16
250 #define FONT_WIDTH 8
251
252 #include "vgafont.h"
253
254 #define cbswap_32(__x) \
255 ((uint32_t)( \
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) ))
260
261 /* XXX: endianness */
262 #if 0
263 #define PAT(x) cbswap_32(x)
264 #else
265 #define PAT(x) x
266 #endif
267
268 static const uint32_t dmask16[16] = {
269     PAT(0x00000000),
270     PAT(0x000000ff),
271     PAT(0x0000ff00),
272     PAT(0x0000ffff),
273     PAT(0x00ff0000),
274     PAT(0x00ff00ff),
275     PAT(0x00ffff00),
276     PAT(0x00ffffff),
277     PAT(0xff000000),
278     PAT(0xff0000ff),
279     PAT(0xff00ff00),
280     PAT(0xff00ffff),
281     PAT(0xffff0000),
282     PAT(0xffff00ff),
283     PAT(0xffffff00),
284     PAT(0xffffffff),
285 };
286
287 static const uint32_t dmask4[4] = {
288     PAT(0x00000000),
289     PAT(0x0000ffff),
290     PAT(0xffff0000),
291     PAT(0xffffffff),
292 };
293
294 int text_width, text_height, text_fgcol, text_bgcol, text_x, text_y;
295
296 static void vga_text_init(void)
297 {
298     text_width = vga_fb_width / FONT_WIDTH;
299     text_height = vga_fb_height / FONT_HEIGHT;
300     text_x = 0;
301     text_y = 0;
302     vga_text_set_fgcol(RGB(0xff, 0xff, 0xff));
303     vga_text_set_bgcol(RGB(0x00, 0x00, 0x00));
304 }
305
306 static inline unsigned int col_expand(unsigned int col)
307 {
308     switch(vga_fb_bpp) {
309     case 1:
310         col |= col << 8;
311         col |= col << 16;
312         break;
313     case 2:
314         col |= col << 16;
315         break;
316     default:
317         text_fgcol = 0xffffff;
318         break;
319     }
320
321     return col;
322 }
323
324 void vga_text_set_fgcol(unsigned int rgba)
325 {
326     text_fgcol = col_expand(vga_get_color(rgba));
327 }
328
329 void vga_text_set_bgcol(unsigned int rgba)
330 {
331     text_bgcol = col_expand(vga_get_color(rgba));
332 }
333
334 void vga_putcharxy(int x, int y, int ch, 
335                    unsigned int fgcol, unsigned int bgcol)
336 {
337     uint8_t *d;
338     const uint8_t *font_ptr;
339     unsigned int font_data, linesize, xorcol;
340     int i;
341
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) {
348     case 8:
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;
353             d += linesize;
354         }
355         break;
356     case 16:
357     case 15:
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;
364             d += linesize;
365         }
366         break;
367     case 32:
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;
378             d += linesize;
379         }
380         break;
381     }
382 }
383
384 static void vga_put_lf(void)
385 {
386     text_x = 0;
387     text_y++;
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);
395     }
396 }
397
398 void vga_putchar(int ch)
399 {
400     if (ch == '\r') {
401         text_x = 0;
402     } else if (ch == '\n') {
403         vga_put_lf();
404     } else if (ch == '\b') {
405         if (text_x == 0) {
406             if (text_y != 0) {
407                 text_x = text_width;
408                 text_y--;
409                 goto eat_char;
410             }
411         } else {
412         eat_char:
413             vga_putcharxy(--text_x, text_y, ' ', text_fgcol, text_bgcol);
414         }
415     } else {
416         vga_putcharxy(text_x, text_y, ch, text_fgcol, text_bgcol);
417         text_x++;
418         if (text_x >= text_width)
419             vga_put_lf();
420     }
421 }
422
423 void vga_puts(const char *s)
424 {
425     while (*s) {
426         vga_putchar(*(uint8_t *)s);
427         s++;
428     }
429 }