Add VMState support for ptimers
[qemu/kevin.git] / hw / vga.c
blob6b5070a2541bbb49c19bc99d14641343a19855bc
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 "console.h"
26 #include "pc.h"
27 #include "pci.h"
28 #include "vga_int.h"
29 #include "pixel_ops.h"
30 #include "qemu-timer.h"
31 #include "kvm.h"
33 //#define DEBUG_VGA
34 //#define DEBUG_VGA_MEM
35 //#define DEBUG_VGA_REG
37 //#define DEBUG_BOCHS_VBE
39 /* force some bits to zero */
40 const uint8_t sr_mask[8] = {
41 0x03,
42 0x3d,
43 0x0f,
44 0x3f,
45 0x0e,
46 0x00,
47 0x00,
48 0xff,
51 const uint8_t gr_mask[16] = {
52 0x0f, /* 0x00 */
53 0x0f, /* 0x01 */
54 0x0f, /* 0x02 */
55 0x1f, /* 0x03 */
56 0x03, /* 0x04 */
57 0x7b, /* 0x05 */
58 0x0f, /* 0x06 */
59 0x0f, /* 0x07 */
60 0xff, /* 0x08 */
61 0x00, /* 0x09 */
62 0x00, /* 0x0a */
63 0x00, /* 0x0b */
64 0x00, /* 0x0c */
65 0x00, /* 0x0d */
66 0x00, /* 0x0e */
67 0x00, /* 0x0f */
70 #define cbswap_32(__x) \
71 ((uint32_t)( \
72 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
74 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
75 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
77 #ifdef HOST_WORDS_BIGENDIAN
78 #define PAT(x) cbswap_32(x)
79 #else
80 #define PAT(x) (x)
81 #endif
83 #ifdef HOST_WORDS_BIGENDIAN
84 #define BIG 1
85 #else
86 #define BIG 0
87 #endif
89 #ifdef HOST_WORDS_BIGENDIAN
90 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
91 #else
92 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93 #endif
95 static const uint32_t mask16[16] = {
96 PAT(0x00000000),
97 PAT(0x000000ff),
98 PAT(0x0000ff00),
99 PAT(0x0000ffff),
100 PAT(0x00ff0000),
101 PAT(0x00ff00ff),
102 PAT(0x00ffff00),
103 PAT(0x00ffffff),
104 PAT(0xff000000),
105 PAT(0xff0000ff),
106 PAT(0xff00ff00),
107 PAT(0xff00ffff),
108 PAT(0xffff0000),
109 PAT(0xffff00ff),
110 PAT(0xffffff00),
111 PAT(0xffffffff),
114 #undef PAT
116 #ifdef HOST_WORDS_BIGENDIAN
117 #define PAT(x) (x)
118 #else
119 #define PAT(x) cbswap_32(x)
120 #endif
122 static const uint32_t dmask16[16] = {
123 PAT(0x00000000),
124 PAT(0x000000ff),
125 PAT(0x0000ff00),
126 PAT(0x0000ffff),
127 PAT(0x00ff0000),
128 PAT(0x00ff00ff),
129 PAT(0x00ffff00),
130 PAT(0x00ffffff),
131 PAT(0xff000000),
132 PAT(0xff0000ff),
133 PAT(0xff00ff00),
134 PAT(0xff00ffff),
135 PAT(0xffff0000),
136 PAT(0xffff00ff),
137 PAT(0xffffff00),
138 PAT(0xffffffff),
141 static const uint32_t dmask4[4] = {
142 PAT(0x00000000),
143 PAT(0x0000ffff),
144 PAT(0xffff0000),
145 PAT(0xffffffff),
148 static uint32_t expand4[256];
149 static uint16_t expand2[256];
150 static uint8_t expand4to8[16];
152 typedef VGACommonState VGAState;
154 static void vga_screen_dump(void *opaque, const char *filename);
155 static char *screen_dump_filename;
156 static DisplayChangeListener *screen_dump_dcl;
158 static void vga_dumb_update_retrace_info(VGAState *s)
160 (void) s;
163 static void vga_precise_update_retrace_info(VGAState *s)
165 int htotal_chars;
166 int hretr_start_char;
167 int hretr_skew_chars;
168 int hretr_end_char;
170 int vtotal_lines;
171 int vretr_start_line;
172 int vretr_end_line;
174 int div2, sldiv2, dots;
175 int clocking_mode;
176 int clock_sel;
177 const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
178 int64_t chars_per_sec;
179 struct vga_precise_retrace *r = &s->retrace_info.precise;
181 htotal_chars = s->cr[0x00] + 5;
182 hretr_start_char = s->cr[0x04];
183 hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
184 hretr_end_char = s->cr[0x05] & 0x1f;
186 vtotal_lines = (s->cr[0x06]
187 | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
189 vretr_start_line = s->cr[0x10]
190 | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
192 vretr_end_line = s->cr[0x11] & 0xf;
195 div2 = (s->cr[0x17] >> 2) & 1;
196 sldiv2 = (s->cr[0x17] >> 3) & 1;
198 clocking_mode = (s->sr[0x01] >> 3) & 1;
199 clock_sel = (s->msr >> 2) & 3;
200 dots = (s->msr & 1) ? 8 : 9;
202 chars_per_sec = clk_hz[clock_sel] / dots;
204 htotal_chars <<= clocking_mode;
206 r->total_chars = vtotal_lines * htotal_chars;
207 if (r->freq) {
208 r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
209 } else {
210 r->ticks_per_char = ticks_per_sec / chars_per_sec;
213 r->vstart = vretr_start_line;
214 r->vend = r->vstart + vretr_end_line + 1;
216 r->hstart = hretr_start_char + hretr_skew_chars;
217 r->hend = r->hstart + hretr_end_char + 1;
218 r->htotal = htotal_chars;
220 #if 0
221 printf (
222 "hz=%f\n"
223 "htotal = %d\n"
224 "hretr_start = %d\n"
225 "hretr_skew = %d\n"
226 "hretr_end = %d\n"
227 "vtotal = %d\n"
228 "vretr_start = %d\n"
229 "vretr_end = %d\n"
230 "div2 = %d sldiv2 = %d\n"
231 "clocking_mode = %d\n"
232 "clock_sel = %d %d\n"
233 "dots = %d\n"
234 "ticks/char = %lld\n"
235 "\n",
236 (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
237 htotal_chars,
238 hretr_start_char,
239 hretr_skew_chars,
240 hretr_end_char,
241 vtotal_lines,
242 vretr_start_line,
243 vretr_end_line,
244 div2, sldiv2,
245 clocking_mode,
246 clock_sel,
247 clk_hz[clock_sel],
248 dots,
249 r->ticks_per_char
251 #endif
254 static uint8_t vga_precise_retrace(VGAState *s)
256 struct vga_precise_retrace *r = &s->retrace_info.precise;
257 uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
259 if (r->total_chars) {
260 int cur_line, cur_line_char, cur_char;
261 int64_t cur_tick;
263 cur_tick = qemu_get_clock(vm_clock);
265 cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
266 cur_line = cur_char / r->htotal;
268 if (cur_line >= r->vstart && cur_line <= r->vend) {
269 val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
270 } else {
271 cur_line_char = cur_char % r->htotal;
272 if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
273 val |= ST01_DISP_ENABLE;
277 return val;
278 } else {
279 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
283 static uint8_t vga_dumb_retrace(VGAState *s)
285 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
288 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
290 VGAState *s = opaque;
291 int val, index;
293 /* check port range access depending on color/monochrome mode */
294 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
295 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
296 val = 0xff;
297 } else {
298 switch(addr) {
299 case 0x3c0:
300 if (s->ar_flip_flop == 0) {
301 val = s->ar_index;
302 } else {
303 val = 0;
305 break;
306 case 0x3c1:
307 index = s->ar_index & 0x1f;
308 if (index < 21)
309 val = s->ar[index];
310 else
311 val = 0;
312 break;
313 case 0x3c2:
314 val = s->st00;
315 break;
316 case 0x3c4:
317 val = s->sr_index;
318 break;
319 case 0x3c5:
320 val = s->sr[s->sr_index];
321 #ifdef DEBUG_VGA_REG
322 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
323 #endif
324 break;
325 case 0x3c7:
326 val = s->dac_state;
327 break;
328 case 0x3c8:
329 val = s->dac_write_index;
330 break;
331 case 0x3c9:
332 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
333 if (++s->dac_sub_index == 3) {
334 s->dac_sub_index = 0;
335 s->dac_read_index++;
337 break;
338 case 0x3ca:
339 val = s->fcr;
340 break;
341 case 0x3cc:
342 val = s->msr;
343 break;
344 case 0x3ce:
345 val = s->gr_index;
346 break;
347 case 0x3cf:
348 val = s->gr[s->gr_index];
349 #ifdef DEBUG_VGA_REG
350 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
351 #endif
352 break;
353 case 0x3b4:
354 case 0x3d4:
355 val = s->cr_index;
356 break;
357 case 0x3b5:
358 case 0x3d5:
359 val = s->cr[s->cr_index];
360 #ifdef DEBUG_VGA_REG
361 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
362 #endif
363 break;
364 case 0x3ba:
365 case 0x3da:
366 /* just toggle to fool polling */
367 val = s->st01 = s->retrace(s);
368 s->ar_flip_flop = 0;
369 break;
370 default:
371 val = 0x00;
372 break;
375 #if defined(DEBUG_VGA)
376 printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
377 #endif
378 return val;
381 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
383 VGAState *s = opaque;
384 int index;
386 /* check port range access depending on color/monochrome mode */
387 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
388 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
389 return;
391 #ifdef DEBUG_VGA
392 printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
393 #endif
395 switch(addr) {
396 case 0x3c0:
397 if (s->ar_flip_flop == 0) {
398 val &= 0x3f;
399 s->ar_index = val;
400 } else {
401 index = s->ar_index & 0x1f;
402 switch(index) {
403 case 0x00 ... 0x0f:
404 s->ar[index] = val & 0x3f;
405 break;
406 case 0x10:
407 s->ar[index] = val & ~0x10;
408 break;
409 case 0x11:
410 s->ar[index] = val;
411 break;
412 case 0x12:
413 s->ar[index] = val & ~0xc0;
414 break;
415 case 0x13:
416 s->ar[index] = val & ~0xf0;
417 break;
418 case 0x14:
419 s->ar[index] = val & ~0xf0;
420 break;
421 default:
422 break;
425 s->ar_flip_flop ^= 1;
426 break;
427 case 0x3c2:
428 s->msr = val & ~0x10;
429 s->update_retrace_info(s);
430 break;
431 case 0x3c4:
432 s->sr_index = val & 7;
433 break;
434 case 0x3c5:
435 #ifdef DEBUG_VGA_REG
436 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
437 #endif
438 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
439 if (s->sr_index == 1) s->update_retrace_info(s);
440 break;
441 case 0x3c7:
442 s->dac_read_index = val;
443 s->dac_sub_index = 0;
444 s->dac_state = 3;
445 break;
446 case 0x3c8:
447 s->dac_write_index = val;
448 s->dac_sub_index = 0;
449 s->dac_state = 0;
450 break;
451 case 0x3c9:
452 s->dac_cache[s->dac_sub_index] = val;
453 if (++s->dac_sub_index == 3) {
454 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
455 s->dac_sub_index = 0;
456 s->dac_write_index++;
458 break;
459 case 0x3ce:
460 s->gr_index = val & 0x0f;
461 break;
462 case 0x3cf:
463 #ifdef DEBUG_VGA_REG
464 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
465 #endif
466 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
467 break;
468 case 0x3b4:
469 case 0x3d4:
470 s->cr_index = val;
471 break;
472 case 0x3b5:
473 case 0x3d5:
474 #ifdef DEBUG_VGA_REG
475 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
476 #endif
477 /* handle CR0-7 protection */
478 if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
479 /* can always write bit 4 of CR7 */
480 if (s->cr_index == 7)
481 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
482 return;
484 switch(s->cr_index) {
485 case 0x01: /* horizontal display end */
486 case 0x07:
487 case 0x09:
488 case 0x0c:
489 case 0x0d:
490 case 0x12: /* vertical display end */
491 s->cr[s->cr_index] = val;
492 break;
493 default:
494 s->cr[s->cr_index] = val;
495 break;
498 switch(s->cr_index) {
499 case 0x00:
500 case 0x04:
501 case 0x05:
502 case 0x06:
503 case 0x07:
504 case 0x11:
505 case 0x17:
506 s->update_retrace_info(s);
507 break;
509 break;
510 case 0x3ba:
511 case 0x3da:
512 s->fcr = val & 0x10;
513 break;
517 #ifdef CONFIG_BOCHS_VBE
518 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
520 VGAState *s = opaque;
521 uint32_t val;
522 val = s->vbe_index;
523 return val;
526 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
528 VGAState *s = opaque;
529 uint32_t val;
531 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
532 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
533 switch(s->vbe_index) {
534 /* XXX: do not hardcode ? */
535 case VBE_DISPI_INDEX_XRES:
536 val = VBE_DISPI_MAX_XRES;
537 break;
538 case VBE_DISPI_INDEX_YRES:
539 val = VBE_DISPI_MAX_YRES;
540 break;
541 case VBE_DISPI_INDEX_BPP:
542 val = VBE_DISPI_MAX_BPP;
543 break;
544 default:
545 val = s->vbe_regs[s->vbe_index];
546 break;
548 } else {
549 val = s->vbe_regs[s->vbe_index];
551 } else {
552 val = 0;
554 #ifdef DEBUG_BOCHS_VBE
555 printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
556 #endif
557 return val;
560 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
562 VGAState *s = opaque;
563 s->vbe_index = val;
566 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
568 VGAState *s = opaque;
570 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
571 #ifdef DEBUG_BOCHS_VBE
572 printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
573 #endif
574 switch(s->vbe_index) {
575 case VBE_DISPI_INDEX_ID:
576 if (val == VBE_DISPI_ID0 ||
577 val == VBE_DISPI_ID1 ||
578 val == VBE_DISPI_ID2 ||
579 val == VBE_DISPI_ID3 ||
580 val == VBE_DISPI_ID4) {
581 s->vbe_regs[s->vbe_index] = val;
583 break;
584 case VBE_DISPI_INDEX_XRES:
585 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
586 s->vbe_regs[s->vbe_index] = val;
588 break;
589 case VBE_DISPI_INDEX_YRES:
590 if (val <= VBE_DISPI_MAX_YRES) {
591 s->vbe_regs[s->vbe_index] = val;
593 break;
594 case VBE_DISPI_INDEX_BPP:
595 if (val == 0)
596 val = 8;
597 if (val == 4 || val == 8 || val == 15 ||
598 val == 16 || val == 24 || val == 32) {
599 s->vbe_regs[s->vbe_index] = val;
601 break;
602 case VBE_DISPI_INDEX_BANK:
603 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
604 val &= (s->vbe_bank_mask >> 2);
605 } else {
606 val &= s->vbe_bank_mask;
608 s->vbe_regs[s->vbe_index] = val;
609 s->bank_offset = (val << 16);
610 break;
611 case VBE_DISPI_INDEX_ENABLE:
612 if ((val & VBE_DISPI_ENABLED) &&
613 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
614 int h, shift_control;
616 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
617 s->vbe_regs[VBE_DISPI_INDEX_XRES];
618 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
619 s->vbe_regs[VBE_DISPI_INDEX_YRES];
620 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
621 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
623 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
624 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
625 else
626 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
627 ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
628 s->vbe_start_addr = 0;
630 /* clear the screen (should be done in BIOS) */
631 if (!(val & VBE_DISPI_NOCLEARMEM)) {
632 memset(s->vram_ptr, 0,
633 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
636 /* we initialize the VGA graphic mode (should be done
637 in BIOS) */
638 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
639 s->cr[0x17] |= 3; /* no CGA modes */
640 s->cr[0x13] = s->vbe_line_offset >> 3;
641 /* width */
642 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
643 /* height (only meaningful if < 1024) */
644 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
645 s->cr[0x12] = h;
646 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
647 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
648 /* line compare to 1023 */
649 s->cr[0x18] = 0xff;
650 s->cr[0x07] |= 0x10;
651 s->cr[0x09] |= 0x40;
653 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
654 shift_control = 0;
655 s->sr[0x01] &= ~8; /* no double line */
656 } else {
657 shift_control = 2;
658 s->sr[4] |= 0x08; /* set chain 4 mode */
659 s->sr[2] |= 0x0f; /* activate all planes */
661 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
662 s->cr[0x09] &= ~0x9f; /* no double scan */
663 } else {
664 /* XXX: the bios should do that */
665 s->bank_offset = 0;
667 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
668 s->vbe_regs[s->vbe_index] = val;
669 break;
670 case VBE_DISPI_INDEX_VIRT_WIDTH:
672 int w, h, line_offset;
674 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
675 return;
676 w = val;
677 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
678 line_offset = w >> 1;
679 else
680 line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
681 h = s->vram_size / line_offset;
682 /* XXX: support weird bochs semantics ? */
683 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
684 return;
685 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
686 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
687 s->vbe_line_offset = line_offset;
689 break;
690 case VBE_DISPI_INDEX_X_OFFSET:
691 case VBE_DISPI_INDEX_Y_OFFSET:
693 int x;
694 s->vbe_regs[s->vbe_index] = val;
695 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
696 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
697 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
698 s->vbe_start_addr += x >> 1;
699 else
700 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
701 s->vbe_start_addr >>= 2;
703 break;
704 default:
705 break;
709 #endif
711 /* called for accesses between 0xa0000 and 0xc0000 */
712 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
714 VGAState *s = opaque;
715 int memory_map_mode, plane;
716 uint32_t ret;
718 /* convert to VGA memory offset */
719 memory_map_mode = (s->gr[6] >> 2) & 3;
720 addr &= 0x1ffff;
721 switch(memory_map_mode) {
722 case 0:
723 break;
724 case 1:
725 if (addr >= 0x10000)
726 return 0xff;
727 addr += s->bank_offset;
728 break;
729 case 2:
730 addr -= 0x10000;
731 if (addr >= 0x8000)
732 return 0xff;
733 break;
734 default:
735 case 3:
736 addr -= 0x18000;
737 if (addr >= 0x8000)
738 return 0xff;
739 break;
742 if (s->sr[4] & 0x08) {
743 /* chain 4 mode : simplest access */
744 ret = s->vram_ptr[addr];
745 } else if (s->gr[5] & 0x10) {
746 /* odd/even mode (aka text mode mapping) */
747 plane = (s->gr[4] & 2) | (addr & 1);
748 ret = s->vram_ptr[((addr & ~1) << 1) | plane];
749 } else {
750 /* standard VGA latched access */
751 s->latch = ((uint32_t *)s->vram_ptr)[addr];
753 if (!(s->gr[5] & 0x08)) {
754 /* read mode 0 */
755 plane = s->gr[4];
756 ret = GET_PLANE(s->latch, plane);
757 } else {
758 /* read mode 1 */
759 ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
760 ret |= ret >> 16;
761 ret |= ret >> 8;
762 ret = (~ret) & 0xff;
765 return ret;
768 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
770 uint32_t v;
771 #ifdef TARGET_WORDS_BIGENDIAN
772 v = vga_mem_readb(opaque, addr) << 8;
773 v |= vga_mem_readb(opaque, addr + 1);
774 #else
775 v = vga_mem_readb(opaque, addr);
776 v |= vga_mem_readb(opaque, addr + 1) << 8;
777 #endif
778 return v;
781 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
783 uint32_t v;
784 #ifdef TARGET_WORDS_BIGENDIAN
785 v = vga_mem_readb(opaque, addr) << 24;
786 v |= vga_mem_readb(opaque, addr + 1) << 16;
787 v |= vga_mem_readb(opaque, addr + 2) << 8;
788 v |= vga_mem_readb(opaque, addr + 3);
789 #else
790 v = vga_mem_readb(opaque, addr);
791 v |= vga_mem_readb(opaque, addr + 1) << 8;
792 v |= vga_mem_readb(opaque, addr + 2) << 16;
793 v |= vga_mem_readb(opaque, addr + 3) << 24;
794 #endif
795 return v;
798 /* called for accesses between 0xa0000 and 0xc0000 */
799 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
801 VGAState *s = opaque;
802 int memory_map_mode, plane, write_mode, b, func_select, mask;
803 uint32_t write_mask, bit_mask, set_mask;
805 #ifdef DEBUG_VGA_MEM
806 printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
807 #endif
808 /* convert to VGA memory offset */
809 memory_map_mode = (s->gr[6] >> 2) & 3;
810 addr &= 0x1ffff;
811 switch(memory_map_mode) {
812 case 0:
813 break;
814 case 1:
815 if (addr >= 0x10000)
816 return;
817 addr += s->bank_offset;
818 break;
819 case 2:
820 addr -= 0x10000;
821 if (addr >= 0x8000)
822 return;
823 break;
824 default:
825 case 3:
826 addr -= 0x18000;
827 if (addr >= 0x8000)
828 return;
829 break;
832 if (s->sr[4] & 0x08) {
833 /* chain 4 mode : simplest access */
834 plane = addr & 3;
835 mask = (1 << plane);
836 if (s->sr[2] & mask) {
837 s->vram_ptr[addr] = val;
838 #ifdef DEBUG_VGA_MEM
839 printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
840 #endif
841 s->plane_updated |= mask; /* only used to detect font change */
842 cpu_physical_memory_set_dirty(s->vram_offset + addr);
844 } else if (s->gr[5] & 0x10) {
845 /* odd/even mode (aka text mode mapping) */
846 plane = (s->gr[4] & 2) | (addr & 1);
847 mask = (1 << plane);
848 if (s->sr[2] & mask) {
849 addr = ((addr & ~1) << 1) | plane;
850 s->vram_ptr[addr] = val;
851 #ifdef DEBUG_VGA_MEM
852 printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
853 #endif
854 s->plane_updated |= mask; /* only used to detect font change */
855 cpu_physical_memory_set_dirty(s->vram_offset + addr);
857 } else {
858 /* standard VGA latched access */
859 write_mode = s->gr[5] & 3;
860 switch(write_mode) {
861 default:
862 case 0:
863 /* rotate */
864 b = s->gr[3] & 7;
865 val = ((val >> b) | (val << (8 - b))) & 0xff;
866 val |= val << 8;
867 val |= val << 16;
869 /* apply set/reset mask */
870 set_mask = mask16[s->gr[1]];
871 val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
872 bit_mask = s->gr[8];
873 break;
874 case 1:
875 val = s->latch;
876 goto do_write;
877 case 2:
878 val = mask16[val & 0x0f];
879 bit_mask = s->gr[8];
880 break;
881 case 3:
882 /* rotate */
883 b = s->gr[3] & 7;
884 val = (val >> b) | (val << (8 - b));
886 bit_mask = s->gr[8] & val;
887 val = mask16[s->gr[0]];
888 break;
891 /* apply logical operation */
892 func_select = s->gr[3] >> 3;
893 switch(func_select) {
894 case 0:
895 default:
896 /* nothing to do */
897 break;
898 case 1:
899 /* and */
900 val &= s->latch;
901 break;
902 case 2:
903 /* or */
904 val |= s->latch;
905 break;
906 case 3:
907 /* xor */
908 val ^= s->latch;
909 break;
912 /* apply bit mask */
913 bit_mask |= bit_mask << 8;
914 bit_mask |= bit_mask << 16;
915 val = (val & bit_mask) | (s->latch & ~bit_mask);
917 do_write:
918 /* mask data according to sr[2] */
919 mask = s->sr[2];
920 s->plane_updated |= mask; /* only used to detect font change */
921 write_mask = mask16[mask];
922 ((uint32_t *)s->vram_ptr)[addr] =
923 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
924 (val & write_mask);
925 #ifdef DEBUG_VGA_MEM
926 printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
927 addr * 4, write_mask, val);
928 #endif
929 cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
933 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
935 #ifdef TARGET_WORDS_BIGENDIAN
936 vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
937 vga_mem_writeb(opaque, addr + 1, val & 0xff);
938 #else
939 vga_mem_writeb(opaque, addr, val & 0xff);
940 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
941 #endif
944 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
946 #ifdef TARGET_WORDS_BIGENDIAN
947 vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
948 vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
949 vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
950 vga_mem_writeb(opaque, addr + 3, val & 0xff);
951 #else
952 vga_mem_writeb(opaque, addr, val & 0xff);
953 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
954 vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
955 vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
956 #endif
959 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
960 const uint8_t *font_ptr, int h,
961 uint32_t fgcol, uint32_t bgcol);
962 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
963 const uint8_t *font_ptr, int h,
964 uint32_t fgcol, uint32_t bgcol, int dup9);
965 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
966 const uint8_t *s, int width);
968 #define DEPTH 8
969 #include "vga_template.h"
971 #define DEPTH 15
972 #include "vga_template.h"
974 #define BGR_FORMAT
975 #define DEPTH 15
976 #include "vga_template.h"
978 #define DEPTH 16
979 #include "vga_template.h"
981 #define BGR_FORMAT
982 #define DEPTH 16
983 #include "vga_template.h"
985 #define DEPTH 32
986 #include "vga_template.h"
988 #define BGR_FORMAT
989 #define DEPTH 32
990 #include "vga_template.h"
992 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
994 unsigned int col;
995 col = rgb_to_pixel8(r, g, b);
996 col |= col << 8;
997 col |= col << 16;
998 return col;
1001 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1003 unsigned int col;
1004 col = rgb_to_pixel15(r, g, b);
1005 col |= col << 16;
1006 return col;
1009 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1010 unsigned int b)
1012 unsigned int col;
1013 col = rgb_to_pixel15bgr(r, g, b);
1014 col |= col << 16;
1015 return col;
1018 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1020 unsigned int col;
1021 col = rgb_to_pixel16(r, g, b);
1022 col |= col << 16;
1023 return col;
1026 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1027 unsigned int b)
1029 unsigned int col;
1030 col = rgb_to_pixel16bgr(r, g, b);
1031 col |= col << 16;
1032 return col;
1035 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1037 unsigned int col;
1038 col = rgb_to_pixel32(r, g, b);
1039 return col;
1042 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1044 unsigned int col;
1045 col = rgb_to_pixel32bgr(r, g, b);
1046 return col;
1049 /* return true if the palette was modified */
1050 static int update_palette16(VGAState *s)
1052 int full_update, i;
1053 uint32_t v, col, *palette;
1055 full_update = 0;
1056 palette = s->last_palette;
1057 for(i = 0; i < 16; i++) {
1058 v = s->ar[i];
1059 if (s->ar[0x10] & 0x80)
1060 v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1061 else
1062 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1063 v = v * 3;
1064 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1065 c6_to_8(s->palette[v + 1]),
1066 c6_to_8(s->palette[v + 2]));
1067 if (col != palette[i]) {
1068 full_update = 1;
1069 palette[i] = col;
1072 return full_update;
1075 /* return true if the palette was modified */
1076 static int update_palette256(VGAState *s)
1078 int full_update, i;
1079 uint32_t v, col, *palette;
1081 full_update = 0;
1082 palette = s->last_palette;
1083 v = 0;
1084 for(i = 0; i < 256; i++) {
1085 if (s->dac_8bit) {
1086 col = s->rgb_to_pixel(s->palette[v],
1087 s->palette[v + 1],
1088 s->palette[v + 2]);
1089 } else {
1090 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1091 c6_to_8(s->palette[v + 1]),
1092 c6_to_8(s->palette[v + 2]));
1094 if (col != palette[i]) {
1095 full_update = 1;
1096 palette[i] = col;
1098 v += 3;
1100 return full_update;
1103 static void vga_get_offsets(VGAState *s,
1104 uint32_t *pline_offset,
1105 uint32_t *pstart_addr,
1106 uint32_t *pline_compare)
1108 uint32_t start_addr, line_offset, line_compare;
1109 #ifdef CONFIG_BOCHS_VBE
1110 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1111 line_offset = s->vbe_line_offset;
1112 start_addr = s->vbe_start_addr;
1113 line_compare = 65535;
1114 } else
1115 #endif
1117 /* compute line_offset in bytes */
1118 line_offset = s->cr[0x13];
1119 line_offset <<= 3;
1121 /* starting address */
1122 start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1124 /* line compare */
1125 line_compare = s->cr[0x18] |
1126 ((s->cr[0x07] & 0x10) << 4) |
1127 ((s->cr[0x09] & 0x40) << 3);
1129 *pline_offset = line_offset;
1130 *pstart_addr = start_addr;
1131 *pline_compare = line_compare;
1134 /* update start_addr and line_offset. Return TRUE if modified */
1135 static int update_basic_params(VGAState *s)
1137 int full_update;
1138 uint32_t start_addr, line_offset, line_compare;
1140 full_update = 0;
1142 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1144 if (line_offset != s->line_offset ||
1145 start_addr != s->start_addr ||
1146 line_compare != s->line_compare) {
1147 s->line_offset = line_offset;
1148 s->start_addr = start_addr;
1149 s->line_compare = line_compare;
1150 full_update = 1;
1152 return full_update;
1155 #define NB_DEPTHS 7
1157 static inline int get_depth_index(DisplayState *s)
1159 switch(ds_get_bits_per_pixel(s)) {
1160 default:
1161 case 8:
1162 return 0;
1163 case 15:
1164 return 1;
1165 case 16:
1166 return 2;
1167 case 32:
1168 if (is_surface_bgr(s->surface))
1169 return 4;
1170 else
1171 return 3;
1175 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1176 vga_draw_glyph8_8,
1177 vga_draw_glyph8_16,
1178 vga_draw_glyph8_16,
1179 vga_draw_glyph8_32,
1180 vga_draw_glyph8_32,
1181 vga_draw_glyph8_16,
1182 vga_draw_glyph8_16,
1185 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1186 vga_draw_glyph16_8,
1187 vga_draw_glyph16_16,
1188 vga_draw_glyph16_16,
1189 vga_draw_glyph16_32,
1190 vga_draw_glyph16_32,
1191 vga_draw_glyph16_16,
1192 vga_draw_glyph16_16,
1195 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1196 vga_draw_glyph9_8,
1197 vga_draw_glyph9_16,
1198 vga_draw_glyph9_16,
1199 vga_draw_glyph9_32,
1200 vga_draw_glyph9_32,
1201 vga_draw_glyph9_16,
1202 vga_draw_glyph9_16,
1205 static const uint8_t cursor_glyph[32 * 4] = {
1206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224 static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1225 int *pcwidth, int *pcheight)
1227 int width, cwidth, height, cheight;
1229 /* total width & height */
1230 cheight = (s->cr[9] & 0x1f) + 1;
1231 cwidth = 8;
1232 if (!(s->sr[1] & 0x01))
1233 cwidth = 9;
1234 if (s->sr[1] & 0x08)
1235 cwidth = 16; /* NOTE: no 18 pixel wide */
1236 width = (s->cr[0x01] + 1);
1237 if (s->cr[0x06] == 100) {
1238 /* ugly hack for CGA 160x100x16 - explain me the logic */
1239 height = 100;
1240 } else {
1241 height = s->cr[0x12] |
1242 ((s->cr[0x07] & 0x02) << 7) |
1243 ((s->cr[0x07] & 0x40) << 3);
1244 height = (height + 1) / cheight;
1247 *pwidth = width;
1248 *pheight = height;
1249 *pcwidth = cwidth;
1250 *pcheight = cheight;
1253 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1255 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1256 rgb_to_pixel8_dup,
1257 rgb_to_pixel15_dup,
1258 rgb_to_pixel16_dup,
1259 rgb_to_pixel32_dup,
1260 rgb_to_pixel32bgr_dup,
1261 rgb_to_pixel15bgr_dup,
1262 rgb_to_pixel16bgr_dup,
1266 * Text mode update
1267 * Missing:
1268 * - double scan
1269 * - double width
1270 * - underline
1271 * - flashing
1273 static void vga_draw_text(VGAState *s, int full_update)
1275 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1276 int cx_min, cx_max, linesize, x_incr;
1277 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1278 uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1279 const uint8_t *font_ptr, *font_base[2];
1280 int dup9, line_offset, depth_index;
1281 uint32_t *palette;
1282 uint32_t *ch_attr_ptr;
1283 vga_draw_glyph8_func *vga_draw_glyph8;
1284 vga_draw_glyph9_func *vga_draw_glyph9;
1286 /* compute font data address (in plane 2) */
1287 v = s->sr[3];
1288 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1289 if (offset != s->font_offsets[0]) {
1290 s->font_offsets[0] = offset;
1291 full_update = 1;
1293 font_base[0] = s->vram_ptr + offset;
1295 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1296 font_base[1] = s->vram_ptr + offset;
1297 if (offset != s->font_offsets[1]) {
1298 s->font_offsets[1] = offset;
1299 full_update = 1;
1301 if (s->plane_updated & (1 << 2)) {
1302 /* if the plane 2 was modified since the last display, it
1303 indicates the font may have been modified */
1304 s->plane_updated = 0;
1305 full_update = 1;
1307 full_update |= update_basic_params(s);
1309 line_offset = s->line_offset;
1310 s1 = s->vram_ptr + (s->start_addr * 4);
1312 vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1313 x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1314 if ((height * width) > CH_ATTR_SIZE) {
1315 /* better than nothing: exit if transient size is too big */
1316 return;
1319 if (width != s->last_width || height != s->last_height ||
1320 cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1321 s->last_scr_width = width * cw;
1322 s->last_scr_height = height * cheight;
1323 qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1324 s->last_depth = 0;
1325 s->last_width = width;
1326 s->last_height = height;
1327 s->last_ch = cheight;
1328 s->last_cw = cw;
1329 full_update = 1;
1331 s->rgb_to_pixel =
1332 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1333 full_update |= update_palette16(s);
1334 palette = s->last_palette;
1335 x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1337 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1338 if (cursor_offset != s->cursor_offset ||
1339 s->cr[0xa] != s->cursor_start ||
1340 s->cr[0xb] != s->cursor_end) {
1341 /* if the cursor position changed, we update the old and new
1342 chars */
1343 if (s->cursor_offset < CH_ATTR_SIZE)
1344 s->last_ch_attr[s->cursor_offset] = -1;
1345 if (cursor_offset < CH_ATTR_SIZE)
1346 s->last_ch_attr[cursor_offset] = -1;
1347 s->cursor_offset = cursor_offset;
1348 s->cursor_start = s->cr[0xa];
1349 s->cursor_end = s->cr[0xb];
1351 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1353 depth_index = get_depth_index(s->ds);
1354 if (cw == 16)
1355 vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1356 else
1357 vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1358 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1360 dest = ds_get_data(s->ds);
1361 linesize = ds_get_linesize(s->ds);
1362 ch_attr_ptr = s->last_ch_attr;
1363 for(cy = 0; cy < height; cy++) {
1364 d1 = dest;
1365 src = s1;
1366 cx_min = width;
1367 cx_max = -1;
1368 for(cx = 0; cx < width; cx++) {
1369 ch_attr = *(uint16_t *)src;
1370 if (full_update || ch_attr != *ch_attr_ptr) {
1371 if (cx < cx_min)
1372 cx_min = cx;
1373 if (cx > cx_max)
1374 cx_max = cx;
1375 *ch_attr_ptr = ch_attr;
1376 #ifdef HOST_WORDS_BIGENDIAN
1377 ch = ch_attr >> 8;
1378 cattr = ch_attr & 0xff;
1379 #else
1380 ch = ch_attr & 0xff;
1381 cattr = ch_attr >> 8;
1382 #endif
1383 font_ptr = font_base[(cattr >> 3) & 1];
1384 font_ptr += 32 * 4 * ch;
1385 bgcol = palette[cattr >> 4];
1386 fgcol = palette[cattr & 0x0f];
1387 if (cw != 9) {
1388 vga_draw_glyph8(d1, linesize,
1389 font_ptr, cheight, fgcol, bgcol);
1390 } else {
1391 dup9 = 0;
1392 if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1393 dup9 = 1;
1394 vga_draw_glyph9(d1, linesize,
1395 font_ptr, cheight, fgcol, bgcol, dup9);
1397 if (src == cursor_ptr &&
1398 !(s->cr[0x0a] & 0x20)) {
1399 int line_start, line_last, h;
1400 /* draw the cursor */
1401 line_start = s->cr[0x0a] & 0x1f;
1402 line_last = s->cr[0x0b] & 0x1f;
1403 /* XXX: check that */
1404 if (line_last > cheight - 1)
1405 line_last = cheight - 1;
1406 if (line_last >= line_start && line_start < cheight) {
1407 h = line_last - line_start + 1;
1408 d = d1 + linesize * line_start;
1409 if (cw != 9) {
1410 vga_draw_glyph8(d, linesize,
1411 cursor_glyph, h, fgcol, bgcol);
1412 } else {
1413 vga_draw_glyph9(d, linesize,
1414 cursor_glyph, h, fgcol, bgcol, 1);
1419 d1 += x_incr;
1420 src += 4;
1421 ch_attr_ptr++;
1423 if (cx_max != -1) {
1424 dpy_update(s->ds, cx_min * cw, cy * cheight,
1425 (cx_max - cx_min + 1) * cw, cheight);
1427 dest += linesize * cheight;
1428 s1 += line_offset;
1432 enum {
1433 VGA_DRAW_LINE2,
1434 VGA_DRAW_LINE2D2,
1435 VGA_DRAW_LINE4,
1436 VGA_DRAW_LINE4D2,
1437 VGA_DRAW_LINE8D2,
1438 VGA_DRAW_LINE8,
1439 VGA_DRAW_LINE15,
1440 VGA_DRAW_LINE16,
1441 VGA_DRAW_LINE24,
1442 VGA_DRAW_LINE32,
1443 VGA_DRAW_LINE_NB,
1446 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1447 vga_draw_line2_8,
1448 vga_draw_line2_16,
1449 vga_draw_line2_16,
1450 vga_draw_line2_32,
1451 vga_draw_line2_32,
1452 vga_draw_line2_16,
1453 vga_draw_line2_16,
1455 vga_draw_line2d2_8,
1456 vga_draw_line2d2_16,
1457 vga_draw_line2d2_16,
1458 vga_draw_line2d2_32,
1459 vga_draw_line2d2_32,
1460 vga_draw_line2d2_16,
1461 vga_draw_line2d2_16,
1463 vga_draw_line4_8,
1464 vga_draw_line4_16,
1465 vga_draw_line4_16,
1466 vga_draw_line4_32,
1467 vga_draw_line4_32,
1468 vga_draw_line4_16,
1469 vga_draw_line4_16,
1471 vga_draw_line4d2_8,
1472 vga_draw_line4d2_16,
1473 vga_draw_line4d2_16,
1474 vga_draw_line4d2_32,
1475 vga_draw_line4d2_32,
1476 vga_draw_line4d2_16,
1477 vga_draw_line4d2_16,
1479 vga_draw_line8d2_8,
1480 vga_draw_line8d2_16,
1481 vga_draw_line8d2_16,
1482 vga_draw_line8d2_32,
1483 vga_draw_line8d2_32,
1484 vga_draw_line8d2_16,
1485 vga_draw_line8d2_16,
1487 vga_draw_line8_8,
1488 vga_draw_line8_16,
1489 vga_draw_line8_16,
1490 vga_draw_line8_32,
1491 vga_draw_line8_32,
1492 vga_draw_line8_16,
1493 vga_draw_line8_16,
1495 vga_draw_line15_8,
1496 vga_draw_line15_15,
1497 vga_draw_line15_16,
1498 vga_draw_line15_32,
1499 vga_draw_line15_32bgr,
1500 vga_draw_line15_15bgr,
1501 vga_draw_line15_16bgr,
1503 vga_draw_line16_8,
1504 vga_draw_line16_15,
1505 vga_draw_line16_16,
1506 vga_draw_line16_32,
1507 vga_draw_line16_32bgr,
1508 vga_draw_line16_15bgr,
1509 vga_draw_line16_16bgr,
1511 vga_draw_line24_8,
1512 vga_draw_line24_15,
1513 vga_draw_line24_16,
1514 vga_draw_line24_32,
1515 vga_draw_line24_32bgr,
1516 vga_draw_line24_15bgr,
1517 vga_draw_line24_16bgr,
1519 vga_draw_line32_8,
1520 vga_draw_line32_15,
1521 vga_draw_line32_16,
1522 vga_draw_line32_32,
1523 vga_draw_line32_32bgr,
1524 vga_draw_line32_15bgr,
1525 vga_draw_line32_16bgr,
1528 static int vga_get_bpp(VGAState *s)
1530 int ret;
1531 #ifdef CONFIG_BOCHS_VBE
1532 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1533 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1534 } else
1535 #endif
1537 ret = 0;
1539 return ret;
1542 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1544 int width, height;
1546 #ifdef CONFIG_BOCHS_VBE
1547 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1548 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1549 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1550 } else
1551 #endif
1553 width = (s->cr[0x01] + 1) * 8;
1554 height = s->cr[0x12] |
1555 ((s->cr[0x07] & 0x02) << 7) |
1556 ((s->cr[0x07] & 0x40) << 3);
1557 height = (height + 1);
1559 *pwidth = width;
1560 *pheight = height;
1563 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1565 int y;
1566 if (y1 >= VGA_MAX_HEIGHT)
1567 return;
1568 if (y2 >= VGA_MAX_HEIGHT)
1569 y2 = VGA_MAX_HEIGHT;
1570 for(y = y1; y < y2; y++) {
1571 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1575 static void vga_sync_dirty_bitmap(VGAState *s)
1577 if (s->map_addr)
1578 cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1580 if (s->lfb_vram_mapped) {
1581 cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1582 cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1587 * graphic modes
1589 static void vga_draw_graphic(VGAState *s, int full_update)
1591 int y1, y, update, linesize, y_start, double_scan, mask, depth;
1592 int width, height, shift_control, line_offset, bwidth, bits;
1593 ram_addr_t page0, page1, page_min, page_max;
1594 int disp_width, multi_scan, multi_run;
1595 uint8_t *d;
1596 uint32_t v, addr1, addr;
1597 vga_draw_line_func *vga_draw_line;
1599 full_update |= update_basic_params(s);
1601 if (!full_update)
1602 vga_sync_dirty_bitmap(s);
1604 s->get_resolution(s, &width, &height);
1605 disp_width = width;
1607 shift_control = (s->gr[0x05] >> 5) & 3;
1608 double_scan = (s->cr[0x09] >> 7);
1609 if (shift_control != 1) {
1610 multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1611 } else {
1612 /* in CGA modes, multi_scan is ignored */
1613 /* XXX: is it correct ? */
1614 multi_scan = double_scan;
1616 multi_run = multi_scan;
1617 if (shift_control != s->shift_control ||
1618 double_scan != s->double_scan) {
1619 full_update = 1;
1620 s->shift_control = shift_control;
1621 s->double_scan = double_scan;
1624 if (shift_control == 0) {
1625 if (s->sr[0x01] & 8) {
1626 disp_width <<= 1;
1628 } else if (shift_control == 1) {
1629 if (s->sr[0x01] & 8) {
1630 disp_width <<= 1;
1634 depth = s->get_bpp(s);
1635 if (s->line_offset != s->last_line_offset ||
1636 disp_width != s->last_width ||
1637 height != s->last_height ||
1638 s->last_depth != depth) {
1639 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1640 if (depth == 16 || depth == 32) {
1641 #else
1642 if (depth == 32) {
1643 #endif
1644 qemu_free_displaysurface(s->ds);
1645 s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1646 s->line_offset,
1647 s->vram_ptr + (s->start_addr * 4));
1648 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1649 s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1650 #endif
1651 dpy_resize(s->ds);
1652 } else {
1653 qemu_console_resize(s->ds, disp_width, height);
1655 s->last_scr_width = disp_width;
1656 s->last_scr_height = height;
1657 s->last_width = disp_width;
1658 s->last_height = height;
1659 s->last_line_offset = s->line_offset;
1660 s->last_depth = depth;
1661 full_update = 1;
1662 } else if (is_buffer_shared(s->ds->surface) &&
1663 (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1664 s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1665 dpy_setdata(s->ds);
1668 s->rgb_to_pixel =
1669 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1671 if (shift_control == 0) {
1672 full_update |= update_palette16(s);
1673 if (s->sr[0x01] & 8) {
1674 v = VGA_DRAW_LINE4D2;
1675 } else {
1676 v = VGA_DRAW_LINE4;
1678 bits = 4;
1679 } else if (shift_control == 1) {
1680 full_update |= update_palette16(s);
1681 if (s->sr[0x01] & 8) {
1682 v = VGA_DRAW_LINE2D2;
1683 } else {
1684 v = VGA_DRAW_LINE2;
1686 bits = 4;
1687 } else {
1688 switch(s->get_bpp(s)) {
1689 default:
1690 case 0:
1691 full_update |= update_palette256(s);
1692 v = VGA_DRAW_LINE8D2;
1693 bits = 4;
1694 break;
1695 case 8:
1696 full_update |= update_palette256(s);
1697 v = VGA_DRAW_LINE8;
1698 bits = 8;
1699 break;
1700 case 15:
1701 v = VGA_DRAW_LINE15;
1702 bits = 16;
1703 break;
1704 case 16:
1705 v = VGA_DRAW_LINE16;
1706 bits = 16;
1707 break;
1708 case 24:
1709 v = VGA_DRAW_LINE24;
1710 bits = 24;
1711 break;
1712 case 32:
1713 v = VGA_DRAW_LINE32;
1714 bits = 32;
1715 break;
1718 vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1720 if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1721 s->cursor_invalidate(s);
1723 line_offset = s->line_offset;
1724 #if 0
1725 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",
1726 width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1727 #endif
1728 addr1 = (s->start_addr * 4);
1729 bwidth = (width * bits + 7) / 8;
1730 y_start = -1;
1731 page_min = -1;
1732 page_max = 0;
1733 d = ds_get_data(s->ds);
1734 linesize = ds_get_linesize(s->ds);
1735 y1 = 0;
1736 for(y = 0; y < height; y++) {
1737 addr = addr1;
1738 if (!(s->cr[0x17] & 1)) {
1739 int shift;
1740 /* CGA compatibility handling */
1741 shift = 14 + ((s->cr[0x17] >> 6) & 1);
1742 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1744 if (!(s->cr[0x17] & 2)) {
1745 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1747 page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1748 page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1749 update = full_update |
1750 cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1751 cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1752 if ((page1 - page0) > TARGET_PAGE_SIZE) {
1753 /* if wide line, can use another page */
1754 update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1755 VGA_DIRTY_FLAG);
1757 /* explicit invalidation for the hardware cursor */
1758 update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1759 if (update) {
1760 if (y_start < 0)
1761 y_start = y;
1762 if (page0 < page_min)
1763 page_min = page0;
1764 if (page1 > page_max)
1765 page_max = page1;
1766 if (!(is_buffer_shared(s->ds->surface))) {
1767 vga_draw_line(s, d, s->vram_ptr + addr, width);
1768 if (s->cursor_draw_line)
1769 s->cursor_draw_line(s, d, y);
1771 } else {
1772 if (y_start >= 0) {
1773 /* flush to display */
1774 dpy_update(s->ds, 0, y_start,
1775 disp_width, y - y_start);
1776 y_start = -1;
1779 if (!multi_run) {
1780 mask = (s->cr[0x17] & 3) ^ 3;
1781 if ((y1 & mask) == mask)
1782 addr1 += line_offset;
1783 y1++;
1784 multi_run = multi_scan;
1785 } else {
1786 multi_run--;
1788 /* line compare acts on the displayed lines */
1789 if (y == s->line_compare)
1790 addr1 = 0;
1791 d += linesize;
1793 if (y_start >= 0) {
1794 /* flush to display */
1795 dpy_update(s->ds, 0, y_start,
1796 disp_width, y - y_start);
1798 /* reset modified pages */
1799 if (page_max >= page_min) {
1800 cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1801 VGA_DIRTY_FLAG);
1803 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1806 static void vga_draw_blank(VGAState *s, int full_update)
1808 int i, w, val;
1809 uint8_t *d;
1811 if (!full_update)
1812 return;
1813 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1814 return;
1816 s->rgb_to_pixel =
1817 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1818 if (ds_get_bits_per_pixel(s->ds) == 8)
1819 val = s->rgb_to_pixel(0, 0, 0);
1820 else
1821 val = 0;
1822 w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1823 d = ds_get_data(s->ds);
1824 for(i = 0; i < s->last_scr_height; i++) {
1825 memset(d, val, w);
1826 d += ds_get_linesize(s->ds);
1828 dpy_update(s->ds, 0, 0,
1829 s->last_scr_width, s->last_scr_height);
1832 #define GMODE_TEXT 0
1833 #define GMODE_GRAPH 1
1834 #define GMODE_BLANK 2
1836 static void vga_update_display(void *opaque)
1838 VGAState *s = (VGAState *)opaque;
1839 int full_update, graphic_mode;
1841 if (ds_get_bits_per_pixel(s->ds) == 0) {
1842 /* nothing to do */
1843 } else {
1844 full_update = s->full_update;
1845 s->full_update = 0;
1846 if (!(s->ar_index & 0x20)) {
1847 graphic_mode = GMODE_BLANK;
1848 } else {
1849 graphic_mode = s->gr[6] & 1;
1851 if (graphic_mode != s->graphic_mode) {
1852 s->graphic_mode = graphic_mode;
1853 full_update = 1;
1855 switch(graphic_mode) {
1856 case GMODE_TEXT:
1857 vga_draw_text(s, full_update);
1858 break;
1859 case GMODE_GRAPH:
1860 vga_draw_graphic(s, full_update);
1861 break;
1862 case GMODE_BLANK:
1863 default:
1864 vga_draw_blank(s, full_update);
1865 break;
1870 /* force a full display refresh */
1871 static void vga_invalidate_display(void *opaque)
1873 VGAState *s = (VGAState *)opaque;
1875 s->full_update = 1;
1878 void vga_common_reset(VGACommonState *s)
1880 s->lfb_addr = 0;
1881 s->lfb_end = 0;
1882 s->map_addr = 0;
1883 s->map_end = 0;
1884 s->lfb_vram_mapped = 0;
1885 s->bios_offset = 0;
1886 s->bios_size = 0;
1887 s->sr_index = 0;
1888 memset(s->sr, '\0', sizeof(s->sr));
1889 s->gr_index = 0;
1890 memset(s->gr, '\0', sizeof(s->gr));
1891 s->ar_index = 0;
1892 memset(s->ar, '\0', sizeof(s->ar));
1893 s->ar_flip_flop = 0;
1894 s->cr_index = 0;
1895 memset(s->cr, '\0', sizeof(s->cr));
1896 s->msr = 0;
1897 s->fcr = 0;
1898 s->st00 = 0;
1899 s->st01 = 0;
1900 s->dac_state = 0;
1901 s->dac_sub_index = 0;
1902 s->dac_read_index = 0;
1903 s->dac_write_index = 0;
1904 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1905 s->dac_8bit = 0;
1906 memset(s->palette, '\0', sizeof(s->palette));
1907 s->bank_offset = 0;
1908 #ifdef CONFIG_BOCHS_VBE
1909 s->vbe_index = 0;
1910 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1911 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1912 s->vbe_start_addr = 0;
1913 s->vbe_line_offset = 0;
1914 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1915 #endif
1916 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1917 s->graphic_mode = -1; /* force full update */
1918 s->shift_control = 0;
1919 s->double_scan = 0;
1920 s->line_offset = 0;
1921 s->line_compare = 0;
1922 s->start_addr = 0;
1923 s->plane_updated = 0;
1924 s->last_cw = 0;
1925 s->last_ch = 0;
1926 s->last_width = 0;
1927 s->last_height = 0;
1928 s->last_scr_width = 0;
1929 s->last_scr_height = 0;
1930 s->cursor_start = 0;
1931 s->cursor_end = 0;
1932 s->cursor_offset = 0;
1933 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1934 memset(s->last_palette, '\0', sizeof(s->last_palette));
1935 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1936 switch (vga_retrace_method) {
1937 case VGA_RETRACE_DUMB:
1938 break;
1939 case VGA_RETRACE_PRECISE:
1940 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1941 break;
1945 static void vga_reset(void *opaque)
1947 VGAState *s = (VGAState *) opaque;
1948 vga_common_reset(s);
1951 #define TEXTMODE_X(x) ((x) % width)
1952 #define TEXTMODE_Y(x) ((x) / width)
1953 #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1954 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1955 /* relay text rendering to the display driver
1956 * instead of doing a full vga_update_display() */
1957 static void vga_update_text(void *opaque, console_ch_t *chardata)
1959 VGAState *s = (VGAState *) opaque;
1960 int graphic_mode, i, cursor_offset, cursor_visible;
1961 int cw, cheight, width, height, size, c_min, c_max;
1962 uint32_t *src;
1963 console_ch_t *dst, val;
1964 char msg_buffer[80];
1965 int full_update = 0;
1967 if (!(s->ar_index & 0x20)) {
1968 graphic_mode = GMODE_BLANK;
1969 } else {
1970 graphic_mode = s->gr[6] & 1;
1972 if (graphic_mode != s->graphic_mode) {
1973 s->graphic_mode = graphic_mode;
1974 full_update = 1;
1976 if (s->last_width == -1) {
1977 s->last_width = 0;
1978 full_update = 1;
1981 switch (graphic_mode) {
1982 case GMODE_TEXT:
1983 /* TODO: update palette */
1984 full_update |= update_basic_params(s);
1986 /* total width & height */
1987 cheight = (s->cr[9] & 0x1f) + 1;
1988 cw = 8;
1989 if (!(s->sr[1] & 0x01))
1990 cw = 9;
1991 if (s->sr[1] & 0x08)
1992 cw = 16; /* NOTE: no 18 pixel wide */
1993 width = (s->cr[0x01] + 1);
1994 if (s->cr[0x06] == 100) {
1995 /* ugly hack for CGA 160x100x16 - explain me the logic */
1996 height = 100;
1997 } else {
1998 height = s->cr[0x12] |
1999 ((s->cr[0x07] & 0x02) << 7) |
2000 ((s->cr[0x07] & 0x40) << 3);
2001 height = (height + 1) / cheight;
2004 size = (height * width);
2005 if (size > CH_ATTR_SIZE) {
2006 if (!full_update)
2007 return;
2009 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2010 width, height);
2011 break;
2014 if (width != s->last_width || height != s->last_height ||
2015 cw != s->last_cw || cheight != s->last_ch) {
2016 s->last_scr_width = width * cw;
2017 s->last_scr_height = height * cheight;
2018 s->ds->surface->width = width;
2019 s->ds->surface->height = height;
2020 dpy_resize(s->ds);
2021 s->last_width = width;
2022 s->last_height = height;
2023 s->last_ch = cheight;
2024 s->last_cw = cw;
2025 full_update = 1;
2028 /* Update "hardware" cursor */
2029 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2030 if (cursor_offset != s->cursor_offset ||
2031 s->cr[0xa] != s->cursor_start ||
2032 s->cr[0xb] != s->cursor_end || full_update) {
2033 cursor_visible = !(s->cr[0xa] & 0x20);
2034 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2035 dpy_cursor(s->ds,
2036 TEXTMODE_X(cursor_offset),
2037 TEXTMODE_Y(cursor_offset));
2038 else
2039 dpy_cursor(s->ds, -1, -1);
2040 s->cursor_offset = cursor_offset;
2041 s->cursor_start = s->cr[0xa];
2042 s->cursor_end = s->cr[0xb];
2045 src = (uint32_t *) s->vram_ptr + s->start_addr;
2046 dst = chardata;
2048 if (full_update) {
2049 for (i = 0; i < size; src ++, dst ++, i ++)
2050 console_write_ch(dst, VMEM2CHTYPE(*src));
2052 dpy_update(s->ds, 0, 0, width, height);
2053 } else {
2054 c_max = 0;
2056 for (i = 0; i < size; src ++, dst ++, i ++) {
2057 console_write_ch(&val, VMEM2CHTYPE(*src));
2058 if (*dst != val) {
2059 *dst = val;
2060 c_max = i;
2061 break;
2064 c_min = i;
2065 for (; i < size; src ++, dst ++, i ++) {
2066 console_write_ch(&val, VMEM2CHTYPE(*src));
2067 if (*dst != val) {
2068 *dst = val;
2069 c_max = i;
2073 if (c_min <= c_max) {
2074 i = TEXTMODE_Y(c_min);
2075 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2079 return;
2080 case GMODE_GRAPH:
2081 if (!full_update)
2082 return;
2084 s->get_resolution(s, &width, &height);
2085 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2086 width, height);
2087 break;
2088 case GMODE_BLANK:
2089 default:
2090 if (!full_update)
2091 return;
2093 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2094 break;
2097 /* Display a message */
2098 s->last_width = 60;
2099 s->last_height = height = 3;
2100 dpy_cursor(s->ds, -1, -1);
2101 s->ds->surface->width = s->last_width;
2102 s->ds->surface->height = height;
2103 dpy_resize(s->ds);
2105 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2106 console_write_ch(dst ++, ' ');
2108 size = strlen(msg_buffer);
2109 width = (s->last_width - size) / 2;
2110 dst = chardata + s->last_width + width;
2111 for (i = 0; i < size; i ++)
2112 console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2114 dpy_update(s->ds, 0, 0, s->last_width, height);
2117 static CPUReadMemoryFunc * const vga_mem_read[3] = {
2118 vga_mem_readb,
2119 vga_mem_readw,
2120 vga_mem_readl,
2123 static CPUWriteMemoryFunc * const vga_mem_write[3] = {
2124 vga_mem_writeb,
2125 vga_mem_writew,
2126 vga_mem_writel,
2129 static void vga_save(QEMUFile *f, void *opaque)
2131 VGAState *s = opaque;
2132 int i;
2134 if (s->pci_dev)
2135 pci_device_save(s->pci_dev, f);
2137 qemu_put_be32s(f, &s->latch);
2138 qemu_put_8s(f, &s->sr_index);
2139 qemu_put_buffer(f, s->sr, 8);
2140 qemu_put_8s(f, &s->gr_index);
2141 qemu_put_buffer(f, s->gr, 16);
2142 qemu_put_8s(f, &s->ar_index);
2143 qemu_put_buffer(f, s->ar, 21);
2144 qemu_put_be32(f, s->ar_flip_flop);
2145 qemu_put_8s(f, &s->cr_index);
2146 qemu_put_buffer(f, s->cr, 256);
2147 qemu_put_8s(f, &s->msr);
2148 qemu_put_8s(f, &s->fcr);
2149 qemu_put_byte(f, s->st00);
2150 qemu_put_8s(f, &s->st01);
2152 qemu_put_8s(f, &s->dac_state);
2153 qemu_put_8s(f, &s->dac_sub_index);
2154 qemu_put_8s(f, &s->dac_read_index);
2155 qemu_put_8s(f, &s->dac_write_index);
2156 qemu_put_buffer(f, s->dac_cache, 3);
2157 qemu_put_buffer(f, s->palette, 768);
2159 qemu_put_be32(f, s->bank_offset);
2160 #ifdef CONFIG_BOCHS_VBE
2161 qemu_put_byte(f, 1);
2162 qemu_put_be16s(f, &s->vbe_index);
2163 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2164 qemu_put_be16s(f, &s->vbe_regs[i]);
2165 qemu_put_be32s(f, &s->vbe_start_addr);
2166 qemu_put_be32s(f, &s->vbe_line_offset);
2167 qemu_put_be32s(f, &s->vbe_bank_mask);
2168 #else
2169 qemu_put_byte(f, 0);
2170 #endif
2173 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2175 VGAState *s = opaque;
2176 int is_vbe, i, ret;
2178 if (version_id > 2)
2179 return -EINVAL;
2181 if (s->pci_dev && version_id >= 2) {
2182 ret = pci_device_load(s->pci_dev, f);
2183 if (ret < 0)
2184 return ret;
2187 qemu_get_be32s(f, &s->latch);
2188 qemu_get_8s(f, &s->sr_index);
2189 qemu_get_buffer(f, s->sr, 8);
2190 qemu_get_8s(f, &s->gr_index);
2191 qemu_get_buffer(f, s->gr, 16);
2192 qemu_get_8s(f, &s->ar_index);
2193 qemu_get_buffer(f, s->ar, 21);
2194 s->ar_flip_flop=qemu_get_be32(f);
2195 qemu_get_8s(f, &s->cr_index);
2196 qemu_get_buffer(f, s->cr, 256);
2197 qemu_get_8s(f, &s->msr);
2198 qemu_get_8s(f, &s->fcr);
2199 qemu_get_8s(f, &s->st00);
2200 qemu_get_8s(f, &s->st01);
2202 qemu_get_8s(f, &s->dac_state);
2203 qemu_get_8s(f, &s->dac_sub_index);
2204 qemu_get_8s(f, &s->dac_read_index);
2205 qemu_get_8s(f, &s->dac_write_index);
2206 qemu_get_buffer(f, s->dac_cache, 3);
2207 qemu_get_buffer(f, s->palette, 768);
2209 s->bank_offset=qemu_get_be32(f);
2210 is_vbe = qemu_get_byte(f);
2211 #ifdef CONFIG_BOCHS_VBE
2212 if (!is_vbe)
2213 return -EINVAL;
2214 qemu_get_be16s(f, &s->vbe_index);
2215 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2216 qemu_get_be16s(f, &s->vbe_regs[i]);
2217 qemu_get_be32s(f, &s->vbe_start_addr);
2218 qemu_get_be32s(f, &s->vbe_line_offset);
2219 qemu_get_be32s(f, &s->vbe_bank_mask);
2220 #else
2221 if (is_vbe)
2222 return -EINVAL;
2223 #endif
2225 /* force refresh */
2226 s->graphic_mode = -1;
2227 return 0;
2230 typedef struct PCIVGAState {
2231 PCIDevice dev;
2232 VGAState vga;
2233 } PCIVGAState;
2235 void vga_dirty_log_start(VGAState *s)
2237 if (kvm_enabled() && s->map_addr)
2238 kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2240 if (kvm_enabled() && s->lfb_vram_mapped) {
2241 kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2242 kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2246 static void vga_map(PCIDevice *pci_dev, int region_num,
2247 uint32_t addr, uint32_t size, int type)
2249 PCIVGAState *d = (PCIVGAState *)pci_dev;
2250 VGAState *s = &d->vga;
2251 if (region_num == PCI_ROM_SLOT) {
2252 cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2253 } else {
2254 cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2255 s->map_addr = addr;
2256 s->map_end = addr + s->vram_size;
2257 vga_dirty_log_start(s);
2261 void vga_common_init(VGACommonState *s, int vga_ram_size)
2263 int i, j, v, b;
2265 for(i = 0;i < 256; i++) {
2266 v = 0;
2267 for(j = 0; j < 8; j++) {
2268 v |= ((i >> j) & 1) << (j * 4);
2270 expand4[i] = v;
2272 v = 0;
2273 for(j = 0; j < 4; j++) {
2274 v |= ((i >> (2 * j)) & 3) << (j * 4);
2276 expand2[i] = v;
2278 for(i = 0; i < 16; i++) {
2279 v = 0;
2280 for(j = 0; j < 4; j++) {
2281 b = ((i >> j) & 1);
2282 v |= b << (2 * j);
2283 v |= b << (2 * j + 1);
2285 expand4to8[i] = v;
2288 s->vram_offset = qemu_ram_alloc(vga_ram_size);
2289 s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2290 s->vram_size = vga_ram_size;
2291 s->get_bpp = vga_get_bpp;
2292 s->get_offsets = vga_get_offsets;
2293 s->get_resolution = vga_get_resolution;
2294 s->update = vga_update_display;
2295 s->invalidate = vga_invalidate_display;
2296 s->screen_dump = vga_screen_dump;
2297 s->text_update = vga_update_text;
2298 switch (vga_retrace_method) {
2299 case VGA_RETRACE_DUMB:
2300 s->retrace = vga_dumb_retrace;
2301 s->update_retrace_info = vga_dumb_update_retrace_info;
2302 break;
2304 case VGA_RETRACE_PRECISE:
2305 s->retrace = vga_precise_retrace;
2306 s->update_retrace_info = vga_precise_update_retrace_info;
2307 break;
2309 vga_reset(s);
2312 /* used by both ISA and PCI */
2313 void vga_init(VGAState *s)
2315 int vga_io_memory;
2317 qemu_register_reset(vga_reset, s);
2318 register_savevm("vga", 0, 2, vga_save, vga_load, s);
2320 register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2322 register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2323 register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2324 register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2325 register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2327 register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2329 register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2330 register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2331 register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2332 register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2333 s->bank_offset = 0;
2335 #ifdef CONFIG_BOCHS_VBE
2336 #if defined (TARGET_I386)
2337 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2338 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2340 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2341 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2343 /* old Bochs IO ports */
2344 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2345 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2347 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2348 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2349 #else
2350 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2351 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2353 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2354 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2355 #endif
2356 #endif /* CONFIG_BOCHS_VBE */
2358 vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2359 cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2360 vga_io_memory);
2361 qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2364 /* Memory mapped interface */
2365 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2367 VGAState *s = opaque;
2369 return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2372 static void vga_mm_writeb (void *opaque,
2373 target_phys_addr_t addr, uint32_t value)
2375 VGAState *s = opaque;
2377 vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2380 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2382 VGAState *s = opaque;
2384 return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2387 static void vga_mm_writew (void *opaque,
2388 target_phys_addr_t addr, uint32_t value)
2390 VGAState *s = opaque;
2392 vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2395 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2397 VGAState *s = opaque;
2399 return vga_ioport_read(s, addr >> s->it_shift);
2402 static void vga_mm_writel (void *opaque,
2403 target_phys_addr_t addr, uint32_t value)
2405 VGAState *s = opaque;
2407 vga_ioport_write(s, addr >> s->it_shift, value);
2410 static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
2411 &vga_mm_readb,
2412 &vga_mm_readw,
2413 &vga_mm_readl,
2416 static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
2417 &vga_mm_writeb,
2418 &vga_mm_writew,
2419 &vga_mm_writel,
2422 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2423 target_phys_addr_t ctrl_base, int it_shift)
2425 int s_ioport_ctrl, vga_io_memory;
2427 s->it_shift = it_shift;
2428 s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2429 vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2431 register_savevm("vga", 0, 2, vga_save, vga_load, s);
2433 cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2434 s->bank_offset = 0;
2435 cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2436 qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2439 int isa_vga_init(void)
2441 VGAState *s;
2443 s = qemu_mallocz(sizeof(VGAState));
2445 vga_common_init(s, VGA_RAM_SIZE);
2446 vga_init(s);
2448 s->ds = graphic_console_init(s->update, s->invalidate,
2449 s->screen_dump, s->text_update, s);
2451 #ifdef CONFIG_BOCHS_VBE
2452 /* XXX: use optimized standard vga accesses */
2453 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2454 VGA_RAM_SIZE, s->vram_offset);
2455 #endif
2456 return 0;
2459 int isa_vga_mm_init(target_phys_addr_t vram_base,
2460 target_phys_addr_t ctrl_base, int it_shift)
2462 VGAState *s;
2464 s = qemu_mallocz(sizeof(VGAState));
2466 vga_common_init(s, VGA_RAM_SIZE);
2467 vga_mm_init(s, vram_base, ctrl_base, it_shift);
2469 s->ds = graphic_console_init(s->update, s->invalidate,
2470 s->screen_dump, s->text_update, s);
2472 #ifdef CONFIG_BOCHS_VBE
2473 /* XXX: use optimized standard vga accesses */
2474 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2475 VGA_RAM_SIZE, s->vram_offset);
2476 #endif
2477 return 0;
2480 static void pci_vga_write_config(PCIDevice *d,
2481 uint32_t address, uint32_t val, int len)
2483 PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2484 VGAState *s = &pvs->vga;
2486 pci_default_write_config(d, address, val, len);
2487 if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
2488 s->map_addr = 0;
2491 static int pci_vga_initfn(PCIDevice *dev)
2493 PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
2494 VGAState *s = &d->vga;
2495 uint8_t *pci_conf = d->dev.config;
2497 // vga + console init
2498 vga_common_init(s, VGA_RAM_SIZE);
2499 vga_init(s);
2500 s->pci_dev = &d->dev;
2501 s->ds = graphic_console_init(s->update, s->invalidate,
2502 s->screen_dump, s->text_update, s);
2504 // dummy VGA (same as Bochs ID)
2505 pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2506 pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2507 pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2508 pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
2510 /* XXX: VGA_RAM_SIZE must be a power of two */
2511 pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
2512 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2514 if (s->bios_size) {
2515 unsigned int bios_total_size;
2516 /* must be a power of two */
2517 bios_total_size = 1;
2518 while (bios_total_size < s->bios_size)
2519 bios_total_size <<= 1;
2520 pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
2521 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2523 return 0;
2526 int pci_vga_init(PCIBus *bus,
2527 unsigned long vga_bios_offset, int vga_bios_size)
2529 PCIDevice *dev;
2531 dev = pci_create("VGA", NULL);
2532 qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset);
2533 qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_offset);
2534 qdev_init(&dev->qdev);
2536 return 0;
2539 static PCIDeviceInfo vga_info = {
2540 .qdev.name = "VGA",
2541 .qdev.size = sizeof(PCIVGAState),
2542 .init = pci_vga_initfn,
2543 .config_write = pci_vga_write_config,
2544 .qdev.props = (Property[]) {
2545 DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga.bios_offset, 0),
2546 DEFINE_PROP_HEX32("bios-size", PCIVGAState, vga.bios_size, 0),
2547 DEFINE_PROP_END_OF_LIST(),
2551 static void vga_register(void)
2553 pci_qdev_register(&vga_info);
2555 device_init(vga_register);
2557 /********************************************************/
2558 /* vga screen dump */
2560 static void vga_save_dpy_update(DisplayState *ds,
2561 int x, int y, int w, int h)
2563 if (screen_dump_filename) {
2564 ppm_save(screen_dump_filename, ds->surface);
2565 screen_dump_filename = NULL;
2569 static void vga_save_dpy_resize(DisplayState *s)
2573 static void vga_save_dpy_refresh(DisplayState *s)
2577 int ppm_save(const char *filename, struct DisplaySurface *ds)
2579 FILE *f;
2580 uint8_t *d, *d1;
2581 uint32_t v;
2582 int y, x;
2583 uint8_t r, g, b;
2585 f = fopen(filename, "wb");
2586 if (!f)
2587 return -1;
2588 fprintf(f, "P6\n%d %d\n%d\n",
2589 ds->width, ds->height, 255);
2590 d1 = ds->data;
2591 for(y = 0; y < ds->height; y++) {
2592 d = d1;
2593 for(x = 0; x < ds->width; x++) {
2594 if (ds->pf.bits_per_pixel == 32)
2595 v = *(uint32_t *)d;
2596 else
2597 v = (uint32_t) (*(uint16_t *)d);
2598 r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2599 (ds->pf.rmax + 1);
2600 g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2601 (ds->pf.gmax + 1);
2602 b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2603 (ds->pf.bmax + 1);
2604 fputc(r, f);
2605 fputc(g, f);
2606 fputc(b, f);
2607 d += ds->pf.bytes_per_pixel;
2609 d1 += ds->linesize;
2611 fclose(f);
2612 return 0;
2615 static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2617 DisplayChangeListener *dcl;
2619 dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2620 dcl->dpy_update = vga_save_dpy_update;
2621 dcl->dpy_resize = vga_save_dpy_resize;
2622 dcl->dpy_refresh = vga_save_dpy_refresh;
2623 register_displaychangelistener(ds, dcl);
2624 return dcl;
2627 /* save the vga display in a PPM image even if no display is
2628 available */
2629 static void vga_screen_dump(void *opaque, const char *filename)
2631 VGAState *s = (VGAState *)opaque;
2633 if (!screen_dump_dcl)
2634 screen_dump_dcl = vga_screen_dump_init(s->ds);
2636 screen_dump_filename = (char *)filename;
2637 vga_invalidate_display(s);
2638 vga_hw_update();