Optional "precise" VGA retrace support
[qemu] / hw / vga.c
1 /*
2  * QEMU VGA Emulator.
3  *
4  * Copyright (c) 2003 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 #include "hw.h"
25 #include "console.h"
26 #include "pc.h"
27 #include "pci.h"
28 #include "vga_int.h"
29 #include "pixel_ops.h"
30 #include "qemu-timer.h"
31
32 //#define DEBUG_VGA
33 //#define DEBUG_VGA_MEM
34 //#define DEBUG_VGA_REG
35
36 //#define DEBUG_BOCHS_VBE
37
38 /* force some bits to zero */
39 const uint8_t sr_mask[8] = {
40     (uint8_t)~0xfc,
41     (uint8_t)~0xc2,
42     (uint8_t)~0xf0,
43     (uint8_t)~0xc0,
44     (uint8_t)~0xf1,
45     (uint8_t)~0xff,
46     (uint8_t)~0xff,
47     (uint8_t)~0x00,
48 };
49
50 const uint8_t gr_mask[16] = {
51     (uint8_t)~0xf0, /* 0x00 */
52     (uint8_t)~0xf0, /* 0x01 */
53     (uint8_t)~0xf0, /* 0x02 */
54     (uint8_t)~0xe0, /* 0x03 */
55     (uint8_t)~0xfc, /* 0x04 */
56     (uint8_t)~0x84, /* 0x05 */
57     (uint8_t)~0xf0, /* 0x06 */
58     (uint8_t)~0xf0, /* 0x07 */
59     (uint8_t)~0x00, /* 0x08 */
60     (uint8_t)~0xff, /* 0x09 */
61     (uint8_t)~0xff, /* 0x0a */
62     (uint8_t)~0xff, /* 0x0b */
63     (uint8_t)~0xff, /* 0x0c */
64     (uint8_t)~0xff, /* 0x0d */
65     (uint8_t)~0xff, /* 0x0e */
66     (uint8_t)~0xff, /* 0x0f */
67 };
68
69 #define cbswap_32(__x) \
70 ((uint32_t)( \
71                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
72                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
73                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
74                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
75
76 #ifdef WORDS_BIGENDIAN
77 #define PAT(x) cbswap_32(x)
78 #else
79 #define PAT(x) (x)
80 #endif
81
82 #ifdef WORDS_BIGENDIAN
83 #define BIG 1
84 #else
85 #define BIG 0
86 #endif
87
88 #ifdef WORDS_BIGENDIAN
89 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
90 #else
91 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
92 #endif
93
94 static const uint32_t mask16[16] = {
95     PAT(0x00000000),
96     PAT(0x000000ff),
97     PAT(0x0000ff00),
98     PAT(0x0000ffff),
99     PAT(0x00ff0000),
100     PAT(0x00ff00ff),
101     PAT(0x00ffff00),
102     PAT(0x00ffffff),
103     PAT(0xff000000),
104     PAT(0xff0000ff),
105     PAT(0xff00ff00),
106     PAT(0xff00ffff),
107     PAT(0xffff0000),
108     PAT(0xffff00ff),
109     PAT(0xffffff00),
110     PAT(0xffffffff),
111 };
112
113 #undef PAT
114
115 #ifdef WORDS_BIGENDIAN
116 #define PAT(x) (x)
117 #else
118 #define PAT(x) cbswap_32(x)
119 #endif
120
121 static const uint32_t dmask16[16] = {
122     PAT(0x00000000),
123     PAT(0x000000ff),
124     PAT(0x0000ff00),
125     PAT(0x0000ffff),
126     PAT(0x00ff0000),
127     PAT(0x00ff00ff),
128     PAT(0x00ffff00),
129     PAT(0x00ffffff),
130     PAT(0xff000000),
131     PAT(0xff0000ff),
132     PAT(0xff00ff00),
133     PAT(0xff00ffff),
134     PAT(0xffff0000),
135     PAT(0xffff00ff),
136     PAT(0xffffff00),
137     PAT(0xffffffff),
138 };
139
140 static const uint32_t dmask4[4] = {
141     PAT(0x00000000),
142     PAT(0x0000ffff),
143     PAT(0xffff0000),
144     PAT(0xffffffff),
145 };
146
147 static uint32_t expand4[256];
148 static uint16_t expand2[256];
149 static uint8_t expand4to8[16];
150
151 static void vga_screen_dump(void *opaque, const char *filename);
152
153 static void vga_dumb_update_retrace_info(VGAState *s)
154 {
155     (void) s;
156 }
157
158 static void vga_precise_update_retrace_info(VGAState *s)
159 {
160     int htotal_chars;
161     int hretr_start_char;
162     int hretr_skew_chars;
163     int hretr_end_char;
164
165     int vtotal_lines;
166     int vretr_start_line;
167     int vretr_end_line;
168
169     int div2, sldiv2, dots;
170     int clocking_mode;
171     int clock_sel;
172     const int hz[] = {25175000, 28322000, 25175000, 25175000};
173     int64_t chars_per_sec;
174     struct vga_precise_retrace *r = &s->retrace_info.precise;
175
176     htotal_chars = s->cr[0x00] + 5;
177     hretr_start_char = s->cr[0x04];
178     hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
179     hretr_end_char = s->cr[0x05] & 0x1f;
180
181     vtotal_lines = (s->cr[0x06]
182                     | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
183         ;
184     vretr_start_line = s->cr[0x10]
185         | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
186         ;
187     vretr_end_line = s->cr[0x11] & 0xf;
188
189
190     div2 = (s->cr[0x17] >> 2) & 1;
191     sldiv2 = (s->cr[0x17] >> 3) & 1;
192
193     clocking_mode = (s->sr[0x01] >> 3) & 1;
194     clock_sel = (s->msr >> 2) & 3;
195     dots = (s->msr & 1) ? 9 : 8;
196
197     chars_per_sec = hz[clock_sel] / dots;
198
199     htotal_chars <<= clocking_mode;
200
201     r->total_chars = vtotal_lines * htotal_chars;
202     r->total_chars = (vretr_start_line + vretr_end_line + 1) * htotal_chars;
203     if (r->freq) {
204         r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
205     } else {
206         r->ticks_per_char = ticks_per_sec / chars_per_sec;
207     }
208
209     r->vstart = vretr_start_line;
210     r->vend = r->vstart + vretr_end_line + 1;
211
212     r->hstart = hretr_start_char + hretr_skew_chars;
213     r->hend = r->hstart + hretr_end_char + 1;
214     r->htotal = htotal_chars;
215
216     printf("hz=%f\n",
217            (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
218 #if 0 /* def DEBUG_RETRACE */
219     printf("hz=%f\n",
220            (double) ticks_per_sec / (r->ticks_per_char * r->total_chars));
221     printf (
222         "htotal = %d\n"
223         "hretr_start = %d\n"
224         "hretr_skew = %d\n"
225         "hretr_end = %d\n"
226         "vtotal = %d\n"
227         "vretr_start = %d\n"
228         "vretr_end = %d\n"
229         "div2 = %d sldiv2 = %d\n"
230         "clocking_mode = %d\n"
231         "clock_sel = %d %d\n"
232         "dots = %d\n"
233         "ticks/char = %lld\n"
234         "\n",
235         htotal_chars,
236         hretr_start_char,
237         hretr_skew_chars,
238         hretr_end_char,
239         vtotal_lines,
240         vretr_start_line,
241         vretr_end_line,
242         div2, sldiv2,
243         clocking_mode,
244         clock_sel,
245         hz[clock_sel],
246         dots,
247         r->ticks_per_char
248         );
249 #endif
250 }
251
252 static uint8_t vga_precise_retrace(VGAState *s)
253 {
254     struct vga_precise_retrace *r = &s->retrace_info.precise;
255     uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
256
257     if (r->total_chars) {
258         int cur_line, cur_line_char, cur_char;
259         int64_t cur_tick;
260
261         cur_tick = qemu_get_clock(vm_clock);
262
263         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
264         cur_line = cur_char / r->htotal;
265
266         if (cur_line >= r->vstart && cur_line <= r->vend) {
267             val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
268         }
269
270         cur_line_char = cur_char % r->htotal;
271         if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
272             val |= ST01_DISP_ENABLE;
273         }
274
275         return val;
276     } else {
277         return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
278     }
279 }
280
281 static uint8_t vga_dumb_retrace(VGAState *s)
282 {
283     return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
284 }
285
286 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
287 {
288     VGAState *s = opaque;
289     int val, index;
290
291     /* check port range access depending on color/monochrome mode */
292     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
293         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
294         val = 0xff;
295     } else {
296         switch(addr) {
297         case 0x3c0:
298             if (s->ar_flip_flop == 0) {
299                 val = s->ar_index;
300             } else {
301                 val = 0;
302             }
303             break;
304         case 0x3c1:
305             index = s->ar_index & 0x1f;
306             if (index < 21)
307                 val = s->ar[index];
308             else
309                 val = 0;
310             break;
311         case 0x3c2:
312             val = s->st00;
313             break;
314         case 0x3c4:
315             val = s->sr_index;
316             break;
317         case 0x3c5:
318             val = s->sr[s->sr_index];
319 #ifdef DEBUG_VGA_REG
320             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
321 #endif
322             break;
323         case 0x3c7:
324             val = s->dac_state;
325             break;
326         case 0x3c8:
327             val = s->dac_write_index;
328             break;
329         case 0x3c9:
330             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
331             if (++s->dac_sub_index == 3) {
332                 s->dac_sub_index = 0;
333                 s->dac_read_index++;
334             }
335             break;
336         case 0x3ca:
337             val = s->fcr;
338             break;
339         case 0x3cc:
340             val = s->msr;
341             break;
342         case 0x3ce:
343             val = s->gr_index;
344             break;
345         case 0x3cf:
346             val = s->gr[s->gr_index];
347 #ifdef DEBUG_VGA_REG
348             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
349 #endif
350             break;
351         case 0x3b4:
352         case 0x3d4:
353             val = s->cr_index;
354             break;
355         case 0x3b5:
356         case 0x3d5:
357             val = s->cr[s->cr_index];
358 #ifdef DEBUG_VGA_REG
359             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
360 #endif
361             break;
362         case 0x3ba:
363         case 0x3da:
364             /* just toggle to fool polling */
365             val = s->st01 = s->retrace(s);
366             s->ar_flip_flop = 0;
367             break;
368         default:
369             val = 0x00;
370             break;
371         }
372     }
373 #if defined(DEBUG_VGA)
374     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
375 #endif
376     return val;
377 }
378
379 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
380 {
381     VGAState *s = opaque;
382     int index;
383
384     /* check port range access depending on color/monochrome mode */
385     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
386         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
387         return;
388
389 #ifdef DEBUG_VGA
390     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
391 #endif
392
393     switch(addr) {
394     case 0x3c0:
395         if (s->ar_flip_flop == 0) {
396             val &= 0x3f;
397             s->ar_index = val;
398         } else {
399             index = s->ar_index & 0x1f;
400             switch(index) {
401             case 0x00 ... 0x0f:
402                 s->ar[index] = val & 0x3f;
403                 break;
404             case 0x10:
405                 s->ar[index] = val & ~0x10;
406                 break;
407             case 0x11:
408                 s->ar[index] = val;
409                 break;
410             case 0x12:
411                 s->ar[index] = val & ~0xc0;
412                 break;
413             case 0x13:
414                 s->ar[index] = val & ~0xf0;
415                 break;
416             case 0x14:
417                 s->ar[index] = val & ~0xf0;
418                 break;
419             default:
420                 break;
421             }
422         }
423         s->ar_flip_flop ^= 1;
424         break;
425     case 0x3c2:
426         s->msr = val & ~0x10;
427         s->update_retrace_info(s);
428         break;
429     case 0x3c4:
430         s->sr_index = val & 7;
431         break;
432     case 0x3c5:
433 #ifdef DEBUG_VGA_REG
434         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
435 #endif
436         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
437         if (s->sr_index == 1) s->update_retrace_info(s);
438         break;
439     case 0x3c7:
440         s->dac_read_index = val;
441         s->dac_sub_index = 0;
442         s->dac_state = 3;
443         break;
444     case 0x3c8:
445         s->dac_write_index = val;
446         s->dac_sub_index = 0;
447         s->dac_state = 0;
448         break;
449     case 0x3c9:
450         s->dac_cache[s->dac_sub_index] = val;
451         if (++s->dac_sub_index == 3) {
452             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
453             s->dac_sub_index = 0;
454             s->dac_write_index++;
455         }
456         break;
457     case 0x3ce:
458         s->gr_index = val & 0x0f;
459         break;
460     case 0x3cf:
461 #ifdef DEBUG_VGA_REG
462         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
463 #endif
464         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
465         break;
466     case 0x3b4:
467     case 0x3d4:
468         s->cr_index = val;
469         break;
470     case 0x3b5:
471     case 0x3d5:
472 #ifdef DEBUG_VGA_REG
473         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
474 #endif
475         /* handle CR0-7 protection */
476         if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
477             /* can always write bit 4 of CR7 */
478             if (s->cr_index == 7)
479                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
480             return;
481         }
482         switch(s->cr_index) {
483         case 0x01: /* horizontal display end */
484         case 0x07:
485         case 0x09:
486         case 0x0c:
487         case 0x0d:
488         case 0x12: /* vertical display end */
489             s->cr[s->cr_index] = val;
490             break;
491         default:
492             s->cr[s->cr_index] = val;
493             break;
494         }
495
496         switch(s->cr_index) {
497         case 0x00:
498         case 0x04:
499         case 0x05:
500         case 0x06:
501         case 0x07:
502         case 0x11:
503         case 0x17:
504             s->update_retrace_info(s);
505             break;
506         }
507         break;
508     case 0x3ba:
509     case 0x3da:
510         s->fcr = val & 0x10;
511         break;
512     }
513 }
514
515 #ifdef CONFIG_BOCHS_VBE
516 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
517 {
518     VGAState *s = opaque;
519     uint32_t val;
520     val = s->vbe_index;
521     return val;
522 }
523
524 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
525 {
526     VGAState *s = opaque;
527     uint32_t val;
528
529     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
530         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
531             switch(s->vbe_index) {
532                 /* XXX: do not hardcode ? */
533             case VBE_DISPI_INDEX_XRES:
534                 val = VBE_DISPI_MAX_XRES;
535                 break;
536             case VBE_DISPI_INDEX_YRES:
537                 val = VBE_DISPI_MAX_YRES;
538                 break;
539             case VBE_DISPI_INDEX_BPP:
540                 val = VBE_DISPI_MAX_BPP;
541                 break;
542             default:
543                 val = s->vbe_regs[s->vbe_index];
544                 break;
545             }
546         } else {
547             val = s->vbe_regs[s->vbe_index];
548         }
549     } else {
550         val = 0;
551     }
552 #ifdef DEBUG_BOCHS_VBE
553     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
554 #endif
555     return val;
556 }
557
558 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
559 {
560     VGAState *s = opaque;
561     s->vbe_index = val;
562 }
563
564 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
565 {
566     VGAState *s = opaque;
567
568     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
569 #ifdef DEBUG_BOCHS_VBE
570         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
571 #endif
572         switch(s->vbe_index) {
573         case VBE_DISPI_INDEX_ID:
574             if (val == VBE_DISPI_ID0 ||
575                 val == VBE_DISPI_ID1 ||
576                 val == VBE_DISPI_ID2 ||
577                 val == VBE_DISPI_ID3 ||
578                 val == VBE_DISPI_ID4) {
579                 s->vbe_regs[s->vbe_index] = val;
580             }
581             break;
582         case VBE_DISPI_INDEX_XRES:
583             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
584                 s->vbe_regs[s->vbe_index] = val;
585             }
586             break;
587         case VBE_DISPI_INDEX_YRES:
588             if (val <= VBE_DISPI_MAX_YRES) {
589                 s->vbe_regs[s->vbe_index] = val;
590             }
591             break;
592         case VBE_DISPI_INDEX_BPP:
593             if (val == 0)
594                 val = 8;
595             if (val == 4 || val == 8 || val == 15 ||
596                 val == 16 || val == 24 || val == 32) {
597                 s->vbe_regs[s->vbe_index] = val;
598             }
599             break;
600         case VBE_DISPI_INDEX_BANK:
601             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
602               val &= (s->vbe_bank_mask >> 2);
603             } else {
604               val &= s->vbe_bank_mask;
605             }
606             s->vbe_regs[s->vbe_index] = val;
607             s->bank_offset = (val << 16);
608             break;
609         case VBE_DISPI_INDEX_ENABLE:
610             if ((val & VBE_DISPI_ENABLED) &&
611                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
612                 int h, shift_control;
613
614                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
615                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
616                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
617                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
618                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
619                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
620
621                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
622                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
623                 else
624                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
625                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
626                 s->vbe_start_addr = 0;
627
628                 /* clear the screen (should be done in BIOS) */
629                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
630                     memset(s->vram_ptr, 0,
631                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
632                 }
633
634                 /* we initialize the VGA graphic mode (should be done
635                    in BIOS) */
636                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
637                 s->cr[0x17] |= 3; /* no CGA modes */
638                 s->cr[0x13] = s->vbe_line_offset >> 3;
639                 /* width */
640                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
641                 /* height (only meaningful if < 1024) */
642                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
643                 s->cr[0x12] = h;
644                 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
645                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
646                 /* line compare to 1023 */
647                 s->cr[0x18] = 0xff;
648                 s->cr[0x07] |= 0x10;
649                 s->cr[0x09] |= 0x40;
650
651                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
652                     shift_control = 0;
653                     s->sr[0x01] &= ~8; /* no double line */
654                 } else {
655                     shift_control = 2;
656                     s->sr[4] |= 0x08; /* set chain 4 mode */
657                     s->sr[2] |= 0x0f; /* activate all planes */
658                 }
659                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
660                 s->cr[0x09] &= ~0x9f; /* no double scan */
661             } else {
662                 /* XXX: the bios should do that */
663                 s->bank_offset = 0;
664             }
665             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
666             s->vbe_regs[s->vbe_index] = val;
667             break;
668         case VBE_DISPI_INDEX_VIRT_WIDTH:
669             {
670                 int w, h, line_offset;
671
672                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
673                     return;
674                 w = val;
675                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
676                     line_offset = w >> 1;
677                 else
678                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
679                 h = s->vram_size / line_offset;
680                 /* XXX: support weird bochs semantics ? */
681                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
682                     return;
683                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
684                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
685                 s->vbe_line_offset = line_offset;
686             }
687             break;
688         case VBE_DISPI_INDEX_X_OFFSET:
689         case VBE_DISPI_INDEX_Y_OFFSET:
690             {
691                 int x;
692                 s->vbe_regs[s->vbe_index] = val;
693                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
694                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
695                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
696                     s->vbe_start_addr += x >> 1;
697                 else
698                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
699                 s->vbe_start_addr >>= 2;
700             }
701             break;
702         default:
703             break;
704         }
705     }
706 }
707 #endif
708
709 /* called for accesses between 0xa0000 and 0xc0000 */
710 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
711 {
712     VGAState *s = opaque;
713     int memory_map_mode, plane;
714     uint32_t ret;
715
716     /* convert to VGA memory offset */
717     memory_map_mode = (s->gr[6] >> 2) & 3;
718     addr &= 0x1ffff;
719     switch(memory_map_mode) {
720     case 0:
721         break;
722     case 1:
723         if (addr >= 0x10000)
724             return 0xff;
725         addr += s->bank_offset;
726         break;
727     case 2:
728         addr -= 0x10000;
729         if (addr >= 0x8000)
730             return 0xff;
731         break;
732     default:
733     case 3:
734         addr -= 0x18000;
735         if (addr >= 0x8000)
736             return 0xff;
737         break;
738     }
739
740     if (s->sr[4] & 0x08) {
741         /* chain 4 mode : simplest access */
742         ret = s->vram_ptr[addr];
743     } else if (s->gr[5] & 0x10) {
744         /* odd/even mode (aka text mode mapping) */
745         plane = (s->gr[4] & 2) | (addr & 1);
746         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
747     } else {
748         /* standard VGA latched access */
749         s->latch = ((uint32_t *)s->vram_ptr)[addr];
750
751         if (!(s->gr[5] & 0x08)) {
752             /* read mode 0 */
753             plane = s->gr[4];
754             ret = GET_PLANE(s->latch, plane);
755         } else {
756             /* read mode 1 */
757             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
758             ret |= ret >> 16;
759             ret |= ret >> 8;
760             ret = (~ret) & 0xff;
761         }
762     }
763     return ret;
764 }
765
766 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
767 {
768     uint32_t v;
769 #ifdef TARGET_WORDS_BIGENDIAN
770     v = vga_mem_readb(opaque, addr) << 8;
771     v |= vga_mem_readb(opaque, addr + 1);
772 #else
773     v = vga_mem_readb(opaque, addr);
774     v |= vga_mem_readb(opaque, addr + 1) << 8;
775 #endif
776     return v;
777 }
778
779 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
780 {
781     uint32_t v;
782 #ifdef TARGET_WORDS_BIGENDIAN
783     v = vga_mem_readb(opaque, addr) << 24;
784     v |= vga_mem_readb(opaque, addr + 1) << 16;
785     v |= vga_mem_readb(opaque, addr + 2) << 8;
786     v |= vga_mem_readb(opaque, addr + 3);
787 #else
788     v = vga_mem_readb(opaque, addr);
789     v |= vga_mem_readb(opaque, addr + 1) << 8;
790     v |= vga_mem_readb(opaque, addr + 2) << 16;
791     v |= vga_mem_readb(opaque, addr + 3) << 24;
792 #endif
793     return v;
794 }
795
796 /* called for accesses between 0xa0000 and 0xc0000 */
797 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
798 {
799     VGAState *s = opaque;
800     int memory_map_mode, plane, write_mode, b, func_select, mask;
801     uint32_t write_mask, bit_mask, set_mask;
802
803 #ifdef DEBUG_VGA_MEM
804     printf("vga: [0x%x] = 0x%02x\n", addr, val);
805 #endif
806     /* convert to VGA memory offset */
807     memory_map_mode = (s->gr[6] >> 2) & 3;
808     addr &= 0x1ffff;
809     switch(memory_map_mode) {
810     case 0:
811         break;
812     case 1:
813         if (addr >= 0x10000)
814             return;
815         addr += s->bank_offset;
816         break;
817     case 2:
818         addr -= 0x10000;
819         if (addr >= 0x8000)
820             return;
821         break;
822     default:
823     case 3:
824         addr -= 0x18000;
825         if (addr >= 0x8000)
826             return;
827         break;
828     }
829
830     if (s->sr[4] & 0x08) {
831         /* chain 4 mode : simplest access */
832         plane = addr & 3;
833         mask = (1 << plane);
834         if (s->sr[2] & mask) {
835             s->vram_ptr[addr] = val;
836 #ifdef DEBUG_VGA_MEM
837             printf("vga: chain4: [0x%x]\n", addr);
838 #endif
839             s->plane_updated |= mask; /* only used to detect font change */
840             cpu_physical_memory_set_dirty(s->vram_offset + addr);
841         }
842     } else if (s->gr[5] & 0x10) {
843         /* odd/even mode (aka text mode mapping) */
844         plane = (s->gr[4] & 2) | (addr & 1);
845         mask = (1 << plane);
846         if (s->sr[2] & mask) {
847             addr = ((addr & ~1) << 1) | plane;
848             s->vram_ptr[addr] = val;
849 #ifdef DEBUG_VGA_MEM
850             printf("vga: odd/even: [0x%x]\n", addr);
851 #endif
852             s->plane_updated |= mask; /* only used to detect font change */
853             cpu_physical_memory_set_dirty(s->vram_offset + addr);
854         }
855     } else {
856         /* standard VGA latched access */
857         write_mode = s->gr[5] & 3;
858         switch(write_mode) {
859         default:
860         case 0:
861             /* rotate */
862             b = s->gr[3] & 7;
863             val = ((val >> b) | (val << (8 - b))) & 0xff;
864             val |= val << 8;
865             val |= val << 16;
866
867             /* apply set/reset mask */
868             set_mask = mask16[s->gr[1]];
869             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
870             bit_mask = s->gr[8];
871             break;
872         case 1:
873             val = s->latch;
874             goto do_write;
875         case 2:
876             val = mask16[val & 0x0f];
877             bit_mask = s->gr[8];
878             break;
879         case 3:
880             /* rotate */
881             b = s->gr[3] & 7;
882             val = (val >> b) | (val << (8 - b));
883
884             bit_mask = s->gr[8] & val;
885             val = mask16[s->gr[0]];
886             break;
887         }
888
889         /* apply logical operation */
890         func_select = s->gr[3] >> 3;
891         switch(func_select) {
892         case 0:
893         default:
894             /* nothing to do */
895             break;
896         case 1:
897             /* and */
898             val &= s->latch;
899             break;
900         case 2:
901             /* or */
902             val |= s->latch;
903             break;
904         case 3:
905             /* xor */
906             val ^= s->latch;
907             break;
908         }
909
910         /* apply bit mask */
911         bit_mask |= bit_mask << 8;
912         bit_mask |= bit_mask << 16;
913         val = (val & bit_mask) | (s->latch & ~bit_mask);
914
915     do_write:
916         /* mask data according to sr[2] */
917         mask = s->sr[2];
918         s->plane_updated |= mask; /* only used to detect font change */
919         write_mask = mask16[mask];
920         ((uint32_t *)s->vram_ptr)[addr] =
921             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
922             (val & write_mask);
923 #ifdef DEBUG_VGA_MEM
924             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
925                    addr * 4, write_mask, val);
926 #endif
927             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
928     }
929 }
930
931 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
932 {
933 #ifdef TARGET_WORDS_BIGENDIAN
934     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
935     vga_mem_writeb(opaque, addr + 1, val & 0xff);
936 #else
937     vga_mem_writeb(opaque, addr, val & 0xff);
938     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
939 #endif
940 }
941
942 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
943 {
944 #ifdef TARGET_WORDS_BIGENDIAN
945     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
946     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
947     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
948     vga_mem_writeb(opaque, addr + 3, val & 0xff);
949 #else
950     vga_mem_writeb(opaque, addr, val & 0xff);
951     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
952     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
953     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
954 #endif
955 }
956
957 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
958                              const uint8_t *font_ptr, int h,
959                              uint32_t fgcol, uint32_t bgcol);
960 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
961                                   const uint8_t *font_ptr, int h,
962                                   uint32_t fgcol, uint32_t bgcol, int dup9);
963 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
964                                 const uint8_t *s, int width);
965
966 #define DEPTH 8
967 #include "vga_template.h"
968
969 #define DEPTH 15
970 #include "vga_template.h"
971
972 #define BGR_FORMAT
973 #define DEPTH 15
974 #include "vga_template.h"
975
976 #define DEPTH 16
977 #include "vga_template.h"
978
979 #define BGR_FORMAT
980 #define DEPTH 16
981 #include "vga_template.h"
982
983 #define DEPTH 32
984 #include "vga_template.h"
985
986 #define BGR_FORMAT
987 #define DEPTH 32
988 #include "vga_template.h"
989
990 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
991 {
992     unsigned int col;
993     col = rgb_to_pixel8(r, g, b);
994     col |= col << 8;
995     col |= col << 16;
996     return col;
997 }
998
999 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1000 {
1001     unsigned int col;
1002     col = rgb_to_pixel15(r, g, b);
1003     col |= col << 16;
1004     return col;
1005 }
1006
1007 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1008                                           unsigned int b)
1009 {
1010     unsigned int col;
1011     col = rgb_to_pixel15bgr(r, g, b);
1012     col |= col << 16;
1013     return col;
1014 }
1015
1016 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1017 {
1018     unsigned int col;
1019     col = rgb_to_pixel16(r, g, b);
1020     col |= col << 16;
1021     return col;
1022 }
1023
1024 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1025                                           unsigned int b)
1026 {
1027     unsigned int col;
1028     col = rgb_to_pixel16bgr(r, g, b);
1029     col |= col << 16;
1030     return col;
1031 }
1032
1033 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1034 {
1035     unsigned int col;
1036     col = rgb_to_pixel32(r, g, b);
1037     return col;
1038 }
1039
1040 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1041 {
1042     unsigned int col;
1043     col = rgb_to_pixel32bgr(r, g, b);
1044     return col;
1045 }
1046
1047 /* return true if the palette was modified */
1048 static int update_palette16(VGAState *s)
1049 {
1050     int full_update, i;
1051     uint32_t v, col, *palette;
1052
1053     full_update = 0;
1054     palette = s->last_palette;
1055     for(i = 0; i < 16; i++) {
1056         v = s->ar[i];
1057         if (s->ar[0x10] & 0x80)
1058             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1059         else
1060             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1061         v = v * 3;
1062         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1063                               c6_to_8(s->palette[v + 1]),
1064                               c6_to_8(s->palette[v + 2]));
1065         if (col != palette[i]) {
1066             full_update = 1;
1067             palette[i] = col;
1068         }
1069     }
1070     return full_update;
1071 }
1072
1073 /* return true if the palette was modified */
1074 static int update_palette256(VGAState *s)
1075 {
1076     int full_update, i;
1077     uint32_t v, col, *palette;
1078
1079     full_update = 0;
1080     palette = s->last_palette;
1081     v = 0;
1082     for(i = 0; i < 256; i++) {
1083         if (s->dac_8bit) {
1084           col = s->rgb_to_pixel(s->palette[v],
1085                                 s->palette[v + 1],
1086                                 s->palette[v + 2]);
1087         } else {
1088           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1089                                 c6_to_8(s->palette[v + 1]),
1090                                 c6_to_8(s->palette[v + 2]));
1091         }
1092         if (col != palette[i]) {
1093             full_update = 1;
1094             palette[i] = col;
1095         }
1096         v += 3;
1097     }
1098     return full_update;
1099 }
1100
1101 static void vga_get_offsets(VGAState *s,
1102                             uint32_t *pline_offset,
1103                             uint32_t *pstart_addr,
1104                             uint32_t *pline_compare)
1105 {
1106     uint32_t start_addr, line_offset, line_compare;
1107 #ifdef CONFIG_BOCHS_VBE
1108     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1109         line_offset = s->vbe_line_offset;
1110         start_addr = s->vbe_start_addr;
1111         line_compare = 65535;
1112     } else
1113 #endif
1114     {
1115         /* compute line_offset in bytes */
1116         line_offset = s->cr[0x13];
1117         line_offset <<= 3;
1118
1119         /* starting address */
1120         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1121
1122         /* line compare */
1123         line_compare = s->cr[0x18] |
1124             ((s->cr[0x07] & 0x10) << 4) |
1125             ((s->cr[0x09] & 0x40) << 3);
1126     }
1127     *pline_offset = line_offset;
1128     *pstart_addr = start_addr;
1129     *pline_compare = line_compare;
1130 }
1131
1132 /* update start_addr and line_offset. Return TRUE if modified */
1133 static int update_basic_params(VGAState *s)
1134 {
1135     int full_update;
1136     uint32_t start_addr, line_offset, line_compare;
1137
1138     full_update = 0;
1139
1140     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1141
1142     if (line_offset != s->line_offset ||
1143         start_addr != s->start_addr ||
1144         line_compare != s->line_compare) {
1145         s->line_offset = line_offset;
1146         s->start_addr = start_addr;
1147         s->line_compare = line_compare;
1148         full_update = 1;
1149     }
1150     return full_update;
1151 }
1152
1153 #define NB_DEPTHS 7
1154
1155 static inline int get_depth_index(DisplayState *s)
1156 {
1157     switch(s->depth) {
1158     default:
1159     case 8:
1160         return 0;
1161     case 15:
1162         if (s->bgr)
1163             return 5;
1164         else
1165             return 1;
1166     case 16:
1167         if (s->bgr)
1168             return 6;
1169         else
1170             return 2;
1171     case 32:
1172         if (s->bgr)
1173             return 4;
1174         else
1175             return 3;
1176     }
1177 }
1178
1179 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1180     vga_draw_glyph8_8,
1181     vga_draw_glyph8_16,
1182     vga_draw_glyph8_16,
1183     vga_draw_glyph8_32,
1184     vga_draw_glyph8_32,
1185     vga_draw_glyph8_16,
1186     vga_draw_glyph8_16,
1187 };
1188
1189 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1190     vga_draw_glyph16_8,
1191     vga_draw_glyph16_16,
1192     vga_draw_glyph16_16,
1193     vga_draw_glyph16_32,
1194     vga_draw_glyph16_32,
1195     vga_draw_glyph16_16,
1196     vga_draw_glyph16_16,
1197 };
1198
1199 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1200     vga_draw_glyph9_8,
1201     vga_draw_glyph9_16,
1202     vga_draw_glyph9_16,
1203     vga_draw_glyph9_32,
1204     vga_draw_glyph9_32,
1205     vga_draw_glyph9_16,
1206     vga_draw_glyph9_16,
1207 };
1208
1209 static const uint8_t cursor_glyph[32 * 4] = {
1210     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1225     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226 };
1227
1228 /*
1229  * Text mode update
1230  * Missing:
1231  * - double scan
1232  * - double width
1233  * - underline
1234  * - flashing
1235  */
1236 static void vga_draw_text(VGAState *s, int full_update)
1237 {
1238     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1239     int cx_min, cx_max, linesize, x_incr;
1240     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1241     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1242     const uint8_t *font_ptr, *font_base[2];
1243     int dup9, line_offset, depth_index;
1244     uint32_t *palette;
1245     uint32_t *ch_attr_ptr;
1246     vga_draw_glyph8_func *vga_draw_glyph8;
1247     vga_draw_glyph9_func *vga_draw_glyph9;
1248
1249     full_update |= update_palette16(s);
1250     palette = s->last_palette;
1251
1252     /* compute font data address (in plane 2) */
1253     v = s->sr[3];
1254     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1255     if (offset != s->font_offsets[0]) {
1256         s->font_offsets[0] = offset;
1257         full_update = 1;
1258     }
1259     font_base[0] = s->vram_ptr + offset;
1260
1261     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1262     font_base[1] = s->vram_ptr + offset;
1263     if (offset != s->font_offsets[1]) {
1264         s->font_offsets[1] = offset;
1265         full_update = 1;
1266     }
1267     if (s->plane_updated & (1 << 2)) {
1268         /* if the plane 2 was modified since the last display, it
1269            indicates the font may have been modified */
1270         s->plane_updated = 0;
1271         full_update = 1;
1272     }
1273     full_update |= update_basic_params(s);
1274
1275     line_offset = s->line_offset;
1276     s1 = s->vram_ptr + (s->start_addr * 4);
1277
1278     /* total width & height */
1279     cheight = (s->cr[9] & 0x1f) + 1;
1280     cw = 8;
1281     if (!(s->sr[1] & 0x01))
1282         cw = 9;
1283     if (s->sr[1] & 0x08)
1284         cw = 16; /* NOTE: no 18 pixel wide */
1285     x_incr = cw * ((s->ds->depth + 7) >> 3);
1286     width = (s->cr[0x01] + 1);
1287     if (s->cr[0x06] == 100) {
1288         /* ugly hack for CGA 160x100x16 - explain me the logic */
1289         height = 100;
1290     } else {
1291         height = s->cr[0x12] |
1292             ((s->cr[0x07] & 0x02) << 7) |
1293             ((s->cr[0x07] & 0x40) << 3);
1294         height = (height + 1) / cheight;
1295     }
1296     if ((height * width) > CH_ATTR_SIZE) {
1297         /* better than nothing: exit if transient size is too big */
1298         return;
1299     }
1300
1301     if (width != s->last_width || height != s->last_height ||
1302         cw != s->last_cw || cheight != s->last_ch) {
1303         s->last_scr_width = width * cw;
1304         s->last_scr_height = height * cheight;
1305         qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
1306         s->last_width = width;
1307         s->last_height = height;
1308         s->last_ch = cheight;
1309         s->last_cw = cw;
1310         full_update = 1;
1311     }
1312     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1313     if (cursor_offset != s->cursor_offset ||
1314         s->cr[0xa] != s->cursor_start ||
1315         s->cr[0xb] != s->cursor_end) {
1316       /* if the cursor position changed, we update the old and new
1317          chars */
1318         if (s->cursor_offset < CH_ATTR_SIZE)
1319             s->last_ch_attr[s->cursor_offset] = -1;
1320         if (cursor_offset < CH_ATTR_SIZE)
1321             s->last_ch_attr[cursor_offset] = -1;
1322         s->cursor_offset = cursor_offset;
1323         s->cursor_start = s->cr[0xa];
1324         s->cursor_end = s->cr[0xb];
1325     }
1326     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1327
1328     depth_index = get_depth_index(s->ds);
1329     if (cw == 16)
1330         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1331     else
1332         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1333     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1334
1335     dest = s->ds->data;
1336     linesize = s->ds->linesize;
1337     ch_attr_ptr = s->last_ch_attr;
1338     for(cy = 0; cy < height; cy++) {
1339         d1 = dest;
1340         src = s1;
1341         cx_min = width;
1342         cx_max = -1;
1343         for(cx = 0; cx < width; cx++) {
1344             ch_attr = *(uint16_t *)src;
1345             if (full_update || ch_attr != *ch_attr_ptr) {
1346                 if (cx < cx_min)
1347                     cx_min = cx;
1348                 if (cx > cx_max)
1349                     cx_max = cx;
1350                 *ch_attr_ptr = ch_attr;
1351 #ifdef WORDS_BIGENDIAN
1352                 ch = ch_attr >> 8;
1353                 cattr = ch_attr & 0xff;
1354 #else
1355                 ch = ch_attr & 0xff;
1356                 cattr = ch_attr >> 8;
1357 #endif
1358                 font_ptr = font_base[(cattr >> 3) & 1];
1359                 font_ptr += 32 * 4 * ch;
1360                 bgcol = palette[cattr >> 4];
1361                 fgcol = palette[cattr & 0x0f];
1362                 if (cw != 9) {
1363                     vga_draw_glyph8(d1, linesize,
1364                                     font_ptr, cheight, fgcol, bgcol);
1365                 } else {
1366                     dup9 = 0;
1367                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1368                         dup9 = 1;
1369                     vga_draw_glyph9(d1, linesize,
1370                                     font_ptr, cheight, fgcol, bgcol, dup9);
1371                 }
1372                 if (src == cursor_ptr &&
1373                     !(s->cr[0x0a] & 0x20)) {
1374                     int line_start, line_last, h;
1375                     /* draw the cursor */
1376                     line_start = s->cr[0x0a] & 0x1f;
1377                     line_last = s->cr[0x0b] & 0x1f;
1378                     /* XXX: check that */
1379                     if (line_last > cheight - 1)
1380                         line_last = cheight - 1;
1381                     if (line_last >= line_start && line_start < cheight) {
1382                         h = line_last - line_start + 1;
1383                         d = d1 + linesize * line_start;
1384                         if (cw != 9) {
1385                             vga_draw_glyph8(d, linesize,
1386                                             cursor_glyph, h, fgcol, bgcol);
1387                         } else {
1388                             vga_draw_glyph9(d, linesize,
1389                                             cursor_glyph, h, fgcol, bgcol, 1);
1390                         }
1391                     }
1392                 }
1393             }
1394             d1 += x_incr;
1395             src += 4;
1396             ch_attr_ptr++;
1397         }
1398         if (cx_max != -1) {
1399             dpy_update(s->ds, cx_min * cw, cy * cheight,
1400                        (cx_max - cx_min + 1) * cw, cheight);
1401         }
1402         dest += linesize * cheight;
1403         s1 += line_offset;
1404     }
1405 }
1406
1407 enum {
1408     VGA_DRAW_LINE2,
1409     VGA_DRAW_LINE2D2,
1410     VGA_DRAW_LINE4,
1411     VGA_DRAW_LINE4D2,
1412     VGA_DRAW_LINE8D2,
1413     VGA_DRAW_LINE8,
1414     VGA_DRAW_LINE15,
1415     VGA_DRAW_LINE16,
1416     VGA_DRAW_LINE24,
1417     VGA_DRAW_LINE32,
1418     VGA_DRAW_LINE_NB,
1419 };
1420
1421 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1422     vga_draw_line2_8,
1423     vga_draw_line2_16,
1424     vga_draw_line2_16,
1425     vga_draw_line2_32,
1426     vga_draw_line2_32,
1427     vga_draw_line2_16,
1428     vga_draw_line2_16,
1429
1430     vga_draw_line2d2_8,
1431     vga_draw_line2d2_16,
1432     vga_draw_line2d2_16,
1433     vga_draw_line2d2_32,
1434     vga_draw_line2d2_32,
1435     vga_draw_line2d2_16,
1436     vga_draw_line2d2_16,
1437
1438     vga_draw_line4_8,
1439     vga_draw_line4_16,
1440     vga_draw_line4_16,
1441     vga_draw_line4_32,
1442     vga_draw_line4_32,
1443     vga_draw_line4_16,
1444     vga_draw_line4_16,
1445
1446     vga_draw_line4d2_8,
1447     vga_draw_line4d2_16,
1448     vga_draw_line4d2_16,
1449     vga_draw_line4d2_32,
1450     vga_draw_line4d2_32,
1451     vga_draw_line4d2_16,
1452     vga_draw_line4d2_16,
1453
1454     vga_draw_line8d2_8,
1455     vga_draw_line8d2_16,
1456     vga_draw_line8d2_16,
1457     vga_draw_line8d2_32,
1458     vga_draw_line8d2_32,
1459     vga_draw_line8d2_16,
1460     vga_draw_line8d2_16,
1461
1462     vga_draw_line8_8,
1463     vga_draw_line8_16,
1464     vga_draw_line8_16,
1465     vga_draw_line8_32,
1466     vga_draw_line8_32,
1467     vga_draw_line8_16,
1468     vga_draw_line8_16,
1469
1470     vga_draw_line15_8,
1471     vga_draw_line15_15,
1472     vga_draw_line15_16,
1473     vga_draw_line15_32,
1474     vga_draw_line15_32bgr,
1475     vga_draw_line15_15bgr,
1476     vga_draw_line15_16bgr,
1477
1478     vga_draw_line16_8,
1479     vga_draw_line16_15,
1480     vga_draw_line16_16,
1481     vga_draw_line16_32,
1482     vga_draw_line16_32bgr,
1483     vga_draw_line16_15bgr,
1484     vga_draw_line16_16bgr,
1485
1486     vga_draw_line24_8,
1487     vga_draw_line24_15,
1488     vga_draw_line24_16,
1489     vga_draw_line24_32,
1490     vga_draw_line24_32bgr,
1491     vga_draw_line24_15bgr,
1492     vga_draw_line24_16bgr,
1493
1494     vga_draw_line32_8,
1495     vga_draw_line32_15,
1496     vga_draw_line32_16,
1497     vga_draw_line32_32,
1498     vga_draw_line32_32bgr,
1499     vga_draw_line32_15bgr,
1500     vga_draw_line32_16bgr,
1501 };
1502
1503 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1504
1505 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1506     rgb_to_pixel8_dup,
1507     rgb_to_pixel15_dup,
1508     rgb_to_pixel16_dup,
1509     rgb_to_pixel32_dup,
1510     rgb_to_pixel32bgr_dup,
1511     rgb_to_pixel15bgr_dup,
1512     rgb_to_pixel16bgr_dup,
1513 };
1514
1515 static int vga_get_bpp(VGAState *s)
1516 {
1517     int ret;
1518 #ifdef CONFIG_BOCHS_VBE
1519     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1520         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1521     } else
1522 #endif
1523     {
1524         ret = 0;
1525     }
1526     return ret;
1527 }
1528
1529 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1530 {
1531     int width, height;
1532
1533 #ifdef CONFIG_BOCHS_VBE
1534     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1535         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1536         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1537     } else
1538 #endif
1539     {
1540         width = (s->cr[0x01] + 1) * 8;
1541         height = s->cr[0x12] |
1542             ((s->cr[0x07] & 0x02) << 7) |
1543             ((s->cr[0x07] & 0x40) << 3);
1544         height = (height + 1);
1545     }
1546     *pwidth = width;
1547     *pheight = height;
1548 }
1549
1550 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1551 {
1552     int y;
1553     if (y1 >= VGA_MAX_HEIGHT)
1554         return;
1555     if (y2 >= VGA_MAX_HEIGHT)
1556         y2 = VGA_MAX_HEIGHT;
1557     for(y = y1; y < y2; y++) {
1558         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1559     }
1560 }
1561
1562 /*
1563  * graphic modes
1564  */
1565 static void vga_draw_graphic(VGAState *s, int full_update)
1566 {
1567     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1568     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1569     int disp_width, multi_scan, multi_run;
1570     uint8_t *d;
1571     uint32_t v, addr1, addr;
1572     vga_draw_line_func *vga_draw_line;
1573
1574     full_update |= update_basic_params(s);
1575
1576     s->get_resolution(s, &width, &height);
1577     disp_width = width;
1578
1579     shift_control = (s->gr[0x05] >> 5) & 3;
1580     double_scan = (s->cr[0x09] >> 7);
1581     if (shift_control != 1) {
1582         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1583     } else {
1584         /* in CGA modes, multi_scan is ignored */
1585         /* XXX: is it correct ? */
1586         multi_scan = double_scan;
1587     }
1588     multi_run = multi_scan;
1589     if (shift_control != s->shift_control ||
1590         double_scan != s->double_scan) {
1591         full_update = 1;
1592         s->shift_control = shift_control;
1593         s->double_scan = double_scan;
1594     }
1595
1596     if (shift_control == 0) {
1597         full_update |= update_palette16(s);
1598         if (s->sr[0x01] & 8) {
1599             v = VGA_DRAW_LINE4D2;
1600             disp_width <<= 1;
1601         } else {
1602             v = VGA_DRAW_LINE4;
1603         }
1604         bits = 4;
1605     } else if (shift_control == 1) {
1606         full_update |= update_palette16(s);
1607         if (s->sr[0x01] & 8) {
1608             v = VGA_DRAW_LINE2D2;
1609             disp_width <<= 1;
1610         } else {
1611             v = VGA_DRAW_LINE2;
1612         }
1613         bits = 4;
1614     } else {
1615         switch(s->get_bpp(s)) {
1616         default:
1617         case 0:
1618             full_update |= update_palette256(s);
1619             v = VGA_DRAW_LINE8D2;
1620             bits = 4;
1621             break;
1622         case 8:
1623             full_update |= update_palette256(s);
1624             v = VGA_DRAW_LINE8;
1625             bits = 8;
1626             break;
1627         case 15:
1628             v = VGA_DRAW_LINE15;
1629             bits = 16;
1630             break;
1631         case 16:
1632             v = VGA_DRAW_LINE16;
1633             bits = 16;
1634             break;
1635         case 24:
1636             v = VGA_DRAW_LINE24;
1637             bits = 24;
1638             break;
1639         case 32:
1640             v = VGA_DRAW_LINE32;
1641             bits = 32;
1642             break;
1643         }
1644     }
1645     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1646
1647     if (disp_width != s->last_width ||
1648         height != s->last_height) {
1649         qemu_console_resize(s->console, disp_width, height);
1650         s->last_scr_width = disp_width;
1651         s->last_scr_height = height;
1652         s->last_width = disp_width;
1653         s->last_height = height;
1654         full_update = 1;
1655     }
1656     if (s->cursor_invalidate)
1657         s->cursor_invalidate(s);
1658
1659     line_offset = s->line_offset;
1660 #if 0
1661     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1662            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1663 #endif
1664     addr1 = (s->start_addr * 4);
1665     bwidth = (width * bits + 7) / 8;
1666     y_start = -1;
1667     page_min = 0x7fffffff;
1668     page_max = -1;
1669     d = s->ds->data;
1670     linesize = s->ds->linesize;
1671     y1 = 0;
1672     for(y = 0; y < height; y++) {
1673         addr = addr1;
1674         if (!(s->cr[0x17] & 1)) {
1675             int shift;
1676             /* CGA compatibility handling */
1677             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1678             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1679         }
1680         if (!(s->cr[0x17] & 2)) {
1681             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1682         }
1683         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1684         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1685         update = full_update |
1686             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1687             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1688         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1689             /* if wide line, can use another page */
1690             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1691                                                     VGA_DIRTY_FLAG);
1692         }
1693         /* explicit invalidation for the hardware cursor */
1694         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1695         if (update) {
1696             if (y_start < 0)
1697                 y_start = y;
1698             if (page0 < page_min)
1699                 page_min = page0;
1700             if (page1 > page_max)
1701                 page_max = page1;
1702             vga_draw_line(s, d, s->vram_ptr + addr, width);
1703             if (s->cursor_draw_line)
1704                 s->cursor_draw_line(s, d, y);
1705         } else {
1706             if (y_start >= 0) {
1707                 /* flush to display */
1708                 dpy_update(s->ds, 0, y_start,
1709                            disp_width, y - y_start);
1710                 y_start = -1;
1711             }
1712         }
1713         if (!multi_run) {
1714             mask = (s->cr[0x17] & 3) ^ 3;
1715             if ((y1 & mask) == mask)
1716                 addr1 += line_offset;
1717             y1++;
1718             multi_run = multi_scan;
1719         } else {
1720             multi_run--;
1721         }
1722         /* line compare acts on the displayed lines */
1723         if (y == s->line_compare)
1724             addr1 = 0;
1725         d += linesize;
1726     }
1727     if (y_start >= 0) {
1728         /* flush to display */
1729         dpy_update(s->ds, 0, y_start,
1730                    disp_width, y - y_start);
1731     }
1732     /* reset modified pages */
1733     if (page_max != -1) {
1734         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1735                                         VGA_DIRTY_FLAG);
1736     }
1737     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1738 }
1739
1740 static void vga_draw_blank(VGAState *s, int full_update)
1741 {
1742     int i, w, val;
1743     uint8_t *d;
1744
1745     if (!full_update)
1746         return;
1747     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1748         return;
1749     if (s->ds->depth == 8)
1750         val = s->rgb_to_pixel(0, 0, 0);
1751     else
1752         val = 0;
1753     w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1754     d = s->ds->data;
1755     for(i = 0; i < s->last_scr_height; i++) {
1756         memset(d, val, w);
1757         d += s->ds->linesize;
1758     }
1759     dpy_update(s->ds, 0, 0,
1760                s->last_scr_width, s->last_scr_height);
1761 }
1762
1763 #define GMODE_TEXT     0
1764 #define GMODE_GRAPH    1
1765 #define GMODE_BLANK 2
1766
1767 static void vga_update_display(void *opaque)
1768 {
1769     VGAState *s = (VGAState *)opaque;
1770     int full_update, graphic_mode;
1771
1772     if (s->ds->depth == 0) {
1773         /* nothing to do */
1774     } else {
1775         s->rgb_to_pixel =
1776             rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1777
1778         full_update = 0;
1779         if (!(s->ar_index & 0x20)) {
1780             graphic_mode = GMODE_BLANK;
1781         } else {
1782             graphic_mode = s->gr[6] & 1;
1783         }
1784         if (graphic_mode != s->graphic_mode) {
1785             s->graphic_mode = graphic_mode;
1786             full_update = 1;
1787         }
1788         switch(graphic_mode) {
1789         case GMODE_TEXT:
1790             vga_draw_text(s, full_update);
1791             break;
1792         case GMODE_GRAPH:
1793             vga_draw_graphic(s, full_update);
1794             break;
1795         case GMODE_BLANK:
1796         default:
1797             vga_draw_blank(s, full_update);
1798             break;
1799         }
1800     }
1801 }
1802
1803 /* force a full display refresh */
1804 static void vga_invalidate_display(void *opaque)
1805 {
1806     VGAState *s = (VGAState *)opaque;
1807
1808     s->last_width = -1;
1809     s->last_height = -1;
1810 }
1811
1812 static void vga_reset(VGAState *s)
1813 {
1814     memset(s, 0, sizeof(VGAState));
1815     s->graphic_mode = -1; /* force full update */
1816 }
1817
1818 #define TEXTMODE_X(x)   ((x) % width)
1819 #define TEXTMODE_Y(x)   ((x) / width)
1820 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1821         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1822 /* relay text rendering to the display driver
1823  * instead of doing a full vga_update_display() */
1824 static void vga_update_text(void *opaque, console_ch_t *chardata)
1825 {
1826     VGAState *s = (VGAState *) opaque;
1827     int graphic_mode, i, cursor_offset, cursor_visible;
1828     int cw, cheight, width, height, size, c_min, c_max;
1829     uint32_t *src;
1830     console_ch_t *dst, val;
1831     char msg_buffer[80];
1832     int full_update = 0;
1833
1834     if (!(s->ar_index & 0x20)) {
1835         graphic_mode = GMODE_BLANK;
1836     } else {
1837         graphic_mode = s->gr[6] & 1;
1838     }
1839     if (graphic_mode != s->graphic_mode) {
1840         s->graphic_mode = graphic_mode;
1841         full_update = 1;
1842     }
1843     if (s->last_width == -1) {
1844         s->last_width = 0;
1845         full_update = 1;
1846     }
1847
1848     switch (graphic_mode) {
1849     case GMODE_TEXT:
1850         /* TODO: update palette */
1851         full_update |= update_basic_params(s);
1852
1853         /* total width & height */
1854         cheight = (s->cr[9] & 0x1f) + 1;
1855         cw = 8;
1856         if (!(s->sr[1] & 0x01))
1857             cw = 9;
1858         if (s->sr[1] & 0x08)
1859             cw = 16; /* NOTE: no 18 pixel wide */
1860         width = (s->cr[0x01] + 1);
1861         if (s->cr[0x06] == 100) {
1862             /* ugly hack for CGA 160x100x16 - explain me the logic */
1863             height = 100;
1864         } else {
1865             height = s->cr[0x12] | 
1866                 ((s->cr[0x07] & 0x02) << 7) | 
1867                 ((s->cr[0x07] & 0x40) << 3);
1868             height = (height + 1) / cheight;
1869         }
1870
1871         size = (height * width);
1872         if (size > CH_ATTR_SIZE) {
1873             if (!full_update)
1874                 return;
1875
1876             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1877                      width, height);
1878             break;
1879         }
1880
1881         if (width != s->last_width || height != s->last_height ||
1882             cw != s->last_cw || cheight != s->last_ch) {
1883             s->last_scr_width = width * cw;
1884             s->last_scr_height = height * cheight;
1885             qemu_console_resize(s->console, width, height);
1886             s->last_width = width;
1887             s->last_height = height;
1888             s->last_ch = cheight;
1889             s->last_cw = cw;
1890             full_update = 1;
1891         }
1892
1893         /* Update "hardware" cursor */
1894         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1895         if (cursor_offset != s->cursor_offset ||
1896             s->cr[0xa] != s->cursor_start ||
1897             s->cr[0xb] != s->cursor_end || full_update) {
1898             cursor_visible = !(s->cr[0xa] & 0x20);
1899             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1900                 dpy_cursor(s->ds,
1901                            TEXTMODE_X(cursor_offset),
1902                            TEXTMODE_Y(cursor_offset));
1903             else
1904                 dpy_cursor(s->ds, -1, -1);
1905             s->cursor_offset = cursor_offset;
1906             s->cursor_start = s->cr[0xa];
1907             s->cursor_end = s->cr[0xb];
1908         }
1909
1910         src = (uint32_t *) s->vram_ptr + s->start_addr;
1911         dst = chardata;
1912
1913         if (full_update) {
1914             for (i = 0; i < size; src ++, dst ++, i ++)
1915                 console_write_ch(dst, VMEM2CHTYPE(*src));
1916
1917             dpy_update(s->ds, 0, 0, width, height);
1918         } else {
1919             c_max = 0;
1920
1921             for (i = 0; i < size; src ++, dst ++, i ++) {
1922                 console_write_ch(&val, VMEM2CHTYPE(*src));
1923                 if (*dst != val) {
1924                     *dst = val;
1925                     c_max = i;
1926                     break;
1927                 }
1928             }
1929             c_min = i;
1930             for (; i < size; src ++, dst ++, i ++) {
1931                 console_write_ch(&val, VMEM2CHTYPE(*src));
1932                 if (*dst != val) {
1933                     *dst = val;
1934                     c_max = i;
1935                 }
1936             }
1937
1938             if (c_min <= c_max) {
1939                 i = TEXTMODE_Y(c_min);
1940                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1941             }
1942         }
1943
1944         return;
1945     case GMODE_GRAPH:
1946         if (!full_update)
1947             return;
1948
1949         s->get_resolution(s, &width, &height);
1950         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
1951                  width, height);
1952         break;
1953     case GMODE_BLANK:
1954     default:
1955         if (!full_update)
1956             return;
1957
1958         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
1959         break;
1960     }
1961
1962     /* Display a message */
1963     s->last_width = 60;
1964     s->last_height = height = 3;
1965     dpy_cursor(s->ds, -1, -1);
1966     qemu_console_resize(s->console, s->last_width, height);
1967
1968     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
1969         console_write_ch(dst ++, ' ');
1970
1971     size = strlen(msg_buffer);
1972     width = (s->last_width - size) / 2;
1973     dst = chardata + s->last_width + width;
1974     for (i = 0; i < size; i ++)
1975         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
1976
1977     dpy_update(s->ds, 0, 0, s->last_width, height);
1978 }
1979
1980 static CPUReadMemoryFunc *vga_mem_read[3] = {
1981     vga_mem_readb,
1982     vga_mem_readw,
1983     vga_mem_readl,
1984 };
1985
1986 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1987     vga_mem_writeb,
1988     vga_mem_writew,
1989     vga_mem_writel,
1990 };
1991
1992 static void vga_save(QEMUFile *f, void *opaque)
1993 {
1994     VGAState *s = opaque;
1995     int i;
1996
1997     if (s->pci_dev)
1998         pci_device_save(s->pci_dev, f);
1999
2000     qemu_put_be32s(f, &s->latch);
2001     qemu_put_8s(f, &s->sr_index);
2002     qemu_put_buffer(f, s->sr, 8);
2003     qemu_put_8s(f, &s->gr_index);
2004     qemu_put_buffer(f, s->gr, 16);
2005     qemu_put_8s(f, &s->ar_index);
2006     qemu_put_buffer(f, s->ar, 21);
2007     qemu_put_be32(f, s->ar_flip_flop);
2008     qemu_put_8s(f, &s->cr_index);
2009     qemu_put_buffer(f, s->cr, 256);
2010     qemu_put_8s(f, &s->msr);
2011     qemu_put_8s(f, &s->fcr);
2012     qemu_put_byte(f, s->st00);
2013     qemu_put_8s(f, &s->st01);
2014
2015     qemu_put_8s(f, &s->dac_state);
2016     qemu_put_8s(f, &s->dac_sub_index);
2017     qemu_put_8s(f, &s->dac_read_index);
2018     qemu_put_8s(f, &s->dac_write_index);
2019     qemu_put_buffer(f, s->dac_cache, 3);
2020     qemu_put_buffer(f, s->palette, 768);
2021
2022     qemu_put_be32(f, s->bank_offset);
2023 #ifdef CONFIG_BOCHS_VBE
2024     qemu_put_byte(f, 1);
2025     qemu_put_be16s(f, &s->vbe_index);
2026     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2027         qemu_put_be16s(f, &s->vbe_regs[i]);
2028     qemu_put_be32s(f, &s->vbe_start_addr);
2029     qemu_put_be32s(f, &s->vbe_line_offset);
2030     qemu_put_be32s(f, &s->vbe_bank_mask);
2031 #else
2032     qemu_put_byte(f, 0);
2033 #endif
2034 }
2035
2036 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2037 {
2038     VGAState *s = opaque;
2039     int is_vbe, i, ret;
2040
2041     if (version_id > 2)
2042         return -EINVAL;
2043
2044     if (s->pci_dev && version_id >= 2) {
2045         ret = pci_device_load(s->pci_dev, f);
2046         if (ret < 0)
2047             return ret;
2048     }
2049
2050     qemu_get_be32s(f, &s->latch);
2051     qemu_get_8s(f, &s->sr_index);
2052     qemu_get_buffer(f, s->sr, 8);
2053     qemu_get_8s(f, &s->gr_index);
2054     qemu_get_buffer(f, s->gr, 16);
2055     qemu_get_8s(f, &s->ar_index);
2056     qemu_get_buffer(f, s->ar, 21);
2057     s->ar_flip_flop=qemu_get_be32(f);
2058     qemu_get_8s(f, &s->cr_index);
2059     qemu_get_buffer(f, s->cr, 256);
2060     qemu_get_8s(f, &s->msr);
2061     qemu_get_8s(f, &s->fcr);
2062     qemu_get_8s(f, &s->st00);
2063     qemu_get_8s(f, &s->st01);
2064
2065     qemu_get_8s(f, &s->dac_state);
2066     qemu_get_8s(f, &s->dac_sub_index);
2067     qemu_get_8s(f, &s->dac_read_index);
2068     qemu_get_8s(f, &s->dac_write_index);
2069     qemu_get_buffer(f, s->dac_cache, 3);
2070     qemu_get_buffer(f, s->palette, 768);
2071
2072     s->bank_offset=qemu_get_be32(f);
2073     is_vbe = qemu_get_byte(f);
2074 #ifdef CONFIG_BOCHS_VBE
2075     if (!is_vbe)
2076         return -EINVAL;
2077     qemu_get_be16s(f, &s->vbe_index);
2078     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2079         qemu_get_be16s(f, &s->vbe_regs[i]);
2080     qemu_get_be32s(f, &s->vbe_start_addr);
2081     qemu_get_be32s(f, &s->vbe_line_offset);
2082     qemu_get_be32s(f, &s->vbe_bank_mask);
2083 #else
2084     if (is_vbe)
2085         return -EINVAL;
2086 #endif
2087
2088     /* force refresh */
2089     s->graphic_mode = -1;
2090     return 0;
2091 }
2092
2093 typedef struct PCIVGAState {
2094     PCIDevice dev;
2095     VGAState vga_state;
2096 } PCIVGAState;
2097
2098 static void vga_map(PCIDevice *pci_dev, int region_num,
2099                     uint32_t addr, uint32_t size, int type)
2100 {
2101     PCIVGAState *d = (PCIVGAState *)pci_dev;
2102     VGAState *s = &d->vga_state;
2103     if (region_num == PCI_ROM_SLOT) {
2104         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2105     } else {
2106         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2107     }
2108 }
2109
2110 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
2111                      unsigned long vga_ram_offset, int vga_ram_size)
2112 {
2113     int i, j, v, b;
2114
2115     for(i = 0;i < 256; i++) {
2116         v = 0;
2117         for(j = 0; j < 8; j++) {
2118             v |= ((i >> j) & 1) << (j * 4);
2119         }
2120         expand4[i] = v;
2121
2122         v = 0;
2123         for(j = 0; j < 4; j++) {
2124             v |= ((i >> (2 * j)) & 3) << (j * 4);
2125         }
2126         expand2[i] = v;
2127     }
2128     for(i = 0; i < 16; i++) {
2129         v = 0;
2130         for(j = 0; j < 4; j++) {
2131             b = ((i >> j) & 1);
2132             v |= b << (2 * j);
2133             v |= b << (2 * j + 1);
2134         }
2135         expand4to8[i] = v;
2136     }
2137
2138     vga_reset(s);
2139
2140     s->vram_ptr = vga_ram_base;
2141     s->vram_offset = vga_ram_offset;
2142     s->vram_size = vga_ram_size;
2143     s->ds = ds;
2144     s->get_bpp = vga_get_bpp;
2145     s->get_offsets = vga_get_offsets;
2146     s->get_resolution = vga_get_resolution;
2147     s->update = vga_update_display;
2148     s->invalidate = vga_invalidate_display;
2149     s->screen_dump = vga_screen_dump;
2150     s->text_update = vga_update_text;
2151     switch (vga_retrace_method) {
2152     case VGA_RETRACE_DUMB:
2153         s->retrace = vga_dumb_retrace;
2154         s->update_retrace_info = vga_dumb_update_retrace_info;
2155         break;
2156
2157     case VGA_RETRACE_PRECISE:
2158         s->retrace = vga_precise_retrace;
2159         s->update_retrace_info = vga_precise_update_retrace_info;
2160         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
2161         break;
2162     }
2163 }
2164
2165 /* used by both ISA and PCI */
2166 void vga_init(VGAState *s)
2167 {
2168     int vga_io_memory;
2169
2170     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2171
2172     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2173
2174     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2175     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2176     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2177     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2178
2179     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2180
2181     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2182     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2183     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2184     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2185     s->bank_offset = 0;
2186
2187 #ifdef CONFIG_BOCHS_VBE
2188     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
2189     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
2190 #if defined (TARGET_I386)
2191     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2192     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2193
2194     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2195     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2196
2197     /* old Bochs IO ports */
2198     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2199     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2200
2201     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2202     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2203 #else
2204     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2205     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2206
2207     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2208     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2209 #endif
2210 #endif /* CONFIG_BOCHS_VBE */
2211
2212     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2213     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2214                                  vga_io_memory);
2215 }
2216
2217 /* Memory mapped interface */
2218 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2219 {
2220     VGAState *s = opaque;
2221
2222     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
2223 }
2224
2225 static void vga_mm_writeb (void *opaque,
2226                            target_phys_addr_t addr, uint32_t value)
2227 {
2228     VGAState *s = opaque;
2229
2230     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
2231 }
2232
2233 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2234 {
2235     VGAState *s = opaque;
2236
2237     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
2238 }
2239
2240 static void vga_mm_writew (void *opaque,
2241                            target_phys_addr_t addr, uint32_t value)
2242 {
2243     VGAState *s = opaque;
2244
2245     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
2246 }
2247
2248 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2249 {
2250     VGAState *s = opaque;
2251
2252     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
2253 }
2254
2255 static void vga_mm_writel (void *opaque,
2256                            target_phys_addr_t addr, uint32_t value)
2257 {
2258     VGAState *s = opaque;
2259
2260     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
2261 }
2262
2263 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2264     &vga_mm_readb,
2265     &vga_mm_readw,
2266     &vga_mm_readl,
2267 };
2268
2269 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2270     &vga_mm_writeb,
2271     &vga_mm_writew,
2272     &vga_mm_writel,
2273 };
2274
2275 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2276                         target_phys_addr_t ctrl_base, int it_shift)
2277 {
2278     int s_ioport_ctrl, vga_io_memory;
2279
2280     s->base_ctrl = ctrl_base;
2281     s->it_shift = it_shift;
2282     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2283     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2284
2285     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2286
2287     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2288     s->bank_offset = 0;
2289     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2290 }
2291
2292 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2293                  unsigned long vga_ram_offset, int vga_ram_size)
2294 {
2295     VGAState *s;
2296
2297     s = qemu_mallocz(sizeof(VGAState));
2298     if (!s)
2299         return -1;
2300
2301     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2302     vga_init(s);
2303
2304     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2305                                       s->screen_dump, s->text_update, s);
2306
2307 #ifdef CONFIG_BOCHS_VBE
2308     /* XXX: use optimized standard vga accesses */
2309     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2310                                  vga_ram_size, vga_ram_offset);
2311 #endif
2312     return 0;
2313 }
2314
2315 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2316                     unsigned long vga_ram_offset, int vga_ram_size,
2317                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2318                     int it_shift)
2319 {
2320     VGAState *s;
2321
2322     s = qemu_mallocz(sizeof(VGAState));
2323     if (!s)
2324         return -1;
2325
2326     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2327     vga_mm_init(s, vram_base, ctrl_base, it_shift);
2328
2329     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2330                                       s->screen_dump, s->text_update, s);
2331
2332 #ifdef CONFIG_BOCHS_VBE
2333     /* XXX: use optimized standard vga accesses */
2334     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2335                                  vga_ram_size, vga_ram_offset);
2336 #endif
2337     return 0;
2338 }
2339
2340 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2341                  unsigned long vga_ram_offset, int vga_ram_size,
2342                  unsigned long vga_bios_offset, int vga_bios_size)
2343 {
2344     PCIVGAState *d;
2345     VGAState *s;
2346     uint8_t *pci_conf;
2347
2348     d = (PCIVGAState *)pci_register_device(bus, "VGA",
2349                                            sizeof(PCIVGAState),
2350                                            -1, NULL, NULL);
2351     if (!d)
2352         return -1;
2353     s = &d->vga_state;
2354
2355     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2356     vga_init(s);
2357
2358     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2359                                       s->screen_dump, s->text_update, s);
2360
2361     s->pci_dev = &d->dev;
2362
2363     pci_conf = d->dev.config;
2364     pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2365     pci_conf[0x01] = 0x12;
2366     pci_conf[0x02] = 0x11;
2367     pci_conf[0x03] = 0x11;
2368     pci_conf[0x0a] = 0x00; // VGA controller
2369     pci_conf[0x0b] = 0x03;
2370     pci_conf[0x0e] = 0x00; // header_type
2371
2372     /* XXX: vga_ram_size must be a power of two */
2373     pci_register_io_region(&d->dev, 0, vga_ram_size,
2374                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2375     if (vga_bios_size != 0) {
2376         unsigned int bios_total_size;
2377         s->bios_offset = vga_bios_offset;
2378         s->bios_size = vga_bios_size;
2379         /* must be a power of two */
2380         bios_total_size = 1;
2381         while (bios_total_size < vga_bios_size)
2382             bios_total_size <<= 1;
2383         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2384                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2385     }
2386     return 0;
2387 }
2388
2389 /********************************************************/
2390 /* vga screen dump */
2391
2392 static int vga_save_w, vga_save_h;
2393
2394 static void vga_save_dpy_update(DisplayState *s,
2395                                 int x, int y, int w, int h)
2396 {
2397 }
2398
2399 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2400 {
2401     s->linesize = w * 4;
2402     s->data = qemu_malloc(h * s->linesize);
2403     vga_save_w = w;
2404     vga_save_h = h;
2405 }
2406
2407 static void vga_save_dpy_refresh(DisplayState *s)
2408 {
2409 }
2410
2411 int ppm_save(const char *filename, uint8_t *data,
2412              int w, int h, int linesize)
2413 {
2414     FILE *f;
2415     uint8_t *d, *d1;
2416     unsigned int v;
2417     int y, x;
2418
2419     f = fopen(filename, "wb");
2420     if (!f)
2421         return -1;
2422     fprintf(f, "P6\n%d %d\n%d\n",
2423             w, h, 255);
2424     d1 = data;
2425     for(y = 0; y < h; y++) {
2426         d = d1;
2427         for(x = 0; x < w; x++) {
2428             v = *(uint32_t *)d;
2429             fputc((v >> 16) & 0xff, f);
2430             fputc((v >> 8) & 0xff, f);
2431             fputc((v) & 0xff, f);
2432             d += 4;
2433         }
2434         d1 += linesize;
2435     }
2436     fclose(f);
2437     return 0;
2438 }
2439
2440 /* save the vga display in a PPM image even if no display is
2441    available */
2442 static void vga_screen_dump(void *opaque, const char *filename)
2443 {
2444     VGAState *s = (VGAState *)opaque;
2445     DisplayState *saved_ds, ds1, *ds = &ds1;
2446
2447     /* XXX: this is a little hackish */
2448     vga_invalidate_display(s);
2449     saved_ds = s->ds;
2450
2451     memset(ds, 0, sizeof(DisplayState));
2452     ds->dpy_update = vga_save_dpy_update;
2453     ds->dpy_resize = vga_save_dpy_resize;
2454     ds->dpy_refresh = vga_save_dpy_refresh;
2455     ds->depth = 32;
2456
2457     s->ds = ds;
2458     s->graphic_mode = -1;
2459     vga_update_display(s);
2460
2461     if (ds->data) {
2462         ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2463                  s->ds->linesize);
2464         qemu_free(ds->data);
2465     }
2466     s->ds = saved_ds;
2467 }