rtoss - Blame information for rev 79

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