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
29 #include "pixel_ops.h"
30 #include "qemu-timer.h"
35 //#define DEBUG_VGA_MEM
36 //#define DEBUG_VGA_REG
38 //#define DEBUG_BOCHS_VBE
44 /* force some bits to zero */
45 const uint8_t sr_mask
[8] = {
56 const uint8_t gr_mask
[16] = {
75 #define cbswap_32(__x) \
77 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
78 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
79 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
80 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
82 #ifdef WORDS_BIGENDIAN
83 #define PAT(x) cbswap_32(x)
88 #ifdef WORDS_BIGENDIAN
94 #ifdef WORDS_BIGENDIAN
95 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
97 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
100 static const uint32_t mask16
[16] = {
121 #ifdef WORDS_BIGENDIAN
124 #define PAT(x) cbswap_32(x)
127 static const uint32_t dmask16
[16] = {
146 static const uint32_t dmask4
[4] = {
153 static uint32_t expand4
[256];
154 static uint16_t expand2
[256];
155 static uint8_t expand4to8
[16];
157 static void vga_screen_dump(void *opaque
, const char *filename
);
159 static void vga_dumb_update_retrace_info(VGAState
*s
)
164 static void vga_precise_update_retrace_info(VGAState
*s
)
167 int hretr_start_char
;
168 int hretr_skew_chars
;
172 int vretr_start_line
;
175 int div2
, sldiv2
, dots
;
178 const int clk_hz
[] = {25175000, 28322000, 25175000, 25175000};
179 int64_t chars_per_sec
;
180 struct vga_precise_retrace
*r
= &s
->retrace_info
.precise
;
182 htotal_chars
= s
->cr
[0x00] + 5;
183 hretr_start_char
= s
->cr
[0x04];
184 hretr_skew_chars
= (s
->cr
[0x05] >> 5) & 3;
185 hretr_end_char
= s
->cr
[0x05] & 0x1f;
187 vtotal_lines
= (s
->cr
[0x06]
188 | (((s
->cr
[0x07] & 1) | ((s
->cr
[0x07] >> 4) & 2)) << 8)) + 2
190 vretr_start_line
= s
->cr
[0x10]
191 | ((((s
->cr
[0x07] >> 2) & 1) | ((s
->cr
[0x07] >> 6) & 2)) << 8)
193 vretr_end_line
= s
->cr
[0x11] & 0xf;
196 div2
= (s
->cr
[0x17] >> 2) & 1;
197 sldiv2
= (s
->cr
[0x17] >> 3) & 1;
199 clocking_mode
= (s
->sr
[0x01] >> 3) & 1;
200 clock_sel
= (s
->msr
>> 2) & 3;
201 dots
= (s
->msr
& 1) ? 8 : 9;
203 chars_per_sec
= clk_hz
[clock_sel
] / dots
;
205 htotal_chars
<<= clocking_mode
;
207 r
->total_chars
= vtotal_lines
* htotal_chars
;
209 r
->ticks_per_char
= ticks_per_sec
/ (r
->total_chars
* r
->freq
);
211 r
->ticks_per_char
= ticks_per_sec
/ chars_per_sec
;
214 r
->vstart
= vretr_start_line
;
215 r
->vend
= r
->vstart
+ vretr_end_line
+ 1;
217 r
->hstart
= hretr_start_char
+ hretr_skew_chars
;
218 r
->hend
= r
->hstart
+ hretr_end_char
+ 1;
219 r
->htotal
= htotal_chars
;
231 "div2 = %d sldiv2 = %d\n"
232 "clocking_mode = %d\n"
233 "clock_sel = %d %d\n"
235 "ticks/char = %lld\n"
237 (double) ticks_per_sec
/ (r
->ticks_per_char
* r
->total_chars
),
255 static uint8_t vga_precise_retrace(VGAState
*s
)
257 struct vga_precise_retrace
*r
= &s
->retrace_info
.precise
;
258 uint8_t val
= s
->st01
& ~(ST01_V_RETRACE
| ST01_DISP_ENABLE
);
260 if (r
->total_chars
) {
261 int cur_line
, cur_line_char
, cur_char
;
264 cur_tick
= qemu_get_clock(vm_clock
);
266 cur_char
= (cur_tick
/ r
->ticks_per_char
) % r
->total_chars
;
267 cur_line
= cur_char
/ r
->htotal
;
269 if (cur_line
>= r
->vstart
&& cur_line
<= r
->vend
) {
270 val
|= ST01_V_RETRACE
| ST01_DISP_ENABLE
;
272 cur_line_char
= cur_char
% r
->htotal
;
273 if (cur_line_char
>= r
->hstart
&& cur_line_char
<= r
->hend
) {
274 val
|= ST01_DISP_ENABLE
;
280 return s
->st01
^ (ST01_V_RETRACE
| ST01_DISP_ENABLE
);
284 static uint8_t vga_dumb_retrace(VGAState
*s
)
286 return s
->st01
^ (ST01_V_RETRACE
| ST01_DISP_ENABLE
);
289 static uint32_t vga_ioport_read(void *opaque
, uint32_t addr
)
291 VGAState
*s
= opaque
;
294 /* check port range access depending on color/monochrome mode */
295 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
296 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
))) {
301 if (s
->ar_flip_flop
== 0) {
308 index
= s
->ar_index
& 0x1f;
321 val
= s
->sr
[s
->sr_index
];
323 printf("vga: read SR%x = 0x%02x\n", s
->sr_index
, val
);
330 val
= s
->dac_write_index
;
333 val
= s
->palette
[s
->dac_read_index
* 3 + s
->dac_sub_index
];
334 if (++s
->dac_sub_index
== 3) {
335 s
->dac_sub_index
= 0;
349 val
= s
->gr
[s
->gr_index
];
351 printf("vga: read GR%x = 0x%02x\n", s
->gr_index
, val
);
360 val
= s
->cr
[s
->cr_index
];
362 printf("vga: read CR%x = 0x%02x\n", s
->cr_index
, val
);
367 /* just toggle to fool polling */
368 val
= s
->st01
= s
->retrace(s
);
376 #if defined(DEBUG_VGA)
377 printf("VGA: read addr=0x%04x data=0x%02x\n", addr
, val
);
382 static void vga_ioport_write(void *opaque
, uint32_t addr
, uint32_t val
)
384 VGAState
*s
= opaque
;
387 /* check port range access depending on color/monochrome mode */
388 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
389 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
)))
393 printf("VGA: write addr=0x%04x data=0x%02x\n", addr
, val
);
398 if (s
->ar_flip_flop
== 0) {
401 vga_update_resolution(s
);
403 index
= s
->ar_index
& 0x1f;
406 s
->ar
[index
] = val
& 0x3f;
409 s
->ar
[index
] = val
& ~0x10;
415 s
->ar
[index
] = val
& ~0xc0;
418 s
->ar
[index
] = val
& ~0xf0;
421 s
->ar
[index
] = val
& ~0xf0;
427 s
->ar_flip_flop
^= 1;
430 s
->msr
= val
& ~0x10;
431 s
->update_retrace_info(s
);
434 s
->sr_index
= val
& 7;
438 printf("vga: write SR%x = 0x%02x\n", s
->sr_index
, val
);
440 s
->sr
[s
->sr_index
] = val
& sr_mask
[s
->sr_index
];
441 if (s
->sr_index
== 1) s
->update_retrace_info(s
);
442 vga_update_resolution(s
);
445 s
->dac_read_index
= val
;
446 s
->dac_sub_index
= 0;
450 s
->dac_write_index
= val
;
451 s
->dac_sub_index
= 0;
455 s
->dac_cache
[s
->dac_sub_index
] = val
;
456 if (++s
->dac_sub_index
== 3) {
457 memcpy(&s
->palette
[s
->dac_write_index
* 3], s
->dac_cache
, 3);
458 s
->dac_sub_index
= 0;
459 s
->dac_write_index
++;
463 s
->gr_index
= val
& 0x0f;
467 printf("vga: write GR%x = 0x%02x\n", s
->gr_index
, val
);
469 s
->gr
[s
->gr_index
] = val
& gr_mask
[s
->gr_index
];
470 vga_update_resolution(s
);
479 printf("vga: write CR%x = 0x%02x\n", s
->cr_index
, val
);
481 /* handle CR0-7 protection */
482 if ((s
->cr
[0x11] & 0x80) && s
->cr_index
<= 7) {
483 /* can always write bit 4 of CR7 */
484 if (s
->cr_index
== 7)
485 s
->cr
[7] = (s
->cr
[7] & ~0x10) | (val
& 0x10);
486 vga_update_resolution(s
);
489 switch(s
->cr_index
) {
490 case 0x01: /* horizontal display end */
495 case 0x12: /* vertical display end */
496 s
->cr
[s
->cr_index
] = val
;
499 s
->cr
[s
->cr_index
] = val
;
503 switch(s
->cr_index
) {
511 s
->update_retrace_info(s
);
514 vga_update_resolution(s
);
523 #ifdef CONFIG_BOCHS_VBE
524 static uint32_t vbe_ioport_read_index(void *opaque
, uint32_t addr
)
526 VGAState
*s
= opaque
;
532 static uint32_t vbe_ioport_read_data(void *opaque
, uint32_t addr
)
534 VGAState
*s
= opaque
;
537 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
538 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_GETCAPS
) {
539 switch(s
->vbe_index
) {
540 /* XXX: do not hardcode ? */
541 case VBE_DISPI_INDEX_XRES
:
542 val
= VBE_DISPI_MAX_XRES
;
544 case VBE_DISPI_INDEX_YRES
:
545 val
= VBE_DISPI_MAX_YRES
;
547 case VBE_DISPI_INDEX_BPP
:
548 val
= VBE_DISPI_MAX_BPP
;
551 val
= s
->vbe_regs
[s
->vbe_index
];
555 val
= s
->vbe_regs
[s
->vbe_index
];
560 #ifdef DEBUG_BOCHS_VBE
561 printf("VBE: read index=0x%x val=0x%x\n", s
->vbe_index
, val
);
566 static void vbe_ioport_write_index(void *opaque
, uint32_t addr
, uint32_t val
)
568 VGAState
*s
= opaque
;
572 static void vbe_ioport_write_data(void *opaque
, uint32_t addr
, uint32_t val
)
574 VGAState
*s
= opaque
;
576 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
577 #ifdef DEBUG_BOCHS_VBE
578 printf("VBE: write index=0x%x val=0x%x\n", s
->vbe_index
, val
);
580 switch(s
->vbe_index
) {
581 case VBE_DISPI_INDEX_ID
:
582 if (val
== VBE_DISPI_ID0
||
583 val
== VBE_DISPI_ID1
||
584 val
== VBE_DISPI_ID2
||
585 val
== VBE_DISPI_ID3
||
586 val
== VBE_DISPI_ID4
) {
587 s
->vbe_regs
[s
->vbe_index
] = val
;
590 case VBE_DISPI_INDEX_XRES
:
591 if ((val
<= VBE_DISPI_MAX_XRES
) && ((val
& 7) == 0)) {
592 s
->vbe_regs
[s
->vbe_index
] = val
;
594 vga_update_resolution(s
);
596 case VBE_DISPI_INDEX_YRES
:
597 if (val
<= VBE_DISPI_MAX_YRES
) {
598 s
->vbe_regs
[s
->vbe_index
] = val
;
600 vga_update_resolution(s
);
602 case VBE_DISPI_INDEX_BPP
:
605 if (val
== 4 || val
== 8 || val
== 15 ||
606 val
== 16 || val
== 24 || val
== 32) {
607 s
->vbe_regs
[s
->vbe_index
] = val
;
609 vga_update_resolution(s
);
611 case VBE_DISPI_INDEX_BANK
:
612 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
613 val
&= (s
->vbe_bank_mask
>> 2);
615 val
&= s
->vbe_bank_mask
;
617 s
->vbe_regs
[s
->vbe_index
] = val
;
618 s
->bank_offset
= (val
<< 16);
620 case VBE_DISPI_INDEX_ENABLE
:
621 if ((val
& VBE_DISPI_ENABLED
) &&
622 !(s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
)) {
623 int h
, shift_control
;
625 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] =
626 s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
627 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] =
628 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
629 s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
] = 0;
630 s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
] = 0;
632 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
633 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 1;
635 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] *
636 ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
637 s
->vbe_start_addr
= 0;
639 /* clear the screen (should be done in BIOS) */
640 if (!(val
& VBE_DISPI_NOCLEARMEM
)) {
641 memset(s
->vram_ptr
, 0,
642 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] * s
->vbe_line_offset
);
645 /* we initialize the VGA graphic mode (should be done
647 s
->gr
[0x06] = (s
->gr
[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
648 s
->cr
[0x17] |= 3; /* no CGA modes */
649 s
->cr
[0x13] = s
->vbe_line_offset
>> 3;
651 s
->cr
[0x01] = (s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 3) - 1;
652 /* height (only meaningful if < 1024) */
653 h
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] - 1;
655 s
->cr
[0x07] = (s
->cr
[0x07] & ~0x42) |
656 ((h
>> 7) & 0x02) | ((h
>> 3) & 0x40);
657 /* line compare to 1023 */
662 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
664 s
->sr
[0x01] &= ~8; /* no double line */
667 s
->sr
[4] |= 0x08; /* set chain 4 mode */
668 s
->sr
[2] |= 0x0f; /* activate all planes */
670 s
->gr
[0x05] = (s
->gr
[0x05] & ~0x60) | (shift_control
<< 5);
671 s
->cr
[0x09] &= ~0x9f; /* no double scan */
673 /* XXX: the bios should do that */
676 s
->dac_8bit
= (val
& VBE_DISPI_8BIT_DAC
) > 0;
677 s
->vbe_regs
[s
->vbe_index
] = val
;
678 vga_update_resolution(s
);
680 case VBE_DISPI_INDEX_VIRT_WIDTH
:
682 int w
, h
, line_offset
;
684 if (val
< s
->vbe_regs
[VBE_DISPI_INDEX_XRES
])
687 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
688 line_offset
= w
>> 1;
690 line_offset
= w
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
691 h
= s
->vram_size
/ line_offset
;
692 /* XXX: support weird bochs semantics ? */
693 if (h
< s
->vbe_regs
[VBE_DISPI_INDEX_YRES
])
695 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] = w
;
696 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] = h
;
697 s
->vbe_line_offset
= line_offset
;
699 vga_update_resolution(s
);
701 case VBE_DISPI_INDEX_X_OFFSET
:
702 case VBE_DISPI_INDEX_Y_OFFSET
:
705 s
->vbe_regs
[s
->vbe_index
] = val
;
706 s
->vbe_start_addr
= s
->vbe_line_offset
* s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
];
707 x
= s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
];
708 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
709 s
->vbe_start_addr
+= x
>> 1;
711 s
->vbe_start_addr
+= x
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
712 s
->vbe_start_addr
>>= 2;
714 vga_update_resolution(s
);
723 /* called for accesses between 0xa0000 and 0xc0000 */
724 uint32_t vga_mem_readb(void *opaque
, target_phys_addr_t addr
)
726 VGAState
*s
= opaque
;
727 int memory_map_mode
, plane
;
730 /* convert to VGA memory offset */
731 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
733 switch(memory_map_mode
) {
739 addr
+= s
->bank_offset
;
754 if (s
->sr
[4] & 0x08) {
755 /* chain 4 mode : simplest access */
756 ret
= s
->vram_ptr
[addr
];
757 } else if (s
->gr
[5] & 0x10) {
758 /* odd/even mode (aka text mode mapping) */
759 plane
= (s
->gr
[4] & 2) | (addr
& 1);
760 ret
= s
->vram_ptr
[((addr
& ~1) << 1) | plane
];
762 /* standard VGA latched access */
763 s
->latch
= ((uint32_t *)s
->vram_ptr
)[addr
];
765 if (!(s
->gr
[5] & 0x08)) {
768 ret
= GET_PLANE(s
->latch
, plane
);
771 ret
= (s
->latch
^ mask16
[s
->gr
[2]]) & mask16
[s
->gr
[7]];
780 static uint32_t vga_mem_readw(void *opaque
, target_phys_addr_t addr
)
783 #ifdef TARGET_WORDS_BIGENDIAN
784 v
= vga_mem_readb(opaque
, addr
) << 8;
785 v
|= vga_mem_readb(opaque
, addr
+ 1);
787 v
= vga_mem_readb(opaque
, addr
);
788 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
793 static uint32_t vga_mem_readl(void *opaque
, target_phys_addr_t addr
)
796 #ifdef TARGET_WORDS_BIGENDIAN
797 v
= vga_mem_readb(opaque
, addr
) << 24;
798 v
|= vga_mem_readb(opaque
, addr
+ 1) << 16;
799 v
|= vga_mem_readb(opaque
, addr
+ 2) << 8;
800 v
|= vga_mem_readb(opaque
, addr
+ 3);
802 v
= vga_mem_readb(opaque
, addr
);
803 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
804 v
|= vga_mem_readb(opaque
, addr
+ 2) << 16;
805 v
|= vga_mem_readb(opaque
, addr
+ 3) << 24;
810 /* called for accesses between 0xa0000 and 0xc0000 */
811 void vga_mem_writeb(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
813 VGAState
*s
= opaque
;
814 int memory_map_mode
, plane
, write_mode
, b
, func_select
, mask
;
815 uint32_t write_mask
, bit_mask
, set_mask
;
818 printf("vga: [0x%x] = 0x%02x\n", addr
, val
);
820 /* convert to VGA memory offset */
821 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
823 switch(memory_map_mode
) {
829 addr
+= s
->bank_offset
;
844 if (s
->sr
[4] & 0x08) {
845 /* chain 4 mode : simplest access */
848 if (s
->sr
[2] & mask
) {
849 s
->vram_ptr
[addr
] = val
;
851 printf("vga: chain4: [0x%x]\n", addr
);
853 s
->plane_updated
|= mask
; /* only used to detect font change */
854 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
856 } else if (s
->gr
[5] & 0x10) {
857 /* odd/even mode (aka text mode mapping) */
858 plane
= (s
->gr
[4] & 2) | (addr
& 1);
860 if (s
->sr
[2] & mask
) {
861 addr
= ((addr
& ~1) << 1) | plane
;
862 s
->vram_ptr
[addr
] = val
;
864 printf("vga: odd/even: [0x%x]\n", addr
);
866 s
->plane_updated
|= mask
; /* only used to detect font change */
867 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
870 /* standard VGA latched access */
871 write_mode
= s
->gr
[5] & 3;
877 val
= ((val
>> b
) | (val
<< (8 - b
))) & 0xff;
881 /* apply set/reset mask */
882 set_mask
= mask16
[s
->gr
[1]];
883 val
= (val
& ~set_mask
) | (mask16
[s
->gr
[0]] & set_mask
);
890 val
= mask16
[val
& 0x0f];
896 val
= (val
>> b
) | (val
<< (8 - b
));
898 bit_mask
= s
->gr
[8] & val
;
899 val
= mask16
[s
->gr
[0]];
903 /* apply logical operation */
904 func_select
= s
->gr
[3] >> 3;
905 switch(func_select
) {
925 bit_mask
|= bit_mask
<< 8;
926 bit_mask
|= bit_mask
<< 16;
927 val
= (val
& bit_mask
) | (s
->latch
& ~bit_mask
);
930 /* mask data according to sr[2] */
932 s
->plane_updated
|= mask
; /* only used to detect font change */
933 write_mask
= mask16
[mask
];
934 ((uint32_t *)s
->vram_ptr
)[addr
] =
935 (((uint32_t *)s
->vram_ptr
)[addr
] & ~write_mask
) |
938 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
939 addr
* 4, write_mask
, val
);
941 cpu_physical_memory_set_dirty(s
->vram_offset
+ (addr
<< 2));
945 static void vga_mem_writew(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
947 #ifdef TARGET_WORDS_BIGENDIAN
948 vga_mem_writeb(opaque
, addr
, (val
>> 8) & 0xff);
949 vga_mem_writeb(opaque
, addr
+ 1, val
& 0xff);
951 vga_mem_writeb(opaque
, addr
, val
& 0xff);
952 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
956 static void vga_mem_writel(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
958 #ifdef TARGET_WORDS_BIGENDIAN
959 vga_mem_writeb(opaque
, addr
, (val
>> 24) & 0xff);
960 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 16) & 0xff);
961 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 8) & 0xff);
962 vga_mem_writeb(opaque
, addr
+ 3, val
& 0xff);
964 vga_mem_writeb(opaque
, addr
, val
& 0xff);
965 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
966 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 16) & 0xff);
967 vga_mem_writeb(opaque
, addr
+ 3, (val
>> 24) & 0xff);
971 typedef void vga_draw_glyph8_func(uint8_t *d
, int linesize
,
972 const uint8_t *font_ptr
, int h
,
973 uint32_t fgcol
, uint32_t bgcol
);
974 typedef void vga_draw_glyph9_func(uint8_t *d
, int linesize
,
975 const uint8_t *font_ptr
, int h
,
976 uint32_t fgcol
, uint32_t bgcol
, int dup9
);
977 typedef void vga_draw_line_func(VGAState
*s1
, uint8_t *d
,
978 const uint8_t *s
, int width
);
981 #include "vga_template.h"
984 #include "vga_template.h"
988 #include "vga_template.h"
991 #include "vga_template.h"
995 #include "vga_template.h"
998 #include "vga_template.h"
1002 #include "vga_template.h"
1004 static unsigned int rgb_to_pixel8_dup(unsigned int r
, unsigned int g
, unsigned b
)
1007 col
= rgb_to_pixel8(r
, g
, b
);
1013 static unsigned int rgb_to_pixel15_dup(unsigned int r
, unsigned int g
, unsigned b
)
1016 col
= rgb_to_pixel15(r
, g
, b
);
1021 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r
, unsigned int g
,
1025 col
= rgb_to_pixel15bgr(r
, g
, b
);
1030 static unsigned int rgb_to_pixel16_dup(unsigned int r
, unsigned int g
, unsigned b
)
1033 col
= rgb_to_pixel16(r
, g
, b
);
1038 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r
, unsigned int g
,
1042 col
= rgb_to_pixel16bgr(r
, g
, b
);
1047 static unsigned int rgb_to_pixel32_dup(unsigned int r
, unsigned int g
, unsigned b
)
1050 col
= rgb_to_pixel32(r
, g
, b
);
1054 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r
, unsigned int g
, unsigned b
)
1057 col
= rgb_to_pixel32bgr(r
, g
, b
);
1061 /* return true if the palette was modified */
1062 static int update_palette16(VGAState
*s
)
1065 uint32_t v
, col
, *palette
;
1068 palette
= s
->last_palette
;
1069 for(i
= 0; i
< 16; i
++) {
1071 if (s
->ar
[0x10] & 0x80)
1072 v
= ((s
->ar
[0x14] & 0xf) << 4) | (v
& 0xf);
1074 v
= ((s
->ar
[0x14] & 0xc) << 4) | (v
& 0x3f);
1076 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
1077 c6_to_8(s
->palette
[v
+ 1]),
1078 c6_to_8(s
->palette
[v
+ 2]));
1079 if (col
!= palette
[i
]) {
1087 /* return true if the palette was modified */
1088 static int update_palette256(VGAState
*s
)
1091 uint32_t v
, col
, *palette
;
1094 palette
= s
->last_palette
;
1096 for(i
= 0; i
< 256; i
++) {
1098 col
= s
->rgb_to_pixel(s
->palette
[v
],
1102 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
1103 c6_to_8(s
->palette
[v
+ 1]),
1104 c6_to_8(s
->palette
[v
+ 2]));
1106 if (col
!= palette
[i
]) {
1115 static void vga_get_offsets(VGAState
*s
,
1116 uint32_t *pline_offset
,
1117 uint32_t *pstart_addr
,
1118 uint32_t *pline_compare
)
1120 uint32_t start_addr
, line_offset
, line_compare
;
1121 #ifdef CONFIG_BOCHS_VBE
1122 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1123 line_offset
= s
->vbe_line_offset
;
1124 start_addr
= s
->vbe_start_addr
;
1125 line_compare
= 65535;
1129 /* compute line_offset in bytes */
1130 line_offset
= s
->cr
[0x13];
1133 /* starting address */
1134 start_addr
= s
->cr
[0x0d] | (s
->cr
[0x0c] << 8);
1137 line_compare
= s
->cr
[0x18] |
1138 ((s
->cr
[0x07] & 0x10) << 4) |
1139 ((s
->cr
[0x09] & 0x40) << 3);
1141 *pline_offset
= line_offset
;
1142 *pstart_addr
= start_addr
;
1143 *pline_compare
= line_compare
;
1146 /* update start_addr and line_offset. Return TRUE if modified */
1147 static int update_basic_params(VGAState
*s
)
1150 uint32_t start_addr
, line_offset
, line_compare
;
1154 s
->get_offsets(s
, &line_offset
, &start_addr
, &line_compare
);
1156 if (line_offset
!= s
->line_offset
||
1157 start_addr
!= s
->start_addr
||
1158 line_compare
!= s
->line_compare
) {
1159 s
->line_offset
= line_offset
;
1160 s
->start_addr
= start_addr
;
1161 s
->line_compare
= line_compare
;
1169 static inline int get_depth_index(DisplayState
*s
)
1171 switch(ds_get_bits_per_pixel(s
)) {
1180 if (is_surface_bgr(s
->surface
))
1187 static vga_draw_glyph8_func
*vga_draw_glyph8_table
[NB_DEPTHS
] = {
1197 static vga_draw_glyph8_func
*vga_draw_glyph16_table
[NB_DEPTHS
] = {
1199 vga_draw_glyph16_16
,
1200 vga_draw_glyph16_16
,
1201 vga_draw_glyph16_32
,
1202 vga_draw_glyph16_32
,
1203 vga_draw_glyph16_16
,
1204 vga_draw_glyph16_16
,
1207 static vga_draw_glyph9_func
*vga_draw_glyph9_table
[NB_DEPTHS
] = {
1217 static const uint8_t cursor_glyph
[32 * 4] = {
1218 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1225 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1227 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1228 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1229 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1230 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1231 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1232 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1233 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1236 static void vga_get_text_resolution(VGAState
*s
, int *pwidth
, int *pheight
,
1237 int *pcwidth
, int *pcheight
)
1239 int width
, cwidth
, height
, cheight
;
1241 /* total width & height */
1242 cheight
= (s
->cr
[9] & 0x1f) + 1;
1244 if (!(s
->sr
[1] & 0x01))
1246 if (s
->sr
[1] & 0x08)
1247 cwidth
= 16; /* NOTE: no 18 pixel wide */
1248 width
= (s
->cr
[0x01] + 1);
1249 if (s
->cr
[0x06] == 100) {
1250 /* ugly hack for CGA 160x100x16 - explain me the logic */
1253 height
= s
->cr
[0x12] |
1254 ((s
->cr
[0x07] & 0x02) << 7) |
1255 ((s
->cr
[0x07] & 0x40) << 3);
1256 height
= (height
+ 1) / cheight
;
1262 *pcheight
= cheight
;
1265 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r
, unsigned int g
, unsigned b
);
1267 static rgb_to_pixel_dup_func
*rgb_to_pixel_dup_table
[NB_DEPTHS
] = {
1272 rgb_to_pixel32bgr_dup
,
1273 rgb_to_pixel15bgr_dup
,
1274 rgb_to_pixel16bgr_dup
,
1285 static void vga_draw_text(VGAState
*s
, int full_update
)
1287 int cx
, cy
, cheight
, cw
, ch
, cattr
, height
, width
, ch_attr
;
1288 int cx_min
, cx_max
, linesize
, x_incr
;
1289 uint32_t offset
, fgcol
, bgcol
, v
, cursor_offset
;
1290 uint8_t *d1
, *d
, *src
, *s1
, *dest
, *cursor_ptr
;
1291 const uint8_t *font_ptr
, *font_base
[2];
1292 int dup9
, line_offset
, depth_index
;
1294 uint32_t *ch_attr_ptr
;
1295 vga_draw_glyph8_func
*vga_draw_glyph8
;
1296 vga_draw_glyph9_func
*vga_draw_glyph9
;
1298 vga_dirty_log_stop(s
);
1300 /* compute font data address (in plane 2) */
1302 offset
= (((v
>> 4) & 1) | ((v
<< 1) & 6)) * 8192 * 4 + 2;
1303 if (offset
!= s
->font_offsets
[0]) {
1304 s
->font_offsets
[0] = offset
;
1307 font_base
[0] = s
->vram_ptr
+ offset
;
1309 offset
= (((v
>> 5) & 1) | ((v
>> 1) & 6)) * 8192 * 4 + 2;
1310 font_base
[1] = s
->vram_ptr
+ offset
;
1311 if (offset
!= s
->font_offsets
[1]) {
1312 s
->font_offsets
[1] = offset
;
1315 if (s
->plane_updated
& (1 << 2)) {
1316 /* if the plane 2 was modified since the last display, it
1317 indicates the font may have been modified */
1318 s
->plane_updated
= 0;
1322 line_offset
= s
->line_offset
;
1323 s1
= s
->vram_ptr
+ (s
->start_addr
* 4);
1325 vga_get_text_resolution(s
, &width
, &height
, &cw
, &cheight
);
1326 x_incr
= cw
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1327 if ((height
* width
) > CH_ATTR_SIZE
) {
1328 /* better than nothing: exit if transient size is too big */
1333 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1334 full_update
|= update_palette16(s
);
1335 palette
= s
->last_palette
;
1336 x_incr
= cw
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1338 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
1339 if (cursor_offset
!= s
->cursor_offset
||
1340 s
->cr
[0xa] != s
->cursor_start
||
1341 s
->cr
[0xb] != s
->cursor_end
) {
1342 /* if the cursor position changed, we update the old and new
1344 if (s
->cursor_offset
< CH_ATTR_SIZE
)
1345 s
->last_ch_attr
[s
->cursor_offset
] = -1;
1346 if (cursor_offset
< CH_ATTR_SIZE
)
1347 s
->last_ch_attr
[cursor_offset
] = -1;
1348 s
->cursor_offset
= cursor_offset
;
1349 s
->cursor_start
= s
->cr
[0xa];
1350 s
->cursor_end
= s
->cr
[0xb];
1352 cursor_ptr
= s
->vram_ptr
+ (s
->start_addr
+ cursor_offset
) * 4;
1354 depth_index
= get_depth_index(s
->ds
);
1356 vga_draw_glyph8
= vga_draw_glyph16_table
[depth_index
];
1358 vga_draw_glyph8
= vga_draw_glyph8_table
[depth_index
];
1359 vga_draw_glyph9
= vga_draw_glyph9_table
[depth_index
];
1361 dest
= ds_get_data(s
->ds
);
1362 linesize
= ds_get_linesize(s
->ds
);
1363 ch_attr_ptr
= s
->last_ch_attr
;
1364 for(cy
= 0; cy
< height
; cy
++) {
1369 for(cx
= 0; cx
< width
; cx
++) {
1370 ch_attr
= *(uint16_t *)src
;
1371 if (full_update
|| ch_attr
!= *ch_attr_ptr
) {
1376 *ch_attr_ptr
= ch_attr
;
1377 #ifdef WORDS_BIGENDIAN
1379 cattr
= ch_attr
& 0xff;
1381 ch
= ch_attr
& 0xff;
1382 cattr
= ch_attr
>> 8;
1384 font_ptr
= font_base
[(cattr
>> 3) & 1];
1385 font_ptr
+= 32 * 4 * ch
;
1386 bgcol
= palette
[cattr
>> 4];
1387 fgcol
= palette
[cattr
& 0x0f];
1389 vga_draw_glyph8(d1
, linesize
,
1390 font_ptr
, cheight
, fgcol
, bgcol
);
1393 if (ch
>= 0xb0 && ch
<= 0xdf && (s
->ar
[0x10] & 0x04))
1395 vga_draw_glyph9(d1
, linesize
,
1396 font_ptr
, cheight
, fgcol
, bgcol
, dup9
);
1398 if (src
== cursor_ptr
&&
1399 !(s
->cr
[0x0a] & 0x20)) {
1400 int line_start
, line_last
, h
;
1401 /* draw the cursor */
1402 line_start
= s
->cr
[0x0a] & 0x1f;
1403 line_last
= s
->cr
[0x0b] & 0x1f;
1404 /* XXX: check that */
1405 if (line_last
> cheight
- 1)
1406 line_last
= cheight
- 1;
1407 if (line_last
>= line_start
&& line_start
< cheight
) {
1408 h
= line_last
- line_start
+ 1;
1409 d
= d1
+ linesize
* line_start
;
1411 vga_draw_glyph8(d
, linesize
,
1412 cursor_glyph
, h
, fgcol
, bgcol
);
1414 vga_draw_glyph9(d
, linesize
,
1415 cursor_glyph
, h
, fgcol
, bgcol
, 1);
1425 dpy_update(s
->ds
, cx_min
* cw
, cy
* cheight
,
1426 (cx_max
- cx_min
+ 1) * cw
, cheight
);
1428 dest
+= linesize
* cheight
;
1447 static vga_draw_line_func
*vga_draw_line_table
[NB_DEPTHS
* VGA_DRAW_LINE_NB
] = {
1457 vga_draw_line2d2_16
,
1458 vga_draw_line2d2_16
,
1459 vga_draw_line2d2_32
,
1460 vga_draw_line2d2_32
,
1461 vga_draw_line2d2_16
,
1462 vga_draw_line2d2_16
,
1473 vga_draw_line4d2_16
,
1474 vga_draw_line4d2_16
,
1475 vga_draw_line4d2_32
,
1476 vga_draw_line4d2_32
,
1477 vga_draw_line4d2_16
,
1478 vga_draw_line4d2_16
,
1481 vga_draw_line8d2_16
,
1482 vga_draw_line8d2_16
,
1483 vga_draw_line8d2_32
,
1484 vga_draw_line8d2_32
,
1485 vga_draw_line8d2_16
,
1486 vga_draw_line8d2_16
,
1500 vga_draw_line15_32bgr
,
1501 vga_draw_line15_15bgr
,
1502 vga_draw_line15_16bgr
,
1508 vga_draw_line16_32bgr
,
1509 vga_draw_line16_15bgr
,
1510 vga_draw_line16_16bgr
,
1516 vga_draw_line24_32bgr
,
1517 vga_draw_line24_15bgr
,
1518 vga_draw_line24_16bgr
,
1524 vga_draw_line32_32bgr
,
1525 vga_draw_line32_15bgr
,
1526 vga_draw_line32_16bgr
,
1529 static int vga_get_bpp(VGAState
*s
)
1532 #ifdef CONFIG_BOCHS_VBE
1533 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1534 ret
= s
->vbe_regs
[VBE_DISPI_INDEX_BPP
];
1543 static void vga_get_resolution(VGAState
*s
, int *pwidth
, int *pheight
)
1547 #ifdef CONFIG_BOCHS_VBE
1548 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1549 width
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
1550 height
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
1554 width
= (s
->cr
[0x01] + 1) * 8;
1555 height
= s
->cr
[0x12] |
1556 ((s
->cr
[0x07] & 0x02) << 7) |
1557 ((s
->cr
[0x07] & 0x40) << 3);
1558 height
= (height
+ 1);
1564 void vga_invalidate_scanlines(VGAState
*s
, int y1
, int y2
)
1567 if (y1
>= VGA_MAX_HEIGHT
)
1569 if (y2
>= VGA_MAX_HEIGHT
)
1570 y2
= VGA_MAX_HEIGHT
;
1571 for(y
= y1
; y
< y2
; y
++) {
1572 s
->invalidated_y_table
[y
>> 5] |= 1 << (y
& 0x1f);
1576 static void vga_sync_dirty_bitmap(VGAState
*s
)
1579 cpu_physical_sync_dirty_bitmap(s
->map_addr
, s
->map_end
);
1581 if (s
->lfb_vram_mapped
) {
1582 cpu_physical_sync_dirty_bitmap(isa_mem_base
+ 0xa0000, 0xa8000);
1583 cpu_physical_sync_dirty_bitmap(isa_mem_base
+ 0xa8000, 0xb0000);
1585 vga_dirty_log_start(s
);
1588 static void vga_update_resolution_graphics(VGAState
*s
)
1590 int depth
= s
->get_bpp(s
);
1591 int width
, height
, shift_control
, double_scan
;
1592 int disp_width
, multi_scan
, multi_run
;
1594 s
->get_resolution(s
, &width
, &height
);
1597 shift_control
= (s
->gr
[0x05] >> 5) & 3;
1598 double_scan
= (s
->cr
[0x09] >> 7);
1600 if (shift_control
!= s
->shift_control
||
1601 double_scan
!= s
->double_scan
) {
1602 s
->want_full_update
= 1;
1603 s
->shift_control
= shift_control
;
1604 s
->double_scan
= double_scan
;
1607 if (shift_control
== 0) {
1608 if (s
->sr
[0x01] & 8) {
1611 } else if (shift_control
== 1) {
1612 if (s
->sr
[0x01] & 8) {
1618 if (shift_control
!= 1) {
1619 multi_scan
= (((s
->cr
[0x09] & 0x1f) + 1) << double_scan
) - 1;
1621 /* in CGA modes, multi_scan is ignored */
1622 /* XXX: is it correct ? */
1623 multi_scan
= double_scan
;
1626 multi_run
= multi_scan
;
1628 if (s
->line_offset
!= s
->last_line_offset
||
1629 disp_width
!= s
->last_width
||
1630 height
!= s
->last_height
||
1631 s
->last_depth
!= depth
||
1632 s
->multi_run
!= multi_run
||
1633 s
->multi_scan
!= multi_scan
||
1634 s
->want_full_update
) {
1635 if (s
->ds
->surface
->pf
.depth
== 0) {
1636 goto dont_touch_display_surface
;
1638 #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1639 if (depth
== 16 || depth
== 32) {
1643 qemu_free_displaysurface(s
->ds
);
1644 s
->ds
->surface
= qemu_create_displaysurface_from(disp_width
, height
, depth
,
1646 s
->vram_ptr
+ (s
->start_addr
* 4));
1647 #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1648 s
->ds
->surface
->pf
= qemu_different_endianness_pixelformat(depth
);
1652 qemu_console_resize(s
->ds
, disp_width
, height
);
1654 dont_touch_display_surface
:
1655 s
->last_scr_width
= disp_width
;
1656 s
->last_scr_height
= height
;
1657 s
->last_width
= disp_width
;
1658 s
->last_height
= height
;
1659 s
->last_line_offset
= s
->line_offset
;
1660 s
->last_depth
= depth
;
1661 s
->multi_run
= multi_run
;
1662 s
->multi_scan
= multi_scan
;
1663 s
->want_full_update
= 1;
1667 static void vga_update_resolution_text(VGAState
*s
)
1669 int width
, height
, cw
, cheight
;
1671 vga_get_text_resolution(s
, &width
, &height
, &cw
, &cheight
);
1672 if (width
!= s
->last_width
|| height
!= s
->last_height
||
1673 cw
!= s
->last_cw
|| cheight
!= s
->last_ch
|| s
->last_depth
) {
1674 s
->last_scr_width
= width
* cw
;
1675 s
->last_scr_height
= height
* cheight
;
1676 if (s
->ds
->surface
->pf
.depth
!= 0) {
1677 qemu_console_resize(s
->ds
, s
->last_scr_width
, s
->last_scr_height
);
1680 * curses expects width and height to be in character cell
1681 * dimensions, not pixels.
1683 s
->ds
->surface
->width
= width
;
1684 s
->ds
->surface
->height
= height
;
1688 s
->last_width
= width
;
1689 s
->last_height
= height
;
1690 s
->last_ch
= cheight
;
1692 s
->want_full_update
= 1;
1696 void vga_update_resolution(VGAState
*s
)
1700 if (!(s
->ar_index
& 0x20)) {
1701 graphic_mode
= GMODE_BLANK
;
1703 graphic_mode
= s
->gr
[6] & 1;
1705 if (graphic_mode
!= s
->graphic_mode
) {
1706 s
->graphic_mode
= graphic_mode
;
1707 s
->want_full_update
= 1;
1709 s
->want_full_update
|= update_basic_params(s
);
1710 switch (graphic_mode
) {
1712 vga_update_resolution_text(s
);
1715 vga_update_resolution_graphics(s
);
1723 static void vga_draw_graphic(VGAState
*s
, int full_update
)
1725 int y1
, y
, update
, linesize
, y_start
, mask
;
1726 int width
, height
, line_offset
, bwidth
, bits
;
1729 uint32_t v
, addr1
, addr
;
1730 long page0
, page1
, page_min
, page_max
;
1731 vga_draw_line_func
*vga_draw_line
;
1734 vga_sync_dirty_bitmap(s
);
1736 s
->get_resolution(s
, &width
, &height
);
1737 multi_run
= s
->multi_run
;
1738 if (is_buffer_shared(s
->ds
->surface
) &&
1739 (full_update
|| s
->ds
->surface
->data
!= s
->vram_ptr
+ (s
->start_addr
* 4))) {
1740 s
->ds
->surface
->data
= s
->vram_ptr
+ (s
->start_addr
* 4);
1745 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1747 if (s
->shift_control
== 0) {
1748 full_update
|= update_palette16(s
);
1749 if (s
->sr
[0x01] & 8) {
1750 v
= VGA_DRAW_LINE4D2
;
1755 } else if (s
->shift_control
== 1) {
1756 full_update
|= update_palette16(s
);
1757 if (s
->sr
[0x01] & 8) {
1758 v
= VGA_DRAW_LINE2D2
;
1764 switch(s
->get_bpp(s
)) {
1767 full_update
|= update_palette256(s
);
1768 v
= VGA_DRAW_LINE8D2
;
1772 full_update
|= update_palette256(s
);
1777 v
= VGA_DRAW_LINE15
;
1781 v
= VGA_DRAW_LINE16
;
1785 v
= VGA_DRAW_LINE24
;
1789 v
= VGA_DRAW_LINE32
;
1794 vga_draw_line
= vga_draw_line_table
[v
* NB_DEPTHS
+ get_depth_index(s
->ds
)];
1796 if (!is_buffer_shared(s
->ds
->surface
) && s
->cursor_invalidate
)
1797 s
->cursor_invalidate(s
);
1799 line_offset
= s
->line_offset
;
1801 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",
1802 width
, height
, v
, line_offset
, s
->cr
[9], s
->cr
[0x17], s
->line_compare
, s
->sr
[0x01]);
1804 addr1
= (s
->start_addr
* 4);
1805 bwidth
= (width
* bits
+ 7) / 8;
1807 page_min
= 0x7fffffff;
1809 d
= ds_get_data(s
->ds
);
1810 linesize
= ds_get_linesize(s
->ds
);
1812 for(y
= 0; y
< height
; y
++) {
1814 if (!(s
->cr
[0x17] & 1)) {
1816 /* CGA compatibility handling */
1817 shift
= 14 + ((s
->cr
[0x17] >> 6) & 1);
1818 addr
= (addr
& ~(1 << shift
)) | ((y1
& 1) << shift
);
1820 if (!(s
->cr
[0x17] & 2)) {
1821 addr
= (addr
& ~0x8000) | ((y1
& 2) << 14);
1823 page0
= s
->vram_offset
+ (addr
& TARGET_PAGE_MASK
);
1824 page1
= s
->vram_offset
+ ((addr
+ bwidth
- 1) & TARGET_PAGE_MASK
);
1825 update
= full_update
|
1826 cpu_physical_memory_get_dirty(page0
, VGA_DIRTY_FLAG
) |
1827 cpu_physical_memory_get_dirty(page1
, VGA_DIRTY_FLAG
);
1828 if ((page1
- page0
) > TARGET_PAGE_SIZE
) {
1829 /* if wide line, can use another page */
1830 update
|= cpu_physical_memory_get_dirty(page0
+ TARGET_PAGE_SIZE
,
1833 /* explicit invalidation for the hardware cursor */
1834 update
|= (s
->invalidated_y_table
[y
>> 5] >> (y
& 0x1f)) & 1;
1838 if (page0
< page_min
)
1840 if (page1
> page_max
)
1842 if (!(is_buffer_shared(s
->ds
->surface
))) {
1843 vga_draw_line(s
, d
, s
->vram_ptr
+ addr
, width
);
1844 if (s
->cursor_draw_line
)
1845 s
->cursor_draw_line(s
, d
, y
);
1849 /* flush to display */
1850 dpy_update(s
->ds
, 0, y_start
,
1851 s
->last_width
, y
- y_start
);
1856 mask
= (s
->cr
[0x17] & 3) ^ 3;
1857 if ((y1
& mask
) == mask
)
1858 addr1
+= line_offset
;
1860 multi_run
= s
->multi_scan
;
1864 /* line compare acts on the displayed lines */
1865 if (y
== s
->line_compare
)
1870 /* flush to display */
1871 dpy_update(s
->ds
, 0, y_start
,
1872 s
->last_width
, y
- y_start
);
1874 /* reset modified pages */
1875 if (page_max
!= -1) {
1876 cpu_physical_memory_reset_dirty(page_min
, page_max
+ TARGET_PAGE_SIZE
,
1879 memset(s
->invalidated_y_table
, 0, ((height
+ 31) >> 5) * 4);
1882 static void vga_draw_blank(VGAState
*s
, int full_update
)
1889 if (s
->last_scr_width
<= 0 || s
->last_scr_height
<= 0)
1891 vga_dirty_log_stop(s
);
1894 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1895 if (ds_get_bits_per_pixel(s
->ds
) == 8)
1896 val
= s
->rgb_to_pixel(0, 0, 0);
1899 w
= s
->last_scr_width
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1900 d
= ds_get_data(s
->ds
);
1901 for(i
= 0; i
< s
->last_scr_height
; i
++) {
1903 d
+= ds_get_linesize(s
->ds
);
1905 dpy_update(s
->ds
, 0, 0,
1906 s
->last_scr_width
, s
->last_scr_height
);
1909 static void vga_update_display(void *opaque
)
1911 VGAState
*s
= (VGAState
*)opaque
;
1914 if (ds_get_bits_per_pixel(s
->ds
) == 0) {
1917 full_update
= s
->want_full_update
;
1918 s
->want_full_update
= 0;
1919 switch(s
->graphic_mode
) {
1921 vga_draw_text(s
, full_update
);
1927 vga_draw_graphic(s
, full_update
);
1931 vga_draw_blank(s
, full_update
);
1937 /* force a full display refresh */
1938 static void vga_invalidate_display(void *opaque
)
1940 VGAState
*s
= (VGAState
*)opaque
;
1942 vga_update_resolution(s
);
1943 s
->want_full_update
= 1;
1946 void vga_reset(void *opaque
)
1948 VGAState
*s
= (VGAState
*) opaque
;
1954 s
->lfb_vram_mapped
= 0;
1958 memset(s
->sr
, '\0', sizeof(s
->sr
));
1960 memset(s
->gr
, '\0', sizeof(s
->gr
));
1962 memset(s
->ar
, '\0', sizeof(s
->ar
));
1963 s
->ar_flip_flop
= 0;
1965 memset(s
->cr
, '\0', sizeof(s
->cr
));
1971 s
->dac_sub_index
= 0;
1972 s
->dac_read_index
= 0;
1973 s
->dac_write_index
= 0;
1974 memset(s
->dac_cache
, '\0', sizeof(s
->dac_cache
));
1976 memset(s
->palette
, '\0', sizeof(s
->palette
));
1978 #ifdef CONFIG_BOCHS_VBE
1980 memset(s
->vbe_regs
, '\0', sizeof(s
->vbe_regs
));
1981 s
->vbe_regs
[VBE_DISPI_INDEX_ID
] = VBE_DISPI_ID0
;
1982 s
->vbe_start_addr
= 0;
1983 s
->vbe_line_offset
= 0;
1984 s
->vbe_bank_mask
= (s
->vram_size
>> 16) - 1;
1986 memset(s
->font_offsets
, '\0', sizeof(s
->font_offsets
));
1987 s
->shift_control
= 0;
1990 s
->line_compare
= 0;
1992 s
->plane_updated
= 0;
1997 s
->last_scr_width
= 0;
1998 s
->last_scr_height
= 0;
1999 s
->cursor_start
= 0;
2001 s
->cursor_offset
= 0;
2002 memset(s
->invalidated_y_table
, '\0', sizeof(s
->invalidated_y_table
));
2003 memset(s
->last_palette
, '\0', sizeof(s
->last_palette
));
2004 memset(s
->last_ch_attr
, '\0', sizeof(s
->last_ch_attr
));
2005 switch (vga_retrace_method
) {
2006 case VGA_RETRACE_DUMB
:
2008 case VGA_RETRACE_PRECISE
:
2009 memset(&s
->retrace_info
, 0, sizeof (s
->retrace_info
));
2012 vga_update_resolution(s
);
2015 #define TEXTMODE_X(x) ((x) % width)
2016 #define TEXTMODE_Y(x) ((x) / width)
2017 #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
2018 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2019 /* relay text rendering to the display driver
2020 * instead of doing a full vga_update_display() */
2021 static void vga_update_text(void *opaque
, console_ch_t
*chardata
)
2023 VGAState
*s
= (VGAState
*) opaque
;
2024 int i
, cursor_offset
, cursor_visible
;
2025 int cw
, cheight
, width
, height
, size
, c_min
, c_max
;
2027 console_ch_t
*dst
, val
;
2028 char msg_buffer
[80];
2029 int full_update
= s
->want_full_update
;
2031 s
->want_full_update
= 0;
2032 switch (s
->graphic_mode
) {
2034 /* TODO: update palette */
2036 vga_get_text_resolution(s
, &width
, &height
, &cw
, &cheight
);
2038 if (s
->ds
->surface
->width
!= width
2039 || s
->ds
->surface
->height
!= height
) {
2040 s
->ds
->surface
->width
= width
;
2041 s
->ds
->surface
->height
= height
;
2045 /* total width & height */
2046 size
= (height
* width
);
2047 if (size
> CH_ATTR_SIZE
) {
2051 snprintf(msg_buffer
, sizeof(msg_buffer
), "%i x %i Text mode",
2056 /* Update "hardware" cursor */
2057 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
2058 if (cursor_offset
!= s
->cursor_offset
||
2059 s
->cr
[0xa] != s
->cursor_start
||
2060 s
->cr
[0xb] != s
->cursor_end
|| full_update
) {
2061 cursor_visible
= !(s
->cr
[0xa] & 0x20);
2062 if (cursor_visible
&& cursor_offset
< size
&& cursor_offset
>= 0)
2064 TEXTMODE_X(cursor_offset
),
2065 TEXTMODE_Y(cursor_offset
));
2067 dpy_cursor(s
->ds
, -1, -1);
2068 s
->cursor_offset
= cursor_offset
;
2069 s
->cursor_start
= s
->cr
[0xa];
2070 s
->cursor_end
= s
->cr
[0xb];
2073 src
= (uint32_t *) s
->vram_ptr
+ s
->start_addr
;
2077 for (i
= 0; i
< size
; src
++, dst
++, i
++)
2078 console_write_ch(dst
, VMEM2CHTYPE(*src
));
2080 dpy_update(s
->ds
, 0, 0, width
, height
);
2084 for (i
= 0; i
< size
; src
++, dst
++, i
++) {
2085 console_write_ch(&val
, VMEM2CHTYPE(*src
));
2093 for (; i
< size
; src
++, dst
++, i
++) {
2094 console_write_ch(&val
, VMEM2CHTYPE(*src
));
2101 if (c_min
<= c_max
) {
2102 i
= TEXTMODE_Y(c_min
);
2103 dpy_update(s
->ds
, 0, i
, width
, TEXTMODE_Y(c_max
) - i
+ 1);
2112 s
->get_resolution(s
, &width
, &height
);
2113 snprintf(msg_buffer
, sizeof(msg_buffer
), "%i x %i Graphic mode",
2121 snprintf(msg_buffer
, sizeof(msg_buffer
), "VGA Blank mode");
2125 /* Display a message */
2127 s
->last_height
= height
= 3;
2128 dpy_cursor(s
->ds
, -1, -1);
2129 s
->ds
->surface
->width
= s
->last_width
;
2130 s
->ds
->surface
->height
= height
;
2133 for (dst
= chardata
, i
= 0; i
< s
->last_width
* height
; i
++)
2134 console_write_ch(dst
++, ' ');
2136 size
= strlen(msg_buffer
);
2137 width
= (s
->last_width
- size
) / 2;
2138 dst
= chardata
+ s
->last_width
+ width
;
2139 for (i
= 0; i
< size
; i
++)
2140 console_write_ch(dst
++, 0x00200100 | msg_buffer
[i
]);
2142 dpy_update(s
->ds
, 0, 0, s
->last_width
, height
);
2145 static CPUReadMemoryFunc
*vga_mem_read
[3] = {
2151 static CPUWriteMemoryFunc
*vga_mem_write
[3] = {
2157 static void vga_save(QEMUFile
*f
, void *opaque
)
2159 VGAState
*s
= opaque
;
2163 pci_device_save(s
->pci_dev
, f
);
2165 qemu_put_be32s(f
, &s
->latch
);
2166 qemu_put_8s(f
, &s
->sr_index
);
2167 qemu_put_buffer(f
, s
->sr
, 8);
2168 qemu_put_8s(f
, &s
->gr_index
);
2169 qemu_put_buffer(f
, s
->gr
, 16);
2170 qemu_put_8s(f
, &s
->ar_index
);
2171 qemu_put_buffer(f
, s
->ar
, 21);
2172 qemu_put_be32(f
, s
->ar_flip_flop
);
2173 qemu_put_8s(f
, &s
->cr_index
);
2174 qemu_put_buffer(f
, s
->cr
, 256);
2175 qemu_put_8s(f
, &s
->msr
);
2176 qemu_put_8s(f
, &s
->fcr
);
2177 qemu_put_byte(f
, s
->st00
);
2178 qemu_put_8s(f
, &s
->st01
);
2180 qemu_put_8s(f
, &s
->dac_state
);
2181 qemu_put_8s(f
, &s
->dac_sub_index
);
2182 qemu_put_8s(f
, &s
->dac_read_index
);
2183 qemu_put_8s(f
, &s
->dac_write_index
);
2184 qemu_put_buffer(f
, s
->dac_cache
, 3);
2185 qemu_put_buffer(f
, s
->palette
, 768);
2187 qemu_put_be32(f
, s
->bank_offset
);
2188 #ifdef CONFIG_BOCHS_VBE
2189 qemu_put_byte(f
, 1);
2190 qemu_put_be16s(f
, &s
->vbe_index
);
2191 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
2192 qemu_put_be16s(f
, &s
->vbe_regs
[i
]);
2193 qemu_put_be32s(f
, &s
->vbe_start_addr
);
2194 qemu_put_be32s(f
, &s
->vbe_line_offset
);
2195 qemu_put_be32s(f
, &s
->vbe_bank_mask
);
2197 qemu_put_byte(f
, 0);
2201 static int vga_load(QEMUFile
*f
, void *opaque
, int version_id
)
2203 VGAState
*s
= opaque
;
2209 if (s
->pci_dev
&& version_id
>= 2) {
2210 ret
= pci_device_load(s
->pci_dev
, f
);
2215 qemu_get_be32s(f
, &s
->latch
);
2216 qemu_get_8s(f
, &s
->sr_index
);
2217 qemu_get_buffer(f
, s
->sr
, 8);
2218 qemu_get_8s(f
, &s
->gr_index
);
2219 qemu_get_buffer(f
, s
->gr
, 16);
2220 qemu_get_8s(f
, &s
->ar_index
);
2221 qemu_get_buffer(f
, s
->ar
, 21);
2222 s
->ar_flip_flop
=qemu_get_be32(f
);
2223 qemu_get_8s(f
, &s
->cr_index
);
2224 qemu_get_buffer(f
, s
->cr
, 256);
2225 qemu_get_8s(f
, &s
->msr
);
2226 qemu_get_8s(f
, &s
->fcr
);
2227 qemu_get_8s(f
, &s
->st00
);
2228 qemu_get_8s(f
, &s
->st01
);
2230 qemu_get_8s(f
, &s
->dac_state
);
2231 qemu_get_8s(f
, &s
->dac_sub_index
);
2232 qemu_get_8s(f
, &s
->dac_read_index
);
2233 qemu_get_8s(f
, &s
->dac_write_index
);
2234 qemu_get_buffer(f
, s
->dac_cache
, 3);
2235 qemu_get_buffer(f
, s
->palette
, 768);
2237 s
->bank_offset
=qemu_get_be32(f
);
2238 is_vbe
= qemu_get_byte(f
);
2239 #ifdef CONFIG_BOCHS_VBE
2242 qemu_get_be16s(f
, &s
->vbe_index
);
2243 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
2244 qemu_get_be16s(f
, &s
->vbe_regs
[i
]);
2245 qemu_get_be32s(f
, &s
->vbe_start_addr
);
2246 qemu_get_be32s(f
, &s
->vbe_line_offset
);
2247 qemu_get_be32s(f
, &s
->vbe_bank_mask
);
2254 vga_update_resolution(s
);
2255 s
->want_full_update
= 1;
2259 typedef struct PCIVGAState
{
2266 static void mark_dirty(target_phys_addr_t start
, target_phys_addr_t len
)
2268 target_phys_addr_t end
= start
+ len
;
2270 while (start
< end
) {
2271 cpu_physical_memory_set_dirty(cpu_get_physical_page_desc(start
));
2272 start
+= TARGET_PAGE_SIZE
;
2276 void vga_dirty_log_start(VGAState
*s
)
2278 if (kvm_enabled() && s
->map_addr
)
2280 kvm_log_start(s
->map_addr
, s
->map_end
- s
->map_addr
);
2281 mark_dirty(s
->map_addr
, s
->map_end
- s
->map_addr
);
2284 if (kvm_enabled() && s
->lfb_vram_mapped
) {
2286 kvm_log_start(isa_mem_base
+ 0xa0000, 0x8000);
2287 kvm_log_start(isa_mem_base
+ 0xa8000, 0x8000);
2288 mark_dirty(isa_mem_base
+ 0xa0000, 0x10000);
2294 void vga_dirty_log_stop(VGAState
*s
)
2296 if (kvm_enabled() && s
->map_addr
&& s1
)
2297 kvm_log_stop(s
->map_addr
, s
->map_end
- s
->map_addr
);
2299 if (kvm_enabled() && s
->lfb_vram_mapped
&& s2
) {
2300 kvm_log_stop(isa_mem_base
+ 0xa0000, 0x8000);
2301 kvm_log_stop(isa_mem_base
+ 0xa8000, 0x8000);
2306 static void vga_map(PCIDevice
*pci_dev
, int region_num
,
2307 uint32_t addr
, uint32_t size
, int type
)
2309 PCIVGAState
*d
= (PCIVGAState
*)pci_dev
;
2310 VGAState
*s
= &d
->vga_state
;
2311 if (region_num
== PCI_ROM_SLOT
) {
2312 cpu_register_physical_memory(addr
, s
->bios_size
, s
->bios_offset
);
2314 cpu_register_physical_memory(addr
, s
->vram_size
, s
->vram_offset
);
2318 s
->map_end
= addr
+ VGA_RAM_SIZE
;
2320 vga_dirty_log_start(s
);
2324 /* do the same job as vgabios before vgabios get ready - yeah */
2325 void vga_bios_init(VGAState
*s
)
2327 uint8_t palette_model
[192] = {
2328 0, 0, 0, 0, 0, 170, 0, 170,
2329 0, 0, 170, 170, 170, 0, 0, 170,
2330 0, 170, 170, 85, 0, 170, 170, 170,
2331 85, 85, 85, 85, 85, 255, 85, 255,
2332 85, 85, 255, 255, 255, 85, 85, 255,
2333 85, 255, 255, 255, 85, 255, 255, 255,
2334 0, 21, 0, 0, 21, 42, 0, 63,
2335 0, 0, 63, 42, 42, 21, 0, 42,
2336 21, 42, 42, 63, 0, 42, 63, 42,
2337 0, 21, 21, 0, 21, 63, 0, 63,
2338 21, 0, 63, 63, 42, 21, 21, 42,
2339 21, 63, 42, 63, 21, 42, 63, 63,
2340 21, 0, 0, 21, 0, 42, 21, 42,
2341 0, 21, 42, 42, 63, 0, 0, 63,
2342 0, 42, 63, 42, 0, 63, 42, 42,
2343 21, 0, 21, 21, 0, 63, 21, 42,
2344 21, 21, 42, 63, 63, 0, 21, 63,
2345 0, 63, 63, 42, 21, 63, 42, 63,
2346 21, 21, 0, 21, 21, 42, 21, 63,
2347 0, 21, 63, 42, 63, 21, 0, 63,
2348 21, 42, 63, 63, 0, 63, 63, 42,
2349 21, 21, 21, 21, 21, 63, 21, 63,
2350 21, 21, 63, 63, 63, 21, 21, 63,
2351 21, 63, 63, 63, 21, 63, 63, 63
2377 /* changed by out 0x03c0 */
2401 s
->ar_flip_flop
= 1;
2435 /* dac_* & palette will be initialized by os through out 0x03c8 &
2436 * out 0c03c9(1:3) */
2438 s
->dac_sub_index
= 0;
2439 s
->dac_read_index
= 0;
2440 s
->dac_write_index
= 16;
2441 s
->dac_cache
[0] = 255;
2442 s
->dac_cache
[1] = 255;
2443 s
->dac_cache
[2] = 255;
2446 memcpy(s
->palette
, palette_model
, 192);
2449 s
->graphic_mode
= -1;
2451 vga_update_resolution(s
);
2453 /* TODO: add vbe support if enabled */
2457 void vga_common_init(VGAState
*s
, uint8_t *vga_ram_base
,
2458 ram_addr_t vga_ram_offset
, int vga_ram_size
)
2462 for(i
= 0;i
< 256; i
++) {
2464 for(j
= 0; j
< 8; j
++) {
2465 v
|= ((i
>> j
) & 1) << (j
* 4);
2470 for(j
= 0; j
< 4; j
++) {
2471 v
|= ((i
>> (2 * j
)) & 3) << (j
* 4);
2475 for(i
= 0; i
< 16; i
++) {
2477 for(j
= 0; j
< 4; j
++) {
2480 v
|= b
<< (2 * j
+ 1);
2485 s
->vram_ptr
= vga_ram_base
;
2486 s
->vram_offset
= vga_ram_offset
;
2487 s
->vram_size
= vga_ram_size
;
2488 s
->get_bpp
= vga_get_bpp
;
2489 s
->get_offsets
= vga_get_offsets
;
2490 s
->get_resolution
= vga_get_resolution
;
2491 s
->update
= vga_update_display
;
2492 s
->invalidate
= vga_invalidate_display
;
2493 s
->screen_dump
= vga_screen_dump
;
2494 s
->text_update
= vga_update_text
;
2495 switch (vga_retrace_method
) {
2496 case VGA_RETRACE_DUMB
:
2497 s
->retrace
= vga_dumb_retrace
;
2498 s
->update_retrace_info
= vga_dumb_update_retrace_info
;
2501 case VGA_RETRACE_PRECISE
:
2502 s
->retrace
= vga_precise_retrace
;
2503 s
->update_retrace_info
= vga_precise_update_retrace_info
;
2512 /* used by both ISA and PCI */
2513 void vga_init(VGAState
*s
)
2517 qemu_register_reset(vga_reset
, s
);
2518 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
2520 register_ioport_write(0x3c0, 16, 1, vga_ioport_write
, s
);
2522 register_ioport_write(0x3b4, 2, 1, vga_ioport_write
, s
);
2523 register_ioport_write(0x3d4, 2, 1, vga_ioport_write
, s
);
2524 register_ioport_write(0x3ba, 1, 1, vga_ioport_write
, s
);
2525 register_ioport_write(0x3da, 1, 1, vga_ioport_write
, s
);
2527 register_ioport_read(0x3c0, 16, 1, vga_ioport_read
, s
);
2529 register_ioport_read(0x3b4, 2, 1, vga_ioport_read
, s
);
2530 register_ioport_read(0x3d4, 2, 1, vga_ioport_read
, s
);
2531 register_ioport_read(0x3ba, 1, 1, vga_ioport_read
, s
);
2532 register_ioport_read(0x3da, 1, 1, vga_ioport_read
, s
);
2535 #ifdef CONFIG_BOCHS_VBE
2536 #if defined (TARGET_I386)
2537 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
2538 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data
, s
);
2540 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
2541 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data
, s
);
2543 /* old Bochs IO ports */
2544 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index
, s
);
2545 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data
, s
);
2547 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index
, s
);
2548 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data
, s
);
2550 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
2551 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data
, s
);
2553 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
2554 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data
, s
);
2556 #endif /* CONFIG_BOCHS_VBE */
2558 vga_io_memory
= cpu_register_io_memory(0, vga_mem_read
, vga_mem_write
, s
);
2559 cpu_register_physical_memory(isa_mem_base
+ 0x000a0000, 0x20000,
2561 qemu_register_coalesced_mmio(isa_mem_base
+ 0x000a0000, 0x20000);
2564 /* Memory mapped interface */
2565 static uint32_t vga_mm_readb (void *opaque
, target_phys_addr_t addr
)
2567 VGAState
*s
= opaque
;
2569 return vga_ioport_read(s
, addr
>> s
->it_shift
) & 0xff;
2572 static void vga_mm_writeb (void *opaque
,
2573 target_phys_addr_t addr
, uint32_t value
)
2575 VGAState
*s
= opaque
;
2577 vga_ioport_write(s
, addr
>> s
->it_shift
, value
& 0xff);
2580 static uint32_t vga_mm_readw (void *opaque
, target_phys_addr_t addr
)
2582 VGAState
*s
= opaque
;
2584 return vga_ioport_read(s
, addr
>> s
->it_shift
) & 0xffff;
2587 static void vga_mm_writew (void *opaque
,
2588 target_phys_addr_t addr
, uint32_t value
)
2590 VGAState
*s
= opaque
;
2592 vga_ioport_write(s
, addr
>> s
->it_shift
, value
& 0xffff);
2595 static uint32_t vga_mm_readl (void *opaque
, target_phys_addr_t addr
)
2597 VGAState
*s
= opaque
;
2599 return vga_ioport_read(s
, addr
>> s
->it_shift
);
2602 static void vga_mm_writel (void *opaque
,
2603 target_phys_addr_t addr
, uint32_t value
)
2605 VGAState
*s
= opaque
;
2607 vga_ioport_write(s
, addr
>> s
->it_shift
, value
);
2610 static CPUReadMemoryFunc
*vga_mm_read_ctrl
[] = {
2616 static CPUWriteMemoryFunc
*vga_mm_write_ctrl
[] = {
2622 static void vga_mm_init(VGAState
*s
, target_phys_addr_t vram_base
,
2623 target_phys_addr_t ctrl_base
, int it_shift
)
2625 int s_ioport_ctrl
, vga_io_memory
;
2627 s
->it_shift
= it_shift
;
2628 s_ioport_ctrl
= cpu_register_io_memory(0, vga_mm_read_ctrl
, vga_mm_write_ctrl
, s
);
2629 vga_io_memory
= cpu_register_io_memory(0, vga_mem_read
, vga_mem_write
, s
);
2631 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
2633 cpu_register_physical_memory(ctrl_base
, 0x100000, s_ioport_ctrl
);
2635 cpu_register_physical_memory(vram_base
+ 0x000a0000, 0x20000, vga_io_memory
);
2636 qemu_register_coalesced_mmio(vram_base
+ 0x000a0000, 0x20000);
2639 int isa_vga_init(uint8_t *vga_ram_base
,
2640 unsigned long vga_ram_offset
, int vga_ram_size
)
2644 s
= qemu_mallocz(sizeof(VGAState
));
2646 vga_common_init(s
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
2649 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2650 s
->screen_dump
, s
->text_update
, s
);
2652 #ifdef CONFIG_BOCHS_VBE
2653 /* XXX: use optimized standard vga accesses */
2654 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
2655 vga_ram_size
, vga_ram_offset
);
2660 int isa_vga_mm_init(uint8_t *vga_ram_base
,
2661 unsigned long vga_ram_offset
, int vga_ram_size
,
2662 target_phys_addr_t vram_base
, target_phys_addr_t ctrl_base
,
2667 s
= qemu_mallocz(sizeof(VGAState
));
2669 vga_common_init(s
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
2670 vga_mm_init(s
, vram_base
, ctrl_base
, it_shift
);
2672 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2673 s
->screen_dump
, s
->text_update
, s
);
2675 #ifdef CONFIG_BOCHS_VBE
2676 /* XXX: use optimized standard vga accesses */
2677 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
2678 vga_ram_size
, vga_ram_offset
);
2683 static void pci_vga_write_config(PCIDevice
*d
,
2684 uint32_t address
, uint32_t val
, int len
)
2686 PCIVGAState
*pvs
= container_of(d
, PCIVGAState
, dev
);
2687 VGAState
*s
= &pvs
->vga_state
;
2689 vga_dirty_log_stop(s
);
2690 pci_default_write_config(d
, address
, val
, len
);
2691 if (s
->map_addr
&& pvs
->dev
.io_regions
[0].addr
== -1)
2693 vga_dirty_log_start(s
);
2696 int pci_vga_init(PCIBus
*bus
, uint8_t *vga_ram_base
,
2697 unsigned long vga_ram_offset
, int vga_ram_size
,
2698 unsigned long vga_bios_offset
, int vga_bios_size
)
2704 d
= (PCIVGAState
*)pci_register_device(bus
, "VGA",
2705 sizeof(PCIVGAState
),
2706 -1, NULL
, pci_vga_write_config
);
2711 vga_common_init(s
, vga_ram_base
, vga_ram_offset
, vga_ram_size
);
2714 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2715 s
->screen_dump
, s
->text_update
, s
);
2717 s
->pci_dev
= &d
->dev
;
2719 pci_conf
= d
->dev
.config
;
2720 // dummy VGA (same as Bochs ID)
2721 pci_config_set_vendor_id(pci_conf
, PCI_VENDOR_ID_QEMU
);
2722 pci_config_set_device_id(pci_conf
, PCI_DEVICE_ID_QEMU_VGA
);
2723 pci_config_set_class(pci_conf
, PCI_CLASS_DISPLAY_VGA
);
2724 pci_conf
[0x0e] = 0x00; // header_type
2726 /* XXX: vga_ram_size must be a power of two */
2727 pci_register_io_region(&d
->dev
, 0, vga_ram_size
,
2728 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2729 if (vga_bios_size
!= 0) {
2730 unsigned int bios_total_size
;
2731 s
->bios_offset
= vga_bios_offset
;
2732 s
->bios_size
= vga_bios_size
;
2733 /* must be a power of two */
2734 bios_total_size
= 1;
2735 while (bios_total_size
< vga_bios_size
)
2736 bios_total_size
<<= 1;
2737 pci_register_io_region(&d
->dev
, PCI_ROM_SLOT
, bios_total_size
,
2738 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2743 /********************************************************/
2744 /* vga screen dump */
2746 static void vga_save_dpy_update(DisplayState
*s
,
2747 int x
, int y
, int w
, int h
)
2751 static void vga_save_dpy_resize(DisplayState
*s
)
2755 static void vga_save_dpy_refresh(DisplayState
*s
)
2759 int ppm_save(const char *filename
, struct DisplaySurface
*ds
)
2767 f
= fopen(filename
, "wb");
2770 fprintf(f
, "P6\n%d %d\n%d\n",
2771 ds
->width
, ds
->height
, 255);
2773 for(y
= 0; y
< ds
->height
; y
++) {
2775 for(x
= 0; x
< ds
->width
; x
++) {
2776 if (ds
->pf
.bits_per_pixel
== 32)
2779 v
= (uint32_t) (*(uint16_t *)d
);
2780 r
= ((v
>> ds
->pf
.rshift
) & ds
->pf
.rmax
) * 256 /
2782 g
= ((v
>> ds
->pf
.gshift
) & ds
->pf
.gmax
) * 256 /
2784 b
= ((v
>> ds
->pf
.bshift
) & ds
->pf
.bmax
) * 256 /
2789 d
+= ds
->pf
.bytes_per_pixel
;
2797 static void vga_screen_dump_blank(VGAState
*s
, const char *filename
)
2800 unsigned int y
, x
, w
, h
;
2802 w
= s
->last_scr_width
* sizeof(uint32_t);
2803 h
= s
->last_scr_height
;
2805 f
= fopen(filename
, "wb");
2808 fprintf(f
, "P6\n%d %d\n%d\n", w
, h
, 255);
2809 for (y
= 0; y
< h
; y
++) {
2810 for (x
= 0; x
< w
; x
++) {
2817 static void vga_screen_dump_common(VGAState
*s
, const char *filename
,
2820 DisplayState
*saved_ds
, ds1
, *ds
= &ds1
;
2821 DisplayChangeListener dcl
;
2823 /* XXX: this is a little hackish */
2824 vga_invalidate_display(s
);
2827 memset(ds
, 0, sizeof(DisplayState
));
2828 memset(&dcl
, 0, sizeof(DisplayChangeListener
));
2829 dcl
.dpy_update
= vga_save_dpy_update
;
2830 dcl
.dpy_resize
= vga_save_dpy_resize
;
2831 dcl
.dpy_refresh
= vga_save_dpy_refresh
;
2832 register_displaychangelistener(ds
, &dcl
);
2833 ds
->allocator
= &default_allocator
;
2834 ds
->surface
= qemu_create_displaysurface(ds
, w
, h
);
2837 vga_update_resolution(s
);
2838 s
->want_full_update
= 1;
2839 vga_update_display(s
);
2841 ppm_save(filename
, ds
->surface
);
2843 qemu_free_displaysurface(ds
);
2847 static void vga_screen_dump_graphic(VGAState
*s
, const char *filename
)
2851 s
->get_resolution(s
, &w
, &h
);
2852 vga_screen_dump_common(s
, filename
, w
, h
);
2855 static void vga_screen_dump_text(VGAState
*s
, const char *filename
)
2857 int w
, h
, cwidth
, cheight
;
2859 vga_get_text_resolution(s
, &w
, &h
, &cwidth
, &cheight
);
2860 vga_screen_dump_common(s
, filename
, w
* cwidth
, h
* cheight
);
2863 /* save the vga display in a PPM image even if no display is
2865 static void vga_screen_dump(void *opaque
, const char *filename
)
2867 VGAState
*s
= (VGAState
*)opaque
;
2869 switch (s
->graphic_mode
) {
2871 vga_screen_dump_text(s
, filename
);
2874 vga_screen_dump_graphic(s
, filename
);
2878 vga_screen_dump_blank(s
, filename
);