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