hw/ppc: Clean up local variable shadowing in _FDT helper routine
[qemu/kevin.git] / hw / display / vga.c
blob37557c3442aa8b709e74930502ed3a573da3d222
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/core/cpu.h"
30 #include "hw/display/vga.h"
31 #include "hw/i386/x86.h"
32 #include "hw/pci/pci.h"
33 #include "vga_int.h"
34 #include "vga_regs.h"
35 #include "ui/pixel_ops.h"
36 #include "ui/console.h"
37 #include "qemu/timer.h"
38 #include "hw/xen/xen.h"
39 #include "migration/vmstate.h"
40 #include "trace.h"
42 //#define DEBUG_VGA_MEM
43 //#define DEBUG_VGA_REG
45 bool have_vga = true;
47 /* 16 state changes per vertical frame @60 Hz */
48 #define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60)
51 * Video Graphics Array (VGA)
53 * Chipset docs for original IBM VGA:
54 * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
56 * FreeVGA site:
57 * http://www.osdever.net/FreeVGA/home.htm
59 * Standard VGA features and Bochs VBE extensions are implemented.
62 /* force some bits to zero */
63 const uint8_t sr_mask[8] = {
64 0x03,
65 0x3d,
66 0x0f,
67 0x3f,
68 0x0e,
69 0x00,
70 0x00,
71 0xff,
74 const uint8_t gr_mask[16] = {
75 0x0f, /* 0x00 */
76 0x0f, /* 0x01 */
77 0x0f, /* 0x02 */
78 0x1f, /* 0x03 */
79 0x03, /* 0x04 */
80 0x7b, /* 0x05 */
81 0x0f, /* 0x06 */
82 0x0f, /* 0x07 */
83 0xff, /* 0x08 */
84 0x00, /* 0x09 */
85 0x00, /* 0x0a */
86 0x00, /* 0x0b */
87 0x00, /* 0x0c */
88 0x00, /* 0x0d */
89 0x00, /* 0x0e */
90 0x00, /* 0x0f */
93 #define cbswap_32(__x) \
94 ((uint32_t)( \
95 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
96 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
97 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
98 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
100 #if HOST_BIG_ENDIAN
101 #define PAT(x) cbswap_32(x)
102 #else
103 #define PAT(x) (x)
104 #endif
106 #if HOST_BIG_ENDIAN
107 #define BIG 1
108 #else
109 #define BIG 0
110 #endif
112 #if HOST_BIG_ENDIAN
113 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
114 #else
115 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
116 #endif
118 static const uint32_t mask16[16] = {
119 PAT(0x00000000),
120 PAT(0x000000ff),
121 PAT(0x0000ff00),
122 PAT(0x0000ffff),
123 PAT(0x00ff0000),
124 PAT(0x00ff00ff),
125 PAT(0x00ffff00),
126 PAT(0x00ffffff),
127 PAT(0xff000000),
128 PAT(0xff0000ff),
129 PAT(0xff00ff00),
130 PAT(0xff00ffff),
131 PAT(0xffff0000),
132 PAT(0xffff00ff),
133 PAT(0xffffff00),
134 PAT(0xffffffff),
137 #undef PAT
139 #if HOST_BIG_ENDIAN
140 #define PAT(x) (x)
141 #else
142 #define PAT(x) cbswap_32(x)
143 #endif
145 static uint32_t expand4[256];
146 static uint16_t expand2[256];
147 static uint8_t expand4to8[16];
149 static void vbe_update_vgaregs(VGACommonState *s);
151 static inline bool vbe_enabled(VGACommonState *s)
153 return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
156 static inline uint8_t sr(VGACommonState *s, int idx)
158 return vbe_enabled(s) ? s->sr_vbe[idx] : s->sr[idx];
161 static void vga_update_memory_access(VGACommonState *s)
163 hwaddr base, offset, size;
165 if (s->legacy_address_space == NULL) {
166 return;
169 if (s->has_chain4_alias) {
170 memory_region_del_subregion(s->legacy_address_space, &s->chain4_alias);
171 object_unparent(OBJECT(&s->chain4_alias));
172 s->has_chain4_alias = false;
173 s->plane_updated = 0xf;
175 if ((sr(s, VGA_SEQ_PLANE_WRITE) & VGA_SR02_ALL_PLANES) ==
176 VGA_SR02_ALL_PLANES && sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
177 offset = 0;
178 switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
179 case 0:
180 base = 0xa0000;
181 size = 0x20000;
182 break;
183 case 1:
184 base = 0xa0000;
185 size = 0x10000;
186 offset = s->bank_offset;
187 break;
188 case 2:
189 base = 0xb0000;
190 size = 0x8000;
191 break;
192 case 3:
193 default:
194 base = 0xb8000;
195 size = 0x8000;
196 break;
198 assert(offset + size <= s->vram_size);
199 memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
200 "vga.chain4", &s->vram, offset, size);
201 memory_region_add_subregion_overlap(s->legacy_address_space, base,
202 &s->chain4_alias, 2);
203 s->has_chain4_alias = true;
207 static void vga_dumb_update_retrace_info(VGACommonState *s)
209 (void) s;
212 static void vga_precise_update_retrace_info(VGACommonState *s)
214 int htotal_chars;
215 int hretr_start_char;
216 int hretr_skew_chars;
217 int hretr_end_char;
219 int vtotal_lines;
220 int vretr_start_line;
221 int vretr_end_line;
223 int dots;
224 #if 0
225 int div2, sldiv2;
226 #endif
227 int clocking_mode;
228 int clock_sel;
229 const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
230 int64_t chars_per_sec;
231 struct vga_precise_retrace *r = &s->retrace_info.precise;
233 htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
234 hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
235 hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
236 hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
238 vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
239 (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
240 ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
241 vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
242 ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
243 ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
244 vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
246 clocking_mode = (sr(s, VGA_SEQ_CLOCK_MODE) >> 3) & 1;
247 clock_sel = (s->msr >> 2) & 3;
248 dots = (s->msr & 1) ? 8 : 9;
250 chars_per_sec = clk_hz[clock_sel] / dots;
252 htotal_chars <<= clocking_mode;
254 r->total_chars = vtotal_lines * htotal_chars;
255 if (r->freq) {
256 r->ticks_per_char = NANOSECONDS_PER_SECOND / (r->total_chars * r->freq);
257 } else {
258 r->ticks_per_char = NANOSECONDS_PER_SECOND / chars_per_sec;
261 r->vstart = vretr_start_line;
262 r->vend = r->vstart + vretr_end_line + 1;
264 r->hstart = hretr_start_char + hretr_skew_chars;
265 r->hend = r->hstart + hretr_end_char + 1;
266 r->htotal = htotal_chars;
268 #if 0
269 div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
270 sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
271 printf (
272 "hz=%f\n"
273 "htotal = %d\n"
274 "hretr_start = %d\n"
275 "hretr_skew = %d\n"
276 "hretr_end = %d\n"
277 "vtotal = %d\n"
278 "vretr_start = %d\n"
279 "vretr_end = %d\n"
280 "div2 = %d sldiv2 = %d\n"
281 "clocking_mode = %d\n"
282 "clock_sel = %d %d\n"
283 "dots = %d\n"
284 "ticks/char = %" PRId64 "\n"
285 "\n",
286 (double) NANOSECONDS_PER_SECOND / (r->ticks_per_char * r->total_chars),
287 htotal_chars,
288 hretr_start_char,
289 hretr_skew_chars,
290 hretr_end_char,
291 vtotal_lines,
292 vretr_start_line,
293 vretr_end_line,
294 div2, sldiv2,
295 clocking_mode,
296 clock_sel,
297 clk_hz[clock_sel],
298 dots,
299 r->ticks_per_char
301 #endif
304 static uint8_t vga_precise_retrace(VGACommonState *s)
306 struct vga_precise_retrace *r = &s->retrace_info.precise;
307 uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
309 if (r->total_chars) {
310 int cur_line, cur_line_char, cur_char;
311 int64_t cur_tick;
313 cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
315 cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
316 cur_line = cur_char / r->htotal;
318 if (cur_line >= r->vstart && cur_line <= r->vend) {
319 val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
320 } else {
321 cur_line_char = cur_char % r->htotal;
322 if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
323 val |= ST01_DISP_ENABLE;
327 return val;
328 } else {
329 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
333 static uint8_t vga_dumb_retrace(VGACommonState *s)
335 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
338 int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
340 if (s->msr & VGA_MIS_COLOR) {
341 /* Color */
342 return (addr >= 0x3b0 && addr <= 0x3bf);
343 } else {
344 /* Monochrome */
345 return (addr >= 0x3d0 && addr <= 0x3df);
349 uint32_t vga_ioport_read(void *opaque, uint32_t addr)
351 VGACommonState *s = opaque;
352 int val, index;
354 if (vga_ioport_invalid(s, addr)) {
355 val = 0xff;
356 } else {
357 switch(addr) {
358 case VGA_ATT_W:
359 if (s->ar_flip_flop == 0) {
360 val = s->ar_index;
361 } else {
362 val = 0;
364 break;
365 case VGA_ATT_R:
366 index = s->ar_index & 0x1f;
367 if (index < VGA_ATT_C) {
368 val = s->ar[index];
369 } else {
370 val = 0;
372 break;
373 case VGA_MIS_W:
374 val = s->st00;
375 break;
376 case VGA_SEQ_I:
377 val = s->sr_index;
378 break;
379 case VGA_SEQ_D:
380 val = s->sr[s->sr_index];
381 #ifdef DEBUG_VGA_REG
382 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
383 #endif
384 break;
385 case VGA_PEL_IR:
386 val = s->dac_state;
387 break;
388 case VGA_PEL_IW:
389 val = s->dac_write_index;
390 break;
391 case VGA_PEL_D:
392 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
393 if (++s->dac_sub_index == 3) {
394 s->dac_sub_index = 0;
395 s->dac_read_index++;
397 break;
398 case VGA_FTC_R:
399 val = s->fcr;
400 break;
401 case VGA_MIS_R:
402 val = s->msr;
403 break;
404 case VGA_GFX_I:
405 val = s->gr_index;
406 break;
407 case VGA_GFX_D:
408 val = s->gr[s->gr_index];
409 #ifdef DEBUG_VGA_REG
410 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
411 #endif
412 break;
413 case VGA_CRT_IM:
414 case VGA_CRT_IC:
415 val = s->cr_index;
416 break;
417 case VGA_CRT_DM:
418 case VGA_CRT_DC:
419 val = s->cr[s->cr_index];
420 #ifdef DEBUG_VGA_REG
421 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
422 #endif
423 break;
424 case VGA_IS1_RM:
425 case VGA_IS1_RC:
426 /* just toggle to fool polling */
427 val = s->st01 = s->retrace(s);
428 s->ar_flip_flop = 0;
429 break;
430 default:
431 val = 0x00;
432 break;
435 trace_vga_std_read_io(addr, val);
436 return val;
439 void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
441 VGACommonState *s = opaque;
442 int index;
444 /* check port range access depending on color/monochrome mode */
445 if (vga_ioport_invalid(s, addr)) {
446 return;
448 trace_vga_std_write_io(addr, val);
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;
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);
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++;
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);
546 return;
548 s->cr[s->cr_index] = val;
549 vbe_update_vgaregs(s);
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;
562 break;
563 case VGA_IS1_RM:
564 case VGA_IS1_RC:
565 s->fcr = val & 0x10;
566 break;
571 * Sanity check vbe register writes.
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.
577 static void vbe_fixup_regs(VGACommonState *s)
579 uint16_t *r = s->vbe_regs;
580 uint32_t bits, linelength, maxy, offset;
582 if (!vbe_enabled(s)) {
583 /* vbe is turned off -- nothing to do */
584 return;
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;
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;
609 if (r[VBE_DISPI_INDEX_XRES] > VBE_DISPI_MAX_XRES) {
610 r[VBE_DISPI_INDEX_XRES] = VBE_DISPI_MAX_XRES;
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;
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];
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;
626 if (r[VBE_DISPI_INDEX_YRES] > VBE_DISPI_MAX_YRES) {
627 r[VBE_DISPI_INDEX_YRES] = VBE_DISPI_MAX_YRES;
629 if (r[VBE_DISPI_INDEX_YRES] > maxy) {
630 r[VBE_DISPI_INDEX_YRES] = maxy;
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;
637 if (r[VBE_DISPI_INDEX_Y_OFFSET] > VBE_DISPI_MAX_YRES) {
638 r[VBE_DISPI_INDEX_Y_OFFSET] = VBE_DISPI_MAX_YRES;
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;
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;
657 /* we initialize the VGA graphic mode */
658 static void vbe_update_vgaregs(VGACommonState *s)
660 int h, shift_control;
662 if (!vbe_enabled(s)) {
663 /* vbe is turned off -- nothing to do */
664 return;
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;
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;
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 */
700 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
702 VGACommonState *s = opaque;
703 return s->vbe_index;
706 uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
708 VGACommonState *s = opaque;
709 uint32_t val;
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;
728 } else {
729 val = s->vbe_regs[s->vbe_index];
731 } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
732 val = s->vbe_size / (64 * KiB);
733 } else {
734 val = 0;
736 trace_vga_vbe_read(s->vbe_index, val);
737 return val;
740 void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
742 VGACommonState *s = opaque;
743 s->vbe_index = val;
746 void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
748 VGACommonState *s = opaque;
750 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
751 trace_vga_vbe_write(s->vbe_index, val);
752 switch(s->vbe_index) {
753 case VBE_DISPI_INDEX_ID:
754 if (val == VBE_DISPI_ID0 ||
755 val == VBE_DISPI_ID1 ||
756 val == VBE_DISPI_ID2 ||
757 val == VBE_DISPI_ID3 ||
758 val == VBE_DISPI_ID4 ||
759 val == VBE_DISPI_ID5) {
760 s->vbe_regs[s->vbe_index] = val;
762 break;
763 case VBE_DISPI_INDEX_XRES:
764 case VBE_DISPI_INDEX_YRES:
765 case VBE_DISPI_INDEX_BPP:
766 case VBE_DISPI_INDEX_VIRT_WIDTH:
767 case VBE_DISPI_INDEX_X_OFFSET:
768 case VBE_DISPI_INDEX_Y_OFFSET:
769 s->vbe_regs[s->vbe_index] = val;
770 vbe_fixup_regs(s);
771 vbe_update_vgaregs(s);
772 break;
773 case VBE_DISPI_INDEX_BANK:
774 val &= s->vbe_bank_mask;
775 s->vbe_regs[s->vbe_index] = val;
776 s->bank_offset = (val << 16);
777 vga_update_memory_access(s);
778 break;
779 case VBE_DISPI_INDEX_ENABLE:
780 if ((val & VBE_DISPI_ENABLED) &&
781 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
783 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;
784 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
785 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
786 s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
787 vbe_fixup_regs(s);
788 vbe_update_vgaregs(s);
790 /* clear the screen */
791 if (!(val & VBE_DISPI_NOCLEARMEM)) {
792 memset(s->vram_ptr, 0,
793 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
795 } else {
796 s->bank_offset = 0;
798 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
799 s->vbe_regs[s->vbe_index] = val;
800 vga_update_memory_access(s);
801 break;
802 default:
803 break;
808 /* called for accesses between 0xa0000 and 0xc0000 */
809 uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
811 int memory_map_mode, plane;
812 uint32_t ret;
814 /* convert to VGA memory offset */
815 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
816 addr &= 0x1ffff;
817 switch(memory_map_mode) {
818 case 0:
819 break;
820 case 1:
821 if (addr >= 0x10000)
822 return 0xff;
823 addr += s->bank_offset;
824 break;
825 case 2:
826 addr -= 0x10000;
827 if (addr >= 0x8000)
828 return 0xff;
829 break;
830 default:
831 case 3:
832 addr -= 0x18000;
833 if (addr >= 0x8000)
834 return 0xff;
835 break;
838 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
839 /* chain 4 mode : simplest access */
840 assert(addr < s->vram_size);
841 ret = s->vram_ptr[addr];
842 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
843 /* odd/even mode (aka text mode mapping) */
844 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
845 addr = ((addr & ~1) << 1) | plane;
846 if (addr >= s->vram_size) {
847 return 0xff;
849 ret = s->vram_ptr[addr];
850 } else {
851 /* standard VGA latched access */
852 if (addr * sizeof(uint32_t) >= s->vram_size) {
853 return 0xff;
855 s->latch = ((uint32_t *)s->vram_ptr)[addr];
857 if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
858 /* read mode 0 */
859 plane = s->gr[VGA_GFX_PLANE_READ];
860 ret = GET_PLANE(s->latch, plane);
861 } else {
862 /* read mode 1 */
863 ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
864 mask16[s->gr[VGA_GFX_COMPARE_MASK]];
865 ret |= ret >> 16;
866 ret |= ret >> 8;
867 ret = (~ret) & 0xff;
870 return ret;
873 /* called for accesses between 0xa0000 and 0xc0000 */
874 void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
876 int memory_map_mode, plane, write_mode, b, func_select, mask;
877 uint32_t write_mask, bit_mask, set_mask;
879 #ifdef DEBUG_VGA_MEM
880 printf("vga: [0x" HWADDR_FMT_plx "] = 0x%02x\n", addr, val);
881 #endif
882 /* convert to VGA memory offset */
883 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
884 addr &= 0x1ffff;
885 switch(memory_map_mode) {
886 case 0:
887 break;
888 case 1:
889 if (addr >= 0x10000)
890 return;
891 addr += s->bank_offset;
892 break;
893 case 2:
894 addr -= 0x10000;
895 if (addr >= 0x8000)
896 return;
897 break;
898 default:
899 case 3:
900 addr -= 0x18000;
901 if (addr >= 0x8000)
902 return;
903 break;
906 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
907 /* chain 4 mode : simplest access */
908 plane = addr & 3;
909 mask = (1 << plane);
910 if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
911 assert(addr < s->vram_size);
912 s->vram_ptr[addr] = val;
913 #ifdef DEBUG_VGA_MEM
914 printf("vga: chain4: [0x" HWADDR_FMT_plx "]\n", addr);
915 #endif
916 s->plane_updated |= mask; /* only used to detect font change */
917 memory_region_set_dirty(&s->vram, addr, 1);
919 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
920 /* odd/even mode (aka text mode mapping) */
921 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
922 mask = (1 << plane);
923 if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
924 addr = ((addr & ~1) << 1) | plane;
925 if (addr >= s->vram_size) {
926 return;
928 s->vram_ptr[addr] = val;
929 #ifdef DEBUG_VGA_MEM
930 printf("vga: odd/even: [0x" HWADDR_FMT_plx "]\n", addr);
931 #endif
932 s->plane_updated |= mask; /* only used to detect font change */
933 memory_region_set_dirty(&s->vram, addr, 1);
935 } else {
936 /* standard VGA latched access */
937 write_mode = s->gr[VGA_GFX_MODE] & 3;
938 switch(write_mode) {
939 default:
940 case 0:
941 /* rotate */
942 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
943 val = ((val >> b) | (val << (8 - b))) & 0xff;
944 val |= val << 8;
945 val |= val << 16;
947 /* apply set/reset mask */
948 set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
949 val = (val & ~set_mask) |
950 (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
951 bit_mask = s->gr[VGA_GFX_BIT_MASK];
952 break;
953 case 1:
954 val = s->latch;
955 goto do_write;
956 case 2:
957 val = mask16[val & 0x0f];
958 bit_mask = s->gr[VGA_GFX_BIT_MASK];
959 break;
960 case 3:
961 /* rotate */
962 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
963 val = (val >> b) | (val << (8 - b));
965 bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
966 val = mask16[s->gr[VGA_GFX_SR_VALUE]];
967 break;
970 /* apply logical operation */
971 func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
972 switch(func_select) {
973 case 0:
974 default:
975 /* nothing to do */
976 break;
977 case 1:
978 /* and */
979 val &= s->latch;
980 break;
981 case 2:
982 /* or */
983 val |= s->latch;
984 break;
985 case 3:
986 /* xor */
987 val ^= s->latch;
988 break;
991 /* apply bit mask */
992 bit_mask |= bit_mask << 8;
993 bit_mask |= bit_mask << 16;
994 val = (val & bit_mask) | (s->latch & ~bit_mask);
996 do_write:
997 /* mask data according to sr[2] */
998 mask = sr(s, VGA_SEQ_PLANE_WRITE);
999 s->plane_updated |= mask; /* only used to detect font change */
1000 write_mask = mask16[mask];
1001 if (addr * sizeof(uint32_t) >= s->vram_size) {
1002 return;
1004 ((uint32_t *)s->vram_ptr)[addr] =
1005 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
1006 (val & write_mask);
1007 #ifdef DEBUG_VGA_MEM
1008 printf("vga: latch: [0x" HWADDR_FMT_plx "] mask=0x%08x val=0x%08x\n",
1009 addr * 4, write_mask, val);
1010 #endif
1011 memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
1015 typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
1016 uint32_t srcaddr, int width);
1018 #include "vga-access.h"
1019 #include "vga-helpers.h"
1021 /* return true if the palette was modified */
1022 static int update_palette16(VGACommonState *s)
1024 int full_update, i;
1025 uint32_t v, col, *palette;
1027 full_update = 0;
1028 palette = s->last_palette;
1029 for(i = 0; i < 16; i++) {
1030 v = s->ar[i];
1031 if (s->ar[VGA_ATC_MODE] & 0x80) {
1032 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
1033 } else {
1034 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
1036 v = v * 3;
1037 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1038 c6_to_8(s->palette[v + 1]),
1039 c6_to_8(s->palette[v + 2]));
1040 if (col != palette[i]) {
1041 full_update = 1;
1042 palette[i] = col;
1045 return full_update;
1048 /* return true if the palette was modified */
1049 static int update_palette256(VGACommonState *s)
1051 int full_update, i;
1052 uint32_t v, col, *palette;
1054 full_update = 0;
1055 palette = s->last_palette;
1056 v = 0;
1057 for(i = 0; i < 256; i++) {
1058 if (s->dac_8bit) {
1059 col = rgb_to_pixel32(s->palette[v],
1060 s->palette[v + 1],
1061 s->palette[v + 2]);
1062 } else {
1063 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1064 c6_to_8(s->palette[v + 1]),
1065 c6_to_8(s->palette[v + 2]));
1067 if (col != palette[i]) {
1068 full_update = 1;
1069 palette[i] = col;
1071 v += 3;
1073 return full_update;
1076 static void vga_get_offsets(VGACommonState *s,
1077 uint32_t *pline_offset,
1078 uint32_t *pstart_addr,
1079 uint32_t *pline_compare)
1081 uint32_t start_addr, line_offset, line_compare;
1083 if (vbe_enabled(s)) {
1084 line_offset = s->vbe_line_offset;
1085 start_addr = s->vbe_start_addr;
1086 line_compare = 65535;
1087 } else {
1088 /* compute line_offset in bytes */
1089 line_offset = s->cr[VGA_CRTC_OFFSET];
1090 line_offset <<= 3;
1092 /* starting address */
1093 start_addr = s->cr[VGA_CRTC_START_LO] |
1094 (s->cr[VGA_CRTC_START_HI] << 8);
1096 /* line compare */
1097 line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
1098 ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
1099 ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
1101 *pline_offset = line_offset;
1102 *pstart_addr = start_addr;
1103 *pline_compare = line_compare;
1106 /* update start_addr and line_offset. Return TRUE if modified */
1107 static int update_basic_params(VGACommonState *s)
1109 int full_update;
1110 uint32_t start_addr, line_offset, line_compare;
1112 full_update = 0;
1114 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1116 if (line_offset != s->line_offset ||
1117 start_addr != s->start_addr ||
1118 line_compare != s->line_compare) {
1119 s->line_offset = line_offset;
1120 s->start_addr = start_addr;
1121 s->line_compare = line_compare;
1122 full_update = 1;
1124 return full_update;
1128 static const uint8_t cursor_glyph[32 * 4] = {
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,
1143 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1144 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1147 static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1148 int *pcwidth, int *pcheight)
1150 int width, cwidth, height, cheight;
1152 /* total width & height */
1153 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1154 cwidth = 8;
1155 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
1156 cwidth = 9;
1158 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
1159 cwidth = 16; /* NOTE: no 18 pixel wide */
1161 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1162 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1163 /* ugly hack for CGA 160x100x16 - explain me the logic */
1164 height = 100;
1165 } else {
1166 height = s->cr[VGA_CRTC_V_DISP_END] |
1167 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1168 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1169 height = (height + 1) / cheight;
1172 *pwidth = width;
1173 *pheight = height;
1174 *pcwidth = cwidth;
1175 *pcheight = cheight;
1179 * Text mode update
1180 * Missing:
1181 * - double scan
1182 * - double width
1183 * - underline
1184 * - flashing
1186 static void vga_draw_text(VGACommonState *s, int full_update)
1188 DisplaySurface *surface = qemu_console_surface(s->con);
1189 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1190 int cx_min, cx_max, linesize, x_incr, line, line1;
1191 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1192 uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1193 const uint8_t *font_ptr, *font_base[2];
1194 int dup9, line_offset;
1195 uint32_t *palette;
1196 uint32_t *ch_attr_ptr;
1197 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
1199 /* compute font data address (in plane 2) */
1200 v = sr(s, VGA_SEQ_CHARACTER_MAP);
1201 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1202 if (offset != s->font_offsets[0]) {
1203 s->font_offsets[0] = offset;
1204 full_update = 1;
1206 font_base[0] = s->vram_ptr + offset;
1208 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1209 font_base[1] = s->vram_ptr + offset;
1210 if (offset != s->font_offsets[1]) {
1211 s->font_offsets[1] = offset;
1212 full_update = 1;
1214 if (s->plane_updated & (1 << 2) || s->has_chain4_alias) {
1215 /* if the plane 2 was modified since the last display, it
1216 indicates the font may have been modified */
1217 s->plane_updated = 0;
1218 full_update = 1;
1220 full_update |= update_basic_params(s);
1222 line_offset = s->line_offset;
1224 vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1225 if ((height * width) <= 1) {
1226 /* better than nothing: exit if transient size is too small */
1227 return;
1229 if ((height * width) > CH_ATTR_SIZE) {
1230 /* better than nothing: exit if transient size is too big */
1231 return;
1234 if (width != s->last_width || height != s->last_height ||
1235 cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1236 s->last_scr_width = width * cw;
1237 s->last_scr_height = height * cheight;
1238 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1239 surface = qemu_console_surface(s->con);
1240 dpy_text_resize(s->con, width, height);
1241 s->last_depth = 0;
1242 s->last_width = width;
1243 s->last_height = height;
1244 s->last_ch = cheight;
1245 s->last_cw = cw;
1246 full_update = 1;
1248 full_update |= update_palette16(s);
1249 palette = s->last_palette;
1250 x_incr = cw * surface_bytes_per_pixel(surface);
1252 if (full_update) {
1253 s->full_update_text = 1;
1255 if (s->full_update_gfx) {
1256 s->full_update_gfx = 0;
1257 full_update |= 1;
1260 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1261 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1262 if (cursor_offset != s->cursor_offset ||
1263 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1264 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1265 /* if the cursor position changed, we update the old and new
1266 chars */
1267 if (s->cursor_offset < CH_ATTR_SIZE)
1268 s->last_ch_attr[s->cursor_offset] = -1;
1269 if (cursor_offset < CH_ATTR_SIZE)
1270 s->last_ch_attr[cursor_offset] = -1;
1271 s->cursor_offset = cursor_offset;
1272 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1273 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1275 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1276 if (now >= s->cursor_blink_time) {
1277 s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
1278 s->cursor_visible_phase = !s->cursor_visible_phase;
1281 dest = surface_data(surface);
1282 linesize = surface_stride(surface);
1283 ch_attr_ptr = s->last_ch_attr;
1284 line = 0;
1285 offset = s->start_addr * 4;
1286 for(cy = 0; cy < height; cy++) {
1287 d1 = dest;
1288 src = s->vram_ptr + offset;
1289 cx_min = width;
1290 cx_max = -1;
1291 for(cx = 0; cx < width; cx++) {
1292 if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
1293 break;
1295 ch_attr = *(uint16_t *)src;
1296 if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
1297 if (cx < cx_min)
1298 cx_min = cx;
1299 if (cx > cx_max)
1300 cx_max = cx;
1301 *ch_attr_ptr = ch_attr;
1302 #if HOST_BIG_ENDIAN
1303 ch = ch_attr >> 8;
1304 cattr = ch_attr & 0xff;
1305 #else
1306 ch = ch_attr & 0xff;
1307 cattr = ch_attr >> 8;
1308 #endif
1309 font_ptr = font_base[(cattr >> 3) & 1];
1310 font_ptr += 32 * 4 * ch;
1311 bgcol = palette[cattr >> 4];
1312 fgcol = palette[cattr & 0x0f];
1313 if (cw == 16) {
1314 vga_draw_glyph16(d1, linesize,
1315 font_ptr, cheight, fgcol, bgcol);
1316 } else if (cw != 9) {
1317 vga_draw_glyph8(d1, linesize,
1318 font_ptr, cheight, fgcol, bgcol);
1319 } else {
1320 dup9 = 0;
1321 if (ch >= 0xb0 && ch <= 0xdf &&
1322 (s->ar[VGA_ATC_MODE] & 0x04)) {
1323 dup9 = 1;
1325 vga_draw_glyph9(d1, linesize,
1326 font_ptr, cheight, fgcol, bgcol, dup9);
1328 if (src == cursor_ptr &&
1329 !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1330 s->cursor_visible_phase) {
1331 int line_start, line_last, h;
1332 /* draw the cursor */
1333 line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1334 line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1335 /* XXX: check that */
1336 if (line_last > cheight - 1)
1337 line_last = cheight - 1;
1338 if (line_last >= line_start && line_start < cheight) {
1339 h = line_last - line_start + 1;
1340 d = d1 + linesize * line_start;
1341 if (cw == 16) {
1342 vga_draw_glyph16(d, linesize,
1343 cursor_glyph, h, fgcol, bgcol);
1344 } else if (cw != 9) {
1345 vga_draw_glyph8(d, linesize,
1346 cursor_glyph, h, fgcol, bgcol);
1347 } else {
1348 vga_draw_glyph9(d, linesize,
1349 cursor_glyph, h, fgcol, bgcol, 1);
1354 d1 += x_incr;
1355 src += 4;
1356 ch_attr_ptr++;
1358 if (cx_max != -1) {
1359 dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
1360 (cx_max - cx_min + 1) * cw, cheight);
1362 dest += linesize * cheight;
1363 line1 = line + cheight;
1364 offset += line_offset;
1365 if (line < s->line_compare && line1 >= s->line_compare) {
1366 offset = 0;
1368 line = line1;
1372 enum {
1373 VGA_DRAW_LINE2,
1374 VGA_DRAW_LINE2D2,
1375 VGA_DRAW_LINE4,
1376 VGA_DRAW_LINE4D2,
1377 VGA_DRAW_LINE8D2,
1378 VGA_DRAW_LINE8,
1379 VGA_DRAW_LINE15_LE,
1380 VGA_DRAW_LINE16_LE,
1381 VGA_DRAW_LINE24_LE,
1382 VGA_DRAW_LINE32_LE,
1383 VGA_DRAW_LINE15_BE,
1384 VGA_DRAW_LINE16_BE,
1385 VGA_DRAW_LINE24_BE,
1386 VGA_DRAW_LINE32_BE,
1387 VGA_DRAW_LINE_NB,
1390 static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
1391 vga_draw_line2,
1392 vga_draw_line2d2,
1393 vga_draw_line4,
1394 vga_draw_line4d2,
1395 vga_draw_line8d2,
1396 vga_draw_line8,
1397 vga_draw_line15_le,
1398 vga_draw_line16_le,
1399 vga_draw_line24_le,
1400 vga_draw_line32_le,
1401 vga_draw_line15_be,
1402 vga_draw_line16_be,
1403 vga_draw_line24_be,
1404 vga_draw_line32_be,
1407 static int vga_get_bpp(VGACommonState *s)
1409 int ret;
1411 if (vbe_enabled(s)) {
1412 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1413 } else {
1414 ret = 0;
1416 return ret;
1419 static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1421 int width, height;
1423 if (vbe_enabled(s)) {
1424 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1425 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1426 } else {
1427 width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1428 height = s->cr[VGA_CRTC_V_DISP_END] |
1429 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1430 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1431 height = (height + 1);
1433 *pwidth = width;
1434 *pheight = height;
1437 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1439 int y;
1440 if (y1 >= VGA_MAX_HEIGHT)
1441 return;
1442 if (y2 >= VGA_MAX_HEIGHT)
1443 y2 = VGA_MAX_HEIGHT;
1444 for(y = y1; y < y2; y++) {
1445 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1449 static bool vga_scanline_invalidated(VGACommonState *s, int y)
1451 if (y >= VGA_MAX_HEIGHT) {
1452 return false;
1454 return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
1457 void vga_dirty_log_start(VGACommonState *s)
1459 memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1462 void vga_dirty_log_stop(VGACommonState *s)
1464 memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1468 * graphic modes
1470 static void vga_draw_graphic(VGACommonState *s, int full_update)
1472 DisplaySurface *surface = qemu_console_surface(s->con);
1473 int y1, y, update, linesize, y_start, double_scan, mask, depth;
1474 int width, height, shift_control, bwidth, bits;
1475 ram_addr_t page0, page1, region_start, region_end;
1476 DirtyBitmapSnapshot *snap = NULL;
1477 int disp_width, multi_scan, multi_run;
1478 uint8_t *d;
1479 uint32_t v, addr1, addr;
1480 vga_draw_line_func *vga_draw_line = NULL;
1481 bool share_surface, force_shadow = false;
1482 pixman_format_code_t format;
1483 #if HOST_BIG_ENDIAN
1484 bool byteswap = !s->big_endian_fb;
1485 #else
1486 bool byteswap = s->big_endian_fb;
1487 #endif
1489 full_update |= update_basic_params(s);
1491 s->get_resolution(s, &width, &height);
1492 disp_width = width;
1493 depth = s->get_bpp(s);
1495 region_start = (s->start_addr * 4);
1496 region_end = region_start + (ram_addr_t)s->line_offset * height;
1497 region_end += width * depth / 8; /* scanline length */
1498 region_end -= s->line_offset;
1499 if (region_end > s->vbe_size || depth == 0 || depth == 15) {
1501 * We land here on:
1502 * - wraps around (can happen with cirrus vbe modes)
1503 * - depth == 0 (256 color palette video mode)
1504 * - depth == 15
1506 * Take the safe and slow route:
1507 * - create a dirty bitmap snapshot for all vga memory.
1508 * - force shadowing (so all vga memory access goes
1509 * through vga_read_*() helpers).
1511 * Given this affects only vga features which are pretty much
1512 * unused by modern guests there should be no performance
1513 * impact.
1515 region_start = 0;
1516 region_end = s->vbe_size;
1517 force_shadow = true;
1520 /* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */
1521 shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1522 double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1523 if (s->cr[VGA_CRTC_MODE] & 1) {
1524 multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1525 - 1;
1526 } else {
1527 /* in CGA modes, multi_scan is ignored */
1528 /* XXX: is it correct ? */
1529 multi_scan = double_scan;
1531 multi_run = multi_scan;
1532 if (shift_control != s->shift_control ||
1533 double_scan != s->double_scan) {
1534 full_update = 1;
1535 s->shift_control = shift_control;
1536 s->double_scan = double_scan;
1539 if (shift_control == 0) {
1540 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1541 disp_width <<= 1;
1543 } else if (shift_control == 1) {
1544 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1545 disp_width <<= 1;
1550 * Check whether we can share the surface with the backend
1551 * or whether we need a shadow surface. We share native
1552 * endian surfaces for 15bpp and above and byteswapped
1553 * surfaces for 24bpp and above.
1555 format = qemu_default_pixman_format(depth, !byteswap);
1556 if (format) {
1557 share_surface = dpy_gfx_check_format(s->con, format)
1558 && !s->force_shadow && !force_shadow;
1559 } else {
1560 share_surface = false;
1563 if (s->line_offset != s->last_line_offset ||
1564 disp_width != s->last_width ||
1565 height != s->last_height ||
1566 s->last_depth != depth ||
1567 s->last_byteswap != byteswap ||
1568 share_surface != is_buffer_shared(surface)) {
1569 /* display parameters changed -> need new display surface */
1570 s->last_scr_width = disp_width;
1571 s->last_scr_height = height;
1572 s->last_width = disp_width;
1573 s->last_height = height;
1574 s->last_line_offset = s->line_offset;
1575 s->last_depth = depth;
1576 s->last_byteswap = byteswap;
1577 full_update = 1;
1579 if (surface_data(surface) != s->vram_ptr + (s->start_addr * 4)
1580 && is_buffer_shared(surface)) {
1581 /* base address changed (page flip) -> shared display surfaces
1582 * must be updated with the new base address */
1583 full_update = 1;
1586 if (full_update) {
1587 if (share_surface) {
1588 surface = qemu_create_displaysurface_from(disp_width,
1589 height, format, s->line_offset,
1590 s->vram_ptr + (s->start_addr * 4));
1591 dpy_gfx_replace_surface(s->con, surface);
1592 } else {
1593 qemu_console_resize(s->con, disp_width, height);
1594 surface = qemu_console_surface(s->con);
1598 if (shift_control == 0) {
1599 full_update |= update_palette16(s);
1600 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1601 v = VGA_DRAW_LINE4D2;
1602 } else {
1603 v = VGA_DRAW_LINE4;
1605 bits = 4;
1606 } else if (shift_control == 1) {
1607 full_update |= update_palette16(s);
1608 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1609 v = VGA_DRAW_LINE2D2;
1610 } else {
1611 v = VGA_DRAW_LINE2;
1613 bits = 4;
1614 } else {
1615 switch(s->get_bpp(s)) {
1616 default:
1617 case 0:
1618 full_update |= update_palette256(s);
1619 v = VGA_DRAW_LINE8D2;
1620 bits = 4;
1621 break;
1622 case 8:
1623 full_update |= update_palette256(s);
1624 v = VGA_DRAW_LINE8;
1625 bits = 8;
1626 break;
1627 case 15:
1628 v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
1629 bits = 16;
1630 break;
1631 case 16:
1632 v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
1633 bits = 16;
1634 break;
1635 case 24:
1636 v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
1637 bits = 24;
1638 break;
1639 case 32:
1640 v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
1641 bits = 32;
1642 break;
1645 vga_draw_line = vga_draw_line_table[v];
1647 if (!is_buffer_shared(surface) && s->cursor_invalidate) {
1648 s->cursor_invalidate(s);
1651 #if 0
1652 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",
1653 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1654 s->line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
1655 #endif
1656 addr1 = (s->start_addr * 4);
1657 bwidth = DIV_ROUND_UP(width * bits, 8);
1658 y_start = -1;
1659 d = surface_data(surface);
1660 linesize = surface_stride(surface);
1661 y1 = 0;
1663 if (!full_update) {
1664 if (s->line_compare < height) {
1665 /* split screen mode */
1666 region_start = 0;
1668 snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
1669 region_end - region_start,
1670 DIRTY_MEMORY_VGA);
1673 for(y = 0; y < height; y++) {
1674 addr = addr1;
1675 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1676 int shift;
1677 /* CGA compatibility handling */
1678 shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1679 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1681 if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1682 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1684 page0 = addr & s->vbe_size_mask;
1685 page1 = (addr + bwidth - 1) & s->vbe_size_mask;
1686 if (full_update) {
1687 update = 1;
1688 } else if (page1 < page0) {
1689 /* scanline wraps from end of video memory to the start */
1690 assert(force_shadow);
1691 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1692 page0, s->vbe_size - page0);
1693 update |= memory_region_snapshot_get_dirty(&s->vram, snap,
1694 0, page1);
1695 } else {
1696 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1697 page0, page1 - page0);
1699 /* explicit invalidation for the hardware cursor (cirrus only) */
1700 update |= vga_scanline_invalidated(s, y);
1701 if (update) {
1702 if (y_start < 0)
1703 y_start = y;
1704 if (!(is_buffer_shared(surface))) {
1705 vga_draw_line(s, d, addr, width);
1706 if (s->cursor_draw_line)
1707 s->cursor_draw_line(s, d, y);
1709 } else {
1710 if (y_start >= 0) {
1711 /* flush to display */
1712 dpy_gfx_update(s->con, 0, y_start,
1713 disp_width, y - y_start);
1714 y_start = -1;
1717 if (!multi_run) {
1718 mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1719 if ((y1 & mask) == mask)
1720 addr1 += s->line_offset;
1721 y1++;
1722 multi_run = multi_scan;
1723 } else {
1724 multi_run--;
1726 /* line compare acts on the displayed lines */
1727 if (y == s->line_compare)
1728 addr1 = 0;
1729 d += linesize;
1731 if (y_start >= 0) {
1732 /* flush to display */
1733 dpy_gfx_update(s->con, 0, y_start,
1734 disp_width, y - y_start);
1736 g_free(snap);
1737 memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
1740 static void vga_draw_blank(VGACommonState *s, int full_update)
1742 DisplaySurface *surface = qemu_console_surface(s->con);
1743 int i, w;
1744 uint8_t *d;
1746 if (!full_update)
1747 return;
1748 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1749 return;
1751 w = s->last_scr_width * surface_bytes_per_pixel(surface);
1752 d = surface_data(surface);
1753 for(i = 0; i < s->last_scr_height; i++) {
1754 memset(d, 0, w);
1755 d += surface_stride(surface);
1757 dpy_gfx_update_full(s->con);
1760 #define GMODE_TEXT 0
1761 #define GMODE_GRAPH 1
1762 #define GMODE_BLANK 2
1764 static void vga_update_display(void *opaque)
1766 VGACommonState *s = opaque;
1767 DisplaySurface *surface = qemu_console_surface(s->con);
1768 int full_update, graphic_mode;
1770 qemu_flush_coalesced_mmio_buffer();
1772 if (surface_bits_per_pixel(surface) == 0) {
1773 /* nothing to do */
1774 } else {
1775 full_update = 0;
1776 if (!(s->ar_index & 0x20)) {
1777 graphic_mode = GMODE_BLANK;
1778 } else {
1779 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1781 if (graphic_mode != s->graphic_mode) {
1782 s->graphic_mode = graphic_mode;
1783 s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
1784 full_update = 1;
1786 switch(graphic_mode) {
1787 case GMODE_TEXT:
1788 vga_draw_text(s, full_update);
1789 break;
1790 case GMODE_GRAPH:
1791 vga_draw_graphic(s, full_update);
1792 break;
1793 case GMODE_BLANK:
1794 default:
1795 vga_draw_blank(s, full_update);
1796 break;
1801 /* force a full display refresh */
1802 static void vga_invalidate_display(void *opaque)
1804 VGACommonState *s = opaque;
1806 s->last_width = -1;
1807 s->last_height = -1;
1810 void vga_common_reset(VGACommonState *s)
1812 s->sr_index = 0;
1813 memset(s->sr, '\0', sizeof(s->sr));
1814 memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
1815 s->gr_index = 0;
1816 memset(s->gr, '\0', sizeof(s->gr));
1817 s->ar_index = 0;
1818 memset(s->ar, '\0', sizeof(s->ar));
1819 s->ar_flip_flop = 0;
1820 s->cr_index = 0;
1821 memset(s->cr, '\0', sizeof(s->cr));
1822 s->msr = 0;
1823 s->fcr = 0;
1824 s->st00 = 0;
1825 s->st01 = 0;
1826 s->dac_state = 0;
1827 s->dac_sub_index = 0;
1828 s->dac_read_index = 0;
1829 s->dac_write_index = 0;
1830 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1831 s->dac_8bit = 0;
1832 memset(s->palette, '\0', sizeof(s->palette));
1833 s->bank_offset = 0;
1834 s->vbe_index = 0;
1835 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1836 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1837 s->vbe_start_addr = 0;
1838 s->vbe_line_offset = 0;
1839 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1840 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1841 s->graphic_mode = -1; /* force full update */
1842 s->shift_control = 0;
1843 s->double_scan = 0;
1844 s->line_offset = 0;
1845 s->line_compare = 0;
1846 s->start_addr = 0;
1847 s->plane_updated = 0;
1848 s->last_cw = 0;
1849 s->last_ch = 0;
1850 s->last_width = 0;
1851 s->last_height = 0;
1852 s->last_scr_width = 0;
1853 s->last_scr_height = 0;
1854 s->cursor_start = 0;
1855 s->cursor_end = 0;
1856 s->cursor_offset = 0;
1857 s->big_endian_fb = s->default_endian_fb;
1858 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1859 memset(s->last_palette, '\0', sizeof(s->last_palette));
1860 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1861 switch (vga_retrace_method) {
1862 case VGA_RETRACE_DUMB:
1863 break;
1864 case VGA_RETRACE_PRECISE:
1865 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1866 break;
1868 vga_update_memory_access(s);
1871 static void vga_reset(void *opaque)
1873 VGACommonState *s = opaque;
1874 vga_common_reset(s);
1877 #define TEXTMODE_X(x) ((x) % width)
1878 #define TEXTMODE_Y(x) ((x) / width)
1879 #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1880 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1881 /* relay text rendering to the display driver
1882 * instead of doing a full vga_update_display() */
1883 static void vga_update_text(void *opaque, console_ch_t *chardata)
1885 VGACommonState *s = opaque;
1886 int graphic_mode, i, cursor_offset, cursor_visible;
1887 int cw, cheight, width, height, size, c_min, c_max;
1888 uint32_t *src;
1889 console_ch_t *dst, val;
1890 char msg_buffer[80];
1891 int full_update = 0;
1893 qemu_flush_coalesced_mmio_buffer();
1895 if (!(s->ar_index & 0x20)) {
1896 graphic_mode = GMODE_BLANK;
1897 } else {
1898 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1900 if (graphic_mode != s->graphic_mode) {
1901 s->graphic_mode = graphic_mode;
1902 full_update = 1;
1904 if (s->last_width == -1) {
1905 s->last_width = 0;
1906 full_update = 1;
1909 switch (graphic_mode) {
1910 case GMODE_TEXT:
1911 /* TODO: update palette */
1912 full_update |= update_basic_params(s);
1914 /* total width & height */
1915 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1916 cw = 8;
1917 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
1918 cw = 9;
1920 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
1921 cw = 16; /* NOTE: no 18 pixel wide */
1923 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1924 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1925 /* ugly hack for CGA 160x100x16 - explain me the logic */
1926 height = 100;
1927 } else {
1928 height = s->cr[VGA_CRTC_V_DISP_END] |
1929 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1930 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1931 height = (height + 1) / cheight;
1934 size = (height * width);
1935 if (size > CH_ATTR_SIZE) {
1936 if (!full_update)
1937 return;
1939 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1940 width, height);
1941 break;
1944 if (width != s->last_width || height != s->last_height ||
1945 cw != s->last_cw || cheight != s->last_ch) {
1946 s->last_scr_width = width * cw;
1947 s->last_scr_height = height * cheight;
1948 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1949 dpy_text_resize(s->con, width, height);
1950 s->last_depth = 0;
1951 s->last_width = width;
1952 s->last_height = height;
1953 s->last_ch = cheight;
1954 s->last_cw = cw;
1955 full_update = 1;
1958 if (full_update) {
1959 s->full_update_gfx = 1;
1961 if (s->full_update_text) {
1962 s->full_update_text = 0;
1963 full_update |= 1;
1966 /* Update "hardware" cursor */
1967 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1968 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1969 if (cursor_offset != s->cursor_offset ||
1970 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1971 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1972 cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
1973 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1974 dpy_text_cursor(s->con,
1975 TEXTMODE_X(cursor_offset),
1976 TEXTMODE_Y(cursor_offset));
1977 else
1978 dpy_text_cursor(s->con, -1, -1);
1979 s->cursor_offset = cursor_offset;
1980 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1981 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1984 src = (uint32_t *) s->vram_ptr + s->start_addr;
1985 dst = chardata;
1987 if (full_update) {
1988 for (i = 0; i < size; src ++, dst ++, i ++)
1989 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
1991 dpy_text_update(s->con, 0, 0, width, height);
1992 } else {
1993 c_max = 0;
1995 for (i = 0; i < size; src ++, dst ++, i ++) {
1996 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1997 if (*dst != val) {
1998 *dst = val;
1999 c_max = i;
2000 break;
2003 c_min = i;
2004 for (; i < size; src ++, dst ++, i ++) {
2005 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2006 if (*dst != val) {
2007 *dst = val;
2008 c_max = i;
2012 if (c_min <= c_max) {
2013 i = TEXTMODE_Y(c_min);
2014 dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2018 return;
2019 case GMODE_GRAPH:
2020 if (!full_update)
2021 return;
2023 s->get_resolution(s, &width, &height);
2024 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2025 width, height);
2026 break;
2027 case GMODE_BLANK:
2028 default:
2029 if (!full_update)
2030 return;
2032 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2033 break;
2036 /* Display a message */
2037 s->last_width = 60;
2038 s->last_height = height = 3;
2039 dpy_text_cursor(s->con, -1, -1);
2040 dpy_text_resize(s->con, s->last_width, height);
2042 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2043 console_write_ch(dst ++, ' ');
2045 size = strlen(msg_buffer);
2046 width = (s->last_width - size) / 2;
2047 dst = chardata + s->last_width + width;
2048 for (i = 0; i < size; i ++)
2049 console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
2050 QEMU_COLOR_BLACK, 1));
2052 dpy_text_update(s->con, 0, 0, s->last_width, height);
2055 static uint64_t vga_mem_read(void *opaque, hwaddr addr,
2056 unsigned size)
2058 VGACommonState *s = opaque;
2060 return vga_mem_readb(s, addr);
2063 static void vga_mem_write(void *opaque, hwaddr addr,
2064 uint64_t data, unsigned size)
2066 VGACommonState *s = opaque;
2068 vga_mem_writeb(s, addr, data);
2071 const MemoryRegionOps vga_mem_ops = {
2072 .read = vga_mem_read,
2073 .write = vga_mem_write,
2074 .endianness = DEVICE_LITTLE_ENDIAN,
2075 .impl = {
2076 .min_access_size = 1,
2077 .max_access_size = 1,
2081 static int vga_common_post_load(void *opaque, int version_id)
2083 VGACommonState *s = opaque;
2085 /* force refresh */
2086 s->graphic_mode = -1;
2087 vbe_update_vgaregs(s);
2088 vga_update_memory_access(s);
2089 return 0;
2092 static bool vga_endian_state_needed(void *opaque)
2094 VGACommonState *s = opaque;
2097 * Only send the endian state if it's different from the
2098 * default one, thus ensuring backward compatibility for
2099 * migration of the common case
2101 return s->default_endian_fb != s->big_endian_fb;
2104 static const VMStateDescription vmstate_vga_endian = {
2105 .name = "vga.endian",
2106 .version_id = 1,
2107 .minimum_version_id = 1,
2108 .needed = vga_endian_state_needed,
2109 .fields = (VMStateField[]) {
2110 VMSTATE_BOOL(big_endian_fb, VGACommonState),
2111 VMSTATE_END_OF_LIST()
2115 const VMStateDescription vmstate_vga_common = {
2116 .name = "vga",
2117 .version_id = 2,
2118 .minimum_version_id = 2,
2119 .post_load = vga_common_post_load,
2120 .fields = (VMStateField[]) {
2121 VMSTATE_UINT32(latch, VGACommonState),
2122 VMSTATE_UINT8(sr_index, VGACommonState),
2123 VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2124 VMSTATE_UINT8(gr_index, VGACommonState),
2125 VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2126 VMSTATE_UINT8(ar_index, VGACommonState),
2127 VMSTATE_BUFFER(ar, VGACommonState),
2128 VMSTATE_INT32(ar_flip_flop, VGACommonState),
2129 VMSTATE_UINT8(cr_index, VGACommonState),
2130 VMSTATE_BUFFER(cr, VGACommonState),
2131 VMSTATE_UINT8(msr, VGACommonState),
2132 VMSTATE_UINT8(fcr, VGACommonState),
2133 VMSTATE_UINT8(st00, VGACommonState),
2134 VMSTATE_UINT8(st01, VGACommonState),
2136 VMSTATE_UINT8(dac_state, VGACommonState),
2137 VMSTATE_UINT8(dac_sub_index, VGACommonState),
2138 VMSTATE_UINT8(dac_read_index, VGACommonState),
2139 VMSTATE_UINT8(dac_write_index, VGACommonState),
2140 VMSTATE_BUFFER(dac_cache, VGACommonState),
2141 VMSTATE_BUFFER(palette, VGACommonState),
2143 VMSTATE_INT32(bank_offset, VGACommonState),
2144 VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState, NULL),
2145 VMSTATE_UINT16(vbe_index, VGACommonState),
2146 VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2147 VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2148 VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2149 VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2150 VMSTATE_END_OF_LIST()
2152 .subsections = (const VMStateDescription*[]) {
2153 &vmstate_vga_endian,
2154 NULL
2158 static const GraphicHwOps vga_ops = {
2159 .invalidate = vga_invalidate_display,
2160 .gfx_update = vga_update_display,
2161 .text_update = vga_update_text,
2164 static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
2166 if (val < vmin) {
2167 return vmin;
2169 if (val > vmax) {
2170 return vmax;
2172 return val;
2175 bool vga_common_init(VGACommonState *s, Object *obj, Error **errp)
2177 int i, j, v, b;
2178 Error *local_err = NULL;
2180 for(i = 0;i < 256; i++) {
2181 v = 0;
2182 for(j = 0; j < 8; j++) {
2183 v |= ((i >> j) & 1) << (j * 4);
2185 expand4[i] = v;
2187 v = 0;
2188 for(j = 0; j < 4; j++) {
2189 v |= ((i >> (2 * j)) & 3) << (j * 4);
2191 expand2[i] = v;
2193 for(i = 0; i < 16; i++) {
2194 v = 0;
2195 for(j = 0; j < 4; j++) {
2196 b = ((i >> j) & 1);
2197 v |= b << (2 * j);
2198 v |= b << (2 * j + 1);
2200 expand4to8[i] = v;
2203 s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
2204 s->vram_size_mb = pow2ceil(s->vram_size_mb);
2205 s->vram_size = s->vram_size_mb * MiB;
2207 if (!s->vbe_size) {
2208 s->vbe_size = s->vram_size;
2210 s->vbe_size_mask = s->vbe_size - 1;
2212 s->is_vbe_vmstate = 1;
2214 if (s->global_vmstate && qemu_ram_block_by_name("vga.vram")) {
2215 error_setg(errp, "Only one global VGA device can be used at a time");
2216 return false;
2219 memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size,
2220 &local_err);
2221 if (local_err) {
2222 error_propagate(errp, local_err);
2223 return false;
2225 vmstate_register_ram(&s->vram, s->global_vmstate ? NULL : DEVICE(obj));
2226 xen_register_framebuffer(&s->vram);
2227 s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2228 s->get_bpp = vga_get_bpp;
2229 s->get_offsets = vga_get_offsets;
2230 s->get_resolution = vga_get_resolution;
2231 s->hw_ops = &vga_ops;
2232 switch (vga_retrace_method) {
2233 case VGA_RETRACE_DUMB:
2234 s->retrace = vga_dumb_retrace;
2235 s->update_retrace_info = vga_dumb_update_retrace_info;
2236 break;
2238 case VGA_RETRACE_PRECISE:
2239 s->retrace = vga_precise_retrace;
2240 s->update_retrace_info = vga_precise_update_retrace_info;
2241 break;
2245 * Set default fb endian based on target, could probably be turned
2246 * into a device attribute set by the machine/platform to remove
2247 * all target endian dependencies from this file.
2249 s->default_endian_fb = target_words_bigendian();
2251 vga_dirty_log_start(s);
2253 return true;
2256 static const MemoryRegionPortio vga_portio_list[] = {
2257 { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2258 { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2259 { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2260 { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2261 { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2262 PORTIO_END_OF_LIST(),
2265 static const MemoryRegionPortio vbe_portio_list_x86[] = {
2266 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2267 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2268 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2269 PORTIO_END_OF_LIST(),
2272 static const MemoryRegionPortio vbe_portio_list_no_x86[] = {
2273 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2274 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2275 PORTIO_END_OF_LIST(),
2278 /* Used by both ISA and PCI */
2279 MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
2280 const MemoryRegionPortio **vga_ports,
2281 const MemoryRegionPortio **vbe_ports)
2283 MemoryRegion *vga_mem;
2284 MachineState *ms = MACHINE(qdev_get_machine());
2287 * We unfortunately need two VBE lists since non-x86 machines might
2288 * not be able to do 16-bit accesses at unaligned addresses (0x1cf)
2290 if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
2291 *vbe_ports = vbe_portio_list_x86;
2292 } else {
2293 *vbe_ports = vbe_portio_list_no_x86;
2296 *vga_ports = vga_portio_list;
2298 vga_mem = g_malloc(sizeof(*vga_mem));
2299 memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
2300 "vga-lowmem", 0x20000);
2301 memory_region_set_flush_coalesced(vga_mem);
2303 return vga_mem;
2306 void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
2307 MemoryRegion *address_space_io, bool init_vga_ports)
2309 MemoryRegion *vga_io_memory;
2310 const MemoryRegionPortio *vga_ports, *vbe_ports;
2312 qemu_register_reset(vga_reset, s);
2314 s->bank_offset = 0;
2316 s->legacy_address_space = address_space;
2318 vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
2319 memory_region_add_subregion_overlap(address_space,
2320 0x000a0000,
2321 vga_io_memory,
2323 memory_region_set_coalescing(vga_io_memory);
2324 if (init_vga_ports) {
2325 portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
2326 portio_list_set_flush_coalesced(&s->vga_port_list);
2327 portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
2329 if (vbe_ports) {
2330 portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
2331 portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);