Fix display breakage when resizing the screen (v2) (Avi Kivity)
[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 #define GMODE_TEXT     0
40 #define GMODE_GRAPH    1
41 #define GMODE_BLANK 2
42
43 /* force some bits to zero */
44 const uint8_t sr_mask[8] = {
45     0x03,
46     0x3d,
47     0x0f,
48     0x3f,
49     0x0e,
50     0x00,
51     0x00,
52     0xff,
53 };
54
55 const uint8_t gr_mask[16] = {
56     0x0f, /* 0x00 */
57     0x0f, /* 0x01 */
58     0x0f, /* 0x02 */
59     0x1f, /* 0x03 */
60     0x03, /* 0x04 */
61     0x7b, /* 0x05 */
62     0x0f, /* 0x06 */
63     0x0f, /* 0x07 */
64     0xff, /* 0x08 */
65     0x00, /* 0x09 */
66     0x00, /* 0x0a */
67     0x00, /* 0x0b */
68     0x00, /* 0x0c */
69     0x00, /* 0x0d */
70     0x00, /* 0x0e */
71     0x00, /* 0x0f */
72 };
73
74 #define cbswap_32(__x) \
75 ((uint32_t)( \
76                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
77                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
78                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
79                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
80
81 #ifdef WORDS_BIGENDIAN
82 #define PAT(x) cbswap_32(x)
83 #else
84 #define PAT(x) (x)
85 #endif
86
87 #ifdef WORDS_BIGENDIAN
88 #define BIG 1
89 #else
90 #define BIG 0
91 #endif
92
93 #ifdef WORDS_BIGENDIAN
94 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
95 #else
96 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
97 #endif
98
99 static const uint32_t mask16[16] = {
100     PAT(0x00000000),
101     PAT(0x000000ff),
102     PAT(0x0000ff00),
103     PAT(0x0000ffff),
104     PAT(0x00ff0000),
105     PAT(0x00ff00ff),
106     PAT(0x00ffff00),
107     PAT(0x00ffffff),
108     PAT(0xff000000),
109     PAT(0xff0000ff),
110     PAT(0xff00ff00),
111     PAT(0xff00ffff),
112     PAT(0xffff0000),
113     PAT(0xffff00ff),
114     PAT(0xffffff00),
115     PAT(0xffffffff),
116 };
117
118 #undef PAT
119
120 #ifdef WORDS_BIGENDIAN
121 #define PAT(x) (x)
122 #else
123 #define PAT(x) cbswap_32(x)
124 #endif
125
126 static const uint32_t dmask16[16] = {
127     PAT(0x00000000),
128     PAT(0x000000ff),
129     PAT(0x0000ff00),
130     PAT(0x0000ffff),
131     PAT(0x00ff0000),
132     PAT(0x00ff00ff),
133     PAT(0x00ffff00),
134     PAT(0x00ffffff),
135     PAT(0xff000000),
136     PAT(0xff0000ff),
137     PAT(0xff00ff00),
138     PAT(0xff00ffff),
139     PAT(0xffff0000),
140     PAT(0xffff00ff),
141     PAT(0xffffff00),
142     PAT(0xffffffff),
143 };
144
145 static const uint32_t dmask4[4] = {
146     PAT(0x00000000),
147     PAT(0x0000ffff),
148     PAT(0xffff0000),
149     PAT(0xffffffff),
150 };
151
152 static uint32_t expand4[256];
153 static uint16_t expand2[256];
154 static uint8_t expand4to8[16];
155
156 static void vga_screen_dump(void *opaque, const char *filename);
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             vga_update_resolution(s);
401         } else {
402             index = s->ar_index & 0x1f;
403             switch(index) {
404             case 0x00 ... 0x0f:
405                 s->ar[index] = val & 0x3f;
406                 break;
407             case 0x10:
408                 s->ar[index] = val & ~0x10;
409                 break;
410             case 0x11:
411                 s->ar[index] = val;
412                 break;
413             case 0x12:
414                 s->ar[index] = val & ~0xc0;
415                 break;
416             case 0x13:
417                 s->ar[index] = val & ~0xf0;
418                 break;
419             case 0x14:
420                 s->ar[index] = val & ~0xf0;
421                 break;
422             default:
423                 break;
424             }
425         }
426         s->ar_flip_flop ^= 1;
427         break;
428     case 0x3c2:
429         s->msr = val & ~0x10;
430         s->update_retrace_info(s);
431         break;
432     case 0x3c4:
433         s->sr_index = val & 7;
434         break;
435     case 0x3c5:
436 #ifdef DEBUG_VGA_REG
437         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
438 #endif
439         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
440         if (s->sr_index == 1) s->update_retrace_info(s);
441         vga_update_resolution(s);
442         break;
443     case 0x3c7:
444         s->dac_read_index = val;
445         s->dac_sub_index = 0;
446         s->dac_state = 3;
447         break;
448     case 0x3c8:
449         s->dac_write_index = val;
450         s->dac_sub_index = 0;
451         s->dac_state = 0;
452         break;
453     case 0x3c9:
454         s->dac_cache[s->dac_sub_index] = val;
455         if (++s->dac_sub_index == 3) {
456             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
457             s->dac_sub_index = 0;
458             s->dac_write_index++;
459         }
460         break;
461     case 0x3ce:
462         s->gr_index = val & 0x0f;
463         break;
464     case 0x3cf:
465 #ifdef DEBUG_VGA_REG
466         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
467 #endif
468         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
469         vga_update_resolution(s);
470         break;
471     case 0x3b4:
472     case 0x3d4:
473         s->cr_index = val;
474         break;
475     case 0x3b5:
476     case 0x3d5:
477 #ifdef DEBUG_VGA_REG
478         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
479 #endif
480         /* handle CR0-7 protection */
481         if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
482             /* can always write bit 4 of CR7 */
483             if (s->cr_index == 7)
484                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
485             vga_update_resolution(s);
486             return;
487         }
488         switch(s->cr_index) {
489         case 0x01: /* horizontal display end */
490         case 0x07:
491         case 0x09:
492         case 0x0c:
493         case 0x0d:
494         case 0x12: /* vertical display end */
495             s->cr[s->cr_index] = val;
496             break;
497         default:
498             s->cr[s->cr_index] = val;
499             break;
500         }
501
502         switch(s->cr_index) {
503         case 0x00:
504         case 0x04:
505         case 0x05:
506         case 0x06:
507         case 0x07:
508         case 0x11:
509         case 0x17:
510             s->update_retrace_info(s);
511             break;
512         }
513         vga_update_resolution(s);
514         break;
515     case 0x3ba:
516     case 0x3da:
517         s->fcr = val & 0x10;
518         break;
519     }
520 }
521
522 #ifdef CONFIG_BOCHS_VBE
523 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
524 {
525     VGAState *s = opaque;
526     uint32_t val;
527     val = s->vbe_index;
528     return val;
529 }
530
531 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
532 {
533     VGAState *s = opaque;
534     uint32_t val;
535
536     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
537         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
538             switch(s->vbe_index) {
539                 /* XXX: do not hardcode ? */
540             case VBE_DISPI_INDEX_XRES:
541                 val = VBE_DISPI_MAX_XRES;
542                 break;
543             case VBE_DISPI_INDEX_YRES:
544                 val = VBE_DISPI_MAX_YRES;
545                 break;
546             case VBE_DISPI_INDEX_BPP:
547                 val = VBE_DISPI_MAX_BPP;
548                 break;
549             default:
550                 val = s->vbe_regs[s->vbe_index];
551                 break;
552             }
553         } else {
554             val = s->vbe_regs[s->vbe_index];
555         }
556     } else {
557         val = 0;
558     }
559 #ifdef DEBUG_BOCHS_VBE
560     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
561 #endif
562     return val;
563 }
564
565 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
566 {
567     VGAState *s = opaque;
568     s->vbe_index = val;
569 }
570
571 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
572 {
573     VGAState *s = opaque;
574
575     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
576 #ifdef DEBUG_BOCHS_VBE
577         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
578 #endif
579         switch(s->vbe_index) {
580         case VBE_DISPI_INDEX_ID:
581             if (val == VBE_DISPI_ID0 ||
582                 val == VBE_DISPI_ID1 ||
583                 val == VBE_DISPI_ID2 ||
584                 val == VBE_DISPI_ID3 ||
585                 val == VBE_DISPI_ID4) {
586                 s->vbe_regs[s->vbe_index] = val;
587             }
588             break;
589         case VBE_DISPI_INDEX_XRES:
590             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
591                 s->vbe_regs[s->vbe_index] = val;
592             }
593             vga_update_resolution(s);
594             break;
595         case VBE_DISPI_INDEX_YRES:
596             if (val <= VBE_DISPI_MAX_YRES) {
597                 s->vbe_regs[s->vbe_index] = val;
598             }
599             vga_update_resolution(s);
600             break;
601         case VBE_DISPI_INDEX_BPP:
602             if (val == 0)
603                 val = 8;
604             if (val == 4 || val == 8 || val == 15 ||
605                 val == 16 || val == 24 || val == 32) {
606                 s->vbe_regs[s->vbe_index] = val;
607             }
608             vga_update_resolution(s);
609             break;
610         case VBE_DISPI_INDEX_BANK:
611             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
612               val &= (s->vbe_bank_mask >> 2);
613             } else {
614               val &= s->vbe_bank_mask;
615             }
616             s->vbe_regs[s->vbe_index] = val;
617             s->bank_offset = (val << 16);
618             break;
619         case VBE_DISPI_INDEX_ENABLE:
620             if ((val & VBE_DISPI_ENABLED) &&
621                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
622                 int h, shift_control;
623
624                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
625                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
626                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
627                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
628                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
629                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
630
631                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
632                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
633                 else
634                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
635                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
636                 s->vbe_start_addr = 0;
637
638                 /* clear the screen (should be done in BIOS) */
639                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
640                     memset(s->vram_ptr, 0,
641                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
642                 }
643
644                 /* we initialize the VGA graphic mode (should be done
645                    in BIOS) */
646                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
647                 s->cr[0x17] |= 3; /* no CGA modes */
648                 s->cr[0x13] = s->vbe_line_offset >> 3;
649                 /* width */
650                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
651                 /* height (only meaningful if < 1024) */
652                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
653                 s->cr[0x12] = h;
654                 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
655                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
656                 /* line compare to 1023 */
657                 s->cr[0x18] = 0xff;
658                 s->cr[0x07] |= 0x10;
659                 s->cr[0x09] |= 0x40;
660
661                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
662                     shift_control = 0;
663                     s->sr[0x01] &= ~8; /* no double line */
664                 } else {
665                     shift_control = 2;
666                     s->sr[4] |= 0x08; /* set chain 4 mode */
667                     s->sr[2] |= 0x0f; /* activate all planes */
668                 }
669                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
670                 s->cr[0x09] &= ~0x9f; /* no double scan */
671             } else {
672                 /* XXX: the bios should do that */
673                 s->bank_offset = 0;
674             }
675             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
676             s->vbe_regs[s->vbe_index] = val;
677             vga_update_resolution(s);
678             break;
679         case VBE_DISPI_INDEX_VIRT_WIDTH:
680             {
681                 int w, h, line_offset;
682
683                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
684                     return;
685                 w = val;
686                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
687                     line_offset = w >> 1;
688                 else
689                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
690                 h = s->vram_size / line_offset;
691                 /* XXX: support weird bochs semantics ? */
692                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
693                     return;
694                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
695                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
696                 s->vbe_line_offset = line_offset;
697             }
698             vga_update_resolution(s);
699             break;
700         case VBE_DISPI_INDEX_X_OFFSET:
701         case VBE_DISPI_INDEX_Y_OFFSET:
702             {
703                 int x;
704                 s->vbe_regs[s->vbe_index] = val;
705                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
706                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
707                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
708                     s->vbe_start_addr += x >> 1;
709                 else
710                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
711                 s->vbe_start_addr >>= 2;
712             }
713             vga_update_resolution(s);
714             break;
715         default:
716             break;
717         }
718     }
719 }
720 #endif
721
722 /* called for accesses between 0xa0000 and 0xc0000 */
723 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
724 {
725     VGAState *s = opaque;
726     int memory_map_mode, plane;
727     uint32_t ret;
728
729     /* convert to VGA memory offset */
730     memory_map_mode = (s->gr[6] >> 2) & 3;
731     addr &= 0x1ffff;
732     switch(memory_map_mode) {
733     case 0:
734         break;
735     case 1:
736         if (addr >= 0x10000)
737             return 0xff;
738         addr += s->bank_offset;
739         break;
740     case 2:
741         addr -= 0x10000;
742         if (addr >= 0x8000)
743             return 0xff;
744         break;
745     default:
746     case 3:
747         addr -= 0x18000;
748         if (addr >= 0x8000)
749             return 0xff;
750         break;
751     }
752
753     if (s->sr[4] & 0x08) {
754         /* chain 4 mode : simplest access */
755         ret = s->vram_ptr[addr];
756     } else if (s->gr[5] & 0x10) {
757         /* odd/even mode (aka text mode mapping) */
758         plane = (s->gr[4] & 2) | (addr & 1);
759         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
760     } else {
761         /* standard VGA latched access */
762         s->latch = ((uint32_t *)s->vram_ptr)[addr];
763
764         if (!(s->gr[5] & 0x08)) {
765             /* read mode 0 */
766             plane = s->gr[4];
767             ret = GET_PLANE(s->latch, plane);
768         } else {
769             /* read mode 1 */
770             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
771             ret |= ret >> 16;
772             ret |= ret >> 8;
773             ret = (~ret) & 0xff;
774         }
775     }
776     return ret;
777 }
778
779 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
780 {
781     uint32_t v;
782 #ifdef TARGET_WORDS_BIGENDIAN
783     v = vga_mem_readb(opaque, addr) << 8;
784     v |= vga_mem_readb(opaque, addr + 1);
785 #else
786     v = vga_mem_readb(opaque, addr);
787     v |= vga_mem_readb(opaque, addr + 1) << 8;
788 #endif
789     return v;
790 }
791
792 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
793 {
794     uint32_t v;
795 #ifdef TARGET_WORDS_BIGENDIAN
796     v = vga_mem_readb(opaque, addr) << 24;
797     v |= vga_mem_readb(opaque, addr + 1) << 16;
798     v |= vga_mem_readb(opaque, addr + 2) << 8;
799     v |= vga_mem_readb(opaque, addr + 3);
800 #else
801     v = vga_mem_readb(opaque, addr);
802     v |= vga_mem_readb(opaque, addr + 1) << 8;
803     v |= vga_mem_readb(opaque, addr + 2) << 16;
804     v |= vga_mem_readb(opaque, addr + 3) << 24;
805 #endif
806     return v;
807 }
808
809 /* called for accesses between 0xa0000 and 0xc0000 */
810 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
811 {
812     VGAState *s = opaque;
813     int memory_map_mode, plane, write_mode, b, func_select, mask;
814     uint32_t write_mask, bit_mask, set_mask;
815
816 #ifdef DEBUG_VGA_MEM
817     printf("vga: [0x%x] = 0x%02x\n", addr, val);
818 #endif
819     /* convert to VGA memory offset */
820     memory_map_mode = (s->gr[6] >> 2) & 3;
821     addr &= 0x1ffff;
822     switch(memory_map_mode) {
823     case 0:
824         break;
825     case 1:
826         if (addr >= 0x10000)
827             return;
828         addr += s->bank_offset;
829         break;
830     case 2:
831         addr -= 0x10000;
832         if (addr >= 0x8000)
833             return;
834         break;
835     default:
836     case 3:
837         addr -= 0x18000;
838         if (addr >= 0x8000)
839             return;
840         break;
841     }
842
843     if (s->sr[4] & 0x08) {
844         /* chain 4 mode : simplest access */
845         plane = addr & 3;
846         mask = (1 << plane);
847         if (s->sr[2] & mask) {
848             s->vram_ptr[addr] = val;
849 #ifdef DEBUG_VGA_MEM
850             printf("vga: chain4: [0x%x]\n", addr);
851 #endif
852             s->plane_updated |= mask; /* only used to detect font change */
853             cpu_physical_memory_set_dirty(s->vram_offset + addr);
854         }
855     } else if (s->gr[5] & 0x10) {
856         /* odd/even mode (aka text mode mapping) */
857         plane = (s->gr[4] & 2) | (addr & 1);
858         mask = (1 << plane);
859         if (s->sr[2] & mask) {
860             addr = ((addr & ~1) << 1) | plane;
861             s->vram_ptr[addr] = val;
862 #ifdef DEBUG_VGA_MEM
863             printf("vga: odd/even: [0x%x]\n", addr);
864 #endif
865             s->plane_updated |= mask; /* only used to detect font change */
866             cpu_physical_memory_set_dirty(s->vram_offset + addr);
867         }
868     } else {
869         /* standard VGA latched access */
870         write_mode = s->gr[5] & 3;
871         switch(write_mode) {
872         default:
873         case 0:
874             /* rotate */
875             b = s->gr[3] & 7;
876             val = ((val >> b) | (val << (8 - b))) & 0xff;
877             val |= val << 8;
878             val |= val << 16;
879
880             /* apply set/reset mask */
881             set_mask = mask16[s->gr[1]];
882             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
883             bit_mask = s->gr[8];
884             break;
885         case 1:
886             val = s->latch;
887             goto do_write;
888         case 2:
889             val = mask16[val & 0x0f];
890             bit_mask = s->gr[8];
891             break;
892         case 3:
893             /* rotate */
894             b = s->gr[3] & 7;
895             val = (val >> b) | (val << (8 - b));
896
897             bit_mask = s->gr[8] & val;
898             val = mask16[s->gr[0]];
899             break;
900         }
901
902         /* apply logical operation */
903         func_select = s->gr[3] >> 3;
904         switch(func_select) {
905         case 0:
906         default:
907             /* nothing to do */
908             break;
909         case 1:
910             /* and */
911             val &= s->latch;
912             break;
913         case 2:
914             /* or */
915             val |= s->latch;
916             break;
917         case 3:
918             /* xor */
919             val ^= s->latch;
920             break;
921         }
922
923         /* apply bit mask */
924         bit_mask |= bit_mask << 8;
925         bit_mask |= bit_mask << 16;
926         val = (val & bit_mask) | (s->latch & ~bit_mask);
927
928     do_write:
929         /* mask data according to sr[2] */
930         mask = s->sr[2];
931         s->plane_updated |= mask; /* only used to detect font change */
932         write_mask = mask16[mask];
933         ((uint32_t *)s->vram_ptr)[addr] =
934             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
935             (val & write_mask);
936 #ifdef DEBUG_VGA_MEM
937             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
938                    addr * 4, write_mask, val);
939 #endif
940             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
941     }
942 }
943
944 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
945 {
946 #ifdef TARGET_WORDS_BIGENDIAN
947     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
948     vga_mem_writeb(opaque, addr + 1, val & 0xff);
949 #else
950     vga_mem_writeb(opaque, addr, val & 0xff);
951     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
952 #endif
953 }
954
955 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
956 {
957 #ifdef TARGET_WORDS_BIGENDIAN
958     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
959     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
960     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
961     vga_mem_writeb(opaque, addr + 3, val & 0xff);
962 #else
963     vga_mem_writeb(opaque, addr, val & 0xff);
964     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
965     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
966     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
967 #endif
968 }
969
970 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
971                              const uint8_t *font_ptr, int h,
972                              uint32_t fgcol, uint32_t bgcol);
973 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
974                                   const uint8_t *font_ptr, int h,
975                                   uint32_t fgcol, uint32_t bgcol, int dup9);
976 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
977                                 const uint8_t *s, int width);
978
979 #define DEPTH 8
980 #include "vga_template.h"
981
982 #define DEPTH 15
983 #include "vga_template.h"
984
985 #define BGR_FORMAT
986 #define DEPTH 15
987 #include "vga_template.h"
988
989 #define DEPTH 16
990 #include "vga_template.h"
991
992 #define BGR_FORMAT
993 #define DEPTH 16
994 #include "vga_template.h"
995
996 #define DEPTH 32
997 #include "vga_template.h"
998
999 #define BGR_FORMAT
1000 #define DEPTH 32
1001 #include "vga_template.h"
1002
1003 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1004 {
1005     unsigned int col;
1006     col = rgb_to_pixel8(r, g, b);
1007     col |= col << 8;
1008     col |= col << 16;
1009     return col;
1010 }
1011
1012 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1013 {
1014     unsigned int col;
1015     col = rgb_to_pixel15(r, g, b);
1016     col |= col << 16;
1017     return col;
1018 }
1019
1020 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1021                                           unsigned int b)
1022 {
1023     unsigned int col;
1024     col = rgb_to_pixel15bgr(r, g, b);
1025     col |= col << 16;
1026     return col;
1027 }
1028
1029 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1030 {
1031     unsigned int col;
1032     col = rgb_to_pixel16(r, g, b);
1033     col |= col << 16;
1034     return col;
1035 }
1036
1037 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1038                                           unsigned int b)
1039 {
1040     unsigned int col;
1041     col = rgb_to_pixel16bgr(r, g, b);
1042     col |= col << 16;
1043     return col;
1044 }
1045
1046 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1047 {
1048     unsigned int col;
1049     col = rgb_to_pixel32(r, g, b);
1050     return col;
1051 }
1052
1053 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1054 {
1055     unsigned int col;
1056     col = rgb_to_pixel32bgr(r, g, b);
1057     return col;
1058 }
1059
1060 /* return true if the palette was modified */
1061 static int update_palette16(VGAState *s)
1062 {
1063     int full_update, i;
1064     uint32_t v, col, *palette;
1065
1066     full_update = 0;
1067     palette = s->last_palette;
1068     for(i = 0; i < 16; i++) {
1069         v = s->ar[i];
1070         if (s->ar[0x10] & 0x80)
1071             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1072         else
1073             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1074         v = v * 3;
1075         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1076                               c6_to_8(s->palette[v + 1]),
1077                               c6_to_8(s->palette[v + 2]));
1078         if (col != palette[i]) {
1079             full_update = 1;
1080             palette[i] = col;
1081         }
1082     }
1083     return full_update;
1084 }
1085
1086 /* return true if the palette was modified */
1087 static int update_palette256(VGAState *s)
1088 {
1089     int full_update, i;
1090     uint32_t v, col, *palette;
1091
1092     full_update = 0;
1093     palette = s->last_palette;
1094     v = 0;
1095     for(i = 0; i < 256; i++) {
1096         if (s->dac_8bit) {
1097           col = s->rgb_to_pixel(s->palette[v],
1098                                 s->palette[v + 1],
1099                                 s->palette[v + 2]);
1100         } else {
1101           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1102                                 c6_to_8(s->palette[v + 1]),
1103                                 c6_to_8(s->palette[v + 2]));
1104         }
1105         if (col != palette[i]) {
1106             full_update = 1;
1107             palette[i] = col;
1108         }
1109         v += 3;
1110     }
1111     return full_update;
1112 }
1113
1114 static void vga_get_offsets(VGAState *s,
1115                             uint32_t *pline_offset,
1116                             uint32_t *pstart_addr,
1117                             uint32_t *pline_compare)
1118 {
1119     uint32_t start_addr, line_offset, line_compare;
1120 #ifdef CONFIG_BOCHS_VBE
1121     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1122         line_offset = s->vbe_line_offset;
1123         start_addr = s->vbe_start_addr;
1124         line_compare = 65535;
1125     } else
1126 #endif
1127     {
1128         /* compute line_offset in bytes */
1129         line_offset = s->cr[0x13];
1130         line_offset <<= 3;
1131
1132         /* starting address */
1133         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1134
1135         /* line compare */
1136         line_compare = s->cr[0x18] |
1137             ((s->cr[0x07] & 0x10) << 4) |
1138             ((s->cr[0x09] & 0x40) << 3);
1139     }
1140     *pline_offset = line_offset;
1141     *pstart_addr = start_addr;
1142     *pline_compare = line_compare;
1143 }
1144
1145 /* update start_addr and line_offset. Return TRUE if modified */
1146 static int update_basic_params(VGAState *s)
1147 {
1148     int full_update;
1149     uint32_t start_addr, line_offset, line_compare;
1150
1151     full_update = 0;
1152
1153     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1154
1155     if (line_offset != s->line_offset ||
1156         start_addr != s->start_addr ||
1157         line_compare != s->line_compare) {
1158         s->line_offset = line_offset;
1159         s->start_addr = start_addr;
1160         s->line_compare = line_compare;
1161         full_update = 1;
1162     }
1163     return full_update;
1164 }
1165
1166 #define NB_DEPTHS 7
1167
1168 static inline int get_depth_index(DisplayState *s)
1169 {
1170     switch(ds_get_bits_per_pixel(s)) {
1171     default:
1172     case 8:
1173         return 0;
1174     case 15:
1175         return 1;
1176     case 16:
1177         return 2;
1178     case 32:
1179         if (is_surface_bgr(s->surface))
1180             return 4;
1181         else
1182             return 3;
1183     }
1184 }
1185
1186 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1187     vga_draw_glyph8_8,
1188     vga_draw_glyph8_16,
1189     vga_draw_glyph8_16,
1190     vga_draw_glyph8_32,
1191     vga_draw_glyph8_32,
1192     vga_draw_glyph8_16,
1193     vga_draw_glyph8_16,
1194 };
1195
1196 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1197     vga_draw_glyph16_8,
1198     vga_draw_glyph16_16,
1199     vga_draw_glyph16_16,
1200     vga_draw_glyph16_32,
1201     vga_draw_glyph16_32,
1202     vga_draw_glyph16_16,
1203     vga_draw_glyph16_16,
1204 };
1205
1206 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1207     vga_draw_glyph9_8,
1208     vga_draw_glyph9_16,
1209     vga_draw_glyph9_16,
1210     vga_draw_glyph9_32,
1211     vga_draw_glyph9_32,
1212     vga_draw_glyph9_16,
1213     vga_draw_glyph9_16,
1214 };
1215
1216 static const uint8_t cursor_glyph[32 * 4] = {
1217     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1225     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1227     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1228     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1229     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1230     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1231     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1232     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1233 };
1234
1235 static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1236                                     int *pcwidth, int *pcheight)
1237 {
1238     int width, cwidth, height, cheight;
1239
1240     /* total width & height */
1241     cheight = (s->cr[9] & 0x1f) + 1;
1242     cwidth = 8;
1243     if (!(s->sr[1] & 0x01))
1244         cwidth = 9;
1245     if (s->sr[1] & 0x08)
1246         cwidth = 16; /* NOTE: no 18 pixel wide */
1247     width = (s->cr[0x01] + 1);
1248     if (s->cr[0x06] == 100) {
1249         /* ugly hack for CGA 160x100x16 - explain me the logic */
1250         height = 100;
1251     } else {
1252         height = s->cr[0x12] |
1253             ((s->cr[0x07] & 0x02) << 7) |
1254             ((s->cr[0x07] & 0x40) << 3);
1255         height = (height + 1) / cheight;
1256     }
1257
1258     *pwidth = width;
1259     *pheight = height;
1260     *pcwidth = cwidth;
1261     *pcheight = cheight;
1262 }
1263
1264 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1265
1266 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1267     rgb_to_pixel8_dup,
1268     rgb_to_pixel15_dup,
1269     rgb_to_pixel16_dup,
1270     rgb_to_pixel32_dup,
1271     rgb_to_pixel32bgr_dup,
1272     rgb_to_pixel15bgr_dup,
1273     rgb_to_pixel16bgr_dup,
1274 };
1275
1276 /*
1277  * Text mode update
1278  * Missing:
1279  * - double scan
1280  * - double width
1281  * - underline
1282  * - flashing
1283  */
1284 static void vga_draw_text(VGAState *s, int full_update)
1285 {
1286     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1287     int cx_min, cx_max, linesize, x_incr;
1288     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1289     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1290     const uint8_t *font_ptr, *font_base[2];
1291     int dup9, line_offset, depth_index;
1292     uint32_t *palette;
1293     uint32_t *ch_attr_ptr;
1294     vga_draw_glyph8_func *vga_draw_glyph8;
1295     vga_draw_glyph9_func *vga_draw_glyph9;
1296
1297     vga_dirty_log_stop(s);
1298
1299     /* compute font data address (in plane 2) */
1300     v = s->sr[3];
1301     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1302     if (offset != s->font_offsets[0]) {
1303         s->font_offsets[0] = offset;
1304         full_update = 1;
1305     }
1306     font_base[0] = s->vram_ptr + offset;
1307
1308     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1309     font_base[1] = s->vram_ptr + offset;
1310     if (offset != s->font_offsets[1]) {
1311         s->font_offsets[1] = offset;
1312         full_update = 1;
1313     }
1314     if (s->plane_updated & (1 << 2)) {
1315         /* if the plane 2 was modified since the last display, it
1316            indicates the font may have been modified */
1317         s->plane_updated = 0;
1318         full_update = 1;
1319     }
1320
1321     line_offset = s->line_offset;
1322     s1 = s->vram_ptr + (s->start_addr * 4);
1323
1324     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1325     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1326     if ((height * width) > CH_ATTR_SIZE) {
1327         /* better than nothing: exit if transient size is too big */
1328         return;
1329     }
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 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     vga_dirty_log_start(s);
1585 }
1586
1587 static void vga_update_resolution_graphics(VGAState *s)
1588 {
1589     int depth = s->get_bpp(s);
1590     int width, height, shift_control, double_scan;
1591     int disp_width, multi_scan, multi_run;
1592
1593     s->get_resolution(s, &width, &height);
1594     disp_width = width;
1595
1596     shift_control = (s->gr[0x05] >> 5) & 3;
1597     double_scan = (s->cr[0x09] >> 7);
1598
1599     if (shift_control != s->shift_control ||
1600         double_scan != s->double_scan) {
1601         s->want_full_update = 1;
1602         s->shift_control = shift_control;
1603         s->double_scan = double_scan;
1604     }
1605
1606     if (shift_control == 0) {
1607         if (s->sr[0x01] & 8) {
1608             disp_width <<= 1;
1609         }
1610     } else if (shift_control == 1) {
1611         if (s->sr[0x01] & 8) {
1612             disp_width <<= 1;
1613         }
1614     }
1615     disp_width = width;
1616
1617     if (shift_control != 1) {
1618         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1619     } else {
1620         /* in CGA modes, multi_scan is ignored */
1621         /* XXX: is it correct ? */
1622         multi_scan = double_scan;
1623     }
1624
1625     multi_run = multi_scan;
1626
1627     if (s->line_offset != s->last_line_offset ||
1628         disp_width != s->last_width ||
1629         height != s->last_height ||
1630         s->last_depth != depth ||
1631         s->multi_run != multi_run ||
1632         s->multi_scan != multi_scan ||
1633         s->want_full_update) {
1634         if (s->ds->surface->pf.depth == 0) {
1635             goto dont_touch_display_surface;
1636         }
1637 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1638         if (depth == 16 || depth == 32) {
1639 #else
1640         if (depth == 32) {
1641 #endif
1642             qemu_free_displaysurface(s->ds);
1643             s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1644                     s->line_offset,
1645                     s->vram_ptr + (s->start_addr * 4));
1646 #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1647             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1648 #endif
1649             dpy_resize(s->ds);
1650         } else {
1651             qemu_console_resize(s->ds, disp_width, height);
1652         }
1653     dont_touch_display_surface:
1654         s->last_scr_width = disp_width;
1655         s->last_scr_height = height;
1656         s->last_width = disp_width;
1657         s->last_height = height;
1658         s->last_line_offset = s->line_offset;
1659         s->last_depth = depth;
1660         s->multi_run = multi_run;
1661         s->multi_scan = multi_scan;
1662         s->want_full_update = 1;
1663     }
1664 }
1665
1666 static void vga_update_resolution_text(VGAState *s)
1667 {
1668     int width, height, cw, cheight;
1669
1670     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1671     if (width != s->last_width || height != s->last_height ||
1672         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1673         s->last_scr_width = width * cw;
1674         s->last_scr_height = height * cheight;
1675         if (s->ds->surface->pf.depth != 0) {
1676             qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1677         } else {
1678             /*
1679              * curses expects width and height to be in character cell
1680              * dimensions, not pixels.
1681              */
1682             s->ds->surface->width = width;
1683             s->ds->surface->height = height;
1684             dpy_resize(s->ds);
1685         }
1686         s->last_depth = 0;
1687         s->last_width = width;
1688         s->last_height = height;
1689         s->last_ch = cheight;
1690         s->last_cw = cw;
1691         s->want_full_update = 1;
1692     }
1693 }
1694
1695 void vga_update_resolution(VGAState *s)
1696 {
1697     int graphic_mode;
1698
1699     if (!(s->ar_index & 0x20)) {
1700         graphic_mode = GMODE_BLANK;
1701     } else {
1702         graphic_mode = s->gr[6] & 1;
1703     }
1704     if (graphic_mode != s->graphic_mode) {
1705         s->graphic_mode = graphic_mode;
1706         s->want_full_update = 1;
1707     }
1708     s->want_full_update |= update_basic_params(s);
1709     switch (graphic_mode) {
1710     case GMODE_TEXT:
1711         vga_update_resolution_text(s);
1712         break;
1713     case GMODE_GRAPH:
1714         vga_update_resolution_graphics(s);
1715         break;
1716     }
1717 }
1718
1719 /*
1720  * graphic modes
1721  */
1722 static void vga_draw_graphic(VGAState *s, int full_update)
1723 {
1724     int y1, y, update, linesize, y_start, mask;
1725     int width, height, line_offset, bwidth, bits;
1726     int multi_run;
1727     uint8_t *d;
1728     uint32_t v, addr1, addr;
1729     long page0, page1, page_min, page_max;
1730     vga_draw_line_func *vga_draw_line;
1731
1732     if (!full_update)
1733         vga_sync_dirty_bitmap(s);
1734
1735     s->get_resolution(s, &width, &height);
1736     multi_run = s->multi_run;
1737     if (is_buffer_shared(s->ds->surface) &&
1738                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1739         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1740         dpy_setdata(s->ds);
1741     }
1742
1743     s->rgb_to_pixel =
1744         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1745
1746     if (s->shift_control == 0) {
1747         full_update |= update_palette16(s);
1748         if (s->sr[0x01] & 8) {
1749             v = VGA_DRAW_LINE4D2;
1750         } else {
1751             v = VGA_DRAW_LINE4;
1752         }
1753         bits = 4;
1754     } else if (s->shift_control == 1) {
1755         full_update |= update_palette16(s);
1756         if (s->sr[0x01] & 8) {
1757             v = VGA_DRAW_LINE2D2;
1758         } else {
1759             v = VGA_DRAW_LINE2;
1760         }
1761         bits = 4;
1762     } else {
1763         switch(s->get_bpp(s)) {
1764         default:
1765         case 0:
1766             full_update |= update_palette256(s);
1767             v = VGA_DRAW_LINE8D2;
1768             bits = 4;
1769             break;
1770         case 8:
1771             full_update |= update_palette256(s);
1772             v = VGA_DRAW_LINE8;
1773             bits = 8;
1774             break;
1775         case 15:
1776             v = VGA_DRAW_LINE15;
1777             bits = 16;
1778             break;
1779         case 16:
1780             v = VGA_DRAW_LINE16;
1781             bits = 16;
1782             break;
1783         case 24:
1784             v = VGA_DRAW_LINE24;
1785             bits = 24;
1786             break;
1787         case 32:
1788             v = VGA_DRAW_LINE32;
1789             bits = 32;
1790             break;
1791         }
1792     }
1793     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1794
1795     if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1796         s->cursor_invalidate(s);
1797
1798     line_offset = s->line_offset;
1799 #if 0
1800     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",
1801            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1802 #endif
1803     addr1 = (s->start_addr * 4);
1804     bwidth = (width * bits + 7) / 8;
1805     y_start = -1;
1806     page_min = 0x7fffffff;
1807     page_max = -1;
1808     d = ds_get_data(s->ds);
1809     linesize = ds_get_linesize(s->ds);
1810     y1 = 0;
1811     for(y = 0; y < height; y++) {
1812         addr = addr1;
1813         if (!(s->cr[0x17] & 1)) {
1814             int shift;
1815             /* CGA compatibility handling */
1816             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1817             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1818         }
1819         if (!(s->cr[0x17] & 2)) {
1820             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1821         }
1822         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1823         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1824         update = full_update |
1825             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1826             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1827         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1828             /* if wide line, can use another page */
1829             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1830                                                     VGA_DIRTY_FLAG);
1831         }
1832         /* explicit invalidation for the hardware cursor */
1833         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1834         if (update) {
1835             if (y_start < 0)
1836                 y_start = y;
1837             if (page0 < page_min)
1838                 page_min = page0;
1839             if (page1 > page_max)
1840                 page_max = page1;
1841             if (!(is_buffer_shared(s->ds->surface))) {
1842                 vga_draw_line(s, d, s->vram_ptr + addr, width);
1843                 if (s->cursor_draw_line)
1844                     s->cursor_draw_line(s, d, y);
1845             }
1846         } else {
1847             if (y_start >= 0) {
1848                 /* flush to display */
1849                 dpy_update(s->ds, 0, y_start,
1850                            s->last_width, y - y_start);
1851                 y_start = -1;
1852             }
1853         }
1854         if (!multi_run) {
1855             mask = (s->cr[0x17] & 3) ^ 3;
1856             if ((y1 & mask) == mask)
1857                 addr1 += line_offset;
1858             y1++;
1859             multi_run = s->multi_scan;
1860         } else {
1861             multi_run--;
1862         }
1863         /* line compare acts on the displayed lines */
1864         if (y == s->line_compare)
1865             addr1 = 0;
1866         d += linesize;
1867     }
1868     if (y_start >= 0) {
1869         /* flush to display */
1870         dpy_update(s->ds, 0, y_start,
1871                    s->last_width, y - y_start);
1872     }
1873     /* reset modified pages */
1874     if (page_max != -1) {
1875         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1876                                         VGA_DIRTY_FLAG);
1877     }
1878     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1879 }
1880
1881 static void vga_draw_blank(VGAState *s, int full_update)
1882 {
1883     int i, w, val;
1884     uint8_t *d;
1885
1886     if (!full_update)
1887         return;
1888     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1889         return;
1890     vga_dirty_log_stop(s);
1891
1892     s->rgb_to_pixel =
1893         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1894     if (ds_get_bits_per_pixel(s->ds) == 8)
1895         val = s->rgb_to_pixel(0, 0, 0);
1896     else
1897         val = 0;
1898     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1899     d = ds_get_data(s->ds);
1900     for(i = 0; i < s->last_scr_height; i++) {
1901         memset(d, val, w);
1902         d += ds_get_linesize(s->ds);
1903     }
1904     dpy_update(s->ds, 0, 0,
1905                s->last_scr_width, s->last_scr_height);
1906 }
1907
1908 static void vga_update_display(void *opaque)
1909 {
1910     VGAState *s = (VGAState *)opaque;
1911     int full_update;
1912
1913     if (ds_get_bits_per_pixel(s->ds) == 0) {
1914         /* nothing to do */
1915     } else {
1916         full_update = s->want_full_update;
1917         s->want_full_update = 0;
1918         switch(s->graphic_mode) {
1919         case GMODE_TEXT:
1920             vga_draw_text(s, full_update);
1921             break;
1922         case GMODE_GRAPH:
1923             vga_draw_graphic(s, full_update);
1924             break;
1925         case GMODE_BLANK:
1926         default:
1927             vga_draw_blank(s, full_update);
1928             break;
1929         }
1930     }
1931 }
1932
1933 /* force a full display refresh */
1934 static void vga_invalidate_display(void *opaque)
1935 {
1936     VGAState *s = (VGAState *)opaque;
1937
1938     vga_update_resolution(s);
1939     s->want_full_update = 1;
1940 }
1941
1942 void vga_reset(void *opaque)
1943 {
1944     VGAState *s = (VGAState *) opaque;
1945
1946     s->lfb_addr = 0;
1947     s->lfb_end = 0;
1948     s->map_addr = 0;
1949     s->map_end = 0;
1950     s->lfb_vram_mapped = 0;
1951     s->bios_offset = 0;
1952     s->bios_size = 0;
1953     s->sr_index = 0;
1954     memset(s->sr, '\0', sizeof(s->sr));
1955     s->gr_index = 0;
1956     memset(s->gr, '\0', sizeof(s->gr));
1957     s->ar_index = 0;
1958     memset(s->ar, '\0', sizeof(s->ar));
1959     s->ar_flip_flop = 0;
1960     s->cr_index = 0;
1961     memset(s->cr, '\0', sizeof(s->cr));
1962     s->msr = 0;
1963     s->fcr = 0;
1964     s->st00 = 0;
1965     s->st01 = 0;
1966     s->dac_state = 0;
1967     s->dac_sub_index = 0;
1968     s->dac_read_index = 0;
1969     s->dac_write_index = 0;
1970     memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1971     s->dac_8bit = 0;
1972     memset(s->palette, '\0', sizeof(s->palette));
1973     s->bank_offset = 0;
1974 #ifdef CONFIG_BOCHS_VBE
1975     s->vbe_index = 0;
1976     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1977     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1978     s->vbe_start_addr = 0;
1979     s->vbe_line_offset = 0;
1980     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1981 #endif
1982     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1983     s->shift_control = 0;
1984     s->double_scan = 0;
1985     s->line_offset = 0;
1986     s->line_compare = 0;
1987     s->start_addr = 0;
1988     s->plane_updated = 0;
1989     s->last_cw = 0;
1990     s->last_ch = 0;
1991     s->last_width = 0;
1992     s->last_height = 0;
1993     s->last_scr_width = 0;
1994     s->last_scr_height = 0;
1995     s->cursor_start = 0;
1996     s->cursor_end = 0;
1997     s->cursor_offset = 0;
1998     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1999     memset(s->last_palette, '\0', sizeof(s->last_palette));
2000     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
2001     switch (vga_retrace_method) {
2002     case VGA_RETRACE_DUMB:
2003         break;
2004     case VGA_RETRACE_PRECISE:
2005         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
2006         break;
2007     }
2008     vga_update_resolution(s);
2009 }
2010
2011 #define TEXTMODE_X(x)   ((x) % width)
2012 #define TEXTMODE_Y(x)   ((x) / width)
2013 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
2014         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2015 /* relay text rendering to the display driver
2016  * instead of doing a full vga_update_display() */
2017 static void vga_update_text(void *opaque, console_ch_t *chardata)
2018 {
2019     VGAState *s = (VGAState *) opaque;
2020     int i, cursor_offset, cursor_visible;
2021     int cw, cheight, width, height, size, c_min, c_max;
2022     uint32_t *src;
2023     console_ch_t *dst, val;
2024     char msg_buffer[80];
2025     int full_update = s->want_full_update;
2026
2027     s->want_full_update = 0;
2028     switch (s->graphic_mode) {
2029     case GMODE_TEXT:
2030         /* TODO: update palette */
2031
2032         vga_get_text_resolution(s, &width, &height, &cw, &cheight);
2033
2034         if (s->ds->surface->width != width
2035             || s->ds->surface->height != height) {
2036             s->ds->surface->width = width;
2037             s->ds->surface->height = height;
2038             dpy_resize(s->ds);
2039         }
2040
2041         /* total width & height */
2042         size = (height * width);
2043         if (size > CH_ATTR_SIZE) {
2044             if (!full_update)
2045                 return;
2046
2047             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2048                      width, height);
2049             break;
2050         }
2051
2052         /* Update "hardware" cursor */
2053         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2054         if (cursor_offset != s->cursor_offset ||
2055             s->cr[0xa] != s->cursor_start ||
2056             s->cr[0xb] != s->cursor_end || full_update) {
2057             cursor_visible = !(s->cr[0xa] & 0x20);
2058             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2059                 dpy_cursor(s->ds,
2060                            TEXTMODE_X(cursor_offset),
2061                            TEXTMODE_Y(cursor_offset));
2062             else
2063                 dpy_cursor(s->ds, -1, -1);
2064             s->cursor_offset = cursor_offset;
2065             s->cursor_start = s->cr[0xa];
2066             s->cursor_end = s->cr[0xb];
2067         }
2068
2069         src = (uint32_t *) s->vram_ptr + s->start_addr;
2070         dst = chardata;
2071
2072         if (full_update) {
2073             for (i = 0; i < size; src ++, dst ++, i ++)
2074                 console_write_ch(dst, VMEM2CHTYPE(*src));
2075
2076             dpy_update(s->ds, 0, 0, width, height);
2077         } else {
2078             c_max = 0;
2079
2080             for (i = 0; i < size; src ++, dst ++, i ++) {
2081                 console_write_ch(&val, VMEM2CHTYPE(*src));
2082                 if (*dst != val) {
2083                     *dst = val;
2084                     c_max = i;
2085                     break;
2086                 }
2087             }
2088             c_min = i;
2089             for (; i < size; src ++, dst ++, i ++) {
2090                 console_write_ch(&val, VMEM2CHTYPE(*src));
2091                 if (*dst != val) {
2092                     *dst = val;
2093                     c_max = i;
2094                 }
2095             }
2096
2097             if (c_min <= c_max) {
2098                 i = TEXTMODE_Y(c_min);
2099                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2100             }
2101         }
2102
2103         return;
2104     case GMODE_GRAPH:
2105         if (!full_update)
2106             return;
2107
2108         s->get_resolution(s, &width, &height);
2109         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2110                  width, height);
2111         break;
2112     case GMODE_BLANK:
2113     default:
2114         if (!full_update)
2115             return;
2116
2117         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2118         break;
2119     }
2120
2121     /* Display a message */
2122     s->last_width = 60;
2123     s->last_height = height = 3;
2124     dpy_cursor(s->ds, -1, -1);
2125     s->ds->surface->width = s->last_width;
2126     s->ds->surface->height = height;
2127     dpy_resize(s->ds);
2128
2129     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2130         console_write_ch(dst ++, ' ');
2131
2132     size = strlen(msg_buffer);
2133     width = (s->last_width - size) / 2;
2134     dst = chardata + s->last_width + width;
2135     for (i = 0; i < size; i ++)
2136         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2137
2138     dpy_update(s->ds, 0, 0, s->last_width, height);
2139 }
2140
2141 static CPUReadMemoryFunc *vga_mem_read[3] = {
2142     vga_mem_readb,
2143     vga_mem_readw,
2144     vga_mem_readl,
2145 };
2146
2147 static CPUWriteMemoryFunc *vga_mem_write[3] = {
2148     vga_mem_writeb,
2149     vga_mem_writew,
2150     vga_mem_writel,
2151 };
2152
2153 static void vga_save(QEMUFile *f, void *opaque)
2154 {
2155     VGAState *s = opaque;
2156     int i;
2157
2158     if (s->pci_dev)
2159         pci_device_save(s->pci_dev, f);
2160
2161     qemu_put_be32s(f, &s->latch);
2162     qemu_put_8s(f, &s->sr_index);
2163     qemu_put_buffer(f, s->sr, 8);
2164     qemu_put_8s(f, &s->gr_index);
2165     qemu_put_buffer(f, s->gr, 16);
2166     qemu_put_8s(f, &s->ar_index);
2167     qemu_put_buffer(f, s->ar, 21);
2168     qemu_put_be32(f, s->ar_flip_flop);
2169     qemu_put_8s(f, &s->cr_index);
2170     qemu_put_buffer(f, s->cr, 256);
2171     qemu_put_8s(f, &s->msr);
2172     qemu_put_8s(f, &s->fcr);
2173     qemu_put_byte(f, s->st00);
2174     qemu_put_8s(f, &s->st01);
2175
2176     qemu_put_8s(f, &s->dac_state);
2177     qemu_put_8s(f, &s->dac_sub_index);
2178     qemu_put_8s(f, &s->dac_read_index);
2179     qemu_put_8s(f, &s->dac_write_index);
2180     qemu_put_buffer(f, s->dac_cache, 3);
2181     qemu_put_buffer(f, s->palette, 768);
2182
2183     qemu_put_be32(f, s->bank_offset);
2184 #ifdef CONFIG_BOCHS_VBE
2185     qemu_put_byte(f, 1);
2186     qemu_put_be16s(f, &s->vbe_index);
2187     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2188         qemu_put_be16s(f, &s->vbe_regs[i]);
2189     qemu_put_be32s(f, &s->vbe_start_addr);
2190     qemu_put_be32s(f, &s->vbe_line_offset);
2191     qemu_put_be32s(f, &s->vbe_bank_mask);
2192 #else
2193     qemu_put_byte(f, 0);
2194 #endif
2195 }
2196
2197 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2198 {
2199     VGAState *s = opaque;
2200     int is_vbe, i, ret;
2201
2202     if (version_id > 2)
2203         return -EINVAL;
2204
2205     if (s->pci_dev && version_id >= 2) {
2206         ret = pci_device_load(s->pci_dev, f);
2207         if (ret < 0)
2208             return ret;
2209     }
2210
2211     qemu_get_be32s(f, &s->latch);
2212     qemu_get_8s(f, &s->sr_index);
2213     qemu_get_buffer(f, s->sr, 8);
2214     qemu_get_8s(f, &s->gr_index);
2215     qemu_get_buffer(f, s->gr, 16);
2216     qemu_get_8s(f, &s->ar_index);
2217     qemu_get_buffer(f, s->ar, 21);
2218     s->ar_flip_flop=qemu_get_be32(f);
2219     qemu_get_8s(f, &s->cr_index);
2220     qemu_get_buffer(f, s->cr, 256);
2221     qemu_get_8s(f, &s->msr);
2222     qemu_get_8s(f, &s->fcr);
2223     qemu_get_8s(f, &s->st00);
2224     qemu_get_8s(f, &s->st01);
2225
2226     qemu_get_8s(f, &s->dac_state);
2227     qemu_get_8s(f, &s->dac_sub_index);
2228     qemu_get_8s(f, &s->dac_read_index);
2229     qemu_get_8s(f, &s->dac_write_index);
2230     qemu_get_buffer(f, s->dac_cache, 3);
2231     qemu_get_buffer(f, s->palette, 768);
2232
2233     s->bank_offset=qemu_get_be32(f);
2234     is_vbe = qemu_get_byte(f);
2235 #ifdef CONFIG_BOCHS_VBE
2236     if (!is_vbe)
2237         return -EINVAL;
2238     qemu_get_be16s(f, &s->vbe_index);
2239     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2240         qemu_get_be16s(f, &s->vbe_regs[i]);
2241     qemu_get_be32s(f, &s->vbe_start_addr);
2242     qemu_get_be32s(f, &s->vbe_line_offset);
2243     qemu_get_be32s(f, &s->vbe_bank_mask);
2244 #else
2245     if (is_vbe)
2246         return -EINVAL;
2247 #endif
2248
2249     /* force refresh */
2250     vga_update_resolution(s);
2251     s->want_full_update = 1;
2252     return 0;
2253 }
2254
2255 typedef struct PCIVGAState {
2256     PCIDevice dev;
2257     VGAState vga_state;
2258 } PCIVGAState;
2259
2260 void vga_dirty_log_start(VGAState *s)
2261 {
2262     if (kvm_enabled() && s->map_addr)
2263         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2264
2265     if (kvm_enabled() && s->lfb_vram_mapped) {
2266         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2267         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2268     }
2269 }
2270
2271 void vga_dirty_log_stop(VGAState *s)
2272 {
2273     if (kvm_enabled() && s->map_addr)
2274         kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2275
2276     if (kvm_enabled() && s->lfb_vram_mapped) {
2277         kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2278         kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2279     }
2280 }
2281
2282 static void vga_map(PCIDevice *pci_dev, int region_num,
2283                     uint32_t addr, uint32_t size, int type)
2284 {
2285     PCIVGAState *d = (PCIVGAState *)pci_dev;
2286     VGAState *s = &d->vga_state;
2287     if (region_num == PCI_ROM_SLOT) {
2288         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2289     } else {
2290         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2291     }
2292
2293     s->map_addr = addr;
2294     s->map_end = addr + VGA_RAM_SIZE;
2295
2296     vga_dirty_log_start(s);
2297 }
2298
2299 void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
2300                      ram_addr_t vga_ram_offset, int vga_ram_size)
2301 {
2302     int i, j, v, b;
2303
2304     for(i = 0;i < 256; i++) {
2305         v = 0;
2306         for(j = 0; j < 8; j++) {
2307             v |= ((i >> j) & 1) << (j * 4);
2308         }
2309         expand4[i] = v;
2310
2311         v = 0;
2312         for(j = 0; j < 4; j++) {
2313             v |= ((i >> (2 * j)) & 3) << (j * 4);
2314         }
2315         expand2[i] = v;
2316     }
2317     for(i = 0; i < 16; i++) {
2318         v = 0;
2319         for(j = 0; j < 4; j++) {
2320             b = ((i >> j) & 1);
2321             v |= b << (2 * j);
2322             v |= b << (2 * j + 1);
2323         }
2324         expand4to8[i] = v;
2325     }
2326
2327     s->vram_ptr = vga_ram_base;
2328     s->vram_offset = vga_ram_offset;
2329     s->vram_size = vga_ram_size;
2330     s->get_bpp = vga_get_bpp;
2331     s->get_offsets = vga_get_offsets;
2332     s->get_resolution = vga_get_resolution;
2333     s->update = vga_update_display;
2334     s->invalidate = vga_invalidate_display;
2335     s->screen_dump = vga_screen_dump;
2336     s->text_update = vga_update_text;
2337     switch (vga_retrace_method) {
2338     case VGA_RETRACE_DUMB:
2339         s->retrace = vga_dumb_retrace;
2340         s->update_retrace_info = vga_dumb_update_retrace_info;
2341         break;
2342
2343     case VGA_RETRACE_PRECISE:
2344         s->retrace = vga_precise_retrace;
2345         s->update_retrace_info = vga_precise_update_retrace_info;
2346         break;
2347     }
2348     vga_reset(s);
2349 }
2350
2351 /* used by both ISA and PCI */
2352 void vga_init(VGAState *s)
2353 {
2354     int vga_io_memory;
2355
2356     qemu_register_reset(vga_reset, s);
2357     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2358
2359     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2360
2361     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2362     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2363     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2364     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2365
2366     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2367
2368     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2369     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2370     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2371     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2372     s->bank_offset = 0;
2373
2374 #ifdef CONFIG_BOCHS_VBE
2375 #if defined (TARGET_I386)
2376     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2377     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2378
2379     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2380     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2381
2382     /* old Bochs IO ports */
2383     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2384     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2385
2386     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2387     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2388 #else
2389     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2390     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2391
2392     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2393     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2394 #endif
2395 #endif /* CONFIG_BOCHS_VBE */
2396
2397     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2398     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2399                                  vga_io_memory);
2400     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2401 }
2402
2403 /* Memory mapped interface */
2404 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2405 {
2406     VGAState *s = opaque;
2407
2408     return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2409 }
2410
2411 static void vga_mm_writeb (void *opaque,
2412                            target_phys_addr_t addr, uint32_t value)
2413 {
2414     VGAState *s = opaque;
2415
2416     vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2417 }
2418
2419 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2420 {
2421     VGAState *s = opaque;
2422
2423     return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2424 }
2425
2426 static void vga_mm_writew (void *opaque,
2427                            target_phys_addr_t addr, uint32_t value)
2428 {
2429     VGAState *s = opaque;
2430
2431     vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2432 }
2433
2434 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2435 {
2436     VGAState *s = opaque;
2437
2438     return vga_ioport_read(s, addr >> s->it_shift);
2439 }
2440
2441 static void vga_mm_writel (void *opaque,
2442                            target_phys_addr_t addr, uint32_t value)
2443 {
2444     VGAState *s = opaque;
2445
2446     vga_ioport_write(s, addr >> s->it_shift, value);
2447 }
2448
2449 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2450     &vga_mm_readb,
2451     &vga_mm_readw,
2452     &vga_mm_readl,
2453 };
2454
2455 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2456     &vga_mm_writeb,
2457     &vga_mm_writew,
2458     &vga_mm_writel,
2459 };
2460
2461 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2462                         target_phys_addr_t ctrl_base, int it_shift)
2463 {
2464     int s_ioport_ctrl, vga_io_memory;
2465
2466     s->it_shift = it_shift;
2467     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2468     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2469
2470     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2471
2472     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2473     s->bank_offset = 0;
2474     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2475     qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2476 }
2477
2478 int isa_vga_init(uint8_t *vga_ram_base,
2479                  unsigned long vga_ram_offset, int vga_ram_size)
2480 {
2481     VGAState *s;
2482
2483     s = qemu_mallocz(sizeof(VGAState));
2484
2485     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2486     vga_init(s);
2487
2488     s->ds = graphic_console_init(s->update, s->invalidate,
2489                                  s->screen_dump, s->text_update, s);
2490
2491 #ifdef CONFIG_BOCHS_VBE
2492     /* XXX: use optimized standard vga accesses */
2493     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2494                                  vga_ram_size, vga_ram_offset);
2495 #endif
2496     return 0;
2497 }
2498
2499 int isa_vga_mm_init(uint8_t *vga_ram_base,
2500                     unsigned long vga_ram_offset, int vga_ram_size,
2501                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2502                     int it_shift)
2503 {
2504     VGAState *s;
2505
2506     s = qemu_mallocz(sizeof(VGAState));
2507
2508     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2509     vga_mm_init(s, vram_base, ctrl_base, it_shift);
2510
2511     s->ds = graphic_console_init(s->update, s->invalidate,
2512                                  s->screen_dump, s->text_update, s);
2513
2514 #ifdef CONFIG_BOCHS_VBE
2515     /* XXX: use optimized standard vga accesses */
2516     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2517                                  vga_ram_size, vga_ram_offset);
2518 #endif
2519     return 0;
2520 }
2521
2522 static void pci_vga_write_config(PCIDevice *d,
2523                                  uint32_t address, uint32_t val, int len)
2524 {
2525     PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2526     VGAState *s = &pvs->vga_state;
2527
2528     vga_dirty_log_stop(s);
2529     pci_default_write_config(d, address, val, len);
2530     vga_dirty_log_start(s);
2531 }
2532
2533 int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
2534                  unsigned long vga_ram_offset, int vga_ram_size,
2535                  unsigned long vga_bios_offset, int vga_bios_size)
2536 {
2537     PCIVGAState *d;
2538     VGAState *s;
2539     uint8_t *pci_conf;
2540
2541     d = (PCIVGAState *)pci_register_device(bus, "VGA",
2542                                            sizeof(PCIVGAState),
2543                                            -1, NULL, pci_vga_write_config);
2544     if (!d)
2545         return -1;
2546     s = &d->vga_state;
2547
2548     vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
2549     vga_init(s);
2550
2551     s->ds = graphic_console_init(s->update, s->invalidate,
2552                                  s->screen_dump, s->text_update, s);
2553
2554     s->pci_dev = &d->dev;
2555
2556     pci_conf = d->dev.config;
2557     // dummy VGA (same as Bochs ID)
2558     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2559     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2560     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2561     pci_conf[0x0e] = 0x00; // header_type
2562
2563     /* XXX: vga_ram_size must be a power of two */
2564     pci_register_io_region(&d->dev, 0, vga_ram_size,
2565                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2566     if (vga_bios_size != 0) {
2567         unsigned int bios_total_size;
2568         s->bios_offset = vga_bios_offset;
2569         s->bios_size = vga_bios_size;
2570         /* must be a power of two */
2571         bios_total_size = 1;
2572         while (bios_total_size < vga_bios_size)
2573             bios_total_size <<= 1;
2574         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2575                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2576     }
2577     return 0;
2578 }
2579
2580 /********************************************************/
2581 /* vga screen dump */
2582
2583 static void vga_save_dpy_update(DisplayState *s,
2584                                 int x, int y, int w, int h)
2585 {
2586 }
2587
2588 static void vga_save_dpy_resize(DisplayState *s)
2589 {
2590 }
2591
2592 static void vga_save_dpy_refresh(DisplayState *s)
2593 {
2594 }
2595
2596 int ppm_save(const char *filename, struct DisplaySurface *ds)
2597 {
2598     FILE *f;
2599     uint8_t *d, *d1;
2600     uint32_t v;
2601     int y, x;
2602     uint8_t r, g, b;
2603
2604     f = fopen(filename, "wb");
2605     if (!f)
2606         return -1;
2607     fprintf(f, "P6\n%d %d\n%d\n",
2608             ds->width, ds->height, 255);
2609     d1 = ds->data;
2610     for(y = 0; y < ds->height; y++) {
2611         d = d1;
2612         for(x = 0; x < ds->width; x++) {
2613             if (ds->pf.bits_per_pixel == 32)
2614                 v = *(uint32_t *)d;
2615             else
2616                 v = (uint32_t) (*(uint16_t *)d);
2617             r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2618                 (ds->pf.rmax + 1);
2619             g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2620                 (ds->pf.gmax + 1);
2621             b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2622                 (ds->pf.bmax + 1);
2623             fputc(r, f);
2624             fputc(g, f);
2625             fputc(b, f);
2626             d += ds->pf.bytes_per_pixel;
2627         }
2628         d1 += ds->linesize;
2629     }
2630     fclose(f);
2631     return 0;
2632 }
2633
2634 static void vga_screen_dump_blank(VGAState *s, const char *filename)
2635 {
2636     FILE *f;
2637     unsigned int y, x, w, h;
2638
2639     w = s->last_scr_width * sizeof(uint32_t);
2640     h = s->last_scr_height;
2641
2642     f = fopen(filename, "wb");
2643     if (!f)
2644         return;
2645     fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
2646     for (y = 0; y < h; y++) {
2647         for (x = 0; x < w; x++) {
2648             fputc(0, f);
2649         }
2650     }
2651     fclose(f);
2652 }
2653
2654 static void vga_screen_dump_common(VGAState *s, const char *filename,
2655                                    int w, int h)
2656 {
2657     DisplayState *saved_ds, ds1, *ds = &ds1;
2658     DisplayChangeListener dcl;
2659
2660     /* XXX: this is a little hackish */
2661     vga_invalidate_display(s);
2662     saved_ds = s->ds;
2663
2664     memset(ds, 0, sizeof(DisplayState));
2665     memset(&dcl, 0, sizeof(DisplayChangeListener));
2666     dcl.dpy_update = vga_save_dpy_update;
2667     dcl.dpy_resize = vga_save_dpy_resize;
2668     dcl.dpy_refresh = vga_save_dpy_refresh;
2669     register_displaychangelistener(ds, &dcl);
2670     ds->allocator = &default_allocator;
2671     ds->surface = qemu_create_displaysurface(ds, w, h);
2672
2673     s->ds = ds;
2674     vga_update_resolution(s);
2675     s->want_full_update = 1;
2676     vga_update_display(s);
2677
2678     ppm_save(filename, ds->surface);
2679
2680     qemu_free_displaysurface(ds);
2681     s->ds = saved_ds;
2682 }
2683
2684 static void vga_screen_dump_graphic(VGAState *s, const char *filename)
2685 {
2686     int w, h;
2687
2688     s->get_resolution(s, &w, &h);
2689     vga_screen_dump_common(s, filename, w, h);
2690 }
2691
2692 static void vga_screen_dump_text(VGAState *s, const char *filename)
2693 {
2694     int w, h, cwidth, cheight;
2695
2696     vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
2697     vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
2698 }
2699
2700 /* save the vga display in a PPM image even if no display is
2701    available */
2702 static void vga_screen_dump(void *opaque, const char *filename)
2703 {
2704     VGAState *s = (VGAState *)opaque;
2705
2706     switch (s->graphic_mode) {
2707     case GMODE_TEXT:
2708         vga_screen_dump_text(s, filename);
2709         break;
2710     case GMODE_GRAPH:
2711         vga_screen_dump_graphic(s, filename);
2712         break;
2713     case GMODE_BLANK:
2714     default:
2715         vga_screen_dump_blank(s, filename);
2716         break;
2717     }
2718 }