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
31 //#define DEBUG_BOCHS_VBE
33 /* force some bits to zero */
34 const uint8_t sr_mask
[8] = {
45 const uint8_t gr_mask
[16] = {
46 (uint8_t)~0xf0, /* 0x00 */
47 (uint8_t)~0xf0, /* 0x01 */
48 (uint8_t)~0xf0, /* 0x02 */
49 (uint8_t)~0xe0, /* 0x03 */
50 (uint8_t)~0xfc, /* 0x04 */
51 (uint8_t)~0x84, /* 0x05 */
52 (uint8_t)~0xf0, /* 0x06 */
53 (uint8_t)~0xf0, /* 0x07 */
54 (uint8_t)~0x00, /* 0x08 */
55 (uint8_t)~0xff, /* 0x09 */
56 (uint8_t)~0xff, /* 0x0a */
57 (uint8_t)~0xff, /* 0x0b */
58 (uint8_t)~0xff, /* 0x0c */
59 (uint8_t)~0xff, /* 0x0d */
60 (uint8_t)~0xff, /* 0x0e */
61 (uint8_t)~0xff, /* 0x0f */
64 #define cbswap_32(__x) \
66 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
67 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
68 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
69 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
71 #ifdef WORDS_BIGENDIAN
72 #define PAT(x) cbswap_32(x)
77 #ifdef WORDS_BIGENDIAN
83 #ifdef WORDS_BIGENDIAN
84 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
86 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
89 static const uint32_t mask16
[16] = {
110 #ifdef WORDS_BIGENDIAN
113 #define PAT(x) cbswap_32(x)
116 static const uint32_t dmask16
[16] = {
135 static const uint32_t dmask4
[4] = {
142 static uint32_t expand4
[256];
143 static uint16_t expand2
[256];
144 static uint8_t expand4to8
[16];
146 static void vga_screen_dump(void *opaque
, const char *filename
);
148 static uint32_t vga_ioport_read(void *opaque
, uint32_t addr
)
150 VGAState
*s
= opaque
;
153 /* check port range access depending on color/monochrome mode */
154 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
155 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
))) {
160 if (s
->ar_flip_flop
== 0) {
167 index
= s
->ar_index
& 0x1f;
180 val
= s
->sr
[s
->sr_index
];
182 printf("vga: read SR%x = 0x%02x\n", s
->sr_index
, val
);
189 val
= s
->dac_write_index
;
192 val
= s
->palette
[s
->dac_read_index
* 3 + s
->dac_sub_index
];
193 if (++s
->dac_sub_index
== 3) {
194 s
->dac_sub_index
= 0;
208 val
= s
->gr
[s
->gr_index
];
210 printf("vga: read GR%x = 0x%02x\n", s
->gr_index
, val
);
219 val
= s
->cr
[s
->cr_index
];
221 printf("vga: read CR%x = 0x%02x\n", s
->cr_index
, val
);
226 /* just toggle to fool polling */
227 s
->st01
^= ST01_V_RETRACE
| ST01_DISP_ENABLE
;
236 #if defined(DEBUG_VGA)
237 printf("VGA: read addr=0x%04x data=0x%02x\n", addr
, val
);
242 static void vga_ioport_write(void *opaque
, uint32_t addr
, uint32_t val
)
244 VGAState
*s
= opaque
;
247 /* check port range access depending on color/monochrome mode */
248 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
249 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
)))
253 printf("VGA: write addr=0x%04x data=0x%02x\n", addr
, val
);
258 if (s
->ar_flip_flop
== 0) {
262 index
= s
->ar_index
& 0x1f;
265 s
->ar
[index
] = val
& 0x3f;
268 s
->ar
[index
] = val
& ~0x10;
274 s
->ar
[index
] = val
& ~0xc0;
277 s
->ar
[index
] = val
& ~0xf0;
280 s
->ar
[index
] = val
& ~0xf0;
286 s
->ar_flip_flop
^= 1;
289 s
->msr
= val
& ~0x10;
292 s
->sr_index
= val
& 7;
296 printf("vga: write SR%x = 0x%02x\n", s
->sr_index
, val
);
298 s
->sr
[s
->sr_index
] = val
& sr_mask
[s
->sr_index
];
301 s
->dac_read_index
= val
;
302 s
->dac_sub_index
= 0;
306 s
->dac_write_index
= val
;
307 s
->dac_sub_index
= 0;
311 s
->dac_cache
[s
->dac_sub_index
] = val
;
312 if (++s
->dac_sub_index
== 3) {
313 memcpy(&s
->palette
[s
->dac_write_index
* 3], s
->dac_cache
, 3);
314 s
->dac_sub_index
= 0;
315 s
->dac_write_index
++;
319 s
->gr_index
= val
& 0x0f;
323 printf("vga: write GR%x = 0x%02x\n", s
->gr_index
, val
);
325 s
->gr
[s
->gr_index
] = val
& gr_mask
[s
->gr_index
];
334 printf("vga: write CR%x = 0x%02x\n", s
->cr_index
, val
);
336 /* handle CR0-7 protection */
337 if ((s
->cr
[0x11] & 0x80) && s
->cr_index
<= 7) {
338 /* can always write bit 4 of CR7 */
339 if (s
->cr_index
== 7)
340 s
->cr
[7] = (s
->cr
[7] & ~0x10) | (val
& 0x10);
343 switch(s
->cr_index
) {
344 case 0x01: /* horizontal display end */
349 case 0x12: /* veritcal display end */
350 s
->cr
[s
->cr_index
] = val
;
353 s
->cr
[s
->cr_index
] = val
;
364 #ifdef CONFIG_BOCHS_VBE
365 static uint32_t vbe_ioport_read_index(void *opaque
, uint32_t addr
)
367 VGAState
*s
= opaque
;
373 static uint32_t vbe_ioport_read_data(void *opaque
, uint32_t addr
)
375 VGAState
*s
= opaque
;
378 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
379 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_GETCAPS
) {
380 switch(s
->vbe_index
) {
381 /* XXX: do not hardcode ? */
382 case VBE_DISPI_INDEX_XRES
:
383 val
= VBE_DISPI_MAX_XRES
;
385 case VBE_DISPI_INDEX_YRES
:
386 val
= VBE_DISPI_MAX_YRES
;
388 case VBE_DISPI_INDEX_BPP
:
389 val
= VBE_DISPI_MAX_BPP
;
392 val
= s
->vbe_regs
[s
->vbe_index
];
396 val
= s
->vbe_regs
[s
->vbe_index
];
401 #ifdef DEBUG_BOCHS_VBE
402 printf("VBE: read index=0x%x val=0x%x\n", s
->vbe_index
, val
);
407 static void vbe_ioport_write_index(void *opaque
, uint32_t addr
, uint32_t val
)
409 VGAState
*s
= opaque
;
413 static void vbe_ioport_write_data(void *opaque
, uint32_t addr
, uint32_t val
)
415 VGAState
*s
= opaque
;
417 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
418 #ifdef DEBUG_BOCHS_VBE
419 printf("VBE: write index=0x%x val=0x%x\n", s
->vbe_index
, val
);
421 switch(s
->vbe_index
) {
422 case VBE_DISPI_INDEX_ID
:
423 if (val
== VBE_DISPI_ID0
||
424 val
== VBE_DISPI_ID1
||
425 val
== VBE_DISPI_ID2
||
426 val
== VBE_DISPI_ID3
||
427 val
== VBE_DISPI_ID4
) {
428 s
->vbe_regs
[s
->vbe_index
] = val
;
431 case VBE_DISPI_INDEX_XRES
:
432 if ((val
<= VBE_DISPI_MAX_XRES
) && ((val
& 7) == 0)) {
433 s
->vbe_regs
[s
->vbe_index
] = val
;
436 case VBE_DISPI_INDEX_YRES
:
437 if (val
<= VBE_DISPI_MAX_YRES
) {
438 s
->vbe_regs
[s
->vbe_index
] = val
;
441 case VBE_DISPI_INDEX_BPP
:
444 if (val
== 4 || val
== 8 || val
== 15 ||
445 val
== 16 || val
== 24 || val
== 32) {
446 s
->vbe_regs
[s
->vbe_index
] = val
;
449 case VBE_DISPI_INDEX_BANK
:
450 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
451 val
&= (s
->vbe_bank_mask
>> 2);
453 val
&= s
->vbe_bank_mask
;
455 s
->vbe_regs
[s
->vbe_index
] = val
;
456 s
->bank_offset
= (val
<< 16);
458 case VBE_DISPI_INDEX_ENABLE
:
459 if ((val
& VBE_DISPI_ENABLED
) &&
460 !(s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
)) {
461 int h
, shift_control
;
463 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] =
464 s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
465 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] =
466 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
467 s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
] = 0;
468 s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
] = 0;
470 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
471 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 1;
473 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] *
474 ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
475 s
->vbe_start_addr
= 0;
477 /* clear the screen (should be done in BIOS) */
478 if (!(val
& VBE_DISPI_NOCLEARMEM
)) {
479 memset(s
->vram_ptr
, 0,
480 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] * s
->vbe_line_offset
);
483 /* we initialize the VGA graphic mode (should be done
485 s
->gr
[0x06] = (s
->gr
[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
486 s
->cr
[0x17] |= 3; /* no CGA modes */
487 s
->cr
[0x13] = s
->vbe_line_offset
>> 3;
489 s
->cr
[0x01] = (s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 3) - 1;
490 /* height (only meaningful if < 1024) */
491 h
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] - 1;
493 s
->cr
[0x07] = (s
->cr
[0x07] & ~0x42) |
494 ((h
>> 7) & 0x02) | ((h
>> 3) & 0x40);
495 /* line compare to 1023 */
500 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
502 s
->sr
[0x01] &= ~8; /* no double line */
505 s
->sr
[4] |= 0x08; /* set chain 4 mode */
506 s
->sr
[2] |= 0x0f; /* activate all planes */
508 s
->gr
[0x05] = (s
->gr
[0x05] & ~0x60) | (shift_control
<< 5);
509 s
->cr
[0x09] &= ~0x9f; /* no double scan */
511 /* XXX: the bios should do that */
514 s
->dac_8bit
= (val
& VBE_DISPI_8BIT_DAC
) > 0;
515 s
->vbe_regs
[s
->vbe_index
] = val
;
517 case VBE_DISPI_INDEX_VIRT_WIDTH
:
519 int w
, h
, line_offset
;
521 if (val
< s
->vbe_regs
[VBE_DISPI_INDEX_XRES
])
524 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
525 line_offset
= w
>> 1;
527 line_offset
= w
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
528 h
= s
->vram_size
/ line_offset
;
529 /* XXX: support weird bochs semantics ? */
530 if (h
< s
->vbe_regs
[VBE_DISPI_INDEX_YRES
])
532 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] = w
;
533 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] = h
;
534 s
->vbe_line_offset
= line_offset
;
537 case VBE_DISPI_INDEX_X_OFFSET
:
538 case VBE_DISPI_INDEX_Y_OFFSET
:
541 s
->vbe_regs
[s
->vbe_index
] = val
;
542 s
->vbe_start_addr
= s
->vbe_line_offset
* s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
];
543 x
= s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
];
544 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
545 s
->vbe_start_addr
+= x
>> 1;
547 s
->vbe_start_addr
+= x
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
548 s
->vbe_start_addr
>>= 2;
558 /* called for accesses between 0xa0000 and 0xc0000 */
559 uint32_t vga_mem_readb(void *opaque
, target_phys_addr_t addr
)
561 VGAState
*s
= opaque
;
562 int memory_map_mode
, plane
;
565 /* convert to VGA memory offset */
566 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
568 switch(memory_map_mode
) {
574 addr
+= s
->bank_offset
;
589 if (s
->sr
[4] & 0x08) {
590 /* chain 4 mode : simplest access */
591 ret
= s
->vram_ptr
[addr
];
592 } else if (s
->gr
[5] & 0x10) {
593 /* odd/even mode (aka text mode mapping) */
594 plane
= (s
->gr
[4] & 2) | (addr
& 1);
595 ret
= s
->vram_ptr
[((addr
& ~1) << 1) | plane
];
597 /* standard VGA latched access */
598 s
->latch
= ((uint32_t *)s
->vram_ptr
)[addr
];
600 if (!(s
->gr
[5] & 0x08)) {
603 ret
= GET_PLANE(s
->latch
, plane
);
606 ret
= (s
->latch
^ mask16
[s
->gr
[2]]) & mask16
[s
->gr
[7]];
615 static uint32_t vga_mem_readw(void *opaque
, target_phys_addr_t addr
)
618 #ifdef TARGET_WORDS_BIGENDIAN
619 v
= vga_mem_readb(opaque
, addr
) << 8;
620 v
|= vga_mem_readb(opaque
, addr
+ 1);
622 v
= vga_mem_readb(opaque
, addr
);
623 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
628 static uint32_t vga_mem_readl(void *opaque
, target_phys_addr_t addr
)
631 #ifdef TARGET_WORDS_BIGENDIAN
632 v
= vga_mem_readb(opaque
, addr
) << 24;
633 v
|= vga_mem_readb(opaque
, addr
+ 1) << 16;
634 v
|= vga_mem_readb(opaque
, addr
+ 2) << 8;
635 v
|= vga_mem_readb(opaque
, addr
+ 3);
637 v
= vga_mem_readb(opaque
, addr
);
638 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
639 v
|= vga_mem_readb(opaque
, addr
+ 2) << 16;
640 v
|= vga_mem_readb(opaque
, addr
+ 3) << 24;
645 /* called for accesses between 0xa0000 and 0xc0000 */
646 void vga_mem_writeb(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
648 VGAState
*s
= opaque
;
649 int memory_map_mode
, plane
, write_mode
, b
, func_select
, mask
;
650 uint32_t write_mask
, bit_mask
, set_mask
;
653 printf("vga: [0x%x] = 0x%02x\n", addr
, val
);
655 /* convert to VGA memory offset */
656 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
658 switch(memory_map_mode
) {
664 addr
+= s
->bank_offset
;
679 if (s
->sr
[4] & 0x08) {
680 /* chain 4 mode : simplest access */
683 if (s
->sr
[2] & mask
) {
684 s
->vram_ptr
[addr
] = val
;
686 printf("vga: chain4: [0x%x]\n", addr
);
688 s
->plane_updated
|= mask
; /* only used to detect font change */
689 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
691 } else if (s
->gr
[5] & 0x10) {
692 /* odd/even mode (aka text mode mapping) */
693 plane
= (s
->gr
[4] & 2) | (addr
& 1);
695 if (s
->sr
[2] & mask
) {
696 addr
= ((addr
& ~1) << 1) | plane
;
697 s
->vram_ptr
[addr
] = val
;
699 printf("vga: odd/even: [0x%x]\n", addr
);
701 s
->plane_updated
|= mask
; /* only used to detect font change */
702 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
705 /* standard VGA latched access */
706 write_mode
= s
->gr
[5] & 3;
712 val
= ((val
>> b
) | (val
<< (8 - b
))) & 0xff;
716 /* apply set/reset mask */
717 set_mask
= mask16
[s
->gr
[1]];
718 val
= (val
& ~set_mask
) | (mask16
[s
->gr
[0]] & set_mask
);
725 val
= mask16
[val
& 0x0f];
731 val
= (val
>> b
) | (val
<< (8 - b
));
733 bit_mask
= s
->gr
[8] & val
;
734 val
= mask16
[s
->gr
[0]];
738 /* apply logical operation */
739 func_select
= s
->gr
[3] >> 3;
740 switch(func_select
) {
760 bit_mask
|= bit_mask
<< 8;
761 bit_mask
|= bit_mask
<< 16;
762 val
= (val
& bit_mask
) | (s
->latch
& ~bit_mask
);
765 /* mask data according to sr[2] */
767 s
->plane_updated
|= mask
; /* only used to detect font change */
768 write_mask
= mask16
[mask
];
769 ((uint32_t *)s
->vram_ptr
)[addr
] =
770 (((uint32_t *)s
->vram_ptr
)[addr
] & ~write_mask
) |
773 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
774 addr
* 4, write_mask
, val
);
776 cpu_physical_memory_set_dirty(s
->vram_offset
+ (addr
<< 2));
780 static void vga_mem_writew(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
782 #ifdef TARGET_WORDS_BIGENDIAN
783 vga_mem_writeb(opaque
, addr
, (val
>> 8) & 0xff);
784 vga_mem_writeb(opaque
, addr
+ 1, val
& 0xff);
786 vga_mem_writeb(opaque
, addr
, val
& 0xff);
787 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
791 static void vga_mem_writel(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
793 #ifdef TARGET_WORDS_BIGENDIAN
794 vga_mem_writeb(opaque
, addr
, (val
>> 24) & 0xff);
795 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 16) & 0xff);
796 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 8) & 0xff);
797 vga_mem_writeb(opaque
, addr
+ 3, val
& 0xff);
799 vga_mem_writeb(opaque
, addr
, val
& 0xff);
800 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
801 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 16) & 0xff);
802 vga_mem_writeb(opaque
, addr
+ 3, (val
>> 24) & 0xff);
806 typedef void vga_draw_glyph8_func(uint8_t *d
, int linesize
,
807 const uint8_t *font_ptr
, int h
,
808 uint32_t fgcol
, uint32_t bgcol
);
809 typedef void vga_draw_glyph9_func(uint8_t *d
, int linesize
,
810 const uint8_t *font_ptr
, int h
,
811 uint32_t fgcol
, uint32_t bgcol
, int dup9
);
812 typedef void vga_draw_line_func(VGAState
*s1
, uint8_t *d
,
813 const uint8_t *s
, int width
);
815 static inline unsigned int rgb_to_pixel8(unsigned int r
, unsigned int g
, unsigned b
)
817 return ((r
>> 5) << 5) | ((g
>> 5) << 2) | (b
>> 6);
820 static inline unsigned int rgb_to_pixel15(unsigned int r
, unsigned int g
, unsigned b
)
822 return ((r
>> 3) << 10) | ((g
>> 3) << 5) | (b
>> 3);
825 static inline unsigned int rgb_to_pixel16(unsigned int r
, unsigned int g
, unsigned b
)
827 return ((r
>> 3) << 11) | ((g
>> 2) << 5) | (b
>> 3);
830 static inline unsigned int rgb_to_pixel32(unsigned int r
, unsigned int g
, unsigned b
)
832 return (r
<< 16) | (g
<< 8) | b
;
835 static inline unsigned int rgb_to_pixel32bgr(unsigned int r
, unsigned int g
, unsigned b
)
837 return (b
<< 16) | (g
<< 8) | r
;
841 #include "vga_template.h"
844 #include "vga_template.h"
847 #include "vga_template.h"
850 #include "vga_template.h"
854 #include "vga_template.h"
856 static unsigned int rgb_to_pixel8_dup(unsigned int r
, unsigned int g
, unsigned b
)
859 col
= rgb_to_pixel8(r
, g
, b
);
865 static unsigned int rgb_to_pixel15_dup(unsigned int r
, unsigned int g
, unsigned b
)
868 col
= rgb_to_pixel15(r
, g
, b
);
873 static unsigned int rgb_to_pixel16_dup(unsigned int r
, unsigned int g
, unsigned b
)
876 col
= rgb_to_pixel16(r
, g
, b
);
881 static unsigned int rgb_to_pixel32_dup(unsigned int r
, unsigned int g
, unsigned b
)
884 col
= rgb_to_pixel32(r
, g
, b
);
888 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r
, unsigned int g
, unsigned b
)
891 col
= rgb_to_pixel32bgr(r
, g
, b
);
895 /* return true if the palette was modified */
896 static int update_palette16(VGAState
*s
)
899 uint32_t v
, col
, *palette
;
902 palette
= s
->last_palette
;
903 for(i
= 0; i
< 16; i
++) {
905 if (s
->ar
[0x10] & 0x80)
906 v
= ((s
->ar
[0x14] & 0xf) << 4) | (v
& 0xf);
908 v
= ((s
->ar
[0x14] & 0xc) << 4) | (v
& 0x3f);
910 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
911 c6_to_8(s
->palette
[v
+ 1]),
912 c6_to_8(s
->palette
[v
+ 2]));
913 if (col
!= palette
[i
]) {
921 /* return true if the palette was modified */
922 static int update_palette256(VGAState
*s
)
925 uint32_t v
, col
, *palette
;
928 palette
= s
->last_palette
;
930 for(i
= 0; i
< 256; i
++) {
932 col
= s
->rgb_to_pixel(s
->palette
[v
],
936 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
937 c6_to_8(s
->palette
[v
+ 1]),
938 c6_to_8(s
->palette
[v
+ 2]));
940 if (col
!= palette
[i
]) {
949 static void vga_get_offsets(VGAState
*s
,
950 uint32_t *pline_offset
,
951 uint32_t *pstart_addr
,
952 uint32_t *pline_compare
)
954 uint32_t start_addr
, line_offset
, line_compare
;
955 #ifdef CONFIG_BOCHS_VBE
956 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
957 line_offset
= s
->vbe_line_offset
;
958 start_addr
= s
->vbe_start_addr
;
959 line_compare
= 65535;
963 /* compute line_offset in bytes */
964 line_offset
= s
->cr
[0x13];
967 /* starting address */
968 start_addr
= s
->cr
[0x0d] | (s
->cr
[0x0c] << 8);
971 line_compare
= s
->cr
[0x18] |
972 ((s
->cr
[0x07] & 0x10) << 4) |
973 ((s
->cr
[0x09] & 0x40) << 3);
975 *pline_offset
= line_offset
;
976 *pstart_addr
= start_addr
;
977 *pline_compare
= line_compare
;
980 /* update start_addr and line_offset. Return TRUE if modified */
981 static int update_basic_params(VGAState
*s
)
984 uint32_t start_addr
, line_offset
, line_compare
;
988 s
->get_offsets(s
, &line_offset
, &start_addr
, &line_compare
);
990 if (line_offset
!= s
->line_offset
||
991 start_addr
!= s
->start_addr
||
992 line_compare
!= s
->line_compare
) {
993 s
->line_offset
= line_offset
;
994 s
->start_addr
= start_addr
;
995 s
->line_compare
= line_compare
;
1003 static inline int get_depth_index(DisplayState
*s
)
1021 static vga_draw_glyph8_func
*vga_draw_glyph8_table
[NB_DEPTHS
] = {
1029 static vga_draw_glyph8_func
*vga_draw_glyph16_table
[NB_DEPTHS
] = {
1031 vga_draw_glyph16_16
,
1032 vga_draw_glyph16_16
,
1033 vga_draw_glyph16_32
,
1034 vga_draw_glyph16_32
,
1037 static vga_draw_glyph9_func
*vga_draw_glyph9_table
[NB_DEPTHS
] = {
1045 static const uint8_t cursor_glyph
[32 * 4] = {
1046 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1047 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1048 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1049 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1050 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1051 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1052 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1053 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1054 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1055 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1056 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1057 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1058 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1059 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1060 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1061 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1072 static void vga_draw_text(VGAState
*s
, int full_update
)
1074 int cx
, cy
, cheight
, cw
, ch
, cattr
, height
, width
, ch_attr
;
1075 int cx_min
, cx_max
, linesize
, x_incr
;
1076 uint32_t offset
, fgcol
, bgcol
, v
, cursor_offset
;
1077 uint8_t *d1
, *d
, *src
, *s1
, *dest
, *cursor_ptr
;
1078 const uint8_t *font_ptr
, *font_base
[2];
1079 int dup9
, line_offset
, depth_index
;
1081 uint32_t *ch_attr_ptr
;
1082 vga_draw_glyph8_func
*vga_draw_glyph8
;
1083 vga_draw_glyph9_func
*vga_draw_glyph9
;
1085 full_update
|= update_palette16(s
);
1086 palette
= s
->last_palette
;
1088 /* compute font data address (in plane 2) */
1090 offset
= (((v
>> 4) & 1) | ((v
<< 1) & 6)) * 8192 * 4 + 2;
1091 if (offset
!= s
->font_offsets
[0]) {
1092 s
->font_offsets
[0] = offset
;
1095 font_base
[0] = s
->vram_ptr
+ offset
;
1097 offset
= (((v
>> 5) & 1) | ((v
>> 1) & 6)) * 8192 * 4 + 2;
1098 font_base
[1] = s
->vram_ptr
+ offset
;
1099 if (offset
!= s
->font_offsets
[1]) {
1100 s
->font_offsets
[1] = offset
;
1103 if (s
->plane_updated
& (1 << 2)) {
1104 /* if the plane 2 was modified since the last display, it
1105 indicates the font may have been modified */
1106 s
->plane_updated
= 0;
1109 full_update
|= update_basic_params(s
);
1111 line_offset
= s
->line_offset
;
1112 s1
= s
->vram_ptr
+ (s
->start_addr
* 4);
1114 /* total width & height */
1115 cheight
= (s
->cr
[9] & 0x1f) + 1;
1117 if (!(s
->sr
[1] & 0x01))
1119 if (s
->sr
[1] & 0x08)
1120 cw
= 16; /* NOTE: no 18 pixel wide */
1121 x_incr
= cw
* ((s
->ds
->depth
+ 7) >> 3);
1122 width
= (s
->cr
[0x01] + 1);
1123 if (s
->cr
[0x06] == 100) {
1124 /* ugly hack for CGA 160x100x16 - explain me the logic */
1127 height
= s
->cr
[0x12] |
1128 ((s
->cr
[0x07] & 0x02) << 7) |
1129 ((s
->cr
[0x07] & 0x40) << 3);
1130 height
= (height
+ 1) / cheight
;
1132 if ((height
* width
) > CH_ATTR_SIZE
) {
1133 /* better than nothing: exit if transient size is too big */
1137 if (width
!= s
->last_width
|| height
!= s
->last_height
||
1138 cw
!= s
->last_cw
|| cheight
!= s
->last_ch
) {
1139 s
->last_scr_width
= width
* cw
;
1140 s
->last_scr_height
= height
* cheight
;
1141 dpy_resize(s
->ds
, s
->last_scr_width
, s
->last_scr_height
);
1142 s
->last_width
= width
;
1143 s
->last_height
= height
;
1144 s
->last_ch
= cheight
;
1148 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
1149 if (cursor_offset
!= s
->cursor_offset
||
1150 s
->cr
[0xa] != s
->cursor_start
||
1151 s
->cr
[0xb] != s
->cursor_end
) {
1152 /* if the cursor position changed, we update the old and new
1154 if (s
->cursor_offset
< CH_ATTR_SIZE
)
1155 s
->last_ch_attr
[s
->cursor_offset
] = -1;
1156 if (cursor_offset
< CH_ATTR_SIZE
)
1157 s
->last_ch_attr
[cursor_offset
] = -1;
1158 s
->cursor_offset
= cursor_offset
;
1159 s
->cursor_start
= s
->cr
[0xa];
1160 s
->cursor_end
= s
->cr
[0xb];
1162 cursor_ptr
= s
->vram_ptr
+ (s
->start_addr
+ cursor_offset
) * 4;
1164 depth_index
= get_depth_index(s
->ds
);
1166 vga_draw_glyph8
= vga_draw_glyph16_table
[depth_index
];
1168 vga_draw_glyph8
= vga_draw_glyph8_table
[depth_index
];
1169 vga_draw_glyph9
= vga_draw_glyph9_table
[depth_index
];
1172 linesize
= s
->ds
->linesize
;
1173 ch_attr_ptr
= s
->last_ch_attr
;
1174 for(cy
= 0; cy
< height
; cy
++) {
1179 for(cx
= 0; cx
< width
; cx
++) {
1180 ch_attr
= *(uint16_t *)src
;
1181 if (full_update
|| ch_attr
!= *ch_attr_ptr
) {
1186 *ch_attr_ptr
= ch_attr
;
1187 #ifdef WORDS_BIGENDIAN
1189 cattr
= ch_attr
& 0xff;
1191 ch
= ch_attr
& 0xff;
1192 cattr
= ch_attr
>> 8;
1194 font_ptr
= font_base
[(cattr
>> 3) & 1];
1195 font_ptr
+= 32 * 4 * ch
;
1196 bgcol
= palette
[cattr
>> 4];
1197 fgcol
= palette
[cattr
& 0x0f];
1199 vga_draw_glyph8(d1
, linesize
,
1200 font_ptr
, cheight
, fgcol
, bgcol
);
1203 if (ch
>= 0xb0 && ch
<= 0xdf && (s
->ar
[0x10] & 0x04))
1205 vga_draw_glyph9(d1
, linesize
,
1206 font_ptr
, cheight
, fgcol
, bgcol
, dup9
);
1208 if (src
== cursor_ptr
&&
1209 !(s
->cr
[0x0a] & 0x20)) {
1210 int line_start
, line_last
, h
;
1211 /* draw the cursor */
1212 line_start
= s
->cr
[0x0a] & 0x1f;
1213 line_last
= s
->cr
[0x0b] & 0x1f;
1214 /* XXX: check that */
1215 if (line_last
> cheight
- 1)
1216 line_last
= cheight
- 1;
1217 if (line_last
>= line_start
&& line_start
< cheight
) {
1218 h
= line_last
- line_start
+ 1;
1219 d
= d1
+ linesize
* line_start
;
1221 vga_draw_glyph8(d
, linesize
,
1222 cursor_glyph
, h
, fgcol
, bgcol
);
1224 vga_draw_glyph9(d
, linesize
,
1225 cursor_glyph
, h
, fgcol
, bgcol
, 1);
1235 dpy_update(s
->ds
, cx_min
* cw
, cy
* cheight
,
1236 (cx_max
- cx_min
+ 1) * cw
, cheight
);
1238 dest
+= linesize
* cheight
;
1257 static vga_draw_line_func
*vga_draw_line_table
[NB_DEPTHS
* VGA_DRAW_LINE_NB
] = {
1265 vga_draw_line2d2_16
,
1266 vga_draw_line2d2_16
,
1267 vga_draw_line2d2_32
,
1268 vga_draw_line2d2_32
,
1277 vga_draw_line4d2_16
,
1278 vga_draw_line4d2_16
,
1279 vga_draw_line4d2_32
,
1280 vga_draw_line4d2_32
,
1283 vga_draw_line8d2_16
,
1284 vga_draw_line8d2_16
,
1285 vga_draw_line8d2_32
,
1286 vga_draw_line8d2_32
,
1298 vga_draw_line15_32bgr
,
1304 vga_draw_line16_32bgr
,
1310 vga_draw_line24_32bgr
,
1316 vga_draw_line32_32bgr
,
1319 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r
, unsigned int g
, unsigned b
);
1321 static rgb_to_pixel_dup_func
*rgb_to_pixel_dup_table
[NB_DEPTHS
] = {
1326 rgb_to_pixel32bgr_dup
,
1329 static int vga_get_bpp(VGAState
*s
)
1332 #ifdef CONFIG_BOCHS_VBE
1333 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1334 ret
= s
->vbe_regs
[VBE_DISPI_INDEX_BPP
];
1343 static void vga_get_resolution(VGAState
*s
, int *pwidth
, int *pheight
)
1347 #ifdef CONFIG_BOCHS_VBE
1348 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1349 width
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
1350 height
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
1354 width
= (s
->cr
[0x01] + 1) * 8;
1355 height
= s
->cr
[0x12] |
1356 ((s
->cr
[0x07] & 0x02) << 7) |
1357 ((s
->cr
[0x07] & 0x40) << 3);
1358 height
= (height
+ 1);
1364 void vga_invalidate_scanlines(VGAState
*s
, int y1
, int y2
)
1367 if (y1
>= VGA_MAX_HEIGHT
)
1369 if (y2
>= VGA_MAX_HEIGHT
)
1370 y2
= VGA_MAX_HEIGHT
;
1371 for(y
= y1
; y
< y2
; y
++) {
1372 s
->invalidated_y_table
[y
>> 5] |= 1 << (y
& 0x1f);
1379 static void vga_draw_graphic(VGAState
*s
, int full_update
)
1381 int y1
, y
, update
, page_min
, page_max
, linesize
, y_start
, double_scan
, mask
;
1382 int width
, height
, shift_control
, line_offset
, page0
, page1
, bwidth
;
1383 int disp_width
, multi_scan
, multi_run
;
1385 uint32_t v
, addr1
, addr
;
1386 vga_draw_line_func
*vga_draw_line
;
1388 full_update
|= update_basic_params(s
);
1390 s
->get_resolution(s
, &width
, &height
);
1393 shift_control
= (s
->gr
[0x05] >> 5) & 3;
1394 double_scan
= (s
->cr
[0x09] >> 7);
1395 if (shift_control
!= 1) {
1396 multi_scan
= (((s
->cr
[0x09] & 0x1f) + 1) << double_scan
) - 1;
1398 /* in CGA modes, multi_scan is ignored */
1399 /* XXX: is it correct ? */
1400 multi_scan
= double_scan
;
1402 multi_run
= multi_scan
;
1403 if (shift_control
!= s
->shift_control
||
1404 double_scan
!= s
->double_scan
) {
1406 s
->shift_control
= shift_control
;
1407 s
->double_scan
= double_scan
;
1410 if (shift_control
== 0) {
1411 full_update
|= update_palette16(s
);
1412 if (s
->sr
[0x01] & 8) {
1413 v
= VGA_DRAW_LINE4D2
;
1418 } else if (shift_control
== 1) {
1419 full_update
|= update_palette16(s
);
1420 if (s
->sr
[0x01] & 8) {
1421 v
= VGA_DRAW_LINE2D2
;
1427 switch(s
->get_bpp(s
)) {
1430 full_update
|= update_palette256(s
);
1431 v
= VGA_DRAW_LINE8D2
;
1434 full_update
|= update_palette256(s
);
1438 v
= VGA_DRAW_LINE15
;
1441 v
= VGA_DRAW_LINE16
;
1444 v
= VGA_DRAW_LINE24
;
1447 v
= VGA_DRAW_LINE32
;
1451 vga_draw_line
= vga_draw_line_table
[v
* NB_DEPTHS
+ get_depth_index(s
->ds
)];
1453 if (disp_width
!= s
->last_width
||
1454 height
!= s
->last_height
) {
1455 dpy_resize(s
->ds
, disp_width
, height
);
1456 s
->last_scr_width
= disp_width
;
1457 s
->last_scr_height
= height
;
1458 s
->last_width
= disp_width
;
1459 s
->last_height
= height
;
1462 if (s
->cursor_invalidate
)
1463 s
->cursor_invalidate(s
);
1465 line_offset
= s
->line_offset
;
1467 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",
1468 width
, height
, v
, line_offset
, s
->cr
[9], s
->cr
[0x17], s
->line_compare
, s
->sr
[0x01]);
1470 addr1
= (s
->start_addr
* 4);
1473 page_min
= 0x7fffffff;
1476 linesize
= s
->ds
->linesize
;
1478 for(y
= 0; y
< height
; y
++) {
1480 if (!(s
->cr
[0x17] & 1)) {
1482 /* CGA compatibility handling */
1483 shift
= 14 + ((s
->cr
[0x17] >> 6) & 1);
1484 addr
= (addr
& ~(1 << shift
)) | ((y1
& 1) << shift
);
1486 if (!(s
->cr
[0x17] & 2)) {
1487 addr
= (addr
& ~0x8000) | ((y1
& 2) << 14);
1489 page0
= s
->vram_offset
+ (addr
& TARGET_PAGE_MASK
);
1490 page1
= s
->vram_offset
+ ((addr
+ bwidth
- 1) & TARGET_PAGE_MASK
);
1491 update
= full_update
|
1492 cpu_physical_memory_get_dirty(page0
, VGA_DIRTY_FLAG
) |
1493 cpu_physical_memory_get_dirty(page1
, VGA_DIRTY_FLAG
);
1494 if ((page1
- page0
) > TARGET_PAGE_SIZE
) {
1495 /* if wide line, can use another page */
1496 update
|= cpu_physical_memory_get_dirty(page0
+ TARGET_PAGE_SIZE
,
1499 /* explicit invalidation for the hardware cursor */
1500 update
|= (s
->invalidated_y_table
[y
>> 5] >> (y
& 0x1f)) & 1;
1504 if (page0
< page_min
)
1506 if (page1
> page_max
)
1508 vga_draw_line(s
, d
, s
->vram_ptr
+ addr
, width
);
1509 if (s
->cursor_draw_line
)
1510 s
->cursor_draw_line(s
, d
, y
);
1513 /* flush to display */
1514 dpy_update(s
->ds
, 0, y_start
,
1515 disp_width
, y
- y_start
);
1520 mask
= (s
->cr
[0x17] & 3) ^ 3;
1521 if ((y1
& mask
) == mask
)
1522 addr1
+= line_offset
;
1524 multi_run
= multi_scan
;
1528 /* line compare acts on the displayed lines */
1529 if (y
== s
->line_compare
)
1534 /* flush to display */
1535 dpy_update(s
->ds
, 0, y_start
,
1536 disp_width
, y
- y_start
);
1538 /* reset modified pages */
1539 if (page_max
!= -1) {
1540 cpu_physical_memory_reset_dirty(page_min
, page_max
+ TARGET_PAGE_SIZE
,
1543 memset(s
->invalidated_y_table
, 0, ((height
+ 31) >> 5) * 4);
1546 static void vga_draw_blank(VGAState
*s
, int full_update
)
1553 if (s
->last_scr_width
<= 0 || s
->last_scr_height
<= 0)
1555 if (s
->ds
->depth
== 8)
1556 val
= s
->rgb_to_pixel(0, 0, 0);
1559 w
= s
->last_scr_width
* ((s
->ds
->depth
+ 7) >> 3);
1561 for(i
= 0; i
< s
->last_scr_height
; i
++) {
1563 d
+= s
->ds
->linesize
;
1565 dpy_update(s
->ds
, 0, 0,
1566 s
->last_scr_width
, s
->last_scr_height
);
1569 #define GMODE_TEXT 0
1570 #define GMODE_GRAPH 1
1571 #define GMODE_BLANK 2
1573 static void vga_update_display(void *opaque
)
1575 VGAState
*s
= (VGAState
*)opaque
;
1576 int full_update
, graphic_mode
;
1578 if (s
->ds
->depth
== 0) {
1582 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1585 if (!(s
->ar_index
& 0x20)) {
1586 graphic_mode
= GMODE_BLANK
;
1588 graphic_mode
= s
->gr
[6] & 1;
1590 if (graphic_mode
!= s
->graphic_mode
) {
1591 s
->graphic_mode
= graphic_mode
;
1594 switch(graphic_mode
) {
1596 vga_draw_text(s
, full_update
);
1599 vga_draw_graphic(s
, full_update
);
1603 vga_draw_blank(s
, full_update
);
1609 /* force a full display refresh */
1610 static void vga_invalidate_display(void *opaque
)
1612 VGAState
*s
= (VGAState
*)opaque
;
1615 s
->last_height
= -1;
1618 static void vga_reset(VGAState
*s
)
1620 memset(s
, 0, sizeof(VGAState
));
1621 s
->graphic_mode
= -1; /* force full update */
1624 static CPUReadMemoryFunc
*vga_mem_read
[3] = {
1630 static CPUWriteMemoryFunc
*vga_mem_write
[3] = {
1636 static void vga_save(QEMUFile
*f
, void *opaque
)
1638 VGAState
*s
= opaque
;
1642 pci_device_save(s
->pci_dev
, f
);
1644 qemu_put_be32s(f
, &s
->latch
);
1645 qemu_put_8s(f
, &s
->sr_index
);
1646 qemu_put_buffer(f
, s
->sr
, 8);
1647 qemu_put_8s(f
, &s
->gr_index
);
1648 qemu_put_buffer(f
, s
->gr
, 16);
1649 qemu_put_8s(f
, &s
->ar_index
);
1650 qemu_put_buffer(f
, s
->ar
, 21);
1651 qemu_put_be32s(f
, &s
->ar_flip_flop
);
1652 qemu_put_8s(f
, &s
->cr_index
);
1653 qemu_put_buffer(f
, s
->cr
, 256);
1654 qemu_put_8s(f
, &s
->msr
);
1655 qemu_put_8s(f
, &s
->fcr
);
1656 qemu_put_8s(f
, &s
->st00
);
1657 qemu_put_8s(f
, &s
->st01
);
1659 qemu_put_8s(f
, &s
->dac_state
);
1660 qemu_put_8s(f
, &s
->dac_sub_index
);
1661 qemu_put_8s(f
, &s
->dac_read_index
);
1662 qemu_put_8s(f
, &s
->dac_write_index
);
1663 qemu_put_buffer(f
, s
->dac_cache
, 3);
1664 qemu_put_buffer(f
, s
->palette
, 768);
1666 qemu_put_be32s(f
, &s
->bank_offset
);
1667 #ifdef CONFIG_BOCHS_VBE
1668 qemu_put_byte(f
, 1);
1669 qemu_put_be16s(f
, &s
->vbe_index
);
1670 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
1671 qemu_put_be16s(f
, &s
->vbe_regs
[i
]);
1672 qemu_put_be32s(f
, &s
->vbe_start_addr
);
1673 qemu_put_be32s(f
, &s
->vbe_line_offset
);
1674 qemu_put_be32s(f
, &s
->vbe_bank_mask
);
1676 qemu_put_byte(f
, 0);
1680 static int vga_load(QEMUFile
*f
, void *opaque
, int version_id
)
1682 VGAState
*s
= opaque
;
1688 if (s
->pci_dev
&& version_id
>= 2) {
1689 ret
= pci_device_load(s
->pci_dev
, f
);
1694 qemu_get_be32s(f
, &s
->latch
);
1695 qemu_get_8s(f
, &s
->sr_index
);
1696 qemu_get_buffer(f
, s
->sr
, 8);
1697 qemu_get_8s(f
, &s
->gr_index
);
1698 qemu_get_buffer(f
, s
->gr
, 16);
1699 qemu_get_8s(f
, &s
->ar_index
);
1700 qemu_get_buffer(f
, s
->ar
, 21);
1701 qemu_get_be32s(f
, &s
->ar_flip_flop
);
1702 qemu_get_8s(f
, &s
->cr_index
);
1703 qemu_get_buffer(f
, s
->cr
, 256);
1704 qemu_get_8s(f
, &s
->msr
);
1705 qemu_get_8s(f
, &s
->fcr
);
1706 qemu_get_8s(f
, &s
->st00
);
1707 qemu_get_8s(f
, &s
->st01
);
1709 qemu_get_8s(f
, &s
->dac_state
);
1710 qemu_get_8s(f
, &s
->dac_sub_index
);
1711 qemu_get_8s(f
, &s
->dac_read_index
);
1712 qemu_get_8s(f
, &s
->dac_write_index
);
1713 qemu_get_buffer(f
, s
->dac_cache
, 3);
1714 qemu_get_buffer(f
, s
->palette
, 768);
1716 qemu_get_be32s(f
, &s
->bank_offset
);
1717 is_vbe
= qemu_get_byte(f
);
1718 #ifdef CONFIG_BOCHS_VBE
1721 qemu_get_be16s(f
, &s
->vbe_index
);
1722 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
1723 qemu_get_be16s(f
, &s
->vbe_regs
[i
]);
1724 qemu_get_be32s(f
, &s
->vbe_start_addr
);
1725 qemu_get_be32s(f
, &s
->vbe_line_offset
);
1726 qemu_get_be32s(f
, &s
->vbe_bank_mask
);
1733 s
->graphic_mode
= -1;
1737 typedef struct PCIVGAState
{
1742 static void vga_map(PCIDevice
*pci_dev
, int region_num
,
1743 uint32_t addr
, uint32_t size
, int type
)
1745 PCIVGAState
*d
= (PCIVGAState
*)pci_dev
;
1746 VGAState
*s
= &d
->vga_state
;
1747 if (region_num
== PCI_ROM_SLOT
) {
1748 cpu_register_physical_memory(addr
, s
->bios_size
, s
->bios_offset
);
1750 cpu_register_physical_memory(addr
, s
->vram_size
, s
->vram_offset
);
1754 void vga_common_init(VGAState
*s
, DisplayState
*ds
, uint8_t *vga_ram_base
,
1755 unsigned long vga_ram_offset
, int vga_ram_size
)
1759 for(i
= 0;i
< 256; i
++) {
1761 for(j
= 0; j
< 8; j
++) {
1762 v
|= ((i
>> j
) & 1) << (j
* 4);
1767 for(j
= 0; j
< 4; j
++) {
1768 v
|= ((i
>> (2 * j
)) & 3) << (j
* 4);
1772 for(i
= 0; i
< 16; i
++) {
1774 for(j
= 0; j
< 4; j
++) {
1777 v
|= b
<< (2 * j
+ 1);
1784 s
->vram_ptr
= vga_ram_base
;
1785 s
->vram_offset
= vga_ram_offset
;
1786 s
->vram_size
= vga_ram_size
;
1788 s
->get_bpp
= vga_get_bpp
;
1789 s
->get_offsets
= vga_get_offsets
;
1790 s
->get_resolution
= vga_get_resolution
;
1791 s
->update
= vga_update_display
;
1792 s
->invalidate
= vga_invalidate_display
;
1793 s
->screen_dump
= vga_screen_dump
;
1796 /* used by both ISA and PCI */
1797 void vga_init(VGAState
*s
)
1801 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
1803 register_ioport_write(0x3c0, 16, 1, vga_ioport_write
, s
);
1805 register_ioport_write(0x3b4, 2, 1, vga_ioport_write
, s
);
1806 register_ioport_write(0x3d4, 2, 1, vga_ioport_write
, s
);
1807 register_ioport_write(0x3ba, 1, 1, vga_ioport_write
, s
);
1808 register_ioport_write(0x3da, 1, 1, vga_ioport_write
, s
);
1810 register_ioport_read(0x3c0, 16, 1, vga_ioport_read
, s
);
1812 register_ioport_read(0x3b4, 2, 1, vga_ioport_read
, s
);
1813 register_ioport_read(0x3d4, 2, 1, vga_ioport_read
, s
);
1814 register_ioport_read(0x3ba, 1, 1, vga_ioport_read
, s
);
1815 register_ioport_read(0x3da, 1, 1, vga_ioport_read
, s
);
1818 #ifdef CONFIG_BOCHS_VBE
1819 s
->vbe_regs
[VBE_DISPI_INDEX_ID
] = VBE_DISPI_ID0
;
1820 s
->vbe_bank_mask
= ((s
->vram_size
>> 16) - 1);
1821 #if defined (TARGET_I386)
1822 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
1823 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data
, s
);
1825 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
1826 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data
, s
);
1828 /* old Bochs IO ports */
1829 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index
, s
);
1830 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data
, s
);
1832 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index
, s
);
1833 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data
, s
);
1835 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
1836 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data
, s
);
1838 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
1839 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data
, s
);
1841 #endif /* CONFIG_BOCHS_VBE */
1843 vga_io_memory
= cpu_register_io_memory(0, vga_mem_read
, vga_mem_write
, s
);
1844 cpu_register_physical_memory(isa_mem_base
+ 0x000a0000, 0x20000,
1848 /* Memory mapped interface */
1849 static uint32_t vga_mm_readb (void *opaque
, target_phys_addr_t addr
)
1851 VGAState
*s
= opaque
;
1853 return vga_ioport_read(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
) & 0xff;
1856 static void vga_mm_writeb (void *opaque
,
1857 target_phys_addr_t addr
, uint32_t value
)
1859 VGAState
*s
= opaque
;
1861 vga_ioport_write(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
, value
& 0xff);
1864 static uint32_t vga_mm_readw (void *opaque
, target_phys_addr_t addr
)
1866 VGAState
*s
= opaque
;
1868 return vga_ioport_read(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
) & 0xffff;
1871 static void vga_mm_writew (void *opaque
,
1872 target_phys_addr_t addr
, uint32_t value
)
1874 VGAState
*s
= opaque
;
1876 vga_ioport_write(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
, value
& 0xffff);
1879 static uint32_t vga_mm_readl (void *opaque
, target_phys_addr_t addr
)
1881 VGAState
*s
= opaque
;
1883 return vga_ioport_read(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
);
1886 static void vga_mm_writel (void *opaque
,
1887 target_phys_addr_t addr
, uint32_t value
)
1889 VGAState
*s
= opaque
;
1891 vga_ioport_write(s
, (addr
- s
->base_ctrl
) >> s
->it_shift
, value
);
1894 static CPUReadMemoryFunc
*vga_mm_read_ctrl
[] = {
1900 static CPUWriteMemoryFunc
*vga_mm_write_ctrl
[] = {
1906 static void vga_mm_init(VGAState
*s
, target_phys_addr_t vram_base
,
1907 target_phys_addr_t ctrl_base
, int it_shift
)
1909 int s_ioport_ctrl
, vga_io_memory
;
1911 s
->base_ctrl
= ctrl_base
;
1912 s
->it_shift
= it_shift
;
1913 s_ioport_ctrl
= cpu_register_io_memory(0, vga_mm_read_ctrl
, vga_mm_write_ctrl
, s
);
1914 vga_io_memory
= cpu_register_io_memory(0, vga_mem_read
, vga_mem_write
, s
);
1916 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
1918 cpu_register_physical_memory(ctrl_base
, 0x100000, s_ioport_ctrl
);
1920 cpu_register_physical_memory(vram_base
+ 0x000a0000, 0x20000, vga_io_memory
);
1923 int isa_vga_init(DisplayState
*ds
, uint8_t *vga_ram_base
,
1924 unsigned long vga_ram_offset
, int vga_ram_size
)
1928 s
= qemu_mallocz(sizeof(VGAState
));
1932 vga_common_init(s
, ds
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
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 isa_vga_mm_init(DisplayState
*ds
, uint8_t *vga_ram_base
,
1946 unsigned long vga_ram_offset
, int vga_ram_size
,
1947 target_phys_addr_t vram_base
, target_phys_addr_t ctrl_base
,
1952 s
= qemu_mallocz(sizeof(VGAState
));
1956 vga_common_init(s
, ds
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
1957 vga_mm_init(s
, vram_base
, ctrl_base
, it_shift
);
1959 graphic_console_init(s
->ds
, s
->update
, s
->invalidate
, s
->screen_dump
, s
);
1961 #ifdef CONFIG_BOCHS_VBE
1962 /* XXX: use optimized standard vga accesses */
1963 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
1964 vga_ram_size
, vga_ram_offset
);
1969 int pci_vga_init(PCIBus
*bus
, DisplayState
*ds
, uint8_t *vga_ram_base
,
1970 unsigned long vga_ram_offset
, int vga_ram_size
,
1971 unsigned long vga_bios_offset
, int vga_bios_size
)
1977 d
= (PCIVGAState
*)pci_register_device(bus
, "VGA",
1978 sizeof(PCIVGAState
),
1984 vga_common_init(s
, ds
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
1987 graphic_console_init(s
->ds
, s
->update
, s
->invalidate
, s
->screen_dump
, s
);
1989 s
->pci_dev
= &d
->dev
;
1991 pci_conf
= d
->dev
.config
;
1992 pci_conf
[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1993 pci_conf
[0x01] = 0x12;
1994 pci_conf
[0x02] = 0x11;
1995 pci_conf
[0x03] = 0x11;
1996 pci_conf
[0x0a] = 0x00; // VGA controller
1997 pci_conf
[0x0b] = 0x03;
1998 pci_conf
[0x0e] = 0x00; // header_type
2000 /* XXX: vga_ram_size must be a power of two */
2001 pci_register_io_region(&d
->dev
, 0, vga_ram_size
,
2002 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2003 if (vga_bios_size
!= 0) {
2004 unsigned int bios_total_size
;
2005 s
->bios_offset
= vga_bios_offset
;
2006 s
->bios_size
= vga_bios_size
;
2007 /* must be a power of two */
2008 bios_total_size
= 1;
2009 while (bios_total_size
< vga_bios_size
)
2010 bios_total_size
<<= 1;
2011 pci_register_io_region(&d
->dev
, PCI_ROM_SLOT
, bios_total_size
,
2012 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2017 /********************************************************/
2018 /* vga screen dump */
2020 static int vga_save_w
, vga_save_h
;
2022 static void vga_save_dpy_update(DisplayState
*s
,
2023 int x
, int y
, int w
, int h
)
2027 static void vga_save_dpy_resize(DisplayState
*s
, int w
, int h
)
2029 s
->linesize
= w
* 4;
2030 s
->data
= qemu_malloc(h
* s
->linesize
);
2035 static void vga_save_dpy_refresh(DisplayState
*s
)
2039 int ppm_save(const char *filename
, uint8_t *data
,
2040 int w
, int h
, int linesize
)
2047 f
= fopen(filename
, "wb");
2050 fprintf(f
, "P6\n%d %d\n%d\n",
2053 for(y
= 0; y
< h
; y
++) {
2055 for(x
= 0; x
< w
; x
++) {
2057 fputc((v
>> 16) & 0xff, f
);
2058 fputc((v
>> 8) & 0xff, f
);
2059 fputc((v
) & 0xff, f
);
2068 /* save the vga display in a PPM image even if no display is
2070 static void vga_screen_dump(void *opaque
, const char *filename
)
2072 VGAState
*s
= (VGAState
*)opaque
;
2073 DisplayState
*saved_ds
, ds1
, *ds
= &ds1
;
2075 /* XXX: this is a little hackish */
2076 vga_invalidate_display(s
);
2079 memset(ds
, 0, sizeof(DisplayState
));
2080 ds
->dpy_update
= vga_save_dpy_update
;
2081 ds
->dpy_resize
= vga_save_dpy_resize
;
2082 ds
->dpy_refresh
= vga_save_dpy_refresh
;
2086 s
->graphic_mode
= -1;
2087 vga_update_display(s
);
2090 ppm_save(filename
, ds
->data
, vga_save_w
, vga_save_h
,
2092 qemu_free(ds
->data
);