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