]> Git Repo - qemu.git/blob - hw/vga.c
VMware VGA: Only enable dirty log tracking when fifo is disabled
[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 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, line, line1;
1271     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1272     uint8_t *d1, *d, *src, *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
1305     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1306     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1307     if ((height * width) > CH_ATTR_SIZE) {
1308         /* better than nothing: exit if transient size is too big */
1309         return;
1310     }
1311
1312     if (width != s->last_width || height != s->last_height ||
1313         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1314         s->last_scr_width = width * cw;
1315         s->last_scr_height = height * cheight;
1316         qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1317         s->last_depth = 0;
1318         s->last_width = width;
1319         s->last_height = height;
1320         s->last_ch = cheight;
1321         s->last_cw = cw;
1322         full_update = 1;
1323     }
1324     s->rgb_to_pixel =
1325         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1326     full_update |= update_palette16(s);
1327     palette = s->last_palette;
1328     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1329
1330     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1331     if (cursor_offset != s->cursor_offset ||
1332         s->cr[0xa] != s->cursor_start ||
1333         s->cr[0xb] != s->cursor_end) {
1334       /* if the cursor position changed, we update the old and new
1335          chars */
1336         if (s->cursor_offset < CH_ATTR_SIZE)
1337             s->last_ch_attr[s->cursor_offset] = -1;
1338         if (cursor_offset < CH_ATTR_SIZE)
1339             s->last_ch_attr[cursor_offset] = -1;
1340         s->cursor_offset = cursor_offset;
1341         s->cursor_start = s->cr[0xa];
1342         s->cursor_end = s->cr[0xb];
1343     }
1344     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1345
1346     depth_index = get_depth_index(s->ds);
1347     if (cw == 16)
1348         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1349     else
1350         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1351     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1352
1353     dest = ds_get_data(s->ds);
1354     linesize = ds_get_linesize(s->ds);
1355     ch_attr_ptr = s->last_ch_attr;
1356     line = 0;
1357     offset = s->start_addr * 4;
1358     for(cy = 0; cy < height; cy++) {
1359         d1 = dest;
1360         src = s->vram_ptr + offset;
1361         cx_min = width;
1362         cx_max = -1;
1363         for(cx = 0; cx < width; cx++) {
1364             ch_attr = *(uint16_t *)src;
1365             if (full_update || ch_attr != *ch_attr_ptr) {
1366                 if (cx < cx_min)
1367                     cx_min = cx;
1368                 if (cx > cx_max)
1369                     cx_max = cx;
1370                 *ch_attr_ptr = ch_attr;
1371 #ifdef HOST_WORDS_BIGENDIAN
1372                 ch = ch_attr >> 8;
1373                 cattr = ch_attr & 0xff;
1374 #else
1375                 ch = ch_attr & 0xff;
1376                 cattr = ch_attr >> 8;
1377 #endif
1378                 font_ptr = font_base[(cattr >> 3) & 1];
1379                 font_ptr += 32 * 4 * ch;
1380                 bgcol = palette[cattr >> 4];
1381                 fgcol = palette[cattr & 0x0f];
1382                 if (cw != 9) {
1383                     vga_draw_glyph8(d1, linesize,
1384                                     font_ptr, cheight, fgcol, bgcol);
1385                 } else {
1386                     dup9 = 0;
1387                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1388                         dup9 = 1;
1389                     vga_draw_glyph9(d1, linesize,
1390                                     font_ptr, cheight, fgcol, bgcol, dup9);
1391                 }
1392                 if (src == cursor_ptr &&
1393                     !(s->cr[0x0a] & 0x20)) {
1394                     int line_start, line_last, h;
1395                     /* draw the cursor */
1396                     line_start = s->cr[0x0a] & 0x1f;
1397                     line_last = s->cr[0x0b] & 0x1f;
1398                     /* XXX: check that */
1399                     if (line_last > cheight - 1)
1400                         line_last = cheight - 1;
1401                     if (line_last >= line_start && line_start < cheight) {
1402                         h = line_last - line_start + 1;
1403                         d = d1 + linesize * line_start;
1404                         if (cw != 9) {
1405                             vga_draw_glyph8(d, linesize,
1406                                             cursor_glyph, h, fgcol, bgcol);
1407                         } else {
1408                             vga_draw_glyph9(d, linesize,
1409                                             cursor_glyph, h, fgcol, bgcol, 1);
1410                         }
1411                     }
1412                 }
1413             }
1414             d1 += x_incr;
1415             src += 4;
1416             ch_attr_ptr++;
1417         }
1418         if (cx_max != -1) {
1419             dpy_update(s->ds, cx_min * cw, cy * cheight,
1420                        (cx_max - cx_min + 1) * cw, cheight);
1421         }
1422         dest += linesize * cheight;
1423         line1 = line + cheight;
1424         offset += line_offset;
1425         if (line < s->line_compare && line1 >= s->line_compare) {
1426             offset = 0;
1427         }
1428         line = line1;
1429     }
1430 }
1431
1432 enum {
1433     VGA_DRAW_LINE2,
1434     VGA_DRAW_LINE2D2,
1435     VGA_DRAW_LINE4,
1436     VGA_DRAW_LINE4D2,
1437     VGA_DRAW_LINE8D2,
1438     VGA_DRAW_LINE8,
1439     VGA_DRAW_LINE15,
1440     VGA_DRAW_LINE16,
1441     VGA_DRAW_LINE24,
1442     VGA_DRAW_LINE32,
1443     VGA_DRAW_LINE_NB,
1444 };
1445
1446 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1447     vga_draw_line2_8,
1448     vga_draw_line2_16,
1449     vga_draw_line2_16,
1450     vga_draw_line2_32,
1451     vga_draw_line2_32,
1452     vga_draw_line2_16,
1453     vga_draw_line2_16,
1454
1455     vga_draw_line2d2_8,
1456     vga_draw_line2d2_16,
1457     vga_draw_line2d2_16,
1458     vga_draw_line2d2_32,
1459     vga_draw_line2d2_32,
1460     vga_draw_line2d2_16,
1461     vga_draw_line2d2_16,
1462
1463     vga_draw_line4_8,
1464     vga_draw_line4_16,
1465     vga_draw_line4_16,
1466     vga_draw_line4_32,
1467     vga_draw_line4_32,
1468     vga_draw_line4_16,
1469     vga_draw_line4_16,
1470
1471     vga_draw_line4d2_8,
1472     vga_draw_line4d2_16,
1473     vga_draw_line4d2_16,
1474     vga_draw_line4d2_32,
1475     vga_draw_line4d2_32,
1476     vga_draw_line4d2_16,
1477     vga_draw_line4d2_16,
1478
1479     vga_draw_line8d2_8,
1480     vga_draw_line8d2_16,
1481     vga_draw_line8d2_16,
1482     vga_draw_line8d2_32,
1483     vga_draw_line8d2_32,
1484     vga_draw_line8d2_16,
1485     vga_draw_line8d2_16,
1486
1487     vga_draw_line8_8,
1488     vga_draw_line8_16,
1489     vga_draw_line8_16,
1490     vga_draw_line8_32,
1491     vga_draw_line8_32,
1492     vga_draw_line8_16,
1493     vga_draw_line8_16,
1494
1495     vga_draw_line15_8,
1496     vga_draw_line15_15,
1497     vga_draw_line15_16,
1498     vga_draw_line15_32,
1499     vga_draw_line15_32bgr,
1500     vga_draw_line15_15bgr,
1501     vga_draw_line15_16bgr,
1502
1503     vga_draw_line16_8,
1504     vga_draw_line16_15,
1505     vga_draw_line16_16,
1506     vga_draw_line16_32,
1507     vga_draw_line16_32bgr,
1508     vga_draw_line16_15bgr,
1509     vga_draw_line16_16bgr,
1510
1511     vga_draw_line24_8,
1512     vga_draw_line24_15,
1513     vga_draw_line24_16,
1514     vga_draw_line24_32,
1515     vga_draw_line24_32bgr,
1516     vga_draw_line24_15bgr,
1517     vga_draw_line24_16bgr,
1518
1519     vga_draw_line32_8,
1520     vga_draw_line32_15,
1521     vga_draw_line32_16,
1522     vga_draw_line32_32,
1523     vga_draw_line32_32bgr,
1524     vga_draw_line32_15bgr,
1525     vga_draw_line32_16bgr,
1526 };
1527
1528 static int vga_get_bpp(VGACommonState *s)
1529 {
1530     int ret;
1531 #ifdef CONFIG_BOCHS_VBE
1532     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1533         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1534     } else
1535 #endif
1536     {
1537         ret = 0;
1538     }
1539     return ret;
1540 }
1541
1542 static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1543 {
1544     int width, height;
1545
1546 #ifdef CONFIG_BOCHS_VBE
1547     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1548         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1549         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1550     } else
1551 #endif
1552     {
1553         width = (s->cr[0x01] + 1) * 8;
1554         height = s->cr[0x12] |
1555             ((s->cr[0x07] & 0x02) << 7) |
1556             ((s->cr[0x07] & 0x40) << 3);
1557         height = (height + 1);
1558     }
1559     *pwidth = width;
1560     *pheight = height;
1561 }
1562
1563 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1564 {
1565     int y;
1566     if (y1 >= VGA_MAX_HEIGHT)
1567         return;
1568     if (y2 >= VGA_MAX_HEIGHT)
1569         y2 = VGA_MAX_HEIGHT;
1570     for(y = y1; y < y2; y++) {
1571         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1572     }
1573 }
1574
1575 static void vga_sync_dirty_bitmap(VGACommonState *s)
1576 {
1577     if (s->map_addr)
1578         cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1579
1580     if (s->lfb_vram_mapped) {
1581         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1582         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1583     }
1584
1585 #ifdef CONFIG_BOCHS_VBE
1586     if (s->vbe_mapped) {
1587         cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1588                                        VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1589     }
1590 #endif
1591
1592 }
1593
1594 void vga_dirty_log_start(VGACommonState *s)
1595 {
1596     if (kvm_enabled() && s->map_addr)
1597         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1598
1599     if (kvm_enabled() && s->lfb_vram_mapped) {
1600         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1601         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1602     }
1603
1604 #ifdef CONFIG_BOCHS_VBE
1605     if (kvm_enabled() && s->vbe_mapped) {
1606         kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1607     }
1608 #endif
1609 }
1610
1611 void vga_dirty_log_stop(VGACommonState *s)
1612 {
1613     if (kvm_enabled() && s->map_addr)
1614         kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
1615
1616     if (kvm_enabled() && s->lfb_vram_mapped) {
1617         kvm_log_stop(isa_mem_base + 0xa0000, 0x80000);
1618         kvm_log_stop(isa_mem_base + 0xa8000, 0x80000);
1619     }
1620
1621 #ifdef CONFIG_BOCHS_VBE
1622     if (kvm_enabled() && s->vbe_mapped) {
1623         kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1624     }
1625 #endif
1626 }
1627
1628 void vga_dirty_log_restart(VGACommonState *s)
1629 {
1630     vga_dirty_log_stop(s);
1631     vga_dirty_log_start(s);
1632 }
1633
1634 /*
1635  * graphic modes
1636  */
1637 static void vga_draw_graphic(VGACommonState *s, int full_update)
1638 {
1639     int y1, y, update, linesize, y_start, double_scan, mask, depth;
1640     int width, height, shift_control, line_offset, bwidth, bits;
1641     ram_addr_t page0, page1, page_min, page_max;
1642     int disp_width, multi_scan, multi_run;
1643     uint8_t *d;
1644     uint32_t v, addr1, addr;
1645     vga_draw_line_func *vga_draw_line;
1646
1647     full_update |= update_basic_params(s);
1648
1649     if (!full_update)
1650         vga_sync_dirty_bitmap(s);
1651
1652     s->get_resolution(s, &width, &height);
1653     disp_width = width;
1654
1655     shift_control = (s->gr[0x05] >> 5) & 3;
1656     double_scan = (s->cr[0x09] >> 7);
1657     if (shift_control != 1) {
1658         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1659     } else {
1660         /* in CGA modes, multi_scan is ignored */
1661         /* XXX: is it correct ? */
1662         multi_scan = double_scan;
1663     }
1664     multi_run = multi_scan;
1665     if (shift_control != s->shift_control ||
1666         double_scan != s->double_scan) {
1667         full_update = 1;
1668         s->shift_control = shift_control;
1669         s->double_scan = double_scan;
1670     }
1671
1672     if (shift_control == 0) {
1673         if (s->sr[0x01] & 8) {
1674             disp_width <<= 1;
1675         }
1676     } else if (shift_control == 1) {
1677         if (s->sr[0x01] & 8) {
1678             disp_width <<= 1;
1679         }
1680     }
1681
1682     depth = s->get_bpp(s);
1683     if (s->line_offset != s->last_line_offset ||
1684         disp_width != s->last_width ||
1685         height != s->last_height ||
1686         s->last_depth != depth) {
1687 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1688         if (depth == 16 || depth == 32) {
1689 #else
1690         if (depth == 32) {
1691 #endif
1692             qemu_free_displaysurface(s->ds);
1693             s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1694                     s->line_offset,
1695                     s->vram_ptr + (s->start_addr * 4));
1696 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1697             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1698 #endif
1699             dpy_resize(s->ds);
1700         } else {
1701             qemu_console_resize(s->ds, disp_width, height);
1702         }
1703         s->last_scr_width = disp_width;
1704         s->last_scr_height = height;
1705         s->last_width = disp_width;
1706         s->last_height = height;
1707         s->last_line_offset = s->line_offset;
1708         s->last_depth = depth;
1709         full_update = 1;
1710     } else if (is_buffer_shared(s->ds->surface) &&
1711                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1712         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1713         dpy_setdata(s->ds);
1714     }
1715
1716     s->rgb_to_pixel =
1717         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1718
1719     if (shift_control == 0) {
1720         full_update |= update_palette16(s);
1721         if (s->sr[0x01] & 8) {
1722             v = VGA_DRAW_LINE4D2;
1723         } else {
1724             v = VGA_DRAW_LINE4;
1725         }
1726         bits = 4;
1727     } else if (shift_control == 1) {
1728         full_update |= update_palette16(s);
1729         if (s->sr[0x01] & 8) {
1730             v = VGA_DRAW_LINE2D2;
1731         } else {
1732             v = VGA_DRAW_LINE2;
1733         }
1734         bits = 4;
1735     } else {
1736         switch(s->get_bpp(s)) {
1737         default:
1738         case 0:
1739             full_update |= update_palette256(s);
1740             v = VGA_DRAW_LINE8D2;
1741             bits = 4;
1742             break;
1743         case 8:
1744             full_update |= update_palette256(s);
1745             v = VGA_DRAW_LINE8;
1746             bits = 8;
1747             break;
1748         case 15:
1749             v = VGA_DRAW_LINE15;
1750             bits = 16;
1751             break;
1752         case 16:
1753             v = VGA_DRAW_LINE16;
1754             bits = 16;
1755             break;
1756         case 24:
1757             v = VGA_DRAW_LINE24;
1758             bits = 24;
1759             break;
1760         case 32:
1761             v = VGA_DRAW_LINE32;
1762             bits = 32;
1763             break;
1764         }
1765     }
1766     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1767
1768     if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1769         s->cursor_invalidate(s);
1770
1771     line_offset = s->line_offset;
1772 #if 0
1773     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",
1774            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1775 #endif
1776     addr1 = (s->start_addr * 4);
1777     bwidth = (width * bits + 7) / 8;
1778     y_start = -1;
1779     page_min = -1;
1780     page_max = 0;
1781     d = ds_get_data(s->ds);
1782     linesize = ds_get_linesize(s->ds);
1783     y1 = 0;
1784     for(y = 0; y < height; y++) {
1785         addr = addr1;
1786         if (!(s->cr[0x17] & 1)) {
1787             int shift;
1788             /* CGA compatibility handling */
1789             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1790             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1791         }
1792         if (!(s->cr[0x17] & 2)) {
1793             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1794         }
1795         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1796         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1797         update = full_update |
1798             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1799             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1800         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1801             /* if wide line, can use another page */
1802             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1803                                                     VGA_DIRTY_FLAG);
1804         }
1805         /* explicit invalidation for the hardware cursor */
1806         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1807         if (update) {
1808             if (y_start < 0)
1809                 y_start = y;
1810             if (page0 < page_min)
1811                 page_min = page0;
1812             if (page1 > page_max)
1813                 page_max = page1;
1814             if (!(is_buffer_shared(s->ds->surface))) {
1815                 vga_draw_line(s, d, s->vram_ptr + addr, width);
1816                 if (s->cursor_draw_line)
1817                     s->cursor_draw_line(s, d, y);
1818             }
1819         } else {
1820             if (y_start >= 0) {
1821                 /* flush to display */
1822                 dpy_update(s->ds, 0, y_start,
1823                            disp_width, y - y_start);
1824                 y_start = -1;
1825             }
1826         }
1827         if (!multi_run) {
1828             mask = (s->cr[0x17] & 3) ^ 3;
1829             if ((y1 & mask) == mask)
1830                 addr1 += line_offset;
1831             y1++;
1832             multi_run = multi_scan;
1833         } else {
1834             multi_run--;
1835         }
1836         /* line compare acts on the displayed lines */
1837         if (y == s->line_compare)
1838             addr1 = 0;
1839         d += linesize;
1840     }
1841     if (y_start >= 0) {
1842         /* flush to display */
1843         dpy_update(s->ds, 0, y_start,
1844                    disp_width, y - y_start);
1845     }
1846     /* reset modified pages */
1847     if (page_max >= page_min) {
1848         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1849                                         VGA_DIRTY_FLAG);
1850     }
1851     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1852 }
1853
1854 static void vga_draw_blank(VGACommonState *s, int full_update)
1855 {
1856     int i, w, val;
1857     uint8_t *d;
1858
1859     if (!full_update)
1860         return;
1861     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1862         return;
1863
1864     s->rgb_to_pixel =
1865         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1866     if (ds_get_bits_per_pixel(s->ds) == 8)
1867         val = s->rgb_to_pixel(0, 0, 0);
1868     else
1869         val = 0;
1870     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1871     d = ds_get_data(s->ds);
1872     for(i = 0; i < s->last_scr_height; i++) {
1873         memset(d, val, w);
1874         d += ds_get_linesize(s->ds);
1875     }
1876     dpy_update(s->ds, 0, 0,
1877                s->last_scr_width, s->last_scr_height);
1878 }
1879
1880 #define GMODE_TEXT     0
1881 #define GMODE_GRAPH    1
1882 #define GMODE_BLANK 2
1883
1884 static void vga_update_display(void *opaque)
1885 {
1886     VGACommonState *s = opaque;
1887     int full_update, graphic_mode;
1888
1889     if (ds_get_bits_per_pixel(s->ds) == 0) {
1890         /* nothing to do */
1891     } else {
1892         full_update = 0;
1893         if (!(s->ar_index & 0x20)) {
1894             graphic_mode = GMODE_BLANK;
1895         } else {
1896             graphic_mode = s->gr[6] & 1;
1897         }
1898         if (graphic_mode != s->graphic_mode) {
1899             s->graphic_mode = graphic_mode;
1900             full_update = 1;
1901         }
1902         switch(graphic_mode) {
1903         case GMODE_TEXT:
1904             vga_draw_text(s, full_update);
1905             break;
1906         case GMODE_GRAPH:
1907             vga_draw_graphic(s, full_update);
1908             break;
1909         case GMODE_BLANK:
1910         default:
1911             vga_draw_blank(s, full_update);
1912             break;
1913         }
1914     }
1915 }
1916
1917 /* force a full display refresh */
1918 static void vga_invalidate_display(void *opaque)
1919 {
1920     VGACommonState *s = opaque;
1921
1922     s->last_width = -1;
1923     s->last_height = -1;
1924 }
1925
1926 void vga_common_reset(VGACommonState *s)
1927 {
1928     s->lfb_addr = 0;
1929     s->lfb_end = 0;
1930     s->map_addr = 0;
1931     s->map_end = 0;
1932     s->lfb_vram_mapped = 0;
1933     s->bios_offset = 0;
1934     s->bios_size = 0;
1935     s->sr_index = 0;
1936     memset(s->sr, '\0', sizeof(s->sr));
1937     s->gr_index = 0;
1938     memset(s->gr, '\0', sizeof(s->gr));
1939     s->ar_index = 0;
1940     memset(s->ar, '\0', sizeof(s->ar));
1941     s->ar_flip_flop = 0;
1942     s->cr_index = 0;
1943     memset(s->cr, '\0', sizeof(s->cr));
1944     s->msr = 0;
1945     s->fcr = 0;
1946     s->st00 = 0;
1947     s->st01 = 0;
1948     s->dac_state = 0;
1949     s->dac_sub_index = 0;
1950     s->dac_read_index = 0;
1951     s->dac_write_index = 0;
1952     memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1953     s->dac_8bit = 0;
1954     memset(s->palette, '\0', sizeof(s->palette));
1955     s->bank_offset = 0;
1956 #ifdef CONFIG_BOCHS_VBE
1957     s->vbe_index = 0;
1958     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1959     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1960     s->vbe_start_addr = 0;
1961     s->vbe_line_offset = 0;
1962     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1963 #endif
1964     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1965     s->graphic_mode = -1; /* force full update */
1966     s->shift_control = 0;
1967     s->double_scan = 0;
1968     s->line_offset = 0;
1969     s->line_compare = 0;
1970     s->start_addr = 0;
1971     s->plane_updated = 0;
1972     s->last_cw = 0;
1973     s->last_ch = 0;
1974     s->last_width = 0;
1975     s->last_height = 0;
1976     s->last_scr_width = 0;
1977     s->last_scr_height = 0;
1978     s->cursor_start = 0;
1979     s->cursor_end = 0;
1980     s->cursor_offset = 0;
1981     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1982     memset(s->last_palette, '\0', sizeof(s->last_palette));
1983     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1984     switch (vga_retrace_method) {
1985     case VGA_RETRACE_DUMB:
1986         break;
1987     case VGA_RETRACE_PRECISE:
1988         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1989         break;
1990     }
1991 }
1992
1993 static void vga_reset(void *opaque)
1994 {
1995     VGACommonState *s =  opaque;
1996     vga_common_reset(s);
1997 }
1998
1999 #define TEXTMODE_X(x)   ((x) % width)
2000 #define TEXTMODE_Y(x)   ((x) / width)
2001 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
2002         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2003 /* relay text rendering to the display driver
2004  * instead of doing a full vga_update_display() */
2005 static void vga_update_text(void *opaque, console_ch_t *chardata)
2006 {
2007     VGACommonState *s =  opaque;
2008     int graphic_mode, i, cursor_offset, cursor_visible;
2009     int cw, cheight, width, height, size, c_min, c_max;
2010     uint32_t *src;
2011     console_ch_t *dst, val;
2012     char msg_buffer[80];
2013     int full_update = 0;
2014
2015     if (!(s->ar_index & 0x20)) {
2016         graphic_mode = GMODE_BLANK;
2017     } else {
2018         graphic_mode = s->gr[6] & 1;
2019     }
2020     if (graphic_mode != s->graphic_mode) {
2021         s->graphic_mode = graphic_mode;
2022         full_update = 1;
2023     }
2024     if (s->last_width == -1) {
2025         s->last_width = 0;
2026         full_update = 1;
2027     }
2028
2029     switch (graphic_mode) {
2030     case GMODE_TEXT:
2031         /* TODO: update palette */
2032         full_update |= update_basic_params(s);
2033
2034         /* total width & height */
2035         cheight = (s->cr[9] & 0x1f) + 1;
2036         cw = 8;
2037         if (!(s->sr[1] & 0x01))
2038             cw = 9;
2039         if (s->sr[1] & 0x08)
2040             cw = 16; /* NOTE: no 18 pixel wide */
2041         width = (s->cr[0x01] + 1);
2042         if (s->cr[0x06] == 100) {
2043             /* ugly hack for CGA 160x100x16 - explain me the logic */
2044             height = 100;
2045         } else {
2046             height = s->cr[0x12] | 
2047                 ((s->cr[0x07] & 0x02) << 7) | 
2048                 ((s->cr[0x07] & 0x40) << 3);
2049             height = (height + 1) / cheight;
2050         }
2051
2052         size = (height * width);
2053         if (size > CH_ATTR_SIZE) {
2054             if (!full_update)
2055                 return;
2056
2057             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2058                      width, height);
2059             break;
2060         }
2061
2062         if (width != s->last_width || height != s->last_height ||
2063             cw != s->last_cw || cheight != s->last_ch) {
2064             s->last_scr_width = width * cw;
2065             s->last_scr_height = height * cheight;
2066             s->ds->surface->width = width;
2067             s->ds->surface->height = height;
2068             dpy_resize(s->ds);
2069             s->last_width = width;
2070             s->last_height = height;
2071             s->last_ch = cheight;
2072             s->last_cw = cw;
2073             full_update = 1;
2074         }
2075
2076         /* Update "hardware" cursor */
2077         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2078         if (cursor_offset != s->cursor_offset ||
2079             s->cr[0xa] != s->cursor_start ||
2080             s->cr[0xb] != s->cursor_end || full_update) {
2081             cursor_visible = !(s->cr[0xa] & 0x20);
2082             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2083                 dpy_cursor(s->ds,
2084                            TEXTMODE_X(cursor_offset),
2085                            TEXTMODE_Y(cursor_offset));
2086             else
2087                 dpy_cursor(s->ds, -1, -1);
2088             s->cursor_offset = cursor_offset;
2089             s->cursor_start = s->cr[0xa];
2090             s->cursor_end = s->cr[0xb];
2091         }
2092
2093         src = (uint32_t *) s->vram_ptr + s->start_addr;
2094         dst = chardata;
2095
2096         if (full_update) {
2097             for (i = 0; i < size; src ++, dst ++, i ++)
2098                 console_write_ch(dst, VMEM2CHTYPE(*src));
2099
2100             dpy_update(s->ds, 0, 0, width, height);
2101         } else {
2102             c_max = 0;
2103
2104             for (i = 0; i < size; src ++, dst ++, i ++) {
2105                 console_write_ch(&val, VMEM2CHTYPE(*src));
2106                 if (*dst != val) {
2107                     *dst = val;
2108                     c_max = i;
2109                     break;
2110                 }
2111             }
2112             c_min = i;
2113             for (; i < size; src ++, dst ++, i ++) {
2114                 console_write_ch(&val, VMEM2CHTYPE(*src));
2115                 if (*dst != val) {
2116                     *dst = val;
2117                     c_max = i;
2118                 }
2119             }
2120
2121             if (c_min <= c_max) {
2122                 i = TEXTMODE_Y(c_min);
2123                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2124             }
2125         }
2126
2127         return;
2128     case GMODE_GRAPH:
2129         if (!full_update)
2130             return;
2131
2132         s->get_resolution(s, &width, &height);
2133         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2134                  width, height);
2135         break;
2136     case GMODE_BLANK:
2137     default:
2138         if (!full_update)
2139             return;
2140
2141         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2142         break;
2143     }
2144
2145     /* Display a message */
2146     s->last_width = 60;
2147     s->last_height = height = 3;
2148     dpy_cursor(s->ds, -1, -1);
2149     s->ds->surface->width = s->last_width;
2150     s->ds->surface->height = height;
2151     dpy_resize(s->ds);
2152
2153     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2154         console_write_ch(dst ++, ' ');
2155
2156     size = strlen(msg_buffer);
2157     width = (s->last_width - size) / 2;
2158     dst = chardata + s->last_width + width;
2159     for (i = 0; i < size; i ++)
2160         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2161
2162     dpy_update(s->ds, 0, 0, s->last_width, height);
2163 }
2164
2165 CPUReadMemoryFunc * const vga_mem_read[3] = {
2166     vga_mem_readb,
2167     vga_mem_readw,
2168     vga_mem_readl,
2169 };
2170
2171 CPUWriteMemoryFunc * const vga_mem_write[3] = {
2172     vga_mem_writeb,
2173     vga_mem_writew,
2174     vga_mem_writel,
2175 };
2176
2177 static int vga_common_post_load(void *opaque, int version_id)
2178 {
2179     VGACommonState *s = opaque;
2180
2181     /* force refresh */
2182     s->graphic_mode = -1;
2183     return 0;
2184 }
2185
2186 const VMStateDescription vmstate_vga_common = {
2187     .name = "vga",
2188     .version_id = 2,
2189     .minimum_version_id = 2,
2190     .minimum_version_id_old = 2,
2191     .post_load = vga_common_post_load,
2192     .fields      = (VMStateField []) {
2193         VMSTATE_UINT32(latch, VGACommonState),
2194         VMSTATE_UINT8(sr_index, VGACommonState),
2195         VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2196         VMSTATE_UINT8(gr_index, VGACommonState),
2197         VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2198         VMSTATE_UINT8(ar_index, VGACommonState),
2199         VMSTATE_BUFFER(ar, VGACommonState),
2200         VMSTATE_INT32(ar_flip_flop, VGACommonState),
2201         VMSTATE_UINT8(cr_index, VGACommonState),
2202         VMSTATE_BUFFER(cr, VGACommonState),
2203         VMSTATE_UINT8(msr, VGACommonState),
2204         VMSTATE_UINT8(fcr, VGACommonState),
2205         VMSTATE_UINT8(st00, VGACommonState),
2206         VMSTATE_UINT8(st01, VGACommonState),
2207
2208         VMSTATE_UINT8(dac_state, VGACommonState),
2209         VMSTATE_UINT8(dac_sub_index, VGACommonState),
2210         VMSTATE_UINT8(dac_read_index, VGACommonState),
2211         VMSTATE_UINT8(dac_write_index, VGACommonState),
2212         VMSTATE_BUFFER(dac_cache, VGACommonState),
2213         VMSTATE_BUFFER(palette, VGACommonState),
2214
2215         VMSTATE_INT32(bank_offset, VGACommonState),
2216         VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2217 #ifdef CONFIG_BOCHS_VBE
2218         VMSTATE_UINT16(vbe_index, VGACommonState),
2219         VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2220         VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2221         VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2222         VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2223 #endif
2224         VMSTATE_END_OF_LIST()
2225     }
2226 };
2227
2228 void vga_common_init(VGACommonState *s, int vga_ram_size)
2229 {
2230     int i, j, v, b;
2231
2232     for(i = 0;i < 256; i++) {
2233         v = 0;
2234         for(j = 0; j < 8; j++) {
2235             v |= ((i >> j) & 1) << (j * 4);
2236         }
2237         expand4[i] = v;
2238
2239         v = 0;
2240         for(j = 0; j < 4; j++) {
2241             v |= ((i >> (2 * j)) & 3) << (j * 4);
2242         }
2243         expand2[i] = v;
2244     }
2245     for(i = 0; i < 16; i++) {
2246         v = 0;
2247         for(j = 0; j < 4; j++) {
2248             b = ((i >> j) & 1);
2249             v |= b << (2 * j);
2250             v |= b << (2 * j + 1);
2251         }
2252         expand4to8[i] = v;
2253     }
2254
2255 #ifdef CONFIG_BOCHS_VBE
2256     s->is_vbe_vmstate = 1;
2257 #else
2258     s->is_vbe_vmstate = 0;
2259 #endif
2260     s->vram_offset = qemu_ram_alloc(vga_ram_size);
2261     s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2262     s->vram_size = vga_ram_size;
2263     s->get_bpp = vga_get_bpp;
2264     s->get_offsets = vga_get_offsets;
2265     s->get_resolution = vga_get_resolution;
2266     s->update = vga_update_display;
2267     s->invalidate = vga_invalidate_display;
2268     s->screen_dump = vga_screen_dump;
2269     s->text_update = vga_update_text;
2270     switch (vga_retrace_method) {
2271     case VGA_RETRACE_DUMB:
2272         s->retrace = vga_dumb_retrace;
2273         s->update_retrace_info = vga_dumb_update_retrace_info;
2274         break;
2275
2276     case VGA_RETRACE_PRECISE:
2277         s->retrace = vga_precise_retrace;
2278         s->update_retrace_info = vga_precise_update_retrace_info;
2279         break;
2280     }
2281 }
2282
2283 /* used by both ISA and PCI */
2284 void vga_init(VGACommonState *s)
2285 {
2286     int vga_io_memory;
2287
2288     qemu_register_reset(vga_reset, s);
2289
2290     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2291
2292     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2293     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2294     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2295     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2296
2297     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2298
2299     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2300     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2301     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2302     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2303     s->bank_offset = 0;
2304
2305 #ifdef CONFIG_BOCHS_VBE
2306 #if defined (TARGET_I386)
2307     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2308     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2309
2310     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2311     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2312
2313     /* old Bochs IO ports */
2314     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2315     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2316
2317     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2318     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2319 #else
2320     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2321     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2322
2323     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2324     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2325 #endif
2326 #endif /* CONFIG_BOCHS_VBE */
2327
2328     vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2329     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2330                                  vga_io_memory);
2331     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2332 }
2333
2334 void vga_init_vbe(VGACommonState *s)
2335 {
2336 #ifdef CONFIG_BOCHS_VBE
2337     /* XXX: use optimized standard vga accesses */
2338     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2339                                  VGA_RAM_SIZE, s->vram_offset);
2340     s->vbe_mapped = 1;
2341 #endif 
2342 }
2343 /********************************************************/
2344 /* vga screen dump */
2345
2346 static void vga_save_dpy_update(DisplayState *ds,
2347                                 int x, int y, int w, int h)
2348 {
2349     if (screen_dump_filename) {
2350         ppm_save(screen_dump_filename, ds->surface);
2351         screen_dump_filename = NULL;
2352     }
2353 }
2354
2355 static void vga_save_dpy_resize(DisplayState *s)
2356 {
2357 }
2358
2359 static void vga_save_dpy_refresh(DisplayState *s)
2360 {
2361 }
2362
2363 int ppm_save(const char *filename, struct DisplaySurface *ds)
2364 {
2365     FILE *f;
2366     uint8_t *d, *d1;
2367     uint32_t v;
2368     int y, x;
2369     uint8_t r, g, b;
2370
2371     f = fopen(filename, "wb");
2372     if (!f)
2373         return -1;
2374     fprintf(f, "P6\n%d %d\n%d\n",
2375             ds->width, ds->height, 255);
2376     d1 = ds->data;
2377     for(y = 0; y < ds->height; y++) {
2378         d = d1;
2379         for(x = 0; x < ds->width; x++) {
2380             if (ds->pf.bits_per_pixel == 32)
2381                 v = *(uint32_t *)d;
2382             else
2383                 v = (uint32_t) (*(uint16_t *)d);
2384             r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2385                 (ds->pf.rmax + 1);
2386             g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2387                 (ds->pf.gmax + 1);
2388             b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2389                 (ds->pf.bmax + 1);
2390             fputc(r, f);
2391             fputc(g, f);
2392             fputc(b, f);
2393             d += ds->pf.bytes_per_pixel;
2394         }
2395         d1 += ds->linesize;
2396     }
2397     fclose(f);
2398     return 0;
2399 }
2400
2401 static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2402 {
2403     DisplayChangeListener *dcl;
2404
2405     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2406     dcl->dpy_update = vga_save_dpy_update;
2407     dcl->dpy_resize = vga_save_dpy_resize;
2408     dcl->dpy_refresh = vga_save_dpy_refresh;
2409     register_displaychangelistener(ds, dcl);
2410     return dcl;
2411 }
2412
2413 /* save the vga display in a PPM image even if no display is
2414    available */
2415 static void vga_screen_dump(void *opaque, const char *filename)
2416 {
2417     VGACommonState *s = opaque;
2418
2419     if (!screen_dump_dcl)
2420         screen_dump_dcl = vga_screen_dump_init(s->ds);
2421
2422     screen_dump_filename = (char *)filename;
2423     vga_invalidate_display(s);
2424     vga_hw_update();
2425 }
2426
This page took 0.159295 seconds and 4 git commands to generate.