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