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