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