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