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