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
26 #include "pixel_ops.h"
29 //#define DEBUG_VGA_MEM
30 //#define DEBUG_VGA_REG
32 //#define DEBUG_BOCHS_VBE
34 /* force some bits to zero */
35 const uint8_t sr_mask[8] = {
46 const uint8_t gr_mask[16] = {
47 (uint8_t)~0xf0, /* 0x00 */
48 (uint8_t)~0xf0, /* 0x01 */
49 (uint8_t)~0xf0, /* 0x02 */
50 (uint8_t)~0xe0, /* 0x03 */
51 (uint8_t)~0xfc, /* 0x04 */
52 (uint8_t)~0x84, /* 0x05 */
53 (uint8_t)~0xf0, /* 0x06 */
54 (uint8_t)~0xf0, /* 0x07 */
55 (uint8_t)~0x00, /* 0x08 */
56 (uint8_t)~0xff, /* 0x09 */
57 (uint8_t)~0xff, /* 0x0a */
58 (uint8_t)~0xff, /* 0x0b */
59 (uint8_t)~0xff, /* 0x0c */
60 (uint8_t)~0xff, /* 0x0d */
61 (uint8_t)~0xff, /* 0x0e */
62 (uint8_t)~0xff, /* 0x0f */
65 #define cbswap_32(__x) \
67 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
68 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
69 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
70 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
72 #ifdef WORDS_BIGENDIAN
73 #define PAT(x) cbswap_32(x)
78 #ifdef WORDS_BIGENDIAN
84 #ifdef WORDS_BIGENDIAN
85 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
87 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
90 static const uint32_t mask16[16] = {
111 #ifdef WORDS_BIGENDIAN
114 #define PAT(x) cbswap_32(x)
117 static const uint32_t dmask16[16] = {
136 static const uint32_t dmask4[4] = {
143 static uint32_t expand4[256];
144 static uint16_t expand2[256];
145 static uint8_t expand4to8[16];
147 static void vga_screen_dump(void *opaque, const char *filename);
149 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
151 VGAState *s = opaque;
154 /* check port range access depending on color/monochrome mode */
155 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
156 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
161 if (s->ar_flip_flop == 0) {
168 index = s->ar_index & 0x1f;
181 val = s->sr[s->sr_index];
183 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
190 val = s->dac_write_index;
193 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
194 if (++s->dac_sub_index == 3) {
195 s->dac_sub_index = 0;
209 val = s->gr[s->gr_index];
211 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
220 val = s->cr[s->cr_index];
222 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
227 /* just toggle to fool polling */
228 s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
237 #if defined(DEBUG_VGA)
238 printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
243 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
245 VGAState *s = opaque;
248 /* check port range access depending on color/monochrome mode */
249 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
250 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
254 printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
259 if (s->ar_flip_flop == 0) {
263 index = s->ar_index & 0x1f;
266 s->ar[index] = val & 0x3f;
269 s->ar[index] = val & ~0x10;
275 s->ar[index] = val & ~0xc0;
278 s->ar[index] = val & ~0xf0;
281 s->ar[index] = val & ~0xf0;
287 s->ar_flip_flop ^= 1;
290 s->msr = val & ~0x10;
293 s->sr_index = val & 7;
297 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
299 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
302 s->dac_read_index = val;
303 s->dac_sub_index = 0;
307 s->dac_write_index = val;
308 s->dac_sub_index = 0;
312 s->dac_cache[s->dac_sub_index] = val;
313 if (++s->dac_sub_index == 3) {
314 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
315 s->dac_sub_index = 0;
316 s->dac_write_index++;
320 s->gr_index = val & 0x0f;
324 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
326 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
335 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
337 /* handle CR0-7 protection */
338 if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
339 /* can always write bit 4 of CR7 */
340 if (s->cr_index == 7)
341 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
344 switch(s->cr_index) {
345 case 0x01: /* horizontal display end */
350 case 0x12: /* vertical display end */
351 s->cr[s->cr_index] = val;
354 s->cr[s->cr_index] = val;
365 #ifdef CONFIG_BOCHS_VBE
366 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
368 VGAState *s = opaque;
374 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
376 VGAState *s = opaque;
379 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
380 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
381 switch(s->vbe_index) {
382 /* XXX: do not hardcode ? */
383 case VBE_DISPI_INDEX_XRES:
384 val = VBE_DISPI_MAX_XRES;
386 case VBE_DISPI_INDEX_YRES:
387 val = VBE_DISPI_MAX_YRES;
389 case VBE_DISPI_INDEX_BPP:
390 val = VBE_DISPI_MAX_BPP;
393 val = s->vbe_regs[s->vbe_index];
397 val = s->vbe_regs[s->vbe_index];
402 #ifdef DEBUG_BOCHS_VBE
403 printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
408 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
410 VGAState *s = opaque;
414 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
416 VGAState *s = opaque;
418 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
419 #ifdef DEBUG_BOCHS_VBE
420 printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
422 switch(s->vbe_index) {
423 case VBE_DISPI_INDEX_ID:
424 if (val == VBE_DISPI_ID0 ||
425 val == VBE_DISPI_ID1 ||
426 val == VBE_DISPI_ID2 ||
427 val == VBE_DISPI_ID3 ||
428 val == VBE_DISPI_ID4) {
429 s->vbe_regs[s->vbe_index] = val;
432 case VBE_DISPI_INDEX_XRES:
433 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
434 s->vbe_regs[s->vbe_index] = val;
437 case VBE_DISPI_INDEX_YRES:
438 if (val <= VBE_DISPI_MAX_YRES) {
439 s->vbe_regs[s->vbe_index] = val;
442 case VBE_DISPI_INDEX_BPP:
445 if (val == 4 || val == 8 || val == 15 ||
446 val == 16 || val == 24 || val == 32) {
447 s->vbe_regs[s->vbe_index] = val;
450 case VBE_DISPI_INDEX_BANK:
451 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
452 val &= (s->vbe_bank_mask >> 2);
454 val &= s->vbe_bank_mask;
456 s->vbe_regs[s->vbe_index] = val;
457 s->bank_offset = (val << 16);
459 case VBE_DISPI_INDEX_ENABLE:
460 if ((val & VBE_DISPI_ENABLED) &&
461 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
462 int h, shift_control;
464 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
465 s->vbe_regs[VBE_DISPI_INDEX_XRES];
466 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
467 s->vbe_regs[VBE_DISPI_INDEX_YRES];
468 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
469 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
471 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
472 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
474 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
475 ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
476 s->vbe_start_addr = 0;
478 /* clear the screen (should be done in BIOS) */
479 if (!(val & VBE_DISPI_NOCLEARMEM)) {
480 memset(s->vram_ptr, 0,
481 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
484 /* we initialize the VGA graphic mode (should be done
486 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
487 s->cr[0x17] |= 3; /* no CGA modes */
488 s->cr[0x13] = s->vbe_line_offset >> 3;
490 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
491 /* height (only meaningful if < 1024) */
492 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
494 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
495 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
496 /* line compare to 1023 */
501 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
503 s->sr[0x01] &= ~8; /* no double line */
506 s->sr[4] |= 0x08; /* set chain 4 mode */
507 s->sr[2] |= 0x0f; /* activate all planes */
509 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
510 s->cr[0x09] &= ~0x9f; /* no double scan */
512 /* XXX: the bios should do that */
515 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
516 s->vbe_regs[s->vbe_index] = val;
518 case VBE_DISPI_INDEX_VIRT_WIDTH:
520 int w, h, line_offset;
522 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
525 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
526 line_offset = w >> 1;
528 line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
529 h = s->vram_size / line_offset;
530 /* XXX: support weird bochs semantics ? */
531 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
533 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
534 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
535 s->vbe_line_offset = line_offset;
538 case VBE_DISPI_INDEX_X_OFFSET:
539 case VBE_DISPI_INDEX_Y_OFFSET:
542 s->vbe_regs[s->vbe_index] = val;
543 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
544 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
545 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
546 s->vbe_start_addr += x >> 1;
548 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
549 s->vbe_start_addr >>= 2;
559 /* called for accesses between 0xa0000 and 0xc0000 */
560 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
562 VGAState *s = opaque;
563 int memory_map_mode, plane;
566 /* convert to VGA memory offset */
567 memory_map_mode = (s->gr[6] >> 2) & 3;
569 switch(memory_map_mode) {
575 addr += s->bank_offset;
590 if (s->sr[4] & 0x08) {
591 /* chain 4 mode : simplest access */
592 ret = s->vram_ptr[addr];
593 } else if (s->gr[5] & 0x10) {
594 /* odd/even mode (aka text mode mapping) */
595 plane = (s->gr[4] & 2) | (addr & 1);
596 ret = s->vram_ptr[((addr & ~1) << 1) | plane];
598 /* standard VGA latched access */
599 s->latch = ((uint32_t *)s->vram_ptr)[addr];
601 if (!(s->gr[5] & 0x08)) {
604 ret = GET_PLANE(s->latch, plane);
607 ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
616 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
619 #ifdef TARGET_WORDS_BIGENDIAN
620 v = vga_mem_readb(opaque, addr) << 8;
621 v |= vga_mem_readb(opaque, addr + 1);
623 v = vga_mem_readb(opaque, addr);
624 v |= vga_mem_readb(opaque, addr + 1) << 8;
629 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
632 #ifdef TARGET_WORDS_BIGENDIAN
633 v = vga_mem_readb(opaque, addr) << 24;
634 v |= vga_mem_readb(opaque, addr + 1) << 16;
635 v |= vga_mem_readb(opaque, addr + 2) << 8;
636 v |= vga_mem_readb(opaque, addr + 3);
638 v = vga_mem_readb(opaque, addr);
639 v |= vga_mem_readb(opaque, addr + 1) << 8;
640 v |= vga_mem_readb(opaque, addr + 2) << 16;
641 v |= vga_mem_readb(opaque, addr + 3) << 24;
646 /* called for accesses between 0xa0000 and 0xc0000 */
647 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
649 VGAState *s = opaque;
650 int memory_map_mode, plane, write_mode, b, func_select, mask;
651 uint32_t write_mask, bit_mask, set_mask;
654 printf("vga: [0x%x] = 0x%02x\n", addr, val);
656 /* convert to VGA memory offset */
657 memory_map_mode = (s->gr[6] >> 2) & 3;
659 switch(memory_map_mode) {
665 addr += s->bank_offset;
680 if (s->sr[4] & 0x08) {
681 /* chain 4 mode : simplest access */
684 if (s->sr[2] & mask) {
685 s->vram_ptr[addr] = val;
687 printf("vga: chain4: [0x%x]\n", addr);
689 s->plane_updated |= mask; /* only used to detect font change */
690 cpu_physical_memory_set_dirty(s->vram_offset + addr);
692 } else if (s->gr[5] & 0x10) {
693 /* odd/even mode (aka text mode mapping) */
694 plane = (s->gr[4] & 2) | (addr & 1);
696 if (s->sr[2] & mask) {
697 addr = ((addr & ~1) << 1) | plane;
698 s->vram_ptr[addr] = val;
700 printf("vga: odd/even: [0x%x]\n", addr);
702 s->plane_updated |= mask; /* only used to detect font change */
703 cpu_physical_memory_set_dirty(s->vram_offset + addr);
706 /* standard VGA latched access */
707 write_mode = s->gr[5] & 3;
713 val = ((val >> b) | (val << (8 - b))) & 0xff;
717 /* apply set/reset mask */
718 set_mask = mask16[s->gr[1]];
719 val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
726 val = mask16[val & 0x0f];
732 val = (val >> b) | (val << (8 - b));
734 bit_mask = s->gr[8] & val;
735 val = mask16[s->gr[0]];
739 /* apply logical operation */
740 func_select = s->gr[3] >> 3;
741 switch(func_select) {
761 bit_mask |= bit_mask << 8;
762 bit_mask |= bit_mask << 16;
763 val = (val & bit_mask) | (s->latch & ~bit_mask);
766 /* mask data according to sr[2] */
768 s->plane_updated |= mask; /* only used to detect font change */
769 write_mask = mask16[mask];
770 ((uint32_t *)s->vram_ptr)[addr] =
771 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
774 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
775 addr * 4, write_mask, val);
777 cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
781 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
783 #ifdef TARGET_WORDS_BIGENDIAN
784 vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
785 vga_mem_writeb(opaque, addr + 1, val & 0xff);
787 vga_mem_writeb(opaque, addr, val & 0xff);
788 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
792 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
794 #ifdef TARGET_WORDS_BIGENDIAN
795 vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
796 vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
797 vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
798 vga_mem_writeb(opaque, addr + 3, val & 0xff);
800 vga_mem_writeb(opaque, addr, val & 0xff);
801 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
802 vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
803 vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
807 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
808 const uint8_t *font_ptr, int h,
809 uint32_t fgcol, uint32_t bgcol);
810 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
811 const uint8_t *font_ptr, int h,
812 uint32_t fgcol, uint32_t bgcol, int dup9);
813 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
814 const uint8_t *s, int width);
817 #include "vga_template.h"
820 #include "vga_template.h"
823 #include "vga_template.h"
826 #include "vga_template.h"
830 #include "vga_template.h"
832 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
835 col = rgb_to_pixel8(r, g, b);
841 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
844 col = rgb_to_pixel15(r, g, b);
849 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
852 col = rgb_to_pixel16(r, g, b);
857 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
860 col = rgb_to_pixel32(r, g, b);
864 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
867 col = rgb_to_pixel32bgr(r, g, b);
871 /* return true if the palette was modified */
872 static int update_palette16(VGAState *s)
875 uint32_t v, col, *palette;
878 palette = s->last_palette;
879 for(i = 0; i < 16; i++) {
881 if (s->ar[0x10] & 0x80)
882 v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
884 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
886 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
887 c6_to_8(s->palette[v + 1]),
888 c6_to_8(s->palette[v + 2]));
889 if (col != palette[i]) {
897 /* return true if the palette was modified */
898 static int update_palette256(VGAState *s)
901 uint32_t v, col, *palette;
904 palette = s->last_palette;
906 for(i = 0; i < 256; i++) {
908 col = s->rgb_to_pixel(s->palette[v],
912 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
913 c6_to_8(s->palette[v + 1]),
914 c6_to_8(s->palette[v + 2]));
916 if (col != palette[i]) {
925 static void vga_get_offsets(VGAState *s,
926 uint32_t *pline_offset,
927 uint32_t *pstart_addr,
928 uint32_t *pline_compare)
930 uint32_t start_addr, line_offset, line_compare;
931 #ifdef CONFIG_BOCHS_VBE
932 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
933 line_offset = s->vbe_line_offset;
934 start_addr = s->vbe_start_addr;
935 line_compare = 65535;
939 /* compute line_offset in bytes */
940 line_offset = s->cr[0x13];
943 /* starting address */
944 start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
947 line_compare = s->cr[0x18] |
948 ((s->cr[0x07] & 0x10) << 4) |
949 ((s->cr[0x09] & 0x40) << 3);
951 *pline_offset = line_offset;
952 *pstart_addr = start_addr;
953 *pline_compare = line_compare;
956 /* update start_addr and line_offset. Return TRUE if modified */
957 static int update_basic_params(VGAState *s)
960 uint32_t start_addr, line_offset, line_compare;
964 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
966 if (line_offset != s->line_offset ||
967 start_addr != s->start_addr ||
968 line_compare != s->line_compare) {
969 s->line_offset = line_offset;
970 s->start_addr = start_addr;
971 s->line_compare = line_compare;
979 static inline int get_depth_index(DisplayState *s)
997 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1005 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1007 vga_draw_glyph16_16,
1008 vga_draw_glyph16_16,
1009 vga_draw_glyph16_32,
1010 vga_draw_glyph16_32,
1013 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1021 static const uint8_t cursor_glyph[32 * 4] = {
1022 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1023 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1024 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1025 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1026 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1027 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1028 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1029 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1030 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1031 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1032 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1033 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1034 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1036 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1048 static void vga_draw_text(VGAState *s, int full_update)
1050 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1051 int cx_min, cx_max, linesize, x_incr;
1052 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1053 uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1054 const uint8_t *font_ptr, *font_base[2];
1055 int dup9, line_offset, depth_index;
1057 uint32_t *ch_attr_ptr;
1058 vga_draw_glyph8_func *vga_draw_glyph8;
1059 vga_draw_glyph9_func *vga_draw_glyph9;
1061 full_update |= update_palette16(s);
1062 palette = s->last_palette;
1064 /* compute font data address (in plane 2) */
1066 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1067 if (offset != s->font_offsets[0]) {
1068 s->font_offsets[0] = offset;
1071 font_base[0] = s->vram_ptr + offset;
1073 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1074 font_base[1] = s->vram_ptr + offset;
1075 if (offset != s->font_offsets[1]) {
1076 s->font_offsets[1] = offset;
1079 if (s->plane_updated & (1 << 2)) {
1080 /* if the plane 2 was modified since the last display, it
1081 indicates the font may have been modified */
1082 s->plane_updated = 0;
1085 full_update |= update_basic_params(s);
1087 line_offset = s->line_offset;
1088 s1 = s->vram_ptr + (s->start_addr * 4);
1090 /* total width & height */
1091 cheight = (s->cr[9] & 0x1f) + 1;
1093 if (!(s->sr[1] & 0x01))
1095 if (s->sr[1] & 0x08)
1096 cw = 16; /* NOTE: no 18 pixel wide */
1097 x_incr = cw * ((s->ds->depth + 7) >> 3);
1098 width = (s->cr[0x01] + 1);
1099 if (s->cr[0x06] == 100) {
1100 /* ugly hack for CGA 160x100x16 - explain me the logic */
1103 height = s->cr[0x12] |
1104 ((s->cr[0x07] & 0x02) << 7) |
1105 ((s->cr[0x07] & 0x40) << 3);
1106 height = (height + 1) / cheight;
1108 if ((height * width) > CH_ATTR_SIZE) {
1109 /* better than nothing: exit if transient size is too big */
1113 if (width != s->last_width || height != s->last_height ||
1114 cw != s->last_cw || cheight != s->last_ch) {
1115 s->last_scr_width = width * cw;
1116 s->last_scr_height = height * cheight;
1117 dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1118 s->last_width = width;
1119 s->last_height = height;
1120 s->last_ch = cheight;
1124 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1125 if (cursor_offset != s->cursor_offset ||
1126 s->cr[0xa] != s->cursor_start ||
1127 s->cr[0xb] != s->cursor_end) {
1128 /* if the cursor position changed, we update the old and new
1130 if (s->cursor_offset < CH_ATTR_SIZE)
1131 s->last_ch_attr[s->cursor_offset] = -1;
1132 if (cursor_offset < CH_ATTR_SIZE)
1133 s->last_ch_attr[cursor_offset] = -1;
1134 s->cursor_offset = cursor_offset;
1135 s->cursor_start = s->cr[0xa];
1136 s->cursor_end = s->cr[0xb];
1138 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1140 depth_index = get_depth_index(s->ds);
1142 vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1144 vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1145 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1148 linesize = s->ds->linesize;
1149 ch_attr_ptr = s->last_ch_attr;
1150 for(cy = 0; cy < height; cy++) {
1155 for(cx = 0; cx < width; cx++) {
1156 ch_attr = *(uint16_t *)src;
1157 if (full_update || ch_attr != *ch_attr_ptr) {
1162 *ch_attr_ptr = ch_attr;
1163 #ifdef WORDS_BIGENDIAN
1165 cattr = ch_attr & 0xff;
1167 ch = ch_attr & 0xff;
1168 cattr = ch_attr >> 8;
1170 font_ptr = font_base[(cattr >> 3) & 1];
1171 font_ptr += 32 * 4 * ch;
1172 bgcol = palette[cattr >> 4];
1173 fgcol = palette[cattr & 0x0f];
1175 vga_draw_glyph8(d1, linesize,
1176 font_ptr, cheight, fgcol, bgcol);
1179 if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1181 vga_draw_glyph9(d1, linesize,
1182 font_ptr, cheight, fgcol, bgcol, dup9);
1184 if (src == cursor_ptr &&
1185 !(s->cr[0x0a] & 0x20)) {
1186 int line_start, line_last, h;
1187 /* draw the cursor */
1188 line_start = s->cr[0x0a] & 0x1f;
1189 line_last = s->cr[0x0b] & 0x1f;
1190 /* XXX: check that */
1191 if (line_last > cheight - 1)
1192 line_last = cheight - 1;
1193 if (line_last >= line_start && line_start < cheight) {
1194 h = line_last - line_start + 1;
1195 d = d1 + linesize * line_start;
1197 vga_draw_glyph8(d, linesize,
1198 cursor_glyph, h, fgcol, bgcol);
1200 vga_draw_glyph9(d, linesize,
1201 cursor_glyph, h, fgcol, bgcol, 1);
1211 dpy_update(s->ds, cx_min * cw, cy * cheight,
1212 (cx_max - cx_min + 1) * cw, cheight);
1214 dest += linesize * cheight;
1233 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1241 vga_draw_line2d2_16,
1242 vga_draw_line2d2_16,
1243 vga_draw_line2d2_32,
1244 vga_draw_line2d2_32,
1253 vga_draw_line4d2_16,
1254 vga_draw_line4d2_16,
1255 vga_draw_line4d2_32,
1256 vga_draw_line4d2_32,
1259 vga_draw_line8d2_16,
1260 vga_draw_line8d2_16,
1261 vga_draw_line8d2_32,
1262 vga_draw_line8d2_32,
1274 vga_draw_line15_32bgr,
1280 vga_draw_line16_32bgr,
1286 vga_draw_line24_32bgr,
1292 vga_draw_line32_32bgr,
1295 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1297 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1302 rgb_to_pixel32bgr_dup,
1305 static int vga_get_bpp(VGAState *s)
1308 #ifdef CONFIG_BOCHS_VBE
1309 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1310 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1319 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1323 #ifdef CONFIG_BOCHS_VBE
1324 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1325 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1326 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1330 width = (s->cr[0x01] + 1) * 8;
1331 height = s->cr[0x12] |
1332 ((s->cr[0x07] & 0x02) << 7) |
1333 ((s->cr[0x07] & 0x40) << 3);
1334 height = (height + 1);
1340 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1343 if (y1 >= VGA_MAX_HEIGHT)
1345 if (y2 >= VGA_MAX_HEIGHT)
1346 y2 = VGA_MAX_HEIGHT;
1347 for(y = y1; y < y2; y++) {
1348 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1355 static void vga_draw_graphic(VGAState *s, int full_update)
1357 int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1358 int width, height, shift_control, line_offset, page0, page1, bwidth;
1359 int disp_width, multi_scan, multi_run;
1361 uint32_t v, addr1, addr;
1362 vga_draw_line_func *vga_draw_line;
1364 full_update |= update_basic_params(s);
1366 s->get_resolution(s, &width, &height);
1369 shift_control = (s->gr[0x05] >> 5) & 3;
1370 double_scan = (s->cr[0x09] >> 7);
1371 if (shift_control != 1) {
1372 multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1374 /* in CGA modes, multi_scan is ignored */
1375 /* XXX: is it correct ? */
1376 multi_scan = double_scan;
1378 multi_run = multi_scan;
1379 if (shift_control != s->shift_control ||
1380 double_scan != s->double_scan) {
1382 s->shift_control = shift_control;
1383 s->double_scan = double_scan;
1386 if (shift_control == 0) {
1387 full_update |= update_palette16(s);
1388 if (s->sr[0x01] & 8) {
1389 v = VGA_DRAW_LINE4D2;
1394 } else if (shift_control == 1) {
1395 full_update |= update_palette16(s);
1396 if (s->sr[0x01] & 8) {
1397 v = VGA_DRAW_LINE2D2;
1403 switch(s->get_bpp(s)) {
1406 full_update |= update_palette256(s);
1407 v = VGA_DRAW_LINE8D2;
1410 full_update |= update_palette256(s);
1414 v = VGA_DRAW_LINE15;
1417 v = VGA_DRAW_LINE16;
1420 v = VGA_DRAW_LINE24;
1423 v = VGA_DRAW_LINE32;
1427 vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1429 if (disp_width != s->last_width ||
1430 height != s->last_height) {
1431 dpy_resize(s->ds, disp_width, height);
1432 s->last_scr_width = disp_width;
1433 s->last_scr_height = height;
1434 s->last_width = disp_width;
1435 s->last_height = height;
1438 if (s->cursor_invalidate)
1439 s->cursor_invalidate(s);
1441 line_offset = s->line_offset;
1443 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",
1444 width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1446 addr1 = (s->start_addr * 4);
1449 page_min = 0x7fffffff;
1452 linesize = s->ds->linesize;
1454 for(y = 0; y < height; y++) {
1456 if (!(s->cr[0x17] & 1)) {
1458 /* CGA compatibility handling */
1459 shift = 14 + ((s->cr[0x17] >> 6) & 1);
1460 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1462 if (!(s->cr[0x17] & 2)) {
1463 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1465 page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1466 page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1467 update = full_update |
1468 cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1469 cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1470 if ((page1 - page0) > TARGET_PAGE_SIZE) {
1471 /* if wide line, can use another page */
1472 update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1475 /* explicit invalidation for the hardware cursor */
1476 update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1480 if (page0 < page_min)
1482 if (page1 > page_max)
1484 vga_draw_line(s, d, s->vram_ptr + addr, width);
1485 if (s->cursor_draw_line)
1486 s->cursor_draw_line(s, d, y);
1489 /* flush to display */
1490 dpy_update(s->ds, 0, y_start,
1491 disp_width, y - y_start);
1496 mask = (s->cr[0x17] & 3) ^ 3;
1497 if ((y1 & mask) == mask)
1498 addr1 += line_offset;
1500 multi_run = multi_scan;
1504 /* line compare acts on the displayed lines */
1505 if (y == s->line_compare)
1510 /* flush to display */
1511 dpy_update(s->ds, 0, y_start,
1512 disp_width, y - y_start);
1514 /* reset modified pages */
1515 if (page_max != -1) {
1516 cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1519 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1522 static void vga_draw_blank(VGAState *s, int full_update)
1529 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1531 if (s->ds->depth == 8)
1532 val = s->rgb_to_pixel(0, 0, 0);
1535 w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1537 for(i = 0; i < s->last_scr_height; i++) {
1539 d += s->ds->linesize;
1541 dpy_update(s->ds, 0, 0,
1542 s->last_scr_width, s->last_scr_height);
1545 #define GMODE_TEXT 0
1546 #define GMODE_GRAPH 1
1547 #define GMODE_BLANK 2
1549 static void vga_update_display(void *opaque)
1551 VGAState *s = (VGAState *)opaque;
1552 int full_update, graphic_mode;
1554 if (s->ds->depth == 0) {
1558 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1561 if (!(s->ar_index & 0x20)) {
1562 graphic_mode = GMODE_BLANK;
1564 graphic_mode = s->gr[6] & 1;
1566 if (graphic_mode != s->graphic_mode) {
1567 s->graphic_mode = graphic_mode;
1570 switch(graphic_mode) {
1572 vga_draw_text(s, full_update);
1575 vga_draw_graphic(s, full_update);
1579 vga_draw_blank(s, full_update);
1585 /* force a full display refresh */
1586 static void vga_invalidate_display(void *opaque)
1588 VGAState *s = (VGAState *)opaque;
1591 s->last_height = -1;
1594 static void vga_reset(VGAState *s)
1596 memset(s, 0, sizeof(VGAState));
1597 s->graphic_mode = -1; /* force full update */
1600 static CPUReadMemoryFunc *vga_mem_read[3] = {
1606 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1612 static void vga_save(QEMUFile *f, void *opaque)
1614 VGAState *s = opaque;
1618 pci_device_save(s->pci_dev, f);
1620 qemu_put_be32s(f, &s->latch);
1621 qemu_put_8s(f, &s->sr_index);
1622 qemu_put_buffer(f, s->sr, 8);
1623 qemu_put_8s(f, &s->gr_index);
1624 qemu_put_buffer(f, s->gr, 16);
1625 qemu_put_8s(f, &s->ar_index);
1626 qemu_put_buffer(f, s->ar, 21);
1627 qemu_put_be32s(f, &s->ar_flip_flop);
1628 qemu_put_8s(f, &s->cr_index);
1629 qemu_put_buffer(f, s->cr, 256);
1630 qemu_put_8s(f, &s->msr);
1631 qemu_put_8s(f, &s->fcr);
1632 qemu_put_8s(f, &s->st00);
1633 qemu_put_8s(f, &s->st01);
1635 qemu_put_8s(f, &s->dac_state);
1636 qemu_put_8s(f, &s->dac_sub_index);
1637 qemu_put_8s(f, &s->dac_read_index);
1638 qemu_put_8s(f, &s->dac_write_index);
1639 qemu_put_buffer(f, s->dac_cache, 3);
1640 qemu_put_buffer(f, s->palette, 768);
1642 qemu_put_be32s(f, &s->bank_offset);
1643 #ifdef CONFIG_BOCHS_VBE
1644 qemu_put_byte(f, 1);
1645 qemu_put_be16s(f, &s->vbe_index);
1646 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1647 qemu_put_be16s(f, &s->vbe_regs[i]);
1648 qemu_put_be32s(f, &s->vbe_start_addr);
1649 qemu_put_be32s(f, &s->vbe_line_offset);
1650 qemu_put_be32s(f, &s->vbe_bank_mask);
1652 qemu_put_byte(f, 0);
1656 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1658 VGAState *s = opaque;
1664 if (s->pci_dev && version_id >= 2) {
1665 ret = pci_device_load(s->pci_dev, f);
1670 qemu_get_be32s(f, &s->latch);
1671 qemu_get_8s(f, &s->sr_index);
1672 qemu_get_buffer(f, s->sr, 8);
1673 qemu_get_8s(f, &s->gr_index);
1674 qemu_get_buffer(f, s->gr, 16);
1675 qemu_get_8s(f, &s->ar_index);
1676 qemu_get_buffer(f, s->ar, 21);
1677 qemu_get_be32s(f, &s->ar_flip_flop);
1678 qemu_get_8s(f, &s->cr_index);
1679 qemu_get_buffer(f, s->cr, 256);
1680 qemu_get_8s(f, &s->msr);
1681 qemu_get_8s(f, &s->fcr);
1682 qemu_get_8s(f, &s->st00);
1683 qemu_get_8s(f, &s->st01);
1685 qemu_get_8s(f, &s->dac_state);
1686 qemu_get_8s(f, &s->dac_sub_index);
1687 qemu_get_8s(f, &s->dac_read_index);
1688 qemu_get_8s(f, &s->dac_write_index);
1689 qemu_get_buffer(f, s->dac_cache, 3);
1690 qemu_get_buffer(f, s->palette, 768);
1692 qemu_get_be32s(f, &s->bank_offset);
1693 is_vbe = qemu_get_byte(f);
1694 #ifdef CONFIG_BOCHS_VBE
1697 qemu_get_be16s(f, &s->vbe_index);
1698 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1699 qemu_get_be16s(f, &s->vbe_regs[i]);
1700 qemu_get_be32s(f, &s->vbe_start_addr);
1701 qemu_get_be32s(f, &s->vbe_line_offset);
1702 qemu_get_be32s(f, &s->vbe_bank_mask);
1709 s->graphic_mode = -1;
1713 typedef struct PCIVGAState {
1718 static void vga_map(PCIDevice *pci_dev, int region_num,
1719 uint32_t addr, uint32_t size, int type)
1721 PCIVGAState *d = (PCIVGAState *)pci_dev;
1722 VGAState *s = &d->vga_state;
1723 if (region_num == PCI_ROM_SLOT) {
1724 cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1726 cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1730 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1731 unsigned long vga_ram_offset, int vga_ram_size)
1735 for(i = 0;i < 256; i++) {
1737 for(j = 0; j < 8; j++) {
1738 v |= ((i >> j) & 1) << (j * 4);
1743 for(j = 0; j < 4; j++) {
1744 v |= ((i >> (2 * j)) & 3) << (j * 4);
1748 for(i = 0; i < 16; i++) {
1750 for(j = 0; j < 4; j++) {
1753 v |= b << (2 * j + 1);
1760 s->vram_ptr = vga_ram_base;
1761 s->vram_offset = vga_ram_offset;
1762 s->vram_size = vga_ram_size;
1764 s->get_bpp = vga_get_bpp;
1765 s->get_offsets = vga_get_offsets;
1766 s->get_resolution = vga_get_resolution;
1767 s->update = vga_update_display;
1768 s->invalidate = vga_invalidate_display;
1769 s->screen_dump = vga_screen_dump;
1772 /* used by both ISA and PCI */
1773 void vga_init(VGAState *s)
1777 register_savevm("vga", 0, 2, vga_save, vga_load, s);
1779 register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1781 register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1782 register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1783 register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1784 register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1786 register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1788 register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1789 register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1790 register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1791 register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1794 #ifdef CONFIG_BOCHS_VBE
1795 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1796 s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1797 #if defined (TARGET_I386)
1798 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1799 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1801 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1802 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1804 /* old Bochs IO ports */
1805 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1806 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1808 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1809 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1811 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1812 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1814 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1815 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1817 #endif /* CONFIG_BOCHS_VBE */
1819 vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1820 cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1824 /* Memory mapped interface */
1825 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
1827 VGAState *s = opaque;
1829 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
1832 static void vga_mm_writeb (void *opaque,
1833 target_phys_addr_t addr, uint32_t value)
1835 VGAState *s = opaque;
1837 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
1840 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
1842 VGAState *s = opaque;
1844 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
1847 static void vga_mm_writew (void *opaque,
1848 target_phys_addr_t addr, uint32_t value)
1850 VGAState *s = opaque;
1852 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
1855 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
1857 VGAState *s = opaque;
1859 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
1862 static void vga_mm_writel (void *opaque,
1863 target_phys_addr_t addr, uint32_t value)
1865 VGAState *s = opaque;
1867 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
1870 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
1876 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
1882 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
1883 target_phys_addr_t ctrl_base, int it_shift)
1885 int s_ioport_ctrl, vga_io_memory;
1887 s->base_ctrl = ctrl_base;
1888 s->it_shift = it_shift;
1889 s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
1890 vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1892 register_savevm("vga", 0, 2, vga_save, vga_load, s);
1894 cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
1896 cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
1899 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1900 unsigned long vga_ram_offset, int vga_ram_size)
1904 s = qemu_mallocz(sizeof(VGAState));
1908 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1911 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1913 #ifdef CONFIG_BOCHS_VBE
1914 /* XXX: use optimized standard vga accesses */
1915 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1916 vga_ram_size, vga_ram_offset);
1921 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
1922 unsigned long vga_ram_offset, int vga_ram_size,
1923 target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
1928 s = qemu_mallocz(sizeof(VGAState));
1932 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1933 vga_mm_init(s, vram_base, ctrl_base, it_shift);
1935 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1937 #ifdef CONFIG_BOCHS_VBE
1938 /* XXX: use optimized standard vga accesses */
1939 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1940 vga_ram_size, vga_ram_offset);
1945 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
1946 unsigned long vga_ram_offset, int vga_ram_size,
1947 unsigned long vga_bios_offset, int vga_bios_size)
1953 d = (PCIVGAState *)pci_register_device(bus, "VGA",
1954 sizeof(PCIVGAState),
1960 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1963 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1965 s->pci_dev = &d->dev;
1967 pci_conf = d->dev.config;
1968 pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1969 pci_conf[0x01] = 0x12;
1970 pci_conf[0x02] = 0x11;
1971 pci_conf[0x03] = 0x11;
1972 pci_conf[0x0a] = 0x00; // VGA controller
1973 pci_conf[0x0b] = 0x03;
1974 pci_conf[0x0e] = 0x00; // header_type
1976 /* XXX: vga_ram_size must be a power of two */
1977 pci_register_io_region(&d->dev, 0, vga_ram_size,
1978 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1979 if (vga_bios_size != 0) {
1980 unsigned int bios_total_size;
1981 s->bios_offset = vga_bios_offset;
1982 s->bios_size = vga_bios_size;
1983 /* must be a power of two */
1984 bios_total_size = 1;
1985 while (bios_total_size < vga_bios_size)
1986 bios_total_size <<= 1;
1987 pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
1988 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1993 /********************************************************/
1994 /* vga screen dump */
1996 static int vga_save_w, vga_save_h;
1998 static void vga_save_dpy_update(DisplayState *s,
1999 int x, int y, int w, int h)
2003 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2005 s->linesize = w * 4;
2006 s->data = qemu_malloc(h * s->linesize);
2011 static void vga_save_dpy_refresh(DisplayState *s)
2015 int ppm_save(const char *filename, uint8_t *data,
2016 int w, int h, int linesize)
2023 f = fopen(filename, "wb");
2026 fprintf(f, "P6\n%d %d\n%d\n",
2029 for(y = 0; y < h; y++) {
2031 for(x = 0; x < w; x++) {
2033 fputc((v >> 16) & 0xff, f);
2034 fputc((v >> 8) & 0xff, f);
2035 fputc((v) & 0xff, f);
2044 /* save the vga display in a PPM image even if no display is
2046 static void vga_screen_dump(void *opaque, const char *filename)
2048 VGAState *s = (VGAState *)opaque;
2049 DisplayState *saved_ds, ds1, *ds = &ds1;
2051 /* XXX: this is a little hackish */
2052 vga_invalidate_display(s);
2055 memset(ds, 0, sizeof(DisplayState));
2056 ds->dpy_update = vga_save_dpy_update;
2057 ds->dpy_resize = vga_save_dpy_resize;
2058 ds->dpy_refresh = vga_save_dpy_refresh;
2062 s->graphic_mode = -1;
2063 vga_update_display(s);
2066 ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2068 qemu_free(ds->data);