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
28 //#define DEBUG_VGA_MEM
29 //#define DEBUG_VGA_REG
32 //#define DEBUG_BOCHS_VBE
34 /* S3 VGA is deprecated - another graphic card will be emulated */
35 //#define CONFIG_S3VGA
37 /* force some bits to zero */
38 const uint8_t sr_mask
[8] = {
49 const uint8_t gr_mask
[16] = {
50 (uint8_t)~0xf0, /* 0x00 */
51 (uint8_t)~0xf0, /* 0x01 */
52 (uint8_t)~0xf0, /* 0x02 */
53 (uint8_t)~0xe0, /* 0x03 */
54 (uint8_t)~0xfc, /* 0x04 */
55 (uint8_t)~0x84, /* 0x05 */
56 (uint8_t)~0xf0, /* 0x06 */
57 (uint8_t)~0xf0, /* 0x07 */
58 (uint8_t)~0x00, /* 0x08 */
59 (uint8_t)~0xff, /* 0x09 */
60 (uint8_t)~0xff, /* 0x0a */
61 (uint8_t)~0xff, /* 0x0b */
62 (uint8_t)~0xff, /* 0x0c */
63 (uint8_t)~0xff, /* 0x0d */
64 (uint8_t)~0xff, /* 0x0e */
65 (uint8_t)~0xff, /* 0x0f */
68 #define cbswap_32(__x) \
70 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
71 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
72 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
73 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
75 #ifdef WORDS_BIGENDIAN
76 #define PAT(x) cbswap_32(x)
81 #ifdef WORDS_BIGENDIAN
87 #ifdef WORDS_BIGENDIAN
88 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
90 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93 static const uint32_t mask16
[16] = {
114 #ifdef WORDS_BIGENDIAN
117 #define PAT(x) cbswap_32(x)
120 static const uint32_t dmask16
[16] = {
139 static const uint32_t dmask4
[4] = {
146 static uint32_t expand4
[256];
147 static uint16_t expand2
[256];
148 static uint8_t expand4to8
[16];
153 static uint32_t vga_ioport_read(void *opaque
, uint32_t addr
)
155 VGAState
*s
= opaque
;
158 /* check port range access depending on color/monochrome mode */
159 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
160 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
))) {
165 if (s
->ar_flip_flop
== 0) {
172 index
= s
->ar_index
& 0x1f;
185 val
= s
->sr
[s
->sr_index
];
187 printf("vga: read SR%x = 0x%02x\n", s
->sr_index
, val
);
194 val
= s
->palette
[s
->dac_read_index
* 3 + s
->dac_sub_index
];
195 if (++s
->dac_sub_index
== 3) {
196 s
->dac_sub_index
= 0;
210 val
= s
->gr
[s
->gr_index
];
212 printf("vga: read GR%x = 0x%02x\n", s
->gr_index
, val
);
221 val
= s
->cr
[s
->cr_index
];
223 printf("vga: read CR%x = 0x%02x\n", s
->cr_index
, val
);
226 if (s
->cr_index
>= 0x20)
227 printf("S3: CR read index=0x%x val=0x%x\n",
233 /* just toggle to fool polling */
234 s
->st01
^= ST01_V_RETRACE
| ST01_DISP_ENABLE
;
243 #if defined(DEBUG_VGA)
244 printf("VGA: read addr=0x%04x data=0x%02x\n", addr
, val
);
249 static void vga_ioport_write(void *opaque
, uint32_t addr
, uint32_t val
)
251 VGAState
*s
= opaque
;
254 /* check port range access depending on color/monochrome mode */
255 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
256 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
)))
260 printf("VGA: write addr=0x%04x data=0x%02x\n", addr
, val
);
265 if (s
->ar_flip_flop
== 0) {
269 index
= s
->ar_index
& 0x1f;
272 s
->ar
[index
] = val
& 0x3f;
275 s
->ar
[index
] = val
& ~0x10;
281 s
->ar
[index
] = val
& ~0xc0;
284 s
->ar
[index
] = val
& ~0xf0;
287 s
->ar
[index
] = val
& ~0xf0;
293 s
->ar_flip_flop
^= 1;
296 s
->msr
= val
& ~0x10;
299 s
->sr_index
= val
& 7;
303 printf("vga: write SR%x = 0x%02x\n", s
->sr_index
, val
);
305 s
->sr
[s
->sr_index
] = val
& sr_mask
[s
->sr_index
];
308 s
->dac_read_index
= val
;
309 s
->dac_sub_index
= 0;
313 s
->dac_write_index
= val
;
314 s
->dac_sub_index
= 0;
318 s
->dac_cache
[s
->dac_sub_index
] = val
;
319 if (++s
->dac_sub_index
== 3) {
320 memcpy(&s
->palette
[s
->dac_write_index
* 3], s
->dac_cache
, 3);
321 s
->dac_sub_index
= 0;
322 s
->dac_write_index
++;
326 s
->gr_index
= val
& 0x0f;
330 printf("vga: write GR%x = 0x%02x\n", s
->gr_index
, val
);
332 s
->gr
[s
->gr_index
] = val
& gr_mask
[s
->gr_index
];
341 printf("vga: write CR%x = 0x%02x\n", s
->cr_index
, val
);
343 /* handle CR0-7 protection */
344 if ((s
->cr
[11] & 0x80) && s
->cr_index
<= 7) {
345 /* can always write bit 4 of CR7 */
346 if (s
->cr_index
== 7)
347 s
->cr
[7] = (s
->cr
[7] & ~0x10) | (val
& 0x10);
350 switch(s
->cr_index
) {
351 case 0x01: /* horizontal display end */
356 case 0x12: /* veritcal display end */
357 s
->cr
[s
->cr_index
] = val
;
366 /* chip ID, cannot write */
369 /* update start address */
372 s
->cr
[s
->cr_index
] = val
;
374 s
->cr
[0x69] = (s
->cr
[69] & ~0x03) | v
;
378 /* update start address */
381 s
->cr
[s
->cr_index
] = val
;
383 s
->cr
[0x69] = (s
->cr
[69] & ~0x0c) | (v
<< 2);
388 s
->cr
[s
->cr_index
] = val
;
392 if (s
->cr_index
>= 0x20)
393 printf("S3: CR write index=0x%x val=0x%x\n",
404 #ifdef CONFIG_BOCHS_VBE
405 static uint32_t vbe_ioport_read_index(void *opaque
, uint32_t addr
)
407 VGAState
*s
= opaque
;
413 static uint32_t vbe_ioport_read_data(void *opaque
, uint32_t addr
)
415 VGAState
*s
= opaque
;
418 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
)
419 val
= s
->vbe_regs
[s
->vbe_index
];
422 #ifdef DEBUG_BOCHS_VBE
423 printf("VBE: read index=0x%x val=0x%x\n", s
->vbe_index
, val
);
428 static void vbe_ioport_write_index(void *opaque
, uint32_t addr
, uint32_t val
)
430 VGAState
*s
= opaque
;
434 static void vbe_ioport_write_data(void *opaque
, uint32_t addr
, uint32_t val
)
436 VGAState
*s
= opaque
;
438 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
439 #ifdef DEBUG_BOCHS_VBE
440 printf("VBE: write index=0x%x val=0x%x\n", s
->vbe_index
, val
);
442 switch(s
->vbe_index
) {
443 case VBE_DISPI_INDEX_ID
:
444 if (val
== VBE_DISPI_ID0
||
445 val
== VBE_DISPI_ID1
||
446 val
== VBE_DISPI_ID2
) {
447 s
->vbe_regs
[s
->vbe_index
] = val
;
450 case VBE_DISPI_INDEX_XRES
:
451 if ((val
<= VBE_DISPI_MAX_XRES
) && ((val
& 7) == 0)) {
452 s
->vbe_regs
[s
->vbe_index
] = val
;
455 case VBE_DISPI_INDEX_YRES
:
456 if (val
<= VBE_DISPI_MAX_YRES
) {
457 s
->vbe_regs
[s
->vbe_index
] = val
;
460 case VBE_DISPI_INDEX_BPP
:
463 if (val
== 4 || val
== 8 || val
== 15 ||
464 val
== 16 || val
== 24 || val
== 32) {
465 s
->vbe_regs
[s
->vbe_index
] = val
;
468 case VBE_DISPI_INDEX_BANK
:
469 val
&= s
->vbe_bank_mask
;
470 s
->vbe_regs
[s
->vbe_index
] = val
;
471 s
->bank_offset
= (val
<< 16);
473 case VBE_DISPI_INDEX_ENABLE
:
474 if (val
& VBE_DISPI_ENABLED
) {
475 int h
, shift_control
;
477 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] =
478 s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
479 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] =
480 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
481 s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
] = 0;
482 s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
] = 0;
484 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
485 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 1;
487 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] *
488 ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
489 s
->vbe_start_addr
= 0;
491 /* clear the screen (should be done in BIOS) */
492 if (!(val
& VBE_DISPI_NOCLEARMEM
)) {
493 memset(s
->vram_ptr
, 0,
494 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] * s
->vbe_line_offset
);
497 /* we initialize the VGA graphic mode (should be done
499 s
->gr
[0x06] = (s
->gr
[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
500 s
->cr
[0x17] |= 3; /* no CGA modes */
501 s
->cr
[0x13] = s
->vbe_line_offset
>> 3;
503 s
->cr
[0x01] = (s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 3) - 1;
505 h
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] - 1;
507 s
->cr
[0x07] = (s
->cr
[0x07] & ~0x42) |
508 ((h
>> 7) & 0x02) | ((h
>> 3) & 0x40);
509 /* line compare to 1023 */
514 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
516 s
->sr
[0x01] &= ~8; /* no double line */
519 s
->sr
[4] |= 0x08; /* set chain 4 mode */
520 s
->sr
[2] |= 0x0f; /* activate all planes */
522 s
->gr
[0x05] = (s
->gr
[0x05] & ~0x60) | (shift_control
<< 5);
523 s
->cr
[0x09] &= ~0x9f; /* no double scan */
525 /* XXX: the bios should do that */
528 s
->vbe_regs
[s
->vbe_index
] = val
;
530 case VBE_DISPI_INDEX_VIRT_WIDTH
:
532 int w
, h
, line_offset
;
534 if (val
< s
->vbe_regs
[VBE_DISPI_INDEX_XRES
])
537 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
538 line_offset
= w
>> 1;
540 line_offset
= w
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
541 h
= s
->vram_size
/ line_offset
;
542 /* XXX: support weird bochs semantics ? */
543 if (h
< s
->vbe_regs
[VBE_DISPI_INDEX_YRES
])
545 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] = w
;
546 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] = h
;
547 s
->vbe_line_offset
= line_offset
;
550 case VBE_DISPI_INDEX_X_OFFSET
:
551 case VBE_DISPI_INDEX_Y_OFFSET
:
554 s
->vbe_regs
[s
->vbe_index
] = val
;
555 s
->vbe_start_addr
= s
->vbe_line_offset
* s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
];
556 x
= s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
];
557 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
558 s
->vbe_start_addr
+= x
>> 1;
560 s
->vbe_start_addr
+= x
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
561 s
->vbe_start_addr
>>= 2;
571 /* called for accesses between 0xa0000 and 0xc0000 */
572 uint32_t vga_mem_readb(void *opaque
, target_phys_addr_t addr
)
574 VGAState
*s
= opaque
;
575 int memory_map_mode
, plane
;
578 /* convert to VGA memory offset */
579 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
581 switch(memory_map_mode
) {
587 addr
+= s
->bank_offset
;
602 if (s
->sr
[4] & 0x08) {
603 /* chain 4 mode : simplest access */
604 ret
= s
->vram_ptr
[addr
];
605 } else if (s
->gr
[5] & 0x10) {
606 /* odd/even mode (aka text mode mapping) */
607 plane
= (s
->gr
[4] & 2) | (addr
& 1);
608 ret
= s
->vram_ptr
[((addr
& ~1) << 1) | plane
];
610 /* standard VGA latched access */
611 s
->latch
= ((uint32_t *)s
->vram_ptr
)[addr
];
613 if (!(s
->gr
[5] & 0x08)) {
616 ret
= GET_PLANE(s
->latch
, plane
);
619 ret
= (s
->latch
^ mask16
[s
->gr
[2]]) & mask16
[s
->gr
[7]];
628 static uint32_t vga_mem_readw(void *opaque
, target_phys_addr_t addr
)
631 #ifdef TARGET_WORDS_BIGENDIAN
632 v
= vga_mem_readb(opaque
, addr
) << 8;
633 v
|= vga_mem_readb(opaque
, addr
+ 1);
635 v
= vga_mem_readb(opaque
, addr
);
636 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
641 static uint32_t vga_mem_readl(void *opaque
, target_phys_addr_t addr
)
644 #ifdef TARGET_WORDS_BIGENDIAN
645 v
= vga_mem_readb(opaque
, addr
) << 24;
646 v
|= vga_mem_readb(opaque
, addr
+ 1) << 16;
647 v
|= vga_mem_readb(opaque
, addr
+ 2) << 8;
648 v
|= vga_mem_readb(opaque
, addr
+ 3);
650 v
= vga_mem_readb(opaque
, addr
);
651 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
652 v
|= vga_mem_readb(opaque
, addr
+ 2) << 16;
653 v
|= vga_mem_readb(opaque
, addr
+ 3) << 24;
658 /* called for accesses between 0xa0000 and 0xc0000 */
659 void vga_mem_writeb(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
661 VGAState
*s
= opaque
;
662 int memory_map_mode
, plane
, write_mode
, b
, func_select
;
663 uint32_t write_mask
, bit_mask
, set_mask
;
666 printf("vga: [0x%x] = 0x%02x\n", addr
, val
);
668 /* convert to VGA memory offset */
669 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
671 switch(memory_map_mode
) {
677 addr
+= s
->bank_offset
;
692 if (s
->sr
[4] & 0x08) {
693 /* chain 4 mode : simplest access */
695 if (s
->sr
[2] & (1 << plane
)) {
696 s
->vram_ptr
[addr
] = val
;
698 printf("vga: chain4: [0x%x]\n", addr
);
700 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
702 } else if (s
->gr
[5] & 0x10) {
703 /* odd/even mode (aka text mode mapping) */
704 plane
= (s
->gr
[4] & 2) | (addr
& 1);
705 if (s
->sr
[2] & (1 << plane
)) {
706 addr
= ((addr
& ~1) << 1) | plane
;
707 s
->vram_ptr
[addr
] = val
;
709 printf("vga: odd/even: [0x%x]\n", addr
);
711 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
714 /* standard VGA latched access */
715 write_mode
= s
->gr
[5] & 3;
721 val
= ((val
>> b
) | (val
<< (8 - b
))) & 0xff;
725 /* apply set/reset mask */
726 set_mask
= mask16
[s
->gr
[1]];
727 val
= (val
& ~set_mask
) | (mask16
[s
->gr
[0]] & set_mask
);
734 val
= mask16
[val
& 0x0f];
740 val
= (val
>> b
) | (val
<< (8 - b
));
742 bit_mask
= s
->gr
[8] & val
;
743 val
= mask16
[s
->gr
[0]];
747 /* apply logical operation */
748 func_select
= s
->gr
[3] >> 3;
749 switch(func_select
) {
769 bit_mask
|= bit_mask
<< 8;
770 bit_mask
|= bit_mask
<< 16;
771 val
= (val
& bit_mask
) | (s
->latch
& ~bit_mask
);
774 /* mask data according to sr[2] */
775 write_mask
= mask16
[s
->sr
[2]];
776 ((uint32_t *)s
->vram_ptr
)[addr
] =
777 (((uint32_t *)s
->vram_ptr
)[addr
] & ~write_mask
) |
780 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
781 addr
* 4, write_mask
, val
);
783 cpu_physical_memory_set_dirty(s
->vram_offset
+ (addr
<< 2));
787 static void vga_mem_writew(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
789 #ifdef TARGET_WORDS_BIGENDIAN
790 vga_mem_writeb(opaque
, addr
, (val
>> 8) & 0xff);
791 vga_mem_writeb(opaque
, addr
+ 1, val
& 0xff);
793 vga_mem_writeb(opaque
, addr
, val
& 0xff);
794 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
798 static void vga_mem_writel(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
800 #ifdef TARGET_WORDS_BIGENDIAN
801 vga_mem_writeb(opaque
, addr
, (val
>> 24) & 0xff);
802 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 16) & 0xff);
803 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 8) & 0xff);
804 vga_mem_writeb(opaque
, addr
+ 3, val
& 0xff);
806 vga_mem_writeb(opaque
, addr
, val
& 0xff);
807 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
808 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 16) & 0xff);
809 vga_mem_writeb(opaque
, addr
+ 3, (val
>> 24) & 0xff);
813 typedef void vga_draw_glyph8_func(uint8_t *d
, int linesize
,
814 const uint8_t *font_ptr
, int h
,
815 uint32_t fgcol
, uint32_t bgcol
);
816 typedef void vga_draw_glyph9_func(uint8_t *d
, int linesize
,
817 const uint8_t *font_ptr
, int h
,
818 uint32_t fgcol
, uint32_t bgcol
, int dup9
);
819 typedef void vga_draw_line_func(VGAState
*s1
, uint8_t *d
,
820 const uint8_t *s
, int width
);
822 static inline unsigned int rgb_to_pixel8(unsigned int r
, unsigned int g
, unsigned b
)
828 static inline unsigned int rgb_to_pixel15(unsigned int r
, unsigned int g
, unsigned b
)
830 return ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
833 static inline unsigned int rgb_to_pixel16(unsigned int r
, unsigned int g
, unsigned b
)
835 return ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
838 static inline unsigned int rgb_to_pixel32(unsigned int r
, unsigned int g
, unsigned b
)
840 return (r
<< 16) | (g
<< 8) | b
;
844 #include "vga_template.h"
847 #include "vga_template.h"
850 #include "vga_template.h"
853 #include "vga_template.h"
855 static unsigned int rgb_to_pixel8_dup(unsigned int r
, unsigned int g
, unsigned b
)
858 col
= rgb_to_pixel8(r
, g
, b
);
864 static unsigned int rgb_to_pixel15_dup(unsigned int r
, unsigned int g
, unsigned b
)
867 col
= rgb_to_pixel15(r
, g
, b
);
872 static unsigned int rgb_to_pixel16_dup(unsigned int r
, unsigned int g
, unsigned b
)
875 col
= rgb_to_pixel16(r
, g
, b
);
880 static unsigned int rgb_to_pixel32_dup(unsigned int r
, unsigned int g
, unsigned b
)
883 col
= rgb_to_pixel32(r
, g
, b
);
887 /* return true if the palette was modified */
888 static int update_palette16(VGAState
*s
)
891 uint32_t v
, col
, *palette
;
894 palette
= s
->last_palette
;
895 for(i
= 0; i
< 16; i
++) {
897 if (s
->ar
[0x10] & 0x80)
898 v
= ((s
->ar
[0x14] & 0xf) << 4) | (v
& 0xf);
900 v
= ((s
->ar
[0x14] & 0xc) << 4) | (v
& 0x3f);
902 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
903 c6_to_8(s
->palette
[v
+ 1]),
904 c6_to_8(s
->palette
[v
+ 2]));
905 if (col
!= palette
[i
]) {
913 /* return true if the palette was modified */
914 static int update_palette256(VGAState
*s
)
917 uint32_t v
, col
, *palette
;
920 palette
= s
->last_palette
;
922 for(i
= 0; i
< 256; i
++) {
923 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
924 c6_to_8(s
->palette
[v
+ 1]),
925 c6_to_8(s
->palette
[v
+ 2]));
926 if (col
!= palette
[i
]) {
935 static void vga_get_offsets(VGAState
*s
,
936 uint32_t *pline_offset
,
937 uint32_t *pstart_addr
)
939 uint32_t start_addr
, line_offset
;
940 #ifdef CONFIG_BOCHS_VBE
941 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
942 line_offset
= s
->vbe_line_offset
;
943 start_addr
= s
->vbe_start_addr
;
947 /* compute line_offset in bytes */
948 line_offset
= s
->cr
[0x13];
952 v
= (s
->cr
[0x51] >> 4) & 3; /* S3 extension */
954 v
= (s
->cr
[0x43] >> 2) & 1; /* S3 extension */
955 line_offset
|= (v
<< 8);
960 /* starting address */
961 start_addr
= s
->cr
[0x0d] | (s
->cr
[0x0c] << 8);
963 start_addr
|= (s
->cr
[0x69] & 0x1f) << 16; /* S3 extension */
966 *pline_offset
= line_offset
;
967 *pstart_addr
= start_addr
;
970 /* update start_addr and line_offset. Return TRUE if modified */
971 static int update_basic_params(VGAState
*s
)
974 uint32_t start_addr
, line_offset
, line_compare
;
978 s
->get_offsets(s
, &line_offset
, &start_addr
);
980 line_compare
= s
->cr
[0x18] |
981 ((s
->cr
[0x07] & 0x10) << 4) |
982 ((s
->cr
[0x09] & 0x40) << 3);
984 if (line_offset
!= s
->line_offset
||
985 start_addr
!= s
->start_addr
||
986 line_compare
!= s
->line_compare
) {
987 s
->line_offset
= line_offset
;
988 s
->start_addr
= start_addr
;
989 s
->line_compare
= line_compare
;
995 static inline int get_depth_index(int depth
)
1010 static vga_draw_glyph8_func
*vga_draw_glyph8_table
[4] = {
1017 static vga_draw_glyph8_func
*vga_draw_glyph16_table
[4] = {
1019 vga_draw_glyph16_16
,
1020 vga_draw_glyph16_16
,
1021 vga_draw_glyph16_32
,
1024 static vga_draw_glyph9_func
*vga_draw_glyph9_table
[4] = {
1031 static const uint8_t cursor_glyph
[32 * 4] = {
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,
1038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1040 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1041 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1043 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1044 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1045 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1046 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1047 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1058 static void vga_draw_text(VGAState
*s
, int full_update
)
1060 int cx
, cy
, cheight
, cw
, ch
, cattr
, height
, width
, ch_attr
;
1061 int cx_min
, cx_max
, linesize
, x_incr
;
1062 uint32_t offset
, fgcol
, bgcol
, v
, cursor_offset
;
1063 uint8_t *d1
, *d
, *src
, *s1
, *dest
, *cursor_ptr
;
1064 const uint8_t *font_ptr
, *font_base
[2];
1065 int dup9
, line_offset
, depth_index
;
1067 uint32_t *ch_attr_ptr
;
1068 vga_draw_glyph8_func
*vga_draw_glyph8
;
1069 vga_draw_glyph9_func
*vga_draw_glyph9
;
1071 full_update
|= update_palette16(s
);
1072 palette
= s
->last_palette
;
1074 /* compute font data address (in plane 2) */
1076 offset
= (((v
>> 4) & 1) | ((v
<< 1) & 6)) * 8192 * 4 + 2;
1077 if (offset
!= s
->font_offsets
[0]) {
1078 s
->font_offsets
[0] = offset
;
1081 font_base
[0] = s
->vram_ptr
+ offset
;
1083 offset
= (((v
>> 5) & 1) | ((v
>> 1) & 6)) * 8192 * 4 + 2;
1084 font_base
[1] = s
->vram_ptr
+ offset
;
1085 if (offset
!= s
->font_offsets
[1]) {
1086 s
->font_offsets
[1] = offset
;
1090 full_update
|= update_basic_params(s
);
1092 line_offset
= s
->line_offset
;
1093 s1
= s
->vram_ptr
+ (s
->start_addr
* 4);
1095 /* total width & height */
1096 cheight
= (s
->cr
[9] & 0x1f) + 1;
1098 if (!(s
->sr
[1] & 0x01))
1100 if (s
->sr
[1] & 0x08)
1101 cw
= 16; /* NOTE: no 18 pixel wide */
1102 x_incr
= cw
* ((s
->ds
->depth
+ 7) >> 3);
1103 width
= (s
->cr
[0x01] + 1);
1104 if (s
->cr
[0x06] == 100) {
1105 /* ugly hack for CGA 160x100x16 - explain me the logic */
1108 height
= s
->cr
[0x12] |
1109 ((s
->cr
[0x07] & 0x02) << 7) |
1110 ((s
->cr
[0x07] & 0x40) << 3);
1111 height
= (height
+ 1) / cheight
;
1113 if ((height
* width
) > CH_ATTR_SIZE
) {
1114 /* better than nothing: exit if transient size is too big */
1118 if (width
!= s
->last_width
|| height
!= s
->last_height
||
1119 cw
!= s
->last_cw
|| cheight
!= s
->last_ch
) {
1120 s
->last_scr_width
= width
* cw
;
1121 s
->last_scr_height
= height
* cheight
;
1122 dpy_resize(s
->ds
, s
->last_scr_width
, s
->last_scr_height
);
1123 s
->last_width
= width
;
1124 s
->last_height
= height
;
1125 s
->last_ch
= cheight
;
1129 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
1130 if (cursor_offset
!= s
->cursor_offset
||
1131 s
->cr
[0xa] != s
->cursor_start
||
1132 s
->cr
[0xb] != s
->cursor_end
) {
1133 /* if the cursor position changed, we update the old and new
1135 if (s
->cursor_offset
< CH_ATTR_SIZE
)
1136 s
->last_ch_attr
[s
->cursor_offset
] = -1;
1137 if (cursor_offset
< CH_ATTR_SIZE
)
1138 s
->last_ch_attr
[cursor_offset
] = -1;
1139 s
->cursor_offset
= cursor_offset
;
1140 s
->cursor_start
= s
->cr
[0xa];
1141 s
->cursor_end
= s
->cr
[0xb];
1143 cursor_ptr
= s
->vram_ptr
+ (s
->start_addr
+ cursor_offset
) * 4;
1145 depth_index
= get_depth_index(s
->ds
->depth
);
1147 vga_draw_glyph8
= vga_draw_glyph16_table
[depth_index
];
1149 vga_draw_glyph8
= vga_draw_glyph8_table
[depth_index
];
1150 vga_draw_glyph9
= vga_draw_glyph9_table
[depth_index
];
1153 linesize
= s
->ds
->linesize
;
1154 ch_attr_ptr
= s
->last_ch_attr
;
1155 for(cy
= 0; cy
< height
; cy
++) {
1160 for(cx
= 0; cx
< width
; cx
++) {
1161 ch_attr
= *(uint16_t *)src
;
1162 if (full_update
|| ch_attr
!= *ch_attr_ptr
) {
1167 *ch_attr_ptr
= ch_attr
;
1168 #ifdef WORDS_BIGENDIAN
1170 cattr
= ch_attr
& 0xff;
1172 ch
= ch_attr
& 0xff;
1173 cattr
= ch_attr
>> 8;
1175 font_ptr
= font_base
[(cattr
>> 3) & 1];
1176 font_ptr
+= 32 * 4 * ch
;
1177 bgcol
= palette
[cattr
>> 4];
1178 fgcol
= palette
[cattr
& 0x0f];
1180 vga_draw_glyph8(d1
, linesize
,
1181 font_ptr
, cheight
, fgcol
, bgcol
);
1184 if (ch
>= 0xb0 && ch
<= 0xdf && (s
->ar
[0x10] & 0x04))
1186 vga_draw_glyph9(d1
, linesize
,
1187 font_ptr
, cheight
, fgcol
, bgcol
, dup9
);
1189 if (src
== cursor_ptr
&&
1190 !(s
->cr
[0x0a] & 0x20)) {
1191 int line_start
, line_last
, h
;
1192 /* draw the cursor */
1193 line_start
= s
->cr
[0x0a] & 0x1f;
1194 line_last
= s
->cr
[0x0b] & 0x1f;
1195 /* XXX: check that */
1196 if (line_last
> cheight
- 1)
1197 line_last
= cheight
- 1;
1198 if (line_last
>= line_start
&& line_start
< cheight
) {
1199 h
= line_last
- line_start
+ 1;
1200 d
= d1
+ linesize
* line_start
;
1202 vga_draw_glyph8(d
, linesize
,
1203 cursor_glyph
, h
, fgcol
, bgcol
);
1205 vga_draw_glyph9(d
, linesize
,
1206 cursor_glyph
, h
, fgcol
, bgcol
, 1);
1216 dpy_update(s
->ds
, cx_min
* cw
, cy
* cheight
,
1217 (cx_max
- cx_min
+ 1) * cw
, cheight
);
1219 dest
+= linesize
* cheight
;
1238 static vga_draw_line_func
*vga_draw_line_table
[4 * VGA_DRAW_LINE_NB
] = {
1245 vga_draw_line2d2_16
,
1246 vga_draw_line2d2_16
,
1247 vga_draw_line2d2_32
,
1255 vga_draw_line4d2_16
,
1256 vga_draw_line4d2_16
,
1257 vga_draw_line4d2_32
,
1260 vga_draw_line8d2_16
,
1261 vga_draw_line8d2_16
,
1262 vga_draw_line8d2_32
,
1290 static int vga_get_bpp(VGAState
*s
)
1293 #ifdef CONFIG_BOCHS_VBE
1294 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1295 ret
= s
->vbe_regs
[VBE_DISPI_INDEX_BPP
];
1304 void vga_invalidate_scanlines(VGAState
*s
, int y1
, int y2
)
1307 if (y1
>= VGA_MAX_HEIGHT
)
1309 if (y2
>= VGA_MAX_HEIGHT
)
1310 y2
= VGA_MAX_HEIGHT
;
1311 for(y
= y1
; y
< y2
; y
++) {
1312 s
->invalidated_y_table
[y
>> 5] |= 1 << (y
& 0x1f);
1319 static void vga_draw_graphic(VGAState
*s
, int full_update
)
1321 int y1
, y
, update
, page_min
, page_max
, linesize
, y_start
, double_scan
, mask
;
1322 int width
, height
, shift_control
, line_offset
, page0
, page1
, bwidth
;
1323 int disp_width
, multi_scan
, multi_run
;
1325 uint32_t v
, addr1
, addr
;
1326 vga_draw_line_func
*vga_draw_line
;
1328 full_update
|= update_basic_params(s
);
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);
1337 shift_control
= (s
->gr
[0x05] >> 5) & 3;
1338 double_scan
= (s
->cr
[0x09] & 0x80);
1339 if (shift_control
> 1) {
1340 multi_scan
= (s
->cr
[0x09] & 0x1f);
1344 multi_run
= multi_scan
;
1345 if (shift_control
!= s
->shift_control
||
1346 double_scan
!= s
->double_scan
) {
1348 s
->shift_control
= shift_control
;
1349 s
->double_scan
= double_scan
;
1352 if (shift_control
== 0) {
1353 full_update
|= update_palette16(s
);
1354 if (s
->sr
[0x01] & 8) {
1355 v
= VGA_DRAW_LINE4D2
;
1360 } else if (shift_control
== 1) {
1361 full_update
|= update_palette16(s
);
1362 if (s
->sr
[0x01] & 8) {
1363 v
= VGA_DRAW_LINE2D2
;
1369 switch(s
->get_bpp(s
)) {
1372 full_update
|= update_palette256(s
);
1373 v
= VGA_DRAW_LINE8D2
;
1376 full_update
|= update_palette256(s
);
1380 v
= VGA_DRAW_LINE15
;
1383 v
= VGA_DRAW_LINE16
;
1386 v
= VGA_DRAW_LINE24
;
1389 v
= VGA_DRAW_LINE32
;
1393 vga_draw_line
= vga_draw_line_table
[v
* 4 + get_depth_index(s
->ds
->depth
)];
1395 if (disp_width
!= s
->last_width
||
1396 height
!= s
->last_height
) {
1397 dpy_resize(s
->ds
, disp_width
, height
);
1398 s
->last_scr_width
= disp_width
;
1399 s
->last_scr_height
= height
;
1400 s
->last_width
= disp_width
;
1401 s
->last_height
= height
;
1404 if (s
->cursor_invalidate
)
1405 s
->cursor_invalidate(s
);
1407 line_offset
= s
->line_offset
;
1409 printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1410 width
, height
, v
, line_offset
, s
->cr
[9], s
->cr
[0x17], s
->line_compare
, s
->sr
[0x01]);
1412 addr1
= (s
->start_addr
* 4);
1415 page_min
= 0x7fffffff;
1418 linesize
= s
->ds
->linesize
;
1420 for(y
= 0; y
< height
; y
++) {
1422 if (!(s
->cr
[0x17] & 1)) {
1424 /* CGA compatibility handling */
1425 shift
= 14 + ((s
->cr
[0x17] >> 6) & 1);
1426 addr
= (addr
& ~(1 << shift
)) | ((y1
& 1) << shift
);
1428 if (!(s
->cr
[0x17] & 2)) {
1429 addr
= (addr
& ~0x8000) | ((y1
& 2) << 14);
1431 page0
= s
->vram_offset
+ (addr
& TARGET_PAGE_MASK
);
1432 page1
= s
->vram_offset
+ ((addr
+ bwidth
- 1) & TARGET_PAGE_MASK
);
1433 update
= full_update
| cpu_physical_memory_is_dirty(page0
) |
1434 cpu_physical_memory_is_dirty(page1
);
1435 if ((page1
- page0
) > TARGET_PAGE_SIZE
) {
1436 /* if wide line, can use another page */
1437 update
|= cpu_physical_memory_is_dirty(page0
+ TARGET_PAGE_SIZE
);
1439 /* explicit invalidation for the hardware cursor */
1440 update
|= (s
->invalidated_y_table
[y
>> 5] >> (y
& 0x1f)) & 1;
1444 if (page0
< page_min
)
1446 if (page1
> page_max
)
1448 vga_draw_line(s
, d
, s
->vram_ptr
+ addr
, width
);
1449 if (s
->cursor_draw_line
)
1450 s
->cursor_draw_line(s
, d
, y
);
1453 /* flush to display */
1454 dpy_update(s
->ds
, 0, y_start
,
1455 disp_width
, y
- y_start
);
1460 if (!double_scan
|| (y
& 1) != 0) {
1461 if (y1
== s
->line_compare
) {
1464 mask
= (s
->cr
[0x17] & 3) ^ 3;
1465 if ((y1
& mask
) == mask
)
1466 addr1
+= line_offset
;
1470 multi_run
= multi_scan
;
1478 /* flush to display */
1479 dpy_update(s
->ds
, 0, y_start
,
1480 disp_width
, y
- y_start
);
1482 /* reset modified pages */
1483 if (page_max
!= -1) {
1484 cpu_physical_memory_reset_dirty(page_min
, page_max
+ TARGET_PAGE_SIZE
);
1486 memset(s
->invalidated_y_table
, 0, ((height
+ 31) >> 5) * 4);
1489 static void vga_draw_blank(VGAState
*s
, int full_update
)
1496 if (s
->last_scr_width
<= 0 || s
->last_scr_height
<= 0)
1498 if (s
->ds
->depth
== 8)
1499 val
= s
->rgb_to_pixel(0, 0, 0);
1502 w
= s
->last_scr_width
* ((s
->ds
->depth
+ 7) >> 3);
1504 for(i
= 0; i
< s
->last_scr_height
; i
++) {
1506 d
+= s
->ds
->linesize
;
1508 dpy_update(s
->ds
, 0, 0,
1509 s
->last_scr_width
, s
->last_scr_height
);
1512 #define GMODE_TEXT 0
1513 #define GMODE_GRAPH 1
1514 #define GMODE_BLANK 2
1516 void vga_update_display(void)
1518 VGAState
*s
= vga_state
;
1519 int full_update
, graphic_mode
;
1521 if (s
->ds
->depth
== 0) {
1524 switch(s
->ds
->depth
) {
1526 s
->rgb_to_pixel
= rgb_to_pixel8_dup
;
1529 s
->rgb_to_pixel
= rgb_to_pixel15_dup
;
1533 s
->rgb_to_pixel
= rgb_to_pixel16_dup
;
1536 s
->rgb_to_pixel
= rgb_to_pixel32_dup
;
1541 if (!(s
->ar_index
& 0x20)) {
1542 graphic_mode
= GMODE_BLANK
;
1544 graphic_mode
= s
->gr
[6] & 1;
1546 if (graphic_mode
!= s
->graphic_mode
) {
1547 s
->graphic_mode
= graphic_mode
;
1550 switch(graphic_mode
) {
1552 vga_draw_text(s
, full_update
);
1555 vga_draw_graphic(s
, full_update
);
1559 vga_draw_blank(s
, full_update
);
1565 static void vga_reset(VGAState
*s
)
1567 memset(s
, 0, sizeof(VGAState
));
1569 /* chip ID for 8c968 */
1572 s
->cr
[0x2f] = 0x01; /* XXX: check revision code */
1575 s
->graphic_mode
= -1; /* force full update */
1578 static CPUReadMemoryFunc
*vga_mem_read
[3] = {
1584 static CPUWriteMemoryFunc
*vga_mem_write
[3] = {
1590 static void vga_save(QEMUFile
*f
, void *opaque
)
1592 VGAState
*s
= opaque
;
1595 qemu_put_be32s(f
, &s
->latch
);
1596 qemu_put_8s(f
, &s
->sr_index
);
1597 qemu_put_buffer(f
, s
->sr
, 8);
1598 qemu_put_8s(f
, &s
->gr_index
);
1599 qemu_put_buffer(f
, s
->gr
, 16);
1600 qemu_put_8s(f
, &s
->ar_index
);
1601 qemu_put_buffer(f
, s
->ar
, 21);
1602 qemu_put_be32s(f
, &s
->ar_flip_flop
);
1603 qemu_put_8s(f
, &s
->cr_index
);
1604 qemu_put_buffer(f
, s
->cr
, 256);
1605 qemu_put_8s(f
, &s
->msr
);
1606 qemu_put_8s(f
, &s
->fcr
);
1607 qemu_put_8s(f
, &s
->st00
);
1608 qemu_put_8s(f
, &s
->st01
);
1610 qemu_put_8s(f
, &s
->dac_state
);
1611 qemu_put_8s(f
, &s
->dac_sub_index
);
1612 qemu_put_8s(f
, &s
->dac_read_index
);
1613 qemu_put_8s(f
, &s
->dac_write_index
);
1614 qemu_put_buffer(f
, s
->dac_cache
, 3);
1615 qemu_put_buffer(f
, s
->palette
, 768);
1617 qemu_put_be32s(f
, &s
->bank_offset
);
1618 #ifdef CONFIG_BOCHS_VBE
1619 qemu_put_byte(f
, 1);
1620 qemu_put_be16s(f
, &s
->vbe_index
);
1621 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
1622 qemu_put_be16s(f
, &s
->vbe_regs
[i
]);
1623 qemu_put_be32s(f
, &s
->vbe_start_addr
);
1624 qemu_put_be32s(f
, &s
->vbe_line_offset
);
1625 qemu_put_be32s(f
, &s
->vbe_bank_mask
);
1627 qemu_put_byte(f
, 0);
1631 static int vga_load(QEMUFile
*f
, void *opaque
, int version_id
)
1633 VGAState
*s
= opaque
;
1636 if (version_id
!= 1)
1639 qemu_get_be32s(f
, &s
->latch
);
1640 qemu_get_8s(f
, &s
->sr_index
);
1641 qemu_get_buffer(f
, s
->sr
, 8);
1642 qemu_get_8s(f
, &s
->gr_index
);
1643 qemu_get_buffer(f
, s
->gr
, 16);
1644 qemu_get_8s(f
, &s
->ar_index
);
1645 qemu_get_buffer(f
, s
->ar
, 21);
1646 qemu_get_be32s(f
, &s
->ar_flip_flop
);
1647 qemu_get_8s(f
, &s
->cr_index
);
1648 qemu_get_buffer(f
, s
->cr
, 256);
1649 qemu_get_8s(f
, &s
->msr
);
1650 qemu_get_8s(f
, &s
->fcr
);
1651 qemu_get_8s(f
, &s
->st00
);
1652 qemu_get_8s(f
, &s
->st01
);
1654 qemu_get_8s(f
, &s
->dac_state
);
1655 qemu_get_8s(f
, &s
->dac_sub_index
);
1656 qemu_get_8s(f
, &s
->dac_read_index
);
1657 qemu_get_8s(f
, &s
->dac_write_index
);
1658 qemu_get_buffer(f
, s
->dac_cache
, 3);
1659 qemu_get_buffer(f
, s
->palette
, 768);
1661 qemu_get_be32s(f
, &s
->bank_offset
);
1662 is_vbe
= qemu_get_byte(f
);
1663 #ifdef CONFIG_BOCHS_VBE
1666 qemu_get_be16s(f
, &s
->vbe_index
);
1667 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
1668 qemu_get_be16s(f
, &s
->vbe_regs
[i
]);
1669 qemu_get_be32s(f
, &s
->vbe_start_addr
);
1670 qemu_get_be32s(f
, &s
->vbe_line_offset
);
1671 qemu_get_be32s(f
, &s
->vbe_bank_mask
);
1678 s
->graphic_mode
= -1;
1682 static void vga_map(PCIDevice
*pci_dev
, int region_num
,
1683 uint32_t addr
, uint32_t size
, int type
)
1685 VGAState
*s
= vga_state
;
1687 cpu_register_physical_memory(addr
, s
->vram_size
, s
->vram_offset
);
1690 void vga_common_init(VGAState
*s
, DisplayState
*ds
, uint8_t *vga_ram_base
,
1691 unsigned long vga_ram_offset
, int vga_ram_size
)
1695 for(i
= 0;i
< 256; i
++) {
1697 for(j
= 0; j
< 8; j
++) {
1698 v
|= ((i
>> j
) & 1) << (j
* 4);
1703 for(j
= 0; j
< 4; j
++) {
1704 v
|= ((i
>> (2 * j
)) & 3) << (j
* 4);
1708 for(i
= 0; i
< 16; i
++) {
1710 for(j
= 0; j
< 4; j
++) {
1713 v
|= b
<< (2 * j
+ 1);
1720 s
->vram_ptr
= vga_ram_base
;
1721 s
->vram_offset
= vga_ram_offset
;
1722 s
->vram_size
= vga_ram_size
;
1724 s
->get_bpp
= vga_get_bpp
;
1725 s
->get_offsets
= vga_get_offsets
;
1726 /* XXX: currently needed for display */
1731 int vga_initialize(DisplayState
*ds
, uint8_t *vga_ram_base
,
1732 unsigned long vga_ram_offset
, int vga_ram_size
,
1737 s
= qemu_mallocz(sizeof(VGAState
));
1741 vga_common_init(s
, ds
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
1743 register_savevm("vga", 0, 1, vga_save
, vga_load
, s
);
1745 register_ioport_write(0x3c0, 16, 1, vga_ioport_write
, s
);
1747 register_ioport_write(0x3b4, 2, 1, vga_ioport_write
, s
);
1748 register_ioport_write(0x3d4, 2, 1, vga_ioport_write
, s
);
1749 register_ioport_write(0x3ba, 1, 1, vga_ioport_write
, s
);
1750 register_ioport_write(0x3da, 1, 1, vga_ioport_write
, s
);
1752 register_ioport_read(0x3c0, 16, 1, vga_ioport_read
, s
);
1754 register_ioport_read(0x3b4, 2, 1, vga_ioport_read
, s
);
1755 register_ioport_read(0x3d4, 2, 1, vga_ioport_read
, s
);
1756 register_ioport_read(0x3ba, 1, 1, vga_ioport_read
, s
);
1757 register_ioport_read(0x3da, 1, 1, vga_ioport_read
, s
);
1760 #ifdef CONFIG_BOCHS_VBE
1761 s
->vbe_regs
[VBE_DISPI_INDEX_ID
] = VBE_DISPI_ID0
;
1762 s
->vbe_bank_mask
= ((s
->vram_size
>> 16) - 1);
1763 #if defined (TARGET_I386)
1764 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
1765 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data
, s
);
1767 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
1768 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data
, s
);
1770 /* old Bochs IO ports */
1771 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index
, s
);
1772 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data
, s
);
1774 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index
, s
);
1775 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data
, s
);
1777 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
1778 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data
, s
);
1780 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
1781 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data
, s
);
1783 #endif /* CONFIG_BOCHS_VBE */
1785 vga_io_memory
= cpu_register_io_memory(0, vga_mem_read
, vga_mem_write
, s
);
1786 cpu_register_physical_memory(isa_mem_base
+ 0x000a0000, 0x20000,
1793 d
= pci_register_device("VGA",
1797 pci_conf
= d
->config
;
1798 pci_conf
[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1799 pci_conf
[0x01] = 0x12;
1800 pci_conf
[0x02] = 0x11;
1801 pci_conf
[0x03] = 0x11;
1802 pci_conf
[0x0a] = 0x00; // VGA controller
1803 pci_conf
[0x0b] = 0x03;
1804 pci_conf
[0x0e] = 0x00; // header_type
1806 /* XXX: vga_ram_size must be a power of two */
1807 pci_register_io_region(d
, 0, vga_ram_size
,
1808 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
1810 #ifdef CONFIG_BOCHS_VBE
1811 /* XXX: use optimized standard vga accesses */
1812 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
1813 vga_ram_size
, vga_ram_offset
);
1819 /********************************************************/
1820 /* vga screen dump */
1822 static int vga_save_w
, vga_save_h
;
1824 static void vga_save_dpy_update(DisplayState
*s
,
1825 int x
, int y
, int w
, int h
)
1829 static void vga_save_dpy_resize(DisplayState
*s
, int w
, int h
)
1831 s
->linesize
= w
* 4;
1832 s
->data
= qemu_malloc(h
* s
->linesize
);
1837 static void vga_save_dpy_refresh(DisplayState
*s
)
1841 static int ppm_save(const char *filename
, uint8_t *data
,
1842 int w
, int h
, int linesize
)
1849 f
= fopen(filename
, "wb");
1852 fprintf(f
, "P6\n%d %d\n%d\n",
1855 for(y
= 0; y
< h
; y
++) {
1857 for(x
= 0; x
< w
; x
++) {
1859 fputc((v
>> 16) & 0xff, f
);
1860 fputc((v
>> 8) & 0xff, f
);
1861 fputc((v
) & 0xff, f
);
1870 /* save the vga display in a PPM image even if no display is
1872 void vga_screen_dump(const char *filename
)
1874 VGAState
*s
= vga_state
;
1875 DisplayState
*saved_ds
, ds1
, *ds
= &ds1
;
1877 /* XXX: this is a little hackish */
1879 s
->last_height
= -1;
1882 memset(ds
, 0, sizeof(DisplayState
));
1883 ds
->dpy_update
= vga_save_dpy_update
;
1884 ds
->dpy_resize
= vga_save_dpy_resize
;
1885 ds
->dpy_refresh
= vga_save_dpy_refresh
;
1889 s
->graphic_mode
= -1;
1890 vga_update_display();
1893 ppm_save(filename
, ds
->data
, vga_save_w
, vga_save_h
,
1895 qemu_free(ds
->data
);