esp: move some definitions to header file
[qemu/qmp-unstable.git] / hw / vga.c
blobf82ced8e662cecfb26d2ac223e56fb340c7fd4cd
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.
24 #include "hw.h"
25 #include "vga.h"
26 #include "console.h"
27 #include "pc.h"
28 #include "pci.h"
29 #include "vga_int.h"
30 #include "pixel_ops.h"
31 #include "qemu-timer.h"
32 #include "xen.h"
33 #include "trace.h"
35 //#define DEBUG_VGA
36 //#define DEBUG_VGA_MEM
37 //#define DEBUG_VGA_REG
39 //#define DEBUG_BOCHS_VBE
41 /* 16 state changes per vertical frame @60 Hz */
42 #define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60)
45 * Video Graphics Array (VGA)
47 * Chipset docs for original IBM VGA:
48 * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
50 * FreeVGA site:
51 * http://www.osdever.net/FreeVGA/home.htm
53 * Standard VGA features and Bochs VBE extensions are implemented.
56 /* force some bits to zero */
57 const uint8_t sr_mask[8] = {
58 0x03,
59 0x3d,
60 0x0f,
61 0x3f,
62 0x0e,
63 0x00,
64 0x00,
65 0xff,
68 const uint8_t gr_mask[16] = {
69 0x0f, /* 0x00 */
70 0x0f, /* 0x01 */
71 0x0f, /* 0x02 */
72 0x1f, /* 0x03 */
73 0x03, /* 0x04 */
74 0x7b, /* 0x05 */
75 0x0f, /* 0x06 */
76 0x0f, /* 0x07 */
77 0xff, /* 0x08 */
78 0x00, /* 0x09 */
79 0x00, /* 0x0a */
80 0x00, /* 0x0b */
81 0x00, /* 0x0c */
82 0x00, /* 0x0d */
83 0x00, /* 0x0e */
84 0x00, /* 0x0f */
87 #define cbswap_32(__x) \
88 ((uint32_t)( \
89 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
90 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
91 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
92 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
94 #ifdef HOST_WORDS_BIGENDIAN
95 #define PAT(x) cbswap_32(x)
96 #else
97 #define PAT(x) (x)
98 #endif
100 #ifdef HOST_WORDS_BIGENDIAN
101 #define BIG 1
102 #else
103 #define BIG 0
104 #endif
106 #ifdef HOST_WORDS_BIGENDIAN
107 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
108 #else
109 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
110 #endif
112 static const uint32_t mask16[16] = {
113 PAT(0x00000000),
114 PAT(0x000000ff),
115 PAT(0x0000ff00),
116 PAT(0x0000ffff),
117 PAT(0x00ff0000),
118 PAT(0x00ff00ff),
119 PAT(0x00ffff00),
120 PAT(0x00ffffff),
121 PAT(0xff000000),
122 PAT(0xff0000ff),
123 PAT(0xff00ff00),
124 PAT(0xff00ffff),
125 PAT(0xffff0000),
126 PAT(0xffff00ff),
127 PAT(0xffffff00),
128 PAT(0xffffffff),
131 #undef PAT
133 #ifdef HOST_WORDS_BIGENDIAN
134 #define PAT(x) (x)
135 #else
136 #define PAT(x) cbswap_32(x)
137 #endif
139 static const uint32_t dmask16[16] = {
140 PAT(0x00000000),
141 PAT(0x000000ff),
142 PAT(0x0000ff00),
143 PAT(0x0000ffff),
144 PAT(0x00ff0000),
145 PAT(0x00ff00ff),
146 PAT(0x00ffff00),
147 PAT(0x00ffffff),
148 PAT(0xff000000),
149 PAT(0xff0000ff),
150 PAT(0xff00ff00),
151 PAT(0xff00ffff),
152 PAT(0xffff0000),
153 PAT(0xffff00ff),
154 PAT(0xffffff00),
155 PAT(0xffffffff),
158 static const uint32_t dmask4[4] = {
159 PAT(0x00000000),
160 PAT(0x0000ffff),
161 PAT(0xffff0000),
162 PAT(0xffffffff),
165 static uint32_t expand4[256];
166 static uint16_t expand2[256];
167 static uint8_t expand4to8[16];
169 static void vga_screen_dump(void *opaque, const char *filename, bool cswitch);
171 static void vga_update_memory_access(VGACommonState *s)
173 MemoryRegion *region, *old_region = s->chain4_alias;
174 target_phys_addr_t base, offset, size;
176 s->chain4_alias = NULL;
178 if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
179 VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
180 offset = 0;
181 switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
182 case 0:
183 base = 0xa0000;
184 size = 0x20000;
185 break;
186 case 1:
187 base = 0xa0000;
188 size = 0x10000;
189 offset = s->bank_offset;
190 break;
191 case 2:
192 base = 0xb0000;
193 size = 0x8000;
194 break;
195 case 3:
196 default:
197 base = 0xb8000;
198 size = 0x8000;
199 break;
201 base += isa_mem_base;
202 region = g_malloc(sizeof(*region));
203 memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
204 memory_region_add_subregion_overlap(s->legacy_address_space, base,
205 region, 2);
206 s->chain4_alias = region;
208 if (old_region) {
209 memory_region_del_subregion(s->legacy_address_space, old_region);
210 memory_region_destroy(old_region);
211 g_free(old_region);
212 s->plane_updated = 0xf;
216 static void vga_dumb_update_retrace_info(VGACommonState *s)
218 (void) s;
221 static void vga_precise_update_retrace_info(VGACommonState *s)
223 int htotal_chars;
224 int hretr_start_char;
225 int hretr_skew_chars;
226 int hretr_end_char;
228 int vtotal_lines;
229 int vretr_start_line;
230 int vretr_end_line;
232 int dots;
233 #if 0
234 int div2, sldiv2;
235 #endif
236 int clocking_mode;
237 int clock_sel;
238 const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
239 int64_t chars_per_sec;
240 struct vga_precise_retrace *r = &s->retrace_info.precise;
242 htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
243 hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
244 hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
245 hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
247 vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
248 (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
249 ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
250 vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
251 ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
252 ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
253 vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
255 clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
256 clock_sel = (s->msr >> 2) & 3;
257 dots = (s->msr & 1) ? 8 : 9;
259 chars_per_sec = clk_hz[clock_sel] / dots;
261 htotal_chars <<= clocking_mode;
263 r->total_chars = vtotal_lines * htotal_chars;
264 if (r->freq) {
265 r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
266 } else {
267 r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
270 r->vstart = vretr_start_line;
271 r->vend = r->vstart + vretr_end_line + 1;
273 r->hstart = hretr_start_char + hretr_skew_chars;
274 r->hend = r->hstart + hretr_end_char + 1;
275 r->htotal = htotal_chars;
277 #if 0
278 div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
279 sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
280 printf (
281 "hz=%f\n"
282 "htotal = %d\n"
283 "hretr_start = %d\n"
284 "hretr_skew = %d\n"
285 "hretr_end = %d\n"
286 "vtotal = %d\n"
287 "vretr_start = %d\n"
288 "vretr_end = %d\n"
289 "div2 = %d sldiv2 = %d\n"
290 "clocking_mode = %d\n"
291 "clock_sel = %d %d\n"
292 "dots = %d\n"
293 "ticks/char = %" PRId64 "\n"
294 "\n",
295 (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
296 htotal_chars,
297 hretr_start_char,
298 hretr_skew_chars,
299 hretr_end_char,
300 vtotal_lines,
301 vretr_start_line,
302 vretr_end_line,
303 div2, sldiv2,
304 clocking_mode,
305 clock_sel,
306 clk_hz[clock_sel],
307 dots,
308 r->ticks_per_char
310 #endif
313 static uint8_t vga_precise_retrace(VGACommonState *s)
315 struct vga_precise_retrace *r = &s->retrace_info.precise;
316 uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
318 if (r->total_chars) {
319 int cur_line, cur_line_char, cur_char;
320 int64_t cur_tick;
322 cur_tick = qemu_get_clock_ns(vm_clock);
324 cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
325 cur_line = cur_char / r->htotal;
327 if (cur_line >= r->vstart && cur_line <= r->vend) {
328 val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
329 } else {
330 cur_line_char = cur_char % r->htotal;
331 if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
332 val |= ST01_DISP_ENABLE;
336 return val;
337 } else {
338 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
342 static uint8_t vga_dumb_retrace(VGACommonState *s)
344 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
347 int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
349 if (s->msr & VGA_MIS_COLOR) {
350 /* Color */
351 return (addr >= 0x3b0 && addr <= 0x3bf);
352 } else {
353 /* Monochrome */
354 return (addr >= 0x3d0 && addr <= 0x3df);
358 uint32_t vga_ioport_read(void *opaque, uint32_t addr)
360 VGACommonState *s = opaque;
361 int val, index;
363 if (vga_ioport_invalid(s, addr)) {
364 val = 0xff;
365 } else {
366 switch(addr) {
367 case VGA_ATT_W:
368 if (s->ar_flip_flop == 0) {
369 val = s->ar_index;
370 } else {
371 val = 0;
373 break;
374 case VGA_ATT_R:
375 index = s->ar_index & 0x1f;
376 if (index < VGA_ATT_C) {
377 val = s->ar[index];
378 } else {
379 val = 0;
381 break;
382 case VGA_MIS_W:
383 val = s->st00;
384 break;
385 case VGA_SEQ_I:
386 val = s->sr_index;
387 break;
388 case VGA_SEQ_D:
389 val = s->sr[s->sr_index];
390 #ifdef DEBUG_VGA_REG
391 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
392 #endif
393 break;
394 case VGA_PEL_IR:
395 val = s->dac_state;
396 break;
397 case VGA_PEL_IW:
398 val = s->dac_write_index;
399 break;
400 case VGA_PEL_D:
401 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
402 if (++s->dac_sub_index == 3) {
403 s->dac_sub_index = 0;
404 s->dac_read_index++;
406 break;
407 case VGA_FTC_R:
408 val = s->fcr;
409 break;
410 case VGA_MIS_R:
411 val = s->msr;
412 break;
413 case VGA_GFX_I:
414 val = s->gr_index;
415 break;
416 case VGA_GFX_D:
417 val = s->gr[s->gr_index];
418 #ifdef DEBUG_VGA_REG
419 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
420 #endif
421 break;
422 case VGA_CRT_IM:
423 case VGA_CRT_IC:
424 val = s->cr_index;
425 break;
426 case VGA_CRT_DM:
427 case VGA_CRT_DC:
428 val = s->cr[s->cr_index];
429 #ifdef DEBUG_VGA_REG
430 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
431 #endif
432 break;
433 case VGA_IS1_RM:
434 case VGA_IS1_RC:
435 /* just toggle to fool polling */
436 val = s->st01 = s->retrace(s);
437 s->ar_flip_flop = 0;
438 break;
439 default:
440 val = 0x00;
441 break;
444 #if defined(DEBUG_VGA)
445 printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
446 #endif
447 return val;
450 void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
452 VGACommonState *s = opaque;
453 int index;
455 /* check port range access depending on color/monochrome mode */
456 if (vga_ioport_invalid(s, addr)) {
457 return;
459 #ifdef DEBUG_VGA
460 printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
461 #endif
463 switch(addr) {
464 case VGA_ATT_W:
465 if (s->ar_flip_flop == 0) {
466 val &= 0x3f;
467 s->ar_index = val;
468 } else {
469 index = s->ar_index & 0x1f;
470 switch(index) {
471 case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
472 s->ar[index] = val & 0x3f;
473 break;
474 case VGA_ATC_MODE:
475 s->ar[index] = val & ~0x10;
476 break;
477 case VGA_ATC_OVERSCAN:
478 s->ar[index] = val;
479 break;
480 case VGA_ATC_PLANE_ENABLE:
481 s->ar[index] = val & ~0xc0;
482 break;
483 case VGA_ATC_PEL:
484 s->ar[index] = val & ~0xf0;
485 break;
486 case VGA_ATC_COLOR_PAGE:
487 s->ar[index] = val & ~0xf0;
488 break;
489 default:
490 break;
493 s->ar_flip_flop ^= 1;
494 break;
495 case VGA_MIS_W:
496 s->msr = val & ~0x10;
497 s->update_retrace_info(s);
498 break;
499 case VGA_SEQ_I:
500 s->sr_index = val & 7;
501 break;
502 case VGA_SEQ_D:
503 #ifdef DEBUG_VGA_REG
504 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
505 #endif
506 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
507 if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
508 s->update_retrace_info(s);
510 vga_update_memory_access(s);
511 break;
512 case VGA_PEL_IR:
513 s->dac_read_index = val;
514 s->dac_sub_index = 0;
515 s->dac_state = 3;
516 break;
517 case VGA_PEL_IW:
518 s->dac_write_index = val;
519 s->dac_sub_index = 0;
520 s->dac_state = 0;
521 break;
522 case VGA_PEL_D:
523 s->dac_cache[s->dac_sub_index] = val;
524 if (++s->dac_sub_index == 3) {
525 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
526 s->dac_sub_index = 0;
527 s->dac_write_index++;
529 break;
530 case VGA_GFX_I:
531 s->gr_index = val & 0x0f;
532 break;
533 case VGA_GFX_D:
534 #ifdef DEBUG_VGA_REG
535 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
536 #endif
537 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
538 vga_update_memory_access(s);
539 break;
540 case VGA_CRT_IM:
541 case VGA_CRT_IC:
542 s->cr_index = val;
543 break;
544 case VGA_CRT_DM:
545 case VGA_CRT_DC:
546 #ifdef DEBUG_VGA_REG
547 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
548 #endif
549 /* handle CR0-7 protection */
550 if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
551 s->cr_index <= VGA_CRTC_OVERFLOW) {
552 /* can always write bit 4 of CR7 */
553 if (s->cr_index == VGA_CRTC_OVERFLOW) {
554 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
555 (val & 0x10);
557 return;
559 s->cr[s->cr_index] = val;
561 switch(s->cr_index) {
562 case VGA_CRTC_H_TOTAL:
563 case VGA_CRTC_H_SYNC_START:
564 case VGA_CRTC_H_SYNC_END:
565 case VGA_CRTC_V_TOTAL:
566 case VGA_CRTC_OVERFLOW:
567 case VGA_CRTC_V_SYNC_END:
568 case VGA_CRTC_MODE:
569 s->update_retrace_info(s);
570 break;
572 break;
573 case VGA_IS1_RM:
574 case VGA_IS1_RC:
575 s->fcr = val & 0x10;
576 break;
580 #ifdef CONFIG_BOCHS_VBE
581 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
583 VGACommonState *s = opaque;
584 uint32_t val;
585 val = s->vbe_index;
586 return val;
589 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
591 VGACommonState *s = opaque;
592 uint32_t val;
594 if (s->vbe_index < VBE_DISPI_INDEX_NB) {
595 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
596 switch(s->vbe_index) {
597 /* XXX: do not hardcode ? */
598 case VBE_DISPI_INDEX_XRES:
599 val = VBE_DISPI_MAX_XRES;
600 break;
601 case VBE_DISPI_INDEX_YRES:
602 val = VBE_DISPI_MAX_YRES;
603 break;
604 case VBE_DISPI_INDEX_BPP:
605 val = VBE_DISPI_MAX_BPP;
606 break;
607 default:
608 val = s->vbe_regs[s->vbe_index];
609 break;
611 } else {
612 val = s->vbe_regs[s->vbe_index];
614 } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
615 val = s->vram_size / (64 * 1024);
616 } else {
617 val = 0;
619 #ifdef DEBUG_BOCHS_VBE
620 printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
621 #endif
622 return val;
625 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
627 VGACommonState *s = opaque;
628 s->vbe_index = val;
631 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
633 VGACommonState *s = opaque;
635 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
636 #ifdef DEBUG_BOCHS_VBE
637 printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
638 #endif
639 switch(s->vbe_index) {
640 case VBE_DISPI_INDEX_ID:
641 if (val == VBE_DISPI_ID0 ||
642 val == VBE_DISPI_ID1 ||
643 val == VBE_DISPI_ID2 ||
644 val == VBE_DISPI_ID3 ||
645 val == VBE_DISPI_ID4) {
646 s->vbe_regs[s->vbe_index] = val;
648 break;
649 case VBE_DISPI_INDEX_XRES:
650 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
651 s->vbe_regs[s->vbe_index] = val;
653 break;
654 case VBE_DISPI_INDEX_YRES:
655 if (val <= VBE_DISPI_MAX_YRES) {
656 s->vbe_regs[s->vbe_index] = val;
658 break;
659 case VBE_DISPI_INDEX_BPP:
660 if (val == 0)
661 val = 8;
662 if (val == 4 || val == 8 || val == 15 ||
663 val == 16 || val == 24 || val == 32) {
664 s->vbe_regs[s->vbe_index] = val;
666 break;
667 case VBE_DISPI_INDEX_BANK:
668 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
669 val &= (s->vbe_bank_mask >> 2);
670 } else {
671 val &= s->vbe_bank_mask;
673 s->vbe_regs[s->vbe_index] = val;
674 s->bank_offset = (val << 16);
675 vga_update_memory_access(s);
676 break;
677 case VBE_DISPI_INDEX_ENABLE:
678 if ((val & VBE_DISPI_ENABLED) &&
679 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
680 int h, shift_control;
682 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
683 s->vbe_regs[VBE_DISPI_INDEX_XRES];
684 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
685 s->vbe_regs[VBE_DISPI_INDEX_YRES];
686 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
687 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
689 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
690 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
691 else
692 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
693 ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
694 s->vbe_start_addr = 0;
696 /* clear the screen (should be done in BIOS) */
697 if (!(val & VBE_DISPI_NOCLEARMEM)) {
698 memset(s->vram_ptr, 0,
699 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
702 /* we initialize the VGA graphic mode (should be done
703 in BIOS) */
704 /* graphic mode + memory map 1 */
705 s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
706 VGA_GR06_GRAPHICS_MODE;
707 s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
708 s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
709 /* width */
710 s->cr[VGA_CRTC_H_DISP] =
711 (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
712 /* height (only meaningful if < 1024) */
713 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
714 s->cr[VGA_CRTC_V_DISP_END] = h;
715 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
716 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
717 /* line compare to 1023 */
718 s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
719 s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
720 s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
722 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
723 shift_control = 0;
724 s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
725 } else {
726 shift_control = 2;
727 /* set chain 4 mode */
728 s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
729 /* activate all planes */
730 s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
732 s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
733 (shift_control << 5);
734 s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
735 } else {
736 /* XXX: the bios should do that */
737 s->bank_offset = 0;
739 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
740 s->vbe_regs[s->vbe_index] = val;
741 vga_update_memory_access(s);
742 break;
743 case VBE_DISPI_INDEX_VIRT_WIDTH:
745 int w, h, line_offset;
747 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
748 return;
749 w = val;
750 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
751 line_offset = w >> 1;
752 else
753 line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
754 h = s->vram_size / line_offset;
755 /* XXX: support weird bochs semantics ? */
756 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
757 return;
758 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
759 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
760 s->vbe_line_offset = line_offset;
762 break;
763 case VBE_DISPI_INDEX_X_OFFSET:
764 case VBE_DISPI_INDEX_Y_OFFSET:
766 int x;
767 s->vbe_regs[s->vbe_index] = val;
768 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
769 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
770 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
771 s->vbe_start_addr += x >> 1;
772 else
773 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
774 s->vbe_start_addr >>= 2;
776 break;
777 default:
778 break;
782 #endif
784 /* called for accesses between 0xa0000 and 0xc0000 */
785 uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
787 int memory_map_mode, plane;
788 uint32_t ret;
790 /* convert to VGA memory offset */
791 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
792 addr &= 0x1ffff;
793 switch(memory_map_mode) {
794 case 0:
795 break;
796 case 1:
797 if (addr >= 0x10000)
798 return 0xff;
799 addr += s->bank_offset;
800 break;
801 case 2:
802 addr -= 0x10000;
803 if (addr >= 0x8000)
804 return 0xff;
805 break;
806 default:
807 case 3:
808 addr -= 0x18000;
809 if (addr >= 0x8000)
810 return 0xff;
811 break;
814 if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
815 /* chain 4 mode : simplest access */
816 ret = s->vram_ptr[addr];
817 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
818 /* odd/even mode (aka text mode mapping) */
819 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
820 ret = s->vram_ptr[((addr & ~1) << 1) | plane];
821 } else {
822 /* standard VGA latched access */
823 s->latch = ((uint32_t *)s->vram_ptr)[addr];
825 if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
826 /* read mode 0 */
827 plane = s->gr[VGA_GFX_PLANE_READ];
828 ret = GET_PLANE(s->latch, plane);
829 } else {
830 /* read mode 1 */
831 ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
832 mask16[s->gr[VGA_GFX_COMPARE_MASK]];
833 ret |= ret >> 16;
834 ret |= ret >> 8;
835 ret = (~ret) & 0xff;
838 return ret;
841 /* called for accesses between 0xa0000 and 0xc0000 */
842 void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
844 int memory_map_mode, plane, write_mode, b, func_select, mask;
845 uint32_t write_mask, bit_mask, set_mask;
847 #ifdef DEBUG_VGA_MEM
848 printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
849 #endif
850 /* convert to VGA memory offset */
851 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
852 addr &= 0x1ffff;
853 switch(memory_map_mode) {
854 case 0:
855 break;
856 case 1:
857 if (addr >= 0x10000)
858 return;
859 addr += s->bank_offset;
860 break;
861 case 2:
862 addr -= 0x10000;
863 if (addr >= 0x8000)
864 return;
865 break;
866 default:
867 case 3:
868 addr -= 0x18000;
869 if (addr >= 0x8000)
870 return;
871 break;
874 if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
875 /* chain 4 mode : simplest access */
876 plane = addr & 3;
877 mask = (1 << plane);
878 if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
879 s->vram_ptr[addr] = val;
880 #ifdef DEBUG_VGA_MEM
881 printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
882 #endif
883 s->plane_updated |= mask; /* only used to detect font change */
884 memory_region_set_dirty(&s->vram, addr, 1);
886 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
887 /* odd/even mode (aka text mode mapping) */
888 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
889 mask = (1 << plane);
890 if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
891 addr = ((addr & ~1) << 1) | plane;
892 s->vram_ptr[addr] = val;
893 #ifdef DEBUG_VGA_MEM
894 printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
895 #endif
896 s->plane_updated |= mask; /* only used to detect font change */
897 memory_region_set_dirty(&s->vram, addr, 1);
899 } else {
900 /* standard VGA latched access */
901 write_mode = s->gr[VGA_GFX_MODE] & 3;
902 switch(write_mode) {
903 default:
904 case 0:
905 /* rotate */
906 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
907 val = ((val >> b) | (val << (8 - b))) & 0xff;
908 val |= val << 8;
909 val |= val << 16;
911 /* apply set/reset mask */
912 set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
913 val = (val & ~set_mask) |
914 (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
915 bit_mask = s->gr[VGA_GFX_BIT_MASK];
916 break;
917 case 1:
918 val = s->latch;
919 goto do_write;
920 case 2:
921 val = mask16[val & 0x0f];
922 bit_mask = s->gr[VGA_GFX_BIT_MASK];
923 break;
924 case 3:
925 /* rotate */
926 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
927 val = (val >> b) | (val << (8 - b));
929 bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
930 val = mask16[s->gr[VGA_GFX_SR_VALUE]];
931 break;
934 /* apply logical operation */
935 func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
936 switch(func_select) {
937 case 0:
938 default:
939 /* nothing to do */
940 break;
941 case 1:
942 /* and */
943 val &= s->latch;
944 break;
945 case 2:
946 /* or */
947 val |= s->latch;
948 break;
949 case 3:
950 /* xor */
951 val ^= s->latch;
952 break;
955 /* apply bit mask */
956 bit_mask |= bit_mask << 8;
957 bit_mask |= bit_mask << 16;
958 val = (val & bit_mask) | (s->latch & ~bit_mask);
960 do_write:
961 /* mask data according to sr[2] */
962 mask = s->sr[VGA_SEQ_PLANE_WRITE];
963 s->plane_updated |= mask; /* only used to detect font change */
964 write_mask = mask16[mask];
965 ((uint32_t *)s->vram_ptr)[addr] =
966 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
967 (val & write_mask);
968 #ifdef DEBUG_VGA_MEM
969 printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
970 addr * 4, write_mask, val);
971 #endif
972 memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
976 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
977 const uint8_t *font_ptr, int h,
978 uint32_t fgcol, uint32_t bgcol);
979 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
980 const uint8_t *font_ptr, int h,
981 uint32_t fgcol, uint32_t bgcol, int dup9);
982 typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
983 const uint8_t *s, int width);
985 #define DEPTH 8
986 #include "vga_template.h"
988 #define DEPTH 15
989 #include "vga_template.h"
991 #define BGR_FORMAT
992 #define DEPTH 15
993 #include "vga_template.h"
995 #define DEPTH 16
996 #include "vga_template.h"
998 #define BGR_FORMAT
999 #define DEPTH 16
1000 #include "vga_template.h"
1002 #define DEPTH 32
1003 #include "vga_template.h"
1005 #define BGR_FORMAT
1006 #define DEPTH 32
1007 #include "vga_template.h"
1009 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1011 unsigned int col;
1012 col = rgb_to_pixel8(r, g, b);
1013 col |= col << 8;
1014 col |= col << 16;
1015 return col;
1018 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1020 unsigned int col;
1021 col = rgb_to_pixel15(r, g, b);
1022 col |= col << 16;
1023 return col;
1026 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1027 unsigned int b)
1029 unsigned int col;
1030 col = rgb_to_pixel15bgr(r, g, b);
1031 col |= col << 16;
1032 return col;
1035 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1037 unsigned int col;
1038 col = rgb_to_pixel16(r, g, b);
1039 col |= col << 16;
1040 return col;
1043 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1044 unsigned int b)
1046 unsigned int col;
1047 col = rgb_to_pixel16bgr(r, g, b);
1048 col |= col << 16;
1049 return col;
1052 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1054 unsigned int col;
1055 col = rgb_to_pixel32(r, g, b);
1056 return col;
1059 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1061 unsigned int col;
1062 col = rgb_to_pixel32bgr(r, g, b);
1063 return col;
1066 /* return true if the palette was modified */
1067 static int update_palette16(VGACommonState *s)
1069 int full_update, i;
1070 uint32_t v, col, *palette;
1072 full_update = 0;
1073 palette = s->last_palette;
1074 for(i = 0; i < 16; i++) {
1075 v = s->ar[i];
1076 if (s->ar[VGA_ATC_MODE] & 0x80) {
1077 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
1078 } else {
1079 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
1081 v = v * 3;
1082 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1083 c6_to_8(s->palette[v + 1]),
1084 c6_to_8(s->palette[v + 2]));
1085 if (col != palette[i]) {
1086 full_update = 1;
1087 palette[i] = col;
1090 return full_update;
1093 /* return true if the palette was modified */
1094 static int update_palette256(VGACommonState *s)
1096 int full_update, i;
1097 uint32_t v, col, *palette;
1099 full_update = 0;
1100 palette = s->last_palette;
1101 v = 0;
1102 for(i = 0; i < 256; i++) {
1103 if (s->dac_8bit) {
1104 col = s->rgb_to_pixel(s->palette[v],
1105 s->palette[v + 1],
1106 s->palette[v + 2]);
1107 } else {
1108 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1109 c6_to_8(s->palette[v + 1]),
1110 c6_to_8(s->palette[v + 2]));
1112 if (col != palette[i]) {
1113 full_update = 1;
1114 palette[i] = col;
1116 v += 3;
1118 return full_update;
1121 static void vga_get_offsets(VGACommonState *s,
1122 uint32_t *pline_offset,
1123 uint32_t *pstart_addr,
1124 uint32_t *pline_compare)
1126 uint32_t start_addr, line_offset, line_compare;
1127 #ifdef CONFIG_BOCHS_VBE
1128 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1129 line_offset = s->vbe_line_offset;
1130 start_addr = s->vbe_start_addr;
1131 line_compare = 65535;
1132 } else
1133 #endif
1135 /* compute line_offset in bytes */
1136 line_offset = s->cr[VGA_CRTC_OFFSET];
1137 line_offset <<= 3;
1139 /* starting address */
1140 start_addr = s->cr[VGA_CRTC_START_LO] |
1141 (s->cr[VGA_CRTC_START_HI] << 8);
1143 /* line compare */
1144 line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
1145 ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
1146 ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
1148 *pline_offset = line_offset;
1149 *pstart_addr = start_addr;
1150 *pline_compare = line_compare;
1153 /* update start_addr and line_offset. Return TRUE if modified */
1154 static int update_basic_params(VGACommonState *s)
1156 int full_update;
1157 uint32_t start_addr, line_offset, line_compare;
1159 full_update = 0;
1161 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1163 if (line_offset != s->line_offset ||
1164 start_addr != s->start_addr ||
1165 line_compare != s->line_compare) {
1166 s->line_offset = line_offset;
1167 s->start_addr = start_addr;
1168 s->line_compare = line_compare;
1169 full_update = 1;
1171 return full_update;
1174 #define NB_DEPTHS 7
1176 static inline int get_depth_index(DisplayState *s)
1178 switch(ds_get_bits_per_pixel(s)) {
1179 default:
1180 case 8:
1181 return 0;
1182 case 15:
1183 return 1;
1184 case 16:
1185 return 2;
1186 case 32:
1187 if (is_surface_bgr(s->surface))
1188 return 4;
1189 else
1190 return 3;
1194 static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1195 vga_draw_glyph8_8,
1196 vga_draw_glyph8_16,
1197 vga_draw_glyph8_16,
1198 vga_draw_glyph8_32,
1199 vga_draw_glyph8_32,
1200 vga_draw_glyph8_16,
1201 vga_draw_glyph8_16,
1204 static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1205 vga_draw_glyph16_8,
1206 vga_draw_glyph16_16,
1207 vga_draw_glyph16_16,
1208 vga_draw_glyph16_32,
1209 vga_draw_glyph16_32,
1210 vga_draw_glyph16_16,
1211 vga_draw_glyph16_16,
1214 static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1215 vga_draw_glyph9_8,
1216 vga_draw_glyph9_16,
1217 vga_draw_glyph9_16,
1218 vga_draw_glyph9_32,
1219 vga_draw_glyph9_32,
1220 vga_draw_glyph9_16,
1221 vga_draw_glyph9_16,
1224 static const uint8_t cursor_glyph[32 * 4] = {
1225 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1227 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1228 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1229 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1230 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1231 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1232 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1233 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1234 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1235 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1236 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1237 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1238 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1239 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1240 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1243 static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1244 int *pcwidth, int *pcheight)
1246 int width, cwidth, height, cheight;
1248 /* total width & height */
1249 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1250 cwidth = 8;
1251 if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
1252 cwidth = 9;
1254 if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
1255 cwidth = 16; /* NOTE: no 18 pixel wide */
1257 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1258 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1259 /* ugly hack for CGA 160x100x16 - explain me the logic */
1260 height = 100;
1261 } else {
1262 height = s->cr[VGA_CRTC_V_DISP_END] |
1263 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1264 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1265 height = (height + 1) / cheight;
1268 *pwidth = width;
1269 *pheight = height;
1270 *pcwidth = cwidth;
1271 *pcheight = cheight;
1274 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1276 static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1277 rgb_to_pixel8_dup,
1278 rgb_to_pixel15_dup,
1279 rgb_to_pixel16_dup,
1280 rgb_to_pixel32_dup,
1281 rgb_to_pixel32bgr_dup,
1282 rgb_to_pixel15bgr_dup,
1283 rgb_to_pixel16bgr_dup,
1287 * Text mode update
1288 * Missing:
1289 * - double scan
1290 * - double width
1291 * - underline
1292 * - flashing
1294 static void vga_draw_text(VGACommonState *s, int full_update)
1296 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1297 int cx_min, cx_max, linesize, x_incr, line, line1;
1298 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1299 uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1300 const uint8_t *font_ptr, *font_base[2];
1301 int dup9, line_offset, depth_index;
1302 uint32_t *palette;
1303 uint32_t *ch_attr_ptr;
1304 vga_draw_glyph8_func *vga_draw_glyph8;
1305 vga_draw_glyph9_func *vga_draw_glyph9;
1306 int64_t now = qemu_get_clock_ms(vm_clock);
1308 /* compute font data address (in plane 2) */
1309 v = s->sr[VGA_SEQ_CHARACTER_MAP];
1310 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1311 if (offset != s->font_offsets[0]) {
1312 s->font_offsets[0] = offset;
1313 full_update = 1;
1315 font_base[0] = s->vram_ptr + offset;
1317 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1318 font_base[1] = s->vram_ptr + offset;
1319 if (offset != s->font_offsets[1]) {
1320 s->font_offsets[1] = offset;
1321 full_update = 1;
1323 if (s->plane_updated & (1 << 2) || s->chain4_alias) {
1324 /* if the plane 2 was modified since the last display, it
1325 indicates the font may have been modified */
1326 s->plane_updated = 0;
1327 full_update = 1;
1329 full_update |= update_basic_params(s);
1331 line_offset = s->line_offset;
1333 vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1334 if ((height * width) <= 1) {
1335 /* better than nothing: exit if transient size is too small */
1336 return;
1338 if ((height * width) > CH_ATTR_SIZE) {
1339 /* better than nothing: exit if transient size is too big */
1340 return;
1343 if (width != s->last_width || height != s->last_height ||
1344 cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1345 s->last_scr_width = width * cw;
1346 s->last_scr_height = height * cheight;
1347 qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1348 s->last_depth = 0;
1349 s->last_width = width;
1350 s->last_height = height;
1351 s->last_ch = cheight;
1352 s->last_cw = cw;
1353 full_update = 1;
1355 s->rgb_to_pixel =
1356 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1357 full_update |= update_palette16(s);
1358 palette = s->last_palette;
1359 x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1361 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1362 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1363 if (cursor_offset != s->cursor_offset ||
1364 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1365 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1366 /* if the cursor position changed, we update the old and new
1367 chars */
1368 if (s->cursor_offset < CH_ATTR_SIZE)
1369 s->last_ch_attr[s->cursor_offset] = -1;
1370 if (cursor_offset < CH_ATTR_SIZE)
1371 s->last_ch_attr[cursor_offset] = -1;
1372 s->cursor_offset = cursor_offset;
1373 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1374 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1376 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1377 if (now >= s->cursor_blink_time) {
1378 s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
1379 s->cursor_visible_phase = !s->cursor_visible_phase;
1382 depth_index = get_depth_index(s->ds);
1383 if (cw == 16)
1384 vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1385 else
1386 vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1387 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1389 dest = ds_get_data(s->ds);
1390 linesize = ds_get_linesize(s->ds);
1391 ch_attr_ptr = s->last_ch_attr;
1392 line = 0;
1393 offset = s->start_addr * 4;
1394 for(cy = 0; cy < height; cy++) {
1395 d1 = dest;
1396 src = s->vram_ptr + offset;
1397 cx_min = width;
1398 cx_max = -1;
1399 for(cx = 0; cx < width; cx++) {
1400 ch_attr = *(uint16_t *)src;
1401 if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
1402 if (cx < cx_min)
1403 cx_min = cx;
1404 if (cx > cx_max)
1405 cx_max = cx;
1406 *ch_attr_ptr = ch_attr;
1407 #ifdef HOST_WORDS_BIGENDIAN
1408 ch = ch_attr >> 8;
1409 cattr = ch_attr & 0xff;
1410 #else
1411 ch = ch_attr & 0xff;
1412 cattr = ch_attr >> 8;
1413 #endif
1414 font_ptr = font_base[(cattr >> 3) & 1];
1415 font_ptr += 32 * 4 * ch;
1416 bgcol = palette[cattr >> 4];
1417 fgcol = palette[cattr & 0x0f];
1418 if (cw != 9) {
1419 vga_draw_glyph8(d1, linesize,
1420 font_ptr, cheight, fgcol, bgcol);
1421 } else {
1422 dup9 = 0;
1423 if (ch >= 0xb0 && ch <= 0xdf &&
1424 (s->ar[VGA_ATC_MODE] & 0x04)) {
1425 dup9 = 1;
1427 vga_draw_glyph9(d1, linesize,
1428 font_ptr, cheight, fgcol, bgcol, dup9);
1430 if (src == cursor_ptr &&
1431 !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1432 s->cursor_visible_phase) {
1433 int line_start, line_last, h;
1434 /* draw the cursor */
1435 line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1436 line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1437 /* XXX: check that */
1438 if (line_last > cheight - 1)
1439 line_last = cheight - 1;
1440 if (line_last >= line_start && line_start < cheight) {
1441 h = line_last - line_start + 1;
1442 d = d1 + linesize * line_start;
1443 if (cw != 9) {
1444 vga_draw_glyph8(d, linesize,
1445 cursor_glyph, h, fgcol, bgcol);
1446 } else {
1447 vga_draw_glyph9(d, linesize,
1448 cursor_glyph, h, fgcol, bgcol, 1);
1453 d1 += x_incr;
1454 src += 4;
1455 ch_attr_ptr++;
1457 if (cx_max != -1) {
1458 dpy_update(s->ds, cx_min * cw, cy * cheight,
1459 (cx_max - cx_min + 1) * cw, cheight);
1461 dest += linesize * cheight;
1462 line1 = line + cheight;
1463 offset += line_offset;
1464 if (line < s->line_compare && line1 >= s->line_compare) {
1465 offset = 0;
1467 line = line1;
1471 enum {
1472 VGA_DRAW_LINE2,
1473 VGA_DRAW_LINE2D2,
1474 VGA_DRAW_LINE4,
1475 VGA_DRAW_LINE4D2,
1476 VGA_DRAW_LINE8D2,
1477 VGA_DRAW_LINE8,
1478 VGA_DRAW_LINE15,
1479 VGA_DRAW_LINE16,
1480 VGA_DRAW_LINE24,
1481 VGA_DRAW_LINE32,
1482 VGA_DRAW_LINE_NB,
1485 static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1486 vga_draw_line2_8,
1487 vga_draw_line2_16,
1488 vga_draw_line2_16,
1489 vga_draw_line2_32,
1490 vga_draw_line2_32,
1491 vga_draw_line2_16,
1492 vga_draw_line2_16,
1494 vga_draw_line2d2_8,
1495 vga_draw_line2d2_16,
1496 vga_draw_line2d2_16,
1497 vga_draw_line2d2_32,
1498 vga_draw_line2d2_32,
1499 vga_draw_line2d2_16,
1500 vga_draw_line2d2_16,
1502 vga_draw_line4_8,
1503 vga_draw_line4_16,
1504 vga_draw_line4_16,
1505 vga_draw_line4_32,
1506 vga_draw_line4_32,
1507 vga_draw_line4_16,
1508 vga_draw_line4_16,
1510 vga_draw_line4d2_8,
1511 vga_draw_line4d2_16,
1512 vga_draw_line4d2_16,
1513 vga_draw_line4d2_32,
1514 vga_draw_line4d2_32,
1515 vga_draw_line4d2_16,
1516 vga_draw_line4d2_16,
1518 vga_draw_line8d2_8,
1519 vga_draw_line8d2_16,
1520 vga_draw_line8d2_16,
1521 vga_draw_line8d2_32,
1522 vga_draw_line8d2_32,
1523 vga_draw_line8d2_16,
1524 vga_draw_line8d2_16,
1526 vga_draw_line8_8,
1527 vga_draw_line8_16,
1528 vga_draw_line8_16,
1529 vga_draw_line8_32,
1530 vga_draw_line8_32,
1531 vga_draw_line8_16,
1532 vga_draw_line8_16,
1534 vga_draw_line15_8,
1535 vga_draw_line15_15,
1536 vga_draw_line15_16,
1537 vga_draw_line15_32,
1538 vga_draw_line15_32bgr,
1539 vga_draw_line15_15bgr,
1540 vga_draw_line15_16bgr,
1542 vga_draw_line16_8,
1543 vga_draw_line16_15,
1544 vga_draw_line16_16,
1545 vga_draw_line16_32,
1546 vga_draw_line16_32bgr,
1547 vga_draw_line16_15bgr,
1548 vga_draw_line16_16bgr,
1550 vga_draw_line24_8,
1551 vga_draw_line24_15,
1552 vga_draw_line24_16,
1553 vga_draw_line24_32,
1554 vga_draw_line24_32bgr,
1555 vga_draw_line24_15bgr,
1556 vga_draw_line24_16bgr,
1558 vga_draw_line32_8,
1559 vga_draw_line32_15,
1560 vga_draw_line32_16,
1561 vga_draw_line32_32,
1562 vga_draw_line32_32bgr,
1563 vga_draw_line32_15bgr,
1564 vga_draw_line32_16bgr,
1567 static int vga_get_bpp(VGACommonState *s)
1569 int ret;
1570 #ifdef CONFIG_BOCHS_VBE
1571 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1572 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1573 } else
1574 #endif
1576 ret = 0;
1578 return ret;
1581 static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1583 int width, height;
1585 #ifdef CONFIG_BOCHS_VBE
1586 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1587 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1588 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1589 } else
1590 #endif
1592 width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1593 height = s->cr[VGA_CRTC_V_DISP_END] |
1594 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1595 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1596 height = (height + 1);
1598 *pwidth = width;
1599 *pheight = height;
1602 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1604 int y;
1605 if (y1 >= VGA_MAX_HEIGHT)
1606 return;
1607 if (y2 >= VGA_MAX_HEIGHT)
1608 y2 = VGA_MAX_HEIGHT;
1609 for(y = y1; y < y2; y++) {
1610 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1614 static void vga_sync_dirty_bitmap(VGACommonState *s)
1616 memory_region_sync_dirty_bitmap(&s->vram);
1619 void vga_dirty_log_start(VGACommonState *s)
1621 memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1624 void vga_dirty_log_stop(VGACommonState *s)
1626 memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1630 * graphic modes
1632 static void vga_draw_graphic(VGACommonState *s, int full_update)
1634 int y1, y, update, linesize, y_start, double_scan, mask, depth;
1635 int width, height, shift_control, line_offset, bwidth, bits;
1636 ram_addr_t page0, page1, page_min, page_max;
1637 int disp_width, multi_scan, multi_run;
1638 uint8_t *d;
1639 uint32_t v, addr1, addr;
1640 vga_draw_line_func *vga_draw_line;
1642 full_update |= update_basic_params(s);
1644 if (!full_update)
1645 vga_sync_dirty_bitmap(s);
1647 s->get_resolution(s, &width, &height);
1648 disp_width = width;
1650 shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1651 double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1652 if (shift_control != 1) {
1653 multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1654 - 1;
1655 } else {
1656 /* in CGA modes, multi_scan is ignored */
1657 /* XXX: is it correct ? */
1658 multi_scan = double_scan;
1660 multi_run = multi_scan;
1661 if (shift_control != s->shift_control ||
1662 double_scan != s->double_scan) {
1663 full_update = 1;
1664 s->shift_control = shift_control;
1665 s->double_scan = double_scan;
1668 if (shift_control == 0) {
1669 if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1670 disp_width <<= 1;
1672 } else if (shift_control == 1) {
1673 if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1674 disp_width <<= 1;
1678 depth = s->get_bpp(s);
1679 if (s->line_offset != s->last_line_offset ||
1680 disp_width != s->last_width ||
1681 height != s->last_height ||
1682 s->last_depth != depth) {
1683 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1684 if (depth == 16 || depth == 32) {
1685 #else
1686 if (depth == 32) {
1687 #endif
1688 qemu_free_displaysurface(s->ds);
1689 s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1690 s->line_offset,
1691 s->vram_ptr + (s->start_addr * 4));
1692 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1693 s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1694 #endif
1695 dpy_resize(s->ds);
1696 } else {
1697 qemu_console_resize(s->ds, disp_width, height);
1699 s->last_scr_width = disp_width;
1700 s->last_scr_height = height;
1701 s->last_width = disp_width;
1702 s->last_height = height;
1703 s->last_line_offset = s->line_offset;
1704 s->last_depth = depth;
1705 full_update = 1;
1706 } else if (is_buffer_shared(s->ds->surface) &&
1707 (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1708 s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1709 dpy_setdata(s->ds);
1712 s->rgb_to_pixel =
1713 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1715 if (shift_control == 0) {
1716 full_update |= update_palette16(s);
1717 if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1718 v = VGA_DRAW_LINE4D2;
1719 } else {
1720 v = VGA_DRAW_LINE4;
1722 bits = 4;
1723 } else if (shift_control == 1) {
1724 full_update |= update_palette16(s);
1725 if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1726 v = VGA_DRAW_LINE2D2;
1727 } else {
1728 v = VGA_DRAW_LINE2;
1730 bits = 4;
1731 } else {
1732 switch(s->get_bpp(s)) {
1733 default:
1734 case 0:
1735 full_update |= update_palette256(s);
1736 v = VGA_DRAW_LINE8D2;
1737 bits = 4;
1738 break;
1739 case 8:
1740 full_update |= update_palette256(s);
1741 v = VGA_DRAW_LINE8;
1742 bits = 8;
1743 break;
1744 case 15:
1745 v = VGA_DRAW_LINE15;
1746 bits = 16;
1747 break;
1748 case 16:
1749 v = VGA_DRAW_LINE16;
1750 bits = 16;
1751 break;
1752 case 24:
1753 v = VGA_DRAW_LINE24;
1754 bits = 24;
1755 break;
1756 case 32:
1757 v = VGA_DRAW_LINE32;
1758 bits = 32;
1759 break;
1762 vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1764 if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1765 s->cursor_invalidate(s);
1767 line_offset = s->line_offset;
1768 #if 0
1769 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",
1770 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1771 s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
1772 #endif
1773 addr1 = (s->start_addr * 4);
1774 bwidth = (width * bits + 7) / 8;
1775 y_start = -1;
1776 page_min = -1;
1777 page_max = 0;
1778 d = ds_get_data(s->ds);
1779 linesize = ds_get_linesize(s->ds);
1780 y1 = 0;
1781 for(y = 0; y < height; y++) {
1782 addr = addr1;
1783 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1784 int shift;
1785 /* CGA compatibility handling */
1786 shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1787 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1789 if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1790 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1792 update = full_update;
1793 page0 = addr;
1794 page1 = addr + bwidth - 1;
1795 update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
1796 DIRTY_MEMORY_VGA);
1797 /* explicit invalidation for the hardware cursor */
1798 update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1799 if (update) {
1800 if (y_start < 0)
1801 y_start = y;
1802 if (page0 < page_min)
1803 page_min = page0;
1804 if (page1 > page_max)
1805 page_max = page1;
1806 if (!(is_buffer_shared(s->ds->surface))) {
1807 vga_draw_line(s, d, s->vram_ptr + addr, width);
1808 if (s->cursor_draw_line)
1809 s->cursor_draw_line(s, d, y);
1811 } else {
1812 if (y_start >= 0) {
1813 /* flush to display */
1814 dpy_update(s->ds, 0, y_start,
1815 disp_width, y - y_start);
1816 y_start = -1;
1819 if (!multi_run) {
1820 mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1821 if ((y1 & mask) == mask)
1822 addr1 += line_offset;
1823 y1++;
1824 multi_run = multi_scan;
1825 } else {
1826 multi_run--;
1828 /* line compare acts on the displayed lines */
1829 if (y == s->line_compare)
1830 addr1 = 0;
1831 d += linesize;
1833 if (y_start >= 0) {
1834 /* flush to display */
1835 dpy_update(s->ds, 0, y_start,
1836 disp_width, y - y_start);
1838 /* reset modified pages */
1839 if (page_max >= page_min) {
1840 memory_region_reset_dirty(&s->vram,
1841 page_min,
1842 page_max - page_min,
1843 DIRTY_MEMORY_VGA);
1845 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1848 static void vga_draw_blank(VGACommonState *s, int full_update)
1850 int i, w, val;
1851 uint8_t *d;
1853 if (!full_update)
1854 return;
1855 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1856 return;
1858 s->rgb_to_pixel =
1859 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1860 if (ds_get_bits_per_pixel(s->ds) == 8)
1861 val = s->rgb_to_pixel(0, 0, 0);
1862 else
1863 val = 0;
1864 w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1865 d = ds_get_data(s->ds);
1866 for(i = 0; i < s->last_scr_height; i++) {
1867 memset(d, val, w);
1868 d += ds_get_linesize(s->ds);
1870 dpy_update(s->ds, 0, 0,
1871 s->last_scr_width, s->last_scr_height);
1874 #define GMODE_TEXT 0
1875 #define GMODE_GRAPH 1
1876 #define GMODE_BLANK 2
1878 static void vga_update_display(void *opaque)
1880 VGACommonState *s = opaque;
1881 int full_update, graphic_mode;
1883 qemu_flush_coalesced_mmio_buffer();
1885 if (ds_get_bits_per_pixel(s->ds) == 0) {
1886 /* nothing to do */
1887 } else {
1888 full_update = 0;
1889 if (!(s->ar_index & 0x20)) {
1890 graphic_mode = GMODE_BLANK;
1891 } else {
1892 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1894 if (graphic_mode != s->graphic_mode) {
1895 s->graphic_mode = graphic_mode;
1896 s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
1897 full_update = 1;
1899 switch(graphic_mode) {
1900 case GMODE_TEXT:
1901 vga_draw_text(s, full_update);
1902 break;
1903 case GMODE_GRAPH:
1904 vga_draw_graphic(s, full_update);
1905 break;
1906 case GMODE_BLANK:
1907 default:
1908 vga_draw_blank(s, full_update);
1909 break;
1914 /* force a full display refresh */
1915 static void vga_invalidate_display(void *opaque)
1917 VGACommonState *s = opaque;
1919 s->last_width = -1;
1920 s->last_height = -1;
1923 void vga_common_reset(VGACommonState *s)
1925 s->sr_index = 0;
1926 memset(s->sr, '\0', sizeof(s->sr));
1927 s->gr_index = 0;
1928 memset(s->gr, '\0', sizeof(s->gr));
1929 s->ar_index = 0;
1930 memset(s->ar, '\0', sizeof(s->ar));
1931 s->ar_flip_flop = 0;
1932 s->cr_index = 0;
1933 memset(s->cr, '\0', sizeof(s->cr));
1934 s->msr = 0;
1935 s->fcr = 0;
1936 s->st00 = 0;
1937 s->st01 = 0;
1938 s->dac_state = 0;
1939 s->dac_sub_index = 0;
1940 s->dac_read_index = 0;
1941 s->dac_write_index = 0;
1942 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1943 s->dac_8bit = 0;
1944 memset(s->palette, '\0', sizeof(s->palette));
1945 s->bank_offset = 0;
1946 #ifdef CONFIG_BOCHS_VBE
1947 s->vbe_index = 0;
1948 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1949 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1950 s->vbe_start_addr = 0;
1951 s->vbe_line_offset = 0;
1952 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1953 #endif
1954 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1955 s->graphic_mode = -1; /* force full update */
1956 s->shift_control = 0;
1957 s->double_scan = 0;
1958 s->line_offset = 0;
1959 s->line_compare = 0;
1960 s->start_addr = 0;
1961 s->plane_updated = 0;
1962 s->last_cw = 0;
1963 s->last_ch = 0;
1964 s->last_width = 0;
1965 s->last_height = 0;
1966 s->last_scr_width = 0;
1967 s->last_scr_height = 0;
1968 s->cursor_start = 0;
1969 s->cursor_end = 0;
1970 s->cursor_offset = 0;
1971 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1972 memset(s->last_palette, '\0', sizeof(s->last_palette));
1973 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1974 switch (vga_retrace_method) {
1975 case VGA_RETRACE_DUMB:
1976 break;
1977 case VGA_RETRACE_PRECISE:
1978 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1979 break;
1981 vga_update_memory_access(s);
1984 static void vga_reset(void *opaque)
1986 VGACommonState *s = opaque;
1987 vga_common_reset(s);
1990 #define TEXTMODE_X(x) ((x) % width)
1991 #define TEXTMODE_Y(x) ((x) / width)
1992 #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1993 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1994 /* relay text rendering to the display driver
1995 * instead of doing a full vga_update_display() */
1996 static void vga_update_text(void *opaque, console_ch_t *chardata)
1998 VGACommonState *s = opaque;
1999 int graphic_mode, i, cursor_offset, cursor_visible;
2000 int cw, cheight, width, height, size, c_min, c_max;
2001 uint32_t *src;
2002 console_ch_t *dst, val;
2003 char msg_buffer[80];
2004 int full_update = 0;
2006 qemu_flush_coalesced_mmio_buffer();
2008 if (!(s->ar_index & 0x20)) {
2009 graphic_mode = GMODE_BLANK;
2010 } else {
2011 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
2013 if (graphic_mode != s->graphic_mode) {
2014 s->graphic_mode = graphic_mode;
2015 full_update = 1;
2017 if (s->last_width == -1) {
2018 s->last_width = 0;
2019 full_update = 1;
2022 switch (graphic_mode) {
2023 case GMODE_TEXT:
2024 /* TODO: update palette */
2025 full_update |= update_basic_params(s);
2027 /* total width & height */
2028 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2029 cw = 8;
2030 if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2031 cw = 9;
2033 if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2034 cw = 16; /* NOTE: no 18 pixel wide */
2036 width = (s->cr[VGA_CRTC_H_DISP] + 1);
2037 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2038 /* ugly hack for CGA 160x100x16 - explain me the logic */
2039 height = 100;
2040 } else {
2041 height = s->cr[VGA_CRTC_V_DISP_END] |
2042 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2043 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
2044 height = (height + 1) / cheight;
2047 size = (height * width);
2048 if (size > CH_ATTR_SIZE) {
2049 if (!full_update)
2050 return;
2052 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2053 width, height);
2054 break;
2057 if (width != s->last_width || height != s->last_height ||
2058 cw != s->last_cw || cheight != s->last_ch) {
2059 s->last_scr_width = width * cw;
2060 s->last_scr_height = height * cheight;
2061 s->ds->surface->width = width;
2062 s->ds->surface->height = height;
2063 dpy_resize(s->ds);
2064 s->last_width = width;
2065 s->last_height = height;
2066 s->last_ch = cheight;
2067 s->last_cw = cw;
2068 full_update = 1;
2071 /* Update "hardware" cursor */
2072 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
2073 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2074 if (cursor_offset != s->cursor_offset ||
2075 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2076 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2077 cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2078 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2079 dpy_cursor(s->ds,
2080 TEXTMODE_X(cursor_offset),
2081 TEXTMODE_Y(cursor_offset));
2082 else
2083 dpy_cursor(s->ds, -1, -1);
2084 s->cursor_offset = cursor_offset;
2085 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2086 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2089 src = (uint32_t *) s->vram_ptr + s->start_addr;
2090 dst = chardata;
2092 if (full_update) {
2093 for (i = 0; i < size; src ++, dst ++, i ++)
2094 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2096 dpy_update(s->ds, 0, 0, width, height);
2097 } else {
2098 c_max = 0;
2100 for (i = 0; i < size; src ++, dst ++, i ++) {
2101 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2102 if (*dst != val) {
2103 *dst = val;
2104 c_max = i;
2105 break;
2108 c_min = i;
2109 for (; i < size; src ++, dst ++, i ++) {
2110 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2111 if (*dst != val) {
2112 *dst = val;
2113 c_max = i;
2117 if (c_min <= c_max) {
2118 i = TEXTMODE_Y(c_min);
2119 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2123 return;
2124 case GMODE_GRAPH:
2125 if (!full_update)
2126 return;
2128 s->get_resolution(s, &width, &height);
2129 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2130 width, height);
2131 break;
2132 case GMODE_BLANK:
2133 default:
2134 if (!full_update)
2135 return;
2137 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2138 break;
2141 /* Display a message */
2142 s->last_width = 60;
2143 s->last_height = height = 3;
2144 dpy_cursor(s->ds, -1, -1);
2145 s->ds->surface->width = s->last_width;
2146 s->ds->surface->height = height;
2147 dpy_resize(s->ds);
2149 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2150 console_write_ch(dst ++, ' ');
2152 size = strlen(msg_buffer);
2153 width = (s->last_width - size) / 2;
2154 dst = chardata + s->last_width + width;
2155 for (i = 0; i < size; i ++)
2156 console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2158 dpy_update(s->ds, 0, 0, s->last_width, height);
2161 static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2162 unsigned size)
2164 VGACommonState *s = opaque;
2166 return vga_mem_readb(s, addr);
2169 static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2170 uint64_t data, unsigned size)
2172 VGACommonState *s = opaque;
2174 return vga_mem_writeb(s, addr, data);
2177 const MemoryRegionOps vga_mem_ops = {
2178 .read = vga_mem_read,
2179 .write = vga_mem_write,
2180 .endianness = DEVICE_LITTLE_ENDIAN,
2181 .impl = {
2182 .min_access_size = 1,
2183 .max_access_size = 1,
2187 static int vga_common_post_load(void *opaque, int version_id)
2189 VGACommonState *s = opaque;
2191 /* force refresh */
2192 s->graphic_mode = -1;
2193 return 0;
2196 const VMStateDescription vmstate_vga_common = {
2197 .name = "vga",
2198 .version_id = 2,
2199 .minimum_version_id = 2,
2200 .minimum_version_id_old = 2,
2201 .post_load = vga_common_post_load,
2202 .fields = (VMStateField []) {
2203 VMSTATE_UINT32(latch, VGACommonState),
2204 VMSTATE_UINT8(sr_index, VGACommonState),
2205 VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2206 VMSTATE_UINT8(gr_index, VGACommonState),
2207 VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2208 VMSTATE_UINT8(ar_index, VGACommonState),
2209 VMSTATE_BUFFER(ar, VGACommonState),
2210 VMSTATE_INT32(ar_flip_flop, VGACommonState),
2211 VMSTATE_UINT8(cr_index, VGACommonState),
2212 VMSTATE_BUFFER(cr, VGACommonState),
2213 VMSTATE_UINT8(msr, VGACommonState),
2214 VMSTATE_UINT8(fcr, VGACommonState),
2215 VMSTATE_UINT8(st00, VGACommonState),
2216 VMSTATE_UINT8(st01, VGACommonState),
2218 VMSTATE_UINT8(dac_state, VGACommonState),
2219 VMSTATE_UINT8(dac_sub_index, VGACommonState),
2220 VMSTATE_UINT8(dac_read_index, VGACommonState),
2221 VMSTATE_UINT8(dac_write_index, VGACommonState),
2222 VMSTATE_BUFFER(dac_cache, VGACommonState),
2223 VMSTATE_BUFFER(palette, VGACommonState),
2225 VMSTATE_INT32(bank_offset, VGACommonState),
2226 VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2227 #ifdef CONFIG_BOCHS_VBE
2228 VMSTATE_UINT16(vbe_index, VGACommonState),
2229 VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2230 VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2231 VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2232 VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2233 #endif
2234 VMSTATE_END_OF_LIST()
2238 void vga_common_init(VGACommonState *s)
2240 int i, j, v, b;
2242 for(i = 0;i < 256; i++) {
2243 v = 0;
2244 for(j = 0; j < 8; j++) {
2245 v |= ((i >> j) & 1) << (j * 4);
2247 expand4[i] = v;
2249 v = 0;
2250 for(j = 0; j < 4; j++) {
2251 v |= ((i >> (2 * j)) & 3) << (j * 4);
2253 expand2[i] = v;
2255 for(i = 0; i < 16; i++) {
2256 v = 0;
2257 for(j = 0; j < 4; j++) {
2258 b = ((i >> j) & 1);
2259 v |= b << (2 * j);
2260 v |= b << (2 * j + 1);
2262 expand4to8[i] = v;
2265 /* valid range: 1 MB -> 256 MB */
2266 s->vram_size = 1024 * 1024;
2267 while (s->vram_size < (s->vram_size_mb << 20) &&
2268 s->vram_size < (256 << 20)) {
2269 s->vram_size <<= 1;
2271 s->vram_size_mb = s->vram_size >> 20;
2273 #ifdef CONFIG_BOCHS_VBE
2274 s->is_vbe_vmstate = 1;
2275 #else
2276 s->is_vbe_vmstate = 0;
2277 #endif
2278 memory_region_init_ram(&s->vram, "vga.vram", s->vram_size);
2279 vmstate_register_ram_global(&s->vram);
2280 xen_register_framebuffer(&s->vram);
2281 s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2282 s->get_bpp = vga_get_bpp;
2283 s->get_offsets = vga_get_offsets;
2284 s->get_resolution = vga_get_resolution;
2285 s->update = vga_update_display;
2286 s->invalidate = vga_invalidate_display;
2287 s->screen_dump = vga_screen_dump;
2288 s->text_update = vga_update_text;
2289 switch (vga_retrace_method) {
2290 case VGA_RETRACE_DUMB:
2291 s->retrace = vga_dumb_retrace;
2292 s->update_retrace_info = vga_dumb_update_retrace_info;
2293 break;
2295 case VGA_RETRACE_PRECISE:
2296 s->retrace = vga_precise_retrace;
2297 s->update_retrace_info = vga_precise_update_retrace_info;
2298 break;
2300 vga_dirty_log_start(s);
2303 static const MemoryRegionPortio vga_portio_list[] = {
2304 { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2305 { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2306 { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2307 { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2308 { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2309 PORTIO_END_OF_LIST(),
2312 #ifdef CONFIG_BOCHS_VBE
2313 static const MemoryRegionPortio vbe_portio_list[] = {
2314 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2315 # ifdef TARGET_I386
2316 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2317 # else
2318 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2319 # endif
2320 PORTIO_END_OF_LIST(),
2322 #endif /* CONFIG_BOCHS_VBE */
2324 /* Used by both ISA and PCI */
2325 MemoryRegion *vga_init_io(VGACommonState *s,
2326 const MemoryRegionPortio **vga_ports,
2327 const MemoryRegionPortio **vbe_ports)
2329 MemoryRegion *vga_mem;
2331 *vga_ports = vga_portio_list;
2332 *vbe_ports = NULL;
2333 #ifdef CONFIG_BOCHS_VBE
2334 *vbe_ports = vbe_portio_list;
2335 #endif
2337 vga_mem = g_malloc(sizeof(*vga_mem));
2338 memory_region_init_io(vga_mem, &vga_mem_ops, s,
2339 "vga-lowmem", 0x20000);
2341 return vga_mem;
2344 void vga_init(VGACommonState *s, MemoryRegion *address_space,
2345 MemoryRegion *address_space_io, bool init_vga_ports)
2347 MemoryRegion *vga_io_memory;
2348 const MemoryRegionPortio *vga_ports, *vbe_ports;
2349 PortioList *vga_port_list = g_new(PortioList, 1);
2350 PortioList *vbe_port_list = g_new(PortioList, 1);
2352 qemu_register_reset(vga_reset, s);
2354 s->bank_offset = 0;
2356 s->legacy_address_space = address_space;
2358 vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
2359 memory_region_add_subregion_overlap(address_space,
2360 isa_mem_base + 0x000a0000,
2361 vga_io_memory,
2363 memory_region_set_coalescing(vga_io_memory);
2364 if (init_vga_ports) {
2365 portio_list_init(vga_port_list, vga_ports, s, "vga");
2366 portio_list_add(vga_port_list, address_space_io, 0x3b0);
2368 if (vbe_ports) {
2369 portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
2370 portio_list_add(vbe_port_list, address_space_io, 0x1ce);
2374 void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
2376 #ifdef CONFIG_BOCHS_VBE
2377 /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
2378 * so use an alias to avoid double-mapping the same region.
2380 memory_region_init_alias(&s->vram_vbe, "vram.vbe",
2381 &s->vram, 0, memory_region_size(&s->vram));
2382 /* XXX: use optimized standard vga accesses */
2383 memory_region_add_subregion(system_memory,
2384 VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2385 &s->vram_vbe);
2386 s->vbe_mapped = 1;
2387 #endif
2389 /********************************************************/
2390 /* vga screen dump */
2392 int ppm_save(const char *filename, struct DisplaySurface *ds)
2394 FILE *f;
2395 uint8_t *d, *d1;
2396 uint32_t v;
2397 int y, x;
2398 uint8_t r, g, b;
2399 int ret;
2400 char *linebuf, *pbuf;
2402 trace_ppm_save(filename, ds);
2403 f = fopen(filename, "wb");
2404 if (!f)
2405 return -1;
2406 fprintf(f, "P6\n%d %d\n%d\n",
2407 ds->width, ds->height, 255);
2408 linebuf = g_malloc(ds->width * 3);
2409 d1 = ds->data;
2410 for(y = 0; y < ds->height; y++) {
2411 d = d1;
2412 pbuf = linebuf;
2413 for(x = 0; x < ds->width; x++) {
2414 if (ds->pf.bits_per_pixel == 32)
2415 v = *(uint32_t *)d;
2416 else
2417 v = (uint32_t) (*(uint16_t *)d);
2418 /* Limited to 8 or fewer bits per channel: */
2419 r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
2420 g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
2421 b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
2422 *pbuf++ = r;
2423 *pbuf++ = g;
2424 *pbuf++ = b;
2425 d += ds->pf.bytes_per_pixel;
2427 d1 += ds->linesize;
2428 ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2429 (void)ret;
2431 g_free(linebuf);
2432 fclose(f);
2433 return 0;
2436 /* save the vga display in a PPM image even if no display is
2437 available */
2438 static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
2440 VGACommonState *s = opaque;
2442 if (cswitch) {
2443 vga_invalidate_display(s);
2445 vga_hw_update();
2446 ppm_save(filename, s->ds->surface);