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