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"
34 //#define DEBUG_VGA_MEM
35 //#define DEBUG_VGA_REG
37 //#define DEBUG_BOCHS_VBE
39 /* force some bits to zero */
40 const uint8_t sr_mask
[8] = {
51 const uint8_t gr_mask
[16] = {
70 #define cbswap_32(__x) \
72 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
74 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
75 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
77 #ifdef HOST_WORDS_BIGENDIAN
78 #define PAT(x) cbswap_32(x)
83 #ifdef HOST_WORDS_BIGENDIAN
89 #ifdef HOST_WORDS_BIGENDIAN
90 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
92 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
95 static const uint32_t mask16
[16] = {
116 #ifdef HOST_WORDS_BIGENDIAN
119 #define PAT(x) cbswap_32(x)
122 static const uint32_t dmask16
[16] = {
141 static const uint32_t dmask4
[4] = {
148 static uint32_t expand4
[256];
149 static uint16_t expand2
[256];
150 static uint8_t expand4to8
[16];
152 typedef VGACommonState VGAState
;
154 static void vga_screen_dump(void *opaque
, const char *filename
);
155 static char *screen_dump_filename
;
156 static DisplayChangeListener
*screen_dump_dcl
;
158 static void vga_dumb_update_retrace_info(VGAState
*s
)
163 static void vga_precise_update_retrace_info(VGAState
*s
)
166 int hretr_start_char
;
167 int hretr_skew_chars
;
171 int vretr_start_line
;
174 int div2
, sldiv2
, dots
;
177 const int clk_hz
[] = {25175000, 28322000, 25175000, 25175000};
178 int64_t chars_per_sec
;
179 struct vga_precise_retrace
*r
= &s
->retrace_info
.precise
;
181 htotal_chars
= s
->cr
[0x00] + 5;
182 hretr_start_char
= s
->cr
[0x04];
183 hretr_skew_chars
= (s
->cr
[0x05] >> 5) & 3;
184 hretr_end_char
= s
->cr
[0x05] & 0x1f;
186 vtotal_lines
= (s
->cr
[0x06]
187 | (((s
->cr
[0x07] & 1) | ((s
->cr
[0x07] >> 4) & 2)) << 8)) + 2
189 vretr_start_line
= s
->cr
[0x10]
190 | ((((s
->cr
[0x07] >> 2) & 1) | ((s
->cr
[0x07] >> 6) & 2)) << 8)
192 vretr_end_line
= s
->cr
[0x11] & 0xf;
195 div2
= (s
->cr
[0x17] >> 2) & 1;
196 sldiv2
= (s
->cr
[0x17] >> 3) & 1;
198 clocking_mode
= (s
->sr
[0x01] >> 3) & 1;
199 clock_sel
= (s
->msr
>> 2) & 3;
200 dots
= (s
->msr
& 1) ? 8 : 9;
202 chars_per_sec
= clk_hz
[clock_sel
] / dots
;
204 htotal_chars
<<= clocking_mode
;
206 r
->total_chars
= vtotal_lines
* htotal_chars
;
208 r
->ticks_per_char
= ticks_per_sec
/ (r
->total_chars
* r
->freq
);
210 r
->ticks_per_char
= ticks_per_sec
/ chars_per_sec
;
213 r
->vstart
= vretr_start_line
;
214 r
->vend
= r
->vstart
+ vretr_end_line
+ 1;
216 r
->hstart
= hretr_start_char
+ hretr_skew_chars
;
217 r
->hend
= r
->hstart
+ hretr_end_char
+ 1;
218 r
->htotal
= htotal_chars
;
230 "div2 = %d sldiv2 = %d\n"
231 "clocking_mode = %d\n"
232 "clock_sel = %d %d\n"
234 "ticks/char = %lld\n"
236 (double) ticks_per_sec
/ (r
->ticks_per_char
* r
->total_chars
),
254 static uint8_t vga_precise_retrace(VGAState
*s
)
256 struct vga_precise_retrace
*r
= &s
->retrace_info
.precise
;
257 uint8_t val
= s
->st01
& ~(ST01_V_RETRACE
| ST01_DISP_ENABLE
);
259 if (r
->total_chars
) {
260 int cur_line
, cur_line_char
, cur_char
;
263 cur_tick
= qemu_get_clock(vm_clock
);
265 cur_char
= (cur_tick
/ r
->ticks_per_char
) % r
->total_chars
;
266 cur_line
= cur_char
/ r
->htotal
;
268 if (cur_line
>= r
->vstart
&& cur_line
<= r
->vend
) {
269 val
|= ST01_V_RETRACE
| ST01_DISP_ENABLE
;
271 cur_line_char
= cur_char
% r
->htotal
;
272 if (cur_line_char
>= r
->hstart
&& cur_line_char
<= r
->hend
) {
273 val
|= ST01_DISP_ENABLE
;
279 return s
->st01
^ (ST01_V_RETRACE
| ST01_DISP_ENABLE
);
283 static uint8_t vga_dumb_retrace(VGAState
*s
)
285 return s
->st01
^ (ST01_V_RETRACE
| ST01_DISP_ENABLE
);
288 static uint32_t vga_ioport_read(void *opaque
, uint32_t addr
)
290 VGAState
*s
= opaque
;
293 /* check port range access depending on color/monochrome mode */
294 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
295 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
))) {
300 if (s
->ar_flip_flop
== 0) {
307 index
= s
->ar_index
& 0x1f;
320 val
= s
->sr
[s
->sr_index
];
322 printf("vga: read SR%x = 0x%02x\n", s
->sr_index
, val
);
329 val
= s
->dac_write_index
;
332 val
= s
->palette
[s
->dac_read_index
* 3 + s
->dac_sub_index
];
333 if (++s
->dac_sub_index
== 3) {
334 s
->dac_sub_index
= 0;
348 val
= s
->gr
[s
->gr_index
];
350 printf("vga: read GR%x = 0x%02x\n", s
->gr_index
, val
);
359 val
= s
->cr
[s
->cr_index
];
361 printf("vga: read CR%x = 0x%02x\n", s
->cr_index
, val
);
366 /* just toggle to fool polling */
367 val
= s
->st01
= s
->retrace(s
);
375 #if defined(DEBUG_VGA)
376 printf("VGA: read addr=0x%04x data=0x%02x\n", addr
, val
);
381 static void vga_ioport_write(void *opaque
, uint32_t addr
, uint32_t val
)
383 VGAState
*s
= opaque
;
386 /* check port range access depending on color/monochrome mode */
387 if ((addr
>= 0x3b0 && addr
<= 0x3bf && (s
->msr
& MSR_COLOR_EMULATION
)) ||
388 (addr
>= 0x3d0 && addr
<= 0x3df && !(s
->msr
& MSR_COLOR_EMULATION
)))
392 printf("VGA: write addr=0x%04x data=0x%02x\n", addr
, val
);
397 if (s
->ar_flip_flop
== 0) {
401 index
= s
->ar_index
& 0x1f;
404 s
->ar
[index
] = val
& 0x3f;
407 s
->ar
[index
] = val
& ~0x10;
413 s
->ar
[index
] = val
& ~0xc0;
416 s
->ar
[index
] = val
& ~0xf0;
419 s
->ar
[index
] = val
& ~0xf0;
425 s
->ar_flip_flop
^= 1;
428 s
->msr
= val
& ~0x10;
429 s
->update_retrace_info(s
);
432 s
->sr_index
= val
& 7;
436 printf("vga: write SR%x = 0x%02x\n", s
->sr_index
, val
);
438 s
->sr
[s
->sr_index
] = val
& sr_mask
[s
->sr_index
];
439 if (s
->sr_index
== 1) s
->update_retrace_info(s
);
442 s
->dac_read_index
= val
;
443 s
->dac_sub_index
= 0;
447 s
->dac_write_index
= val
;
448 s
->dac_sub_index
= 0;
452 s
->dac_cache
[s
->dac_sub_index
] = val
;
453 if (++s
->dac_sub_index
== 3) {
454 memcpy(&s
->palette
[s
->dac_write_index
* 3], s
->dac_cache
, 3);
455 s
->dac_sub_index
= 0;
456 s
->dac_write_index
++;
460 s
->gr_index
= val
& 0x0f;
464 printf("vga: write GR%x = 0x%02x\n", s
->gr_index
, val
);
466 s
->gr
[s
->gr_index
] = val
& gr_mask
[s
->gr_index
];
475 printf("vga: write CR%x = 0x%02x\n", s
->cr_index
, val
);
477 /* handle CR0-7 protection */
478 if ((s
->cr
[0x11] & 0x80) && s
->cr_index
<= 7) {
479 /* can always write bit 4 of CR7 */
480 if (s
->cr_index
== 7)
481 s
->cr
[7] = (s
->cr
[7] & ~0x10) | (val
& 0x10);
484 switch(s
->cr_index
) {
485 case 0x01: /* horizontal display end */
490 case 0x12: /* vertical display end */
491 s
->cr
[s
->cr_index
] = val
;
494 s
->cr
[s
->cr_index
] = val
;
498 switch(s
->cr_index
) {
506 s
->update_retrace_info(s
);
517 #ifdef CONFIG_BOCHS_VBE
518 static uint32_t vbe_ioport_read_index(void *opaque
, uint32_t addr
)
520 VGAState
*s
= opaque
;
526 static uint32_t vbe_ioport_read_data(void *opaque
, uint32_t addr
)
528 VGAState
*s
= opaque
;
531 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
532 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_GETCAPS
) {
533 switch(s
->vbe_index
) {
534 /* XXX: do not hardcode ? */
535 case VBE_DISPI_INDEX_XRES
:
536 val
= VBE_DISPI_MAX_XRES
;
538 case VBE_DISPI_INDEX_YRES
:
539 val
= VBE_DISPI_MAX_YRES
;
541 case VBE_DISPI_INDEX_BPP
:
542 val
= VBE_DISPI_MAX_BPP
;
545 val
= s
->vbe_regs
[s
->vbe_index
];
549 val
= s
->vbe_regs
[s
->vbe_index
];
554 #ifdef DEBUG_BOCHS_VBE
555 printf("VBE: read index=0x%x val=0x%x\n", s
->vbe_index
, val
);
560 static void vbe_ioport_write_index(void *opaque
, uint32_t addr
, uint32_t val
)
562 VGAState
*s
= opaque
;
566 static void vbe_ioport_write_data(void *opaque
, uint32_t addr
, uint32_t val
)
568 VGAState
*s
= opaque
;
570 if (s
->vbe_index
<= VBE_DISPI_INDEX_NB
) {
571 #ifdef DEBUG_BOCHS_VBE
572 printf("VBE: write index=0x%x val=0x%x\n", s
->vbe_index
, val
);
574 switch(s
->vbe_index
) {
575 case VBE_DISPI_INDEX_ID
:
576 if (val
== VBE_DISPI_ID0
||
577 val
== VBE_DISPI_ID1
||
578 val
== VBE_DISPI_ID2
||
579 val
== VBE_DISPI_ID3
||
580 val
== VBE_DISPI_ID4
) {
581 s
->vbe_regs
[s
->vbe_index
] = val
;
584 case VBE_DISPI_INDEX_XRES
:
585 if ((val
<= VBE_DISPI_MAX_XRES
) && ((val
& 7) == 0)) {
586 s
->vbe_regs
[s
->vbe_index
] = val
;
589 case VBE_DISPI_INDEX_YRES
:
590 if (val
<= VBE_DISPI_MAX_YRES
) {
591 s
->vbe_regs
[s
->vbe_index
] = val
;
594 case VBE_DISPI_INDEX_BPP
:
597 if (val
== 4 || val
== 8 || val
== 15 ||
598 val
== 16 || val
== 24 || val
== 32) {
599 s
->vbe_regs
[s
->vbe_index
] = val
;
602 case VBE_DISPI_INDEX_BANK
:
603 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
604 val
&= (s
->vbe_bank_mask
>> 2);
606 val
&= s
->vbe_bank_mask
;
608 s
->vbe_regs
[s
->vbe_index
] = val
;
609 s
->bank_offset
= (val
<< 16);
611 case VBE_DISPI_INDEX_ENABLE
:
612 if ((val
& VBE_DISPI_ENABLED
) &&
613 !(s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
)) {
614 int h
, shift_control
;
616 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] =
617 s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
618 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] =
619 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
620 s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
] = 0;
621 s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
] = 0;
623 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
624 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 1;
626 s
->vbe_line_offset
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] *
627 ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
628 s
->vbe_start_addr
= 0;
630 /* clear the screen (should be done in BIOS) */
631 if (!(val
& VBE_DISPI_NOCLEARMEM
)) {
632 memset(s
->vram_ptr
, 0,
633 s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] * s
->vbe_line_offset
);
636 /* we initialize the VGA graphic mode (should be done
638 s
->gr
[0x06] = (s
->gr
[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
639 s
->cr
[0x17] |= 3; /* no CGA modes */
640 s
->cr
[0x13] = s
->vbe_line_offset
>> 3;
642 s
->cr
[0x01] = (s
->vbe_regs
[VBE_DISPI_INDEX_XRES
] >> 3) - 1;
643 /* height (only meaningful if < 1024) */
644 h
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
] - 1;
646 s
->cr
[0x07] = (s
->cr
[0x07] & ~0x42) |
647 ((h
>> 7) & 0x02) | ((h
>> 3) & 0x40);
648 /* line compare to 1023 */
653 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4) {
655 s
->sr
[0x01] &= ~8; /* no double line */
658 s
->sr
[4] |= 0x08; /* set chain 4 mode */
659 s
->sr
[2] |= 0x0f; /* activate all planes */
661 s
->gr
[0x05] = (s
->gr
[0x05] & ~0x60) | (shift_control
<< 5);
662 s
->cr
[0x09] &= ~0x9f; /* no double scan */
664 /* XXX: the bios should do that */
667 s
->dac_8bit
= (val
& VBE_DISPI_8BIT_DAC
) > 0;
668 s
->vbe_regs
[s
->vbe_index
] = val
;
670 case VBE_DISPI_INDEX_VIRT_WIDTH
:
672 int w
, h
, line_offset
;
674 if (val
< s
->vbe_regs
[VBE_DISPI_INDEX_XRES
])
677 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
678 line_offset
= w
>> 1;
680 line_offset
= w
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
681 h
= s
->vram_size
/ line_offset
;
682 /* XXX: support weird bochs semantics ? */
683 if (h
< s
->vbe_regs
[VBE_DISPI_INDEX_YRES
])
685 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_WIDTH
] = w
;
686 s
->vbe_regs
[VBE_DISPI_INDEX_VIRT_HEIGHT
] = h
;
687 s
->vbe_line_offset
= line_offset
;
690 case VBE_DISPI_INDEX_X_OFFSET
:
691 case VBE_DISPI_INDEX_Y_OFFSET
:
694 s
->vbe_regs
[s
->vbe_index
] = val
;
695 s
->vbe_start_addr
= s
->vbe_line_offset
* s
->vbe_regs
[VBE_DISPI_INDEX_Y_OFFSET
];
696 x
= s
->vbe_regs
[VBE_DISPI_INDEX_X_OFFSET
];
697 if (s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] == 4)
698 s
->vbe_start_addr
+= x
>> 1;
700 s
->vbe_start_addr
+= x
* ((s
->vbe_regs
[VBE_DISPI_INDEX_BPP
] + 7) >> 3);
701 s
->vbe_start_addr
>>= 2;
711 /* called for accesses between 0xa0000 and 0xc0000 */
712 uint32_t vga_mem_readb(void *opaque
, target_phys_addr_t addr
)
714 VGAState
*s
= opaque
;
715 int memory_map_mode
, plane
;
718 /* convert to VGA memory offset */
719 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
721 switch(memory_map_mode
) {
727 addr
+= s
->bank_offset
;
742 if (s
->sr
[4] & 0x08) {
743 /* chain 4 mode : simplest access */
744 ret
= s
->vram_ptr
[addr
];
745 } else if (s
->gr
[5] & 0x10) {
746 /* odd/even mode (aka text mode mapping) */
747 plane
= (s
->gr
[4] & 2) | (addr
& 1);
748 ret
= s
->vram_ptr
[((addr
& ~1) << 1) | plane
];
750 /* standard VGA latched access */
751 s
->latch
= ((uint32_t *)s
->vram_ptr
)[addr
];
753 if (!(s
->gr
[5] & 0x08)) {
756 ret
= GET_PLANE(s
->latch
, plane
);
759 ret
= (s
->latch
^ mask16
[s
->gr
[2]]) & mask16
[s
->gr
[7]];
768 static uint32_t vga_mem_readw(void *opaque
, target_phys_addr_t addr
)
771 #ifdef TARGET_WORDS_BIGENDIAN
772 v
= vga_mem_readb(opaque
, addr
) << 8;
773 v
|= vga_mem_readb(opaque
, addr
+ 1);
775 v
= vga_mem_readb(opaque
, addr
);
776 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
781 static uint32_t vga_mem_readl(void *opaque
, target_phys_addr_t addr
)
784 #ifdef TARGET_WORDS_BIGENDIAN
785 v
= vga_mem_readb(opaque
, addr
) << 24;
786 v
|= vga_mem_readb(opaque
, addr
+ 1) << 16;
787 v
|= vga_mem_readb(opaque
, addr
+ 2) << 8;
788 v
|= vga_mem_readb(opaque
, addr
+ 3);
790 v
= vga_mem_readb(opaque
, addr
);
791 v
|= vga_mem_readb(opaque
, addr
+ 1) << 8;
792 v
|= vga_mem_readb(opaque
, addr
+ 2) << 16;
793 v
|= vga_mem_readb(opaque
, addr
+ 3) << 24;
798 /* called for accesses between 0xa0000 and 0xc0000 */
799 void vga_mem_writeb(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
801 VGAState
*s
= opaque
;
802 int memory_map_mode
, plane
, write_mode
, b
, func_select
, mask
;
803 uint32_t write_mask
, bit_mask
, set_mask
;
806 printf("vga: [0x" TARGET_FMT_plx
"] = 0x%02x\n", addr
, val
);
808 /* convert to VGA memory offset */
809 memory_map_mode
= (s
->gr
[6] >> 2) & 3;
811 switch(memory_map_mode
) {
817 addr
+= s
->bank_offset
;
832 if (s
->sr
[4] & 0x08) {
833 /* chain 4 mode : simplest access */
836 if (s
->sr
[2] & mask
) {
837 s
->vram_ptr
[addr
] = val
;
839 printf("vga: chain4: [0x" TARGET_FMT_plx
"]\n", addr
);
841 s
->plane_updated
|= mask
; /* only used to detect font change */
842 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
844 } else if (s
->gr
[5] & 0x10) {
845 /* odd/even mode (aka text mode mapping) */
846 plane
= (s
->gr
[4] & 2) | (addr
& 1);
848 if (s
->sr
[2] & mask
) {
849 addr
= ((addr
& ~1) << 1) | plane
;
850 s
->vram_ptr
[addr
] = val
;
852 printf("vga: odd/even: [0x" TARGET_FMT_plx
"]\n", addr
);
854 s
->plane_updated
|= mask
; /* only used to detect font change */
855 cpu_physical_memory_set_dirty(s
->vram_offset
+ addr
);
858 /* standard VGA latched access */
859 write_mode
= s
->gr
[5] & 3;
865 val
= ((val
>> b
) | (val
<< (8 - b
))) & 0xff;
869 /* apply set/reset mask */
870 set_mask
= mask16
[s
->gr
[1]];
871 val
= (val
& ~set_mask
) | (mask16
[s
->gr
[0]] & set_mask
);
878 val
= mask16
[val
& 0x0f];
884 val
= (val
>> b
) | (val
<< (8 - b
));
886 bit_mask
= s
->gr
[8] & val
;
887 val
= mask16
[s
->gr
[0]];
891 /* apply logical operation */
892 func_select
= s
->gr
[3] >> 3;
893 switch(func_select
) {
913 bit_mask
|= bit_mask
<< 8;
914 bit_mask
|= bit_mask
<< 16;
915 val
= (val
& bit_mask
) | (s
->latch
& ~bit_mask
);
918 /* mask data according to sr[2] */
920 s
->plane_updated
|= mask
; /* only used to detect font change */
921 write_mask
= mask16
[mask
];
922 ((uint32_t *)s
->vram_ptr
)[addr
] =
923 (((uint32_t *)s
->vram_ptr
)[addr
] & ~write_mask
) |
926 printf("vga: latch: [0x" TARGET_FMT_plx
"] mask=0x%08x val=0x%08x\n",
927 addr
* 4, write_mask
, val
);
929 cpu_physical_memory_set_dirty(s
->vram_offset
+ (addr
<< 2));
933 static void vga_mem_writew(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
935 #ifdef TARGET_WORDS_BIGENDIAN
936 vga_mem_writeb(opaque
, addr
, (val
>> 8) & 0xff);
937 vga_mem_writeb(opaque
, addr
+ 1, val
& 0xff);
939 vga_mem_writeb(opaque
, addr
, val
& 0xff);
940 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
944 static void vga_mem_writel(void *opaque
, target_phys_addr_t addr
, uint32_t val
)
946 #ifdef TARGET_WORDS_BIGENDIAN
947 vga_mem_writeb(opaque
, addr
, (val
>> 24) & 0xff);
948 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 16) & 0xff);
949 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 8) & 0xff);
950 vga_mem_writeb(opaque
, addr
+ 3, val
& 0xff);
952 vga_mem_writeb(opaque
, addr
, val
& 0xff);
953 vga_mem_writeb(opaque
, addr
+ 1, (val
>> 8) & 0xff);
954 vga_mem_writeb(opaque
, addr
+ 2, (val
>> 16) & 0xff);
955 vga_mem_writeb(opaque
, addr
+ 3, (val
>> 24) & 0xff);
959 typedef void vga_draw_glyph8_func(uint8_t *d
, int linesize
,
960 const uint8_t *font_ptr
, int h
,
961 uint32_t fgcol
, uint32_t bgcol
);
962 typedef void vga_draw_glyph9_func(uint8_t *d
, int linesize
,
963 const uint8_t *font_ptr
, int h
,
964 uint32_t fgcol
, uint32_t bgcol
, int dup9
);
965 typedef void vga_draw_line_func(VGAState
*s1
, uint8_t *d
,
966 const uint8_t *s
, int width
);
969 #include "vga_template.h"
972 #include "vga_template.h"
976 #include "vga_template.h"
979 #include "vga_template.h"
983 #include "vga_template.h"
986 #include "vga_template.h"
990 #include "vga_template.h"
992 static unsigned int rgb_to_pixel8_dup(unsigned int r
, unsigned int g
, unsigned b
)
995 col
= rgb_to_pixel8(r
, g
, b
);
1001 static unsigned int rgb_to_pixel15_dup(unsigned int r
, unsigned int g
, unsigned b
)
1004 col
= rgb_to_pixel15(r
, g
, b
);
1009 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r
, unsigned int g
,
1013 col
= rgb_to_pixel15bgr(r
, g
, b
);
1018 static unsigned int rgb_to_pixel16_dup(unsigned int r
, unsigned int g
, unsigned b
)
1021 col
= rgb_to_pixel16(r
, g
, b
);
1026 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r
, unsigned int g
,
1030 col
= rgb_to_pixel16bgr(r
, g
, b
);
1035 static unsigned int rgb_to_pixel32_dup(unsigned int r
, unsigned int g
, unsigned b
)
1038 col
= rgb_to_pixel32(r
, g
, b
);
1042 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r
, unsigned int g
, unsigned b
)
1045 col
= rgb_to_pixel32bgr(r
, g
, b
);
1049 /* return true if the palette was modified */
1050 static int update_palette16(VGAState
*s
)
1053 uint32_t v
, col
, *palette
;
1056 palette
= s
->last_palette
;
1057 for(i
= 0; i
< 16; i
++) {
1059 if (s
->ar
[0x10] & 0x80)
1060 v
= ((s
->ar
[0x14] & 0xf) << 4) | (v
& 0xf);
1062 v
= ((s
->ar
[0x14] & 0xc) << 4) | (v
& 0x3f);
1064 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
1065 c6_to_8(s
->palette
[v
+ 1]),
1066 c6_to_8(s
->palette
[v
+ 2]));
1067 if (col
!= palette
[i
]) {
1075 /* return true if the palette was modified */
1076 static int update_palette256(VGAState
*s
)
1079 uint32_t v
, col
, *palette
;
1082 palette
= s
->last_palette
;
1084 for(i
= 0; i
< 256; i
++) {
1086 col
= s
->rgb_to_pixel(s
->palette
[v
],
1090 col
= s
->rgb_to_pixel(c6_to_8(s
->palette
[v
]),
1091 c6_to_8(s
->palette
[v
+ 1]),
1092 c6_to_8(s
->palette
[v
+ 2]));
1094 if (col
!= palette
[i
]) {
1103 static void vga_get_offsets(VGAState
*s
,
1104 uint32_t *pline_offset
,
1105 uint32_t *pstart_addr
,
1106 uint32_t *pline_compare
)
1108 uint32_t start_addr
, line_offset
, line_compare
;
1109 #ifdef CONFIG_BOCHS_VBE
1110 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1111 line_offset
= s
->vbe_line_offset
;
1112 start_addr
= s
->vbe_start_addr
;
1113 line_compare
= 65535;
1117 /* compute line_offset in bytes */
1118 line_offset
= s
->cr
[0x13];
1121 /* starting address */
1122 start_addr
= s
->cr
[0x0d] | (s
->cr
[0x0c] << 8);
1125 line_compare
= s
->cr
[0x18] |
1126 ((s
->cr
[0x07] & 0x10) << 4) |
1127 ((s
->cr
[0x09] & 0x40) << 3);
1129 *pline_offset
= line_offset
;
1130 *pstart_addr
= start_addr
;
1131 *pline_compare
= line_compare
;
1134 /* update start_addr and line_offset. Return TRUE if modified */
1135 static int update_basic_params(VGAState
*s
)
1138 uint32_t start_addr
, line_offset
, line_compare
;
1142 s
->get_offsets(s
, &line_offset
, &start_addr
, &line_compare
);
1144 if (line_offset
!= s
->line_offset
||
1145 start_addr
!= s
->start_addr
||
1146 line_compare
!= s
->line_compare
) {
1147 s
->line_offset
= line_offset
;
1148 s
->start_addr
= start_addr
;
1149 s
->line_compare
= line_compare
;
1157 static inline int get_depth_index(DisplayState
*s
)
1159 switch(ds_get_bits_per_pixel(s
)) {
1168 if (is_surface_bgr(s
->surface
))
1175 static vga_draw_glyph8_func
*vga_draw_glyph8_table
[NB_DEPTHS
] = {
1185 static vga_draw_glyph8_func
*vga_draw_glyph16_table
[NB_DEPTHS
] = {
1187 vga_draw_glyph16_16
,
1188 vga_draw_glyph16_16
,
1189 vga_draw_glyph16_32
,
1190 vga_draw_glyph16_32
,
1191 vga_draw_glyph16_16
,
1192 vga_draw_glyph16_16
,
1195 static vga_draw_glyph9_func
*vga_draw_glyph9_table
[NB_DEPTHS
] = {
1205 static const uint8_t cursor_glyph
[32 * 4] = {
1206 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224 static void vga_get_text_resolution(VGAState
*s
, int *pwidth
, int *pheight
,
1225 int *pcwidth
, int *pcheight
)
1227 int width
, cwidth
, height
, cheight
;
1229 /* total width & height */
1230 cheight
= (s
->cr
[9] & 0x1f) + 1;
1232 if (!(s
->sr
[1] & 0x01))
1234 if (s
->sr
[1] & 0x08)
1235 cwidth
= 16; /* NOTE: no 18 pixel wide */
1236 width
= (s
->cr
[0x01] + 1);
1237 if (s
->cr
[0x06] == 100) {
1238 /* ugly hack for CGA 160x100x16 - explain me the logic */
1241 height
= s
->cr
[0x12] |
1242 ((s
->cr
[0x07] & 0x02) << 7) |
1243 ((s
->cr
[0x07] & 0x40) << 3);
1244 height
= (height
+ 1) / cheight
;
1250 *pcheight
= cheight
;
1253 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r
, unsigned int g
, unsigned b
);
1255 static rgb_to_pixel_dup_func
*rgb_to_pixel_dup_table
[NB_DEPTHS
] = {
1260 rgb_to_pixel32bgr_dup
,
1261 rgb_to_pixel15bgr_dup
,
1262 rgb_to_pixel16bgr_dup
,
1273 static void vga_draw_text(VGAState
*s
, int full_update
)
1275 int cx
, cy
, cheight
, cw
, ch
, cattr
, height
, width
, ch_attr
;
1276 int cx_min
, cx_max
, linesize
, x_incr
;
1277 uint32_t offset
, fgcol
, bgcol
, v
, cursor_offset
;
1278 uint8_t *d1
, *d
, *src
, *s1
, *dest
, *cursor_ptr
;
1279 const uint8_t *font_ptr
, *font_base
[2];
1280 int dup9
, line_offset
, depth_index
;
1282 uint32_t *ch_attr_ptr
;
1283 vga_draw_glyph8_func
*vga_draw_glyph8
;
1284 vga_draw_glyph9_func
*vga_draw_glyph9
;
1286 /* compute font data address (in plane 2) */
1288 offset
= (((v
>> 4) & 1) | ((v
<< 1) & 6)) * 8192 * 4 + 2;
1289 if (offset
!= s
->font_offsets
[0]) {
1290 s
->font_offsets
[0] = offset
;
1293 font_base
[0] = s
->vram_ptr
+ offset
;
1295 offset
= (((v
>> 5) & 1) | ((v
>> 1) & 6)) * 8192 * 4 + 2;
1296 font_base
[1] = s
->vram_ptr
+ offset
;
1297 if (offset
!= s
->font_offsets
[1]) {
1298 s
->font_offsets
[1] = offset
;
1301 if (s
->plane_updated
& (1 << 2)) {
1302 /* if the plane 2 was modified since the last display, it
1303 indicates the font may have been modified */
1304 s
->plane_updated
= 0;
1307 full_update
|= update_basic_params(s
);
1309 line_offset
= s
->line_offset
;
1310 s1
= s
->vram_ptr
+ (s
->start_addr
* 4);
1312 vga_get_text_resolution(s
, &width
, &height
, &cw
, &cheight
);
1313 x_incr
= cw
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1314 if ((height
* width
) > CH_ATTR_SIZE
) {
1315 /* better than nothing: exit if transient size is too big */
1319 if (width
!= s
->last_width
|| height
!= s
->last_height
||
1320 cw
!= s
->last_cw
|| cheight
!= s
->last_ch
|| s
->last_depth
) {
1321 s
->last_scr_width
= width
* cw
;
1322 s
->last_scr_height
= height
* cheight
;
1323 qemu_console_resize(s
->ds
, s
->last_scr_width
, s
->last_scr_height
);
1325 s
->last_width
= width
;
1326 s
->last_height
= height
;
1327 s
->last_ch
= cheight
;
1332 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1333 full_update
|= update_palette16(s
);
1334 palette
= s
->last_palette
;
1335 x_incr
= cw
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1337 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
1338 if (cursor_offset
!= s
->cursor_offset
||
1339 s
->cr
[0xa] != s
->cursor_start
||
1340 s
->cr
[0xb] != s
->cursor_end
) {
1341 /* if the cursor position changed, we update the old and new
1343 if (s
->cursor_offset
< CH_ATTR_SIZE
)
1344 s
->last_ch_attr
[s
->cursor_offset
] = -1;
1345 if (cursor_offset
< CH_ATTR_SIZE
)
1346 s
->last_ch_attr
[cursor_offset
] = -1;
1347 s
->cursor_offset
= cursor_offset
;
1348 s
->cursor_start
= s
->cr
[0xa];
1349 s
->cursor_end
= s
->cr
[0xb];
1351 cursor_ptr
= s
->vram_ptr
+ (s
->start_addr
+ cursor_offset
) * 4;
1353 depth_index
= get_depth_index(s
->ds
);
1355 vga_draw_glyph8
= vga_draw_glyph16_table
[depth_index
];
1357 vga_draw_glyph8
= vga_draw_glyph8_table
[depth_index
];
1358 vga_draw_glyph9
= vga_draw_glyph9_table
[depth_index
];
1360 dest
= ds_get_data(s
->ds
);
1361 linesize
= ds_get_linesize(s
->ds
);
1362 ch_attr_ptr
= s
->last_ch_attr
;
1363 for(cy
= 0; cy
< height
; cy
++) {
1368 for(cx
= 0; cx
< width
; cx
++) {
1369 ch_attr
= *(uint16_t *)src
;
1370 if (full_update
|| ch_attr
!= *ch_attr_ptr
) {
1375 *ch_attr_ptr
= ch_attr
;
1376 #ifdef HOST_WORDS_BIGENDIAN
1378 cattr
= ch_attr
& 0xff;
1380 ch
= ch_attr
& 0xff;
1381 cattr
= ch_attr
>> 8;
1383 font_ptr
= font_base
[(cattr
>> 3) & 1];
1384 font_ptr
+= 32 * 4 * ch
;
1385 bgcol
= palette
[cattr
>> 4];
1386 fgcol
= palette
[cattr
& 0x0f];
1388 vga_draw_glyph8(d1
, linesize
,
1389 font_ptr
, cheight
, fgcol
, bgcol
);
1392 if (ch
>= 0xb0 && ch
<= 0xdf && (s
->ar
[0x10] & 0x04))
1394 vga_draw_glyph9(d1
, linesize
,
1395 font_ptr
, cheight
, fgcol
, bgcol
, dup9
);
1397 if (src
== cursor_ptr
&&
1398 !(s
->cr
[0x0a] & 0x20)) {
1399 int line_start
, line_last
, h
;
1400 /* draw the cursor */
1401 line_start
= s
->cr
[0x0a] & 0x1f;
1402 line_last
= s
->cr
[0x0b] & 0x1f;
1403 /* XXX: check that */
1404 if (line_last
> cheight
- 1)
1405 line_last
= cheight
- 1;
1406 if (line_last
>= line_start
&& line_start
< cheight
) {
1407 h
= line_last
- line_start
+ 1;
1408 d
= d1
+ linesize
* line_start
;
1410 vga_draw_glyph8(d
, linesize
,
1411 cursor_glyph
, h
, fgcol
, bgcol
);
1413 vga_draw_glyph9(d
, linesize
,
1414 cursor_glyph
, h
, fgcol
, bgcol
, 1);
1424 dpy_update(s
->ds
, cx_min
* cw
, cy
* cheight
,
1425 (cx_max
- cx_min
+ 1) * cw
, cheight
);
1427 dest
+= linesize
* cheight
;
1446 static vga_draw_line_func
*vga_draw_line_table
[NB_DEPTHS
* VGA_DRAW_LINE_NB
] = {
1456 vga_draw_line2d2_16
,
1457 vga_draw_line2d2_16
,
1458 vga_draw_line2d2_32
,
1459 vga_draw_line2d2_32
,
1460 vga_draw_line2d2_16
,
1461 vga_draw_line2d2_16
,
1472 vga_draw_line4d2_16
,
1473 vga_draw_line4d2_16
,
1474 vga_draw_line4d2_32
,
1475 vga_draw_line4d2_32
,
1476 vga_draw_line4d2_16
,
1477 vga_draw_line4d2_16
,
1480 vga_draw_line8d2_16
,
1481 vga_draw_line8d2_16
,
1482 vga_draw_line8d2_32
,
1483 vga_draw_line8d2_32
,
1484 vga_draw_line8d2_16
,
1485 vga_draw_line8d2_16
,
1499 vga_draw_line15_32bgr
,
1500 vga_draw_line15_15bgr
,
1501 vga_draw_line15_16bgr
,
1507 vga_draw_line16_32bgr
,
1508 vga_draw_line16_15bgr
,
1509 vga_draw_line16_16bgr
,
1515 vga_draw_line24_32bgr
,
1516 vga_draw_line24_15bgr
,
1517 vga_draw_line24_16bgr
,
1523 vga_draw_line32_32bgr
,
1524 vga_draw_line32_15bgr
,
1525 vga_draw_line32_16bgr
,
1528 static int vga_get_bpp(VGAState
*s
)
1531 #ifdef CONFIG_BOCHS_VBE
1532 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1533 ret
= s
->vbe_regs
[VBE_DISPI_INDEX_BPP
];
1542 static void vga_get_resolution(VGAState
*s
, int *pwidth
, int *pheight
)
1546 #ifdef CONFIG_BOCHS_VBE
1547 if (s
->vbe_regs
[VBE_DISPI_INDEX_ENABLE
] & VBE_DISPI_ENABLED
) {
1548 width
= s
->vbe_regs
[VBE_DISPI_INDEX_XRES
];
1549 height
= s
->vbe_regs
[VBE_DISPI_INDEX_YRES
];
1553 width
= (s
->cr
[0x01] + 1) * 8;
1554 height
= s
->cr
[0x12] |
1555 ((s
->cr
[0x07] & 0x02) << 7) |
1556 ((s
->cr
[0x07] & 0x40) << 3);
1557 height
= (height
+ 1);
1563 void vga_invalidate_scanlines(VGAState
*s
, int y1
, int y2
)
1566 if (y1
>= VGA_MAX_HEIGHT
)
1568 if (y2
>= VGA_MAX_HEIGHT
)
1569 y2
= VGA_MAX_HEIGHT
;
1570 for(y
= y1
; y
< y2
; y
++) {
1571 s
->invalidated_y_table
[y
>> 5] |= 1 << (y
& 0x1f);
1575 static void vga_sync_dirty_bitmap(VGAState
*s
)
1578 cpu_physical_sync_dirty_bitmap(s
->map_addr
, s
->map_end
);
1580 if (s
->lfb_vram_mapped
) {
1581 cpu_physical_sync_dirty_bitmap(isa_mem_base
+ 0xa0000, 0xa8000);
1582 cpu_physical_sync_dirty_bitmap(isa_mem_base
+ 0xa8000, 0xb0000);
1589 static void vga_draw_graphic(VGAState
*s
, int full_update
)
1591 int y1
, y
, update
, linesize
, y_start
, double_scan
, mask
, depth
;
1592 int width
, height
, shift_control
, line_offset
, bwidth
, bits
;
1593 ram_addr_t page0
, page1
, page_min
, page_max
;
1594 int disp_width
, multi_scan
, multi_run
;
1596 uint32_t v
, addr1
, addr
;
1597 vga_draw_line_func
*vga_draw_line
;
1599 full_update
|= update_basic_params(s
);
1602 vga_sync_dirty_bitmap(s
);
1604 s
->get_resolution(s
, &width
, &height
);
1607 shift_control
= (s
->gr
[0x05] >> 5) & 3;
1608 double_scan
= (s
->cr
[0x09] >> 7);
1609 if (shift_control
!= 1) {
1610 multi_scan
= (((s
->cr
[0x09] & 0x1f) + 1) << double_scan
) - 1;
1612 /* in CGA modes, multi_scan is ignored */
1613 /* XXX: is it correct ? */
1614 multi_scan
= double_scan
;
1616 multi_run
= multi_scan
;
1617 if (shift_control
!= s
->shift_control
||
1618 double_scan
!= s
->double_scan
) {
1620 s
->shift_control
= shift_control
;
1621 s
->double_scan
= double_scan
;
1624 if (shift_control
== 0) {
1625 if (s
->sr
[0x01] & 8) {
1628 } else if (shift_control
== 1) {
1629 if (s
->sr
[0x01] & 8) {
1634 depth
= s
->get_bpp(s
);
1635 if (s
->line_offset
!= s
->last_line_offset
||
1636 disp_width
!= s
->last_width
||
1637 height
!= s
->last_height
||
1638 s
->last_depth
!= depth
) {
1639 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1640 if (depth
== 16 || depth
== 32) {
1644 qemu_free_displaysurface(s
->ds
);
1645 s
->ds
->surface
= qemu_create_displaysurface_from(disp_width
, height
, depth
,
1647 s
->vram_ptr
+ (s
->start_addr
* 4));
1648 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1649 s
->ds
->surface
->pf
= qemu_different_endianness_pixelformat(depth
);
1653 qemu_console_resize(s
->ds
, disp_width
, height
);
1655 s
->last_scr_width
= disp_width
;
1656 s
->last_scr_height
= height
;
1657 s
->last_width
= disp_width
;
1658 s
->last_height
= height
;
1659 s
->last_line_offset
= s
->line_offset
;
1660 s
->last_depth
= depth
;
1662 } else if (is_buffer_shared(s
->ds
->surface
) &&
1663 (full_update
|| s
->ds
->surface
->data
!= s
->vram_ptr
+ (s
->start_addr
* 4))) {
1664 s
->ds
->surface
->data
= s
->vram_ptr
+ (s
->start_addr
* 4);
1669 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1671 if (shift_control
== 0) {
1672 full_update
|= update_palette16(s
);
1673 if (s
->sr
[0x01] & 8) {
1674 v
= VGA_DRAW_LINE4D2
;
1679 } else if (shift_control
== 1) {
1680 full_update
|= update_palette16(s
);
1681 if (s
->sr
[0x01] & 8) {
1682 v
= VGA_DRAW_LINE2D2
;
1688 switch(s
->get_bpp(s
)) {
1691 full_update
|= update_palette256(s
);
1692 v
= VGA_DRAW_LINE8D2
;
1696 full_update
|= update_palette256(s
);
1701 v
= VGA_DRAW_LINE15
;
1705 v
= VGA_DRAW_LINE16
;
1709 v
= VGA_DRAW_LINE24
;
1713 v
= VGA_DRAW_LINE32
;
1718 vga_draw_line
= vga_draw_line_table
[v
* NB_DEPTHS
+ get_depth_index(s
->ds
)];
1720 if (!is_buffer_shared(s
->ds
->surface
) && s
->cursor_invalidate
)
1721 s
->cursor_invalidate(s
);
1723 line_offset
= s
->line_offset
;
1725 printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1726 width
, height
, v
, line_offset
, s
->cr
[9], s
->cr
[0x17], s
->line_compare
, s
->sr
[0x01]);
1728 addr1
= (s
->start_addr
* 4);
1729 bwidth
= (width
* bits
+ 7) / 8;
1733 d
= ds_get_data(s
->ds
);
1734 linesize
= ds_get_linesize(s
->ds
);
1736 for(y
= 0; y
< height
; y
++) {
1738 if (!(s
->cr
[0x17] & 1)) {
1740 /* CGA compatibility handling */
1741 shift
= 14 + ((s
->cr
[0x17] >> 6) & 1);
1742 addr
= (addr
& ~(1 << shift
)) | ((y1
& 1) << shift
);
1744 if (!(s
->cr
[0x17] & 2)) {
1745 addr
= (addr
& ~0x8000) | ((y1
& 2) << 14);
1747 page0
= s
->vram_offset
+ (addr
& TARGET_PAGE_MASK
);
1748 page1
= s
->vram_offset
+ ((addr
+ bwidth
- 1) & TARGET_PAGE_MASK
);
1749 update
= full_update
|
1750 cpu_physical_memory_get_dirty(page0
, VGA_DIRTY_FLAG
) |
1751 cpu_physical_memory_get_dirty(page1
, VGA_DIRTY_FLAG
);
1752 if ((page1
- page0
) > TARGET_PAGE_SIZE
) {
1753 /* if wide line, can use another page */
1754 update
|= cpu_physical_memory_get_dirty(page0
+ TARGET_PAGE_SIZE
,
1757 /* explicit invalidation for the hardware cursor */
1758 update
|= (s
->invalidated_y_table
[y
>> 5] >> (y
& 0x1f)) & 1;
1762 if (page0
< page_min
)
1764 if (page1
> page_max
)
1766 if (!(is_buffer_shared(s
->ds
->surface
))) {
1767 vga_draw_line(s
, d
, s
->vram_ptr
+ addr
, width
);
1768 if (s
->cursor_draw_line
)
1769 s
->cursor_draw_line(s
, d
, y
);
1773 /* flush to display */
1774 dpy_update(s
->ds
, 0, y_start
,
1775 disp_width
, y
- y_start
);
1780 mask
= (s
->cr
[0x17] & 3) ^ 3;
1781 if ((y1
& mask
) == mask
)
1782 addr1
+= line_offset
;
1784 multi_run
= multi_scan
;
1788 /* line compare acts on the displayed lines */
1789 if (y
== s
->line_compare
)
1794 /* flush to display */
1795 dpy_update(s
->ds
, 0, y_start
,
1796 disp_width
, y
- y_start
);
1798 /* reset modified pages */
1799 if (page_max
>= page_min
) {
1800 cpu_physical_memory_reset_dirty(page_min
, page_max
+ TARGET_PAGE_SIZE
,
1803 memset(s
->invalidated_y_table
, 0, ((height
+ 31) >> 5) * 4);
1806 static void vga_draw_blank(VGAState
*s
, int full_update
)
1813 if (s
->last_scr_width
<= 0 || s
->last_scr_height
<= 0)
1817 rgb_to_pixel_dup_table
[get_depth_index(s
->ds
)];
1818 if (ds_get_bits_per_pixel(s
->ds
) == 8)
1819 val
= s
->rgb_to_pixel(0, 0, 0);
1822 w
= s
->last_scr_width
* ((ds_get_bits_per_pixel(s
->ds
) + 7) >> 3);
1823 d
= ds_get_data(s
->ds
);
1824 for(i
= 0; i
< s
->last_scr_height
; i
++) {
1826 d
+= ds_get_linesize(s
->ds
);
1828 dpy_update(s
->ds
, 0, 0,
1829 s
->last_scr_width
, s
->last_scr_height
);
1832 #define GMODE_TEXT 0
1833 #define GMODE_GRAPH 1
1834 #define GMODE_BLANK 2
1836 static void vga_update_display(void *opaque
)
1838 VGAState
*s
= (VGAState
*)opaque
;
1839 int full_update
, graphic_mode
;
1841 if (ds_get_bits_per_pixel(s
->ds
) == 0) {
1844 full_update
= s
->full_update
;
1846 if (!(s
->ar_index
& 0x20)) {
1847 graphic_mode
= GMODE_BLANK
;
1849 graphic_mode
= s
->gr
[6] & 1;
1851 if (graphic_mode
!= s
->graphic_mode
) {
1852 s
->graphic_mode
= graphic_mode
;
1855 switch(graphic_mode
) {
1857 vga_draw_text(s
, full_update
);
1860 vga_draw_graphic(s
, full_update
);
1864 vga_draw_blank(s
, full_update
);
1870 /* force a full display refresh */
1871 static void vga_invalidate_display(void *opaque
)
1873 VGAState
*s
= (VGAState
*)opaque
;
1878 void vga_common_reset(VGACommonState
*s
)
1884 s
->lfb_vram_mapped
= 0;
1888 memset(s
->sr
, '\0', sizeof(s
->sr
));
1890 memset(s
->gr
, '\0', sizeof(s
->gr
));
1892 memset(s
->ar
, '\0', sizeof(s
->ar
));
1893 s
->ar_flip_flop
= 0;
1895 memset(s
->cr
, '\0', sizeof(s
->cr
));
1901 s
->dac_sub_index
= 0;
1902 s
->dac_read_index
= 0;
1903 s
->dac_write_index
= 0;
1904 memset(s
->dac_cache
, '\0', sizeof(s
->dac_cache
));
1906 memset(s
->palette
, '\0', sizeof(s
->palette
));
1908 #ifdef CONFIG_BOCHS_VBE
1910 memset(s
->vbe_regs
, '\0', sizeof(s
->vbe_regs
));
1911 s
->vbe_regs
[VBE_DISPI_INDEX_ID
] = VBE_DISPI_ID0
;
1912 s
->vbe_start_addr
= 0;
1913 s
->vbe_line_offset
= 0;
1914 s
->vbe_bank_mask
= (s
->vram_size
>> 16) - 1;
1916 memset(s
->font_offsets
, '\0', sizeof(s
->font_offsets
));
1917 s
->graphic_mode
= -1; /* force full update */
1918 s
->shift_control
= 0;
1921 s
->line_compare
= 0;
1923 s
->plane_updated
= 0;
1928 s
->last_scr_width
= 0;
1929 s
->last_scr_height
= 0;
1930 s
->cursor_start
= 0;
1932 s
->cursor_offset
= 0;
1933 memset(s
->invalidated_y_table
, '\0', sizeof(s
->invalidated_y_table
));
1934 memset(s
->last_palette
, '\0', sizeof(s
->last_palette
));
1935 memset(s
->last_ch_attr
, '\0', sizeof(s
->last_ch_attr
));
1936 switch (vga_retrace_method
) {
1937 case VGA_RETRACE_DUMB
:
1939 case VGA_RETRACE_PRECISE
:
1940 memset(&s
->retrace_info
, 0, sizeof (s
->retrace_info
));
1945 static void vga_reset(void *opaque
)
1947 VGAState
*s
= (VGAState
*) opaque
;
1948 vga_common_reset(s
);
1951 #define TEXTMODE_X(x) ((x) % width)
1952 #define TEXTMODE_Y(x) ((x) / width)
1953 #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1954 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1955 /* relay text rendering to the display driver
1956 * instead of doing a full vga_update_display() */
1957 static void vga_update_text(void *opaque
, console_ch_t
*chardata
)
1959 VGAState
*s
= (VGAState
*) opaque
;
1960 int graphic_mode
, i
, cursor_offset
, cursor_visible
;
1961 int cw
, cheight
, width
, height
, size
, c_min
, c_max
;
1963 console_ch_t
*dst
, val
;
1964 char msg_buffer
[80];
1965 int full_update
= 0;
1967 if (!(s
->ar_index
& 0x20)) {
1968 graphic_mode
= GMODE_BLANK
;
1970 graphic_mode
= s
->gr
[6] & 1;
1972 if (graphic_mode
!= s
->graphic_mode
) {
1973 s
->graphic_mode
= graphic_mode
;
1976 if (s
->last_width
== -1) {
1981 switch (graphic_mode
) {
1983 /* TODO: update palette */
1984 full_update
|= update_basic_params(s
);
1986 /* total width & height */
1987 cheight
= (s
->cr
[9] & 0x1f) + 1;
1989 if (!(s
->sr
[1] & 0x01))
1991 if (s
->sr
[1] & 0x08)
1992 cw
= 16; /* NOTE: no 18 pixel wide */
1993 width
= (s
->cr
[0x01] + 1);
1994 if (s
->cr
[0x06] == 100) {
1995 /* ugly hack for CGA 160x100x16 - explain me the logic */
1998 height
= s
->cr
[0x12] |
1999 ((s
->cr
[0x07] & 0x02) << 7) |
2000 ((s
->cr
[0x07] & 0x40) << 3);
2001 height
= (height
+ 1) / cheight
;
2004 size
= (height
* width
);
2005 if (size
> CH_ATTR_SIZE
) {
2009 snprintf(msg_buffer
, sizeof(msg_buffer
), "%i x %i Text mode",
2014 if (width
!= s
->last_width
|| height
!= s
->last_height
||
2015 cw
!= s
->last_cw
|| cheight
!= s
->last_ch
) {
2016 s
->last_scr_width
= width
* cw
;
2017 s
->last_scr_height
= height
* cheight
;
2018 s
->ds
->surface
->width
= width
;
2019 s
->ds
->surface
->height
= height
;
2021 s
->last_width
= width
;
2022 s
->last_height
= height
;
2023 s
->last_ch
= cheight
;
2028 /* Update "hardware" cursor */
2029 cursor_offset
= ((s
->cr
[0x0e] << 8) | s
->cr
[0x0f]) - s
->start_addr
;
2030 if (cursor_offset
!= s
->cursor_offset
||
2031 s
->cr
[0xa] != s
->cursor_start
||
2032 s
->cr
[0xb] != s
->cursor_end
|| full_update
) {
2033 cursor_visible
= !(s
->cr
[0xa] & 0x20);
2034 if (cursor_visible
&& cursor_offset
< size
&& cursor_offset
>= 0)
2036 TEXTMODE_X(cursor_offset
),
2037 TEXTMODE_Y(cursor_offset
));
2039 dpy_cursor(s
->ds
, -1, -1);
2040 s
->cursor_offset
= cursor_offset
;
2041 s
->cursor_start
= s
->cr
[0xa];
2042 s
->cursor_end
= s
->cr
[0xb];
2045 src
= (uint32_t *) s
->vram_ptr
+ s
->start_addr
;
2049 for (i
= 0; i
< size
; src
++, dst
++, i
++)
2050 console_write_ch(dst
, VMEM2CHTYPE(*src
));
2052 dpy_update(s
->ds
, 0, 0, width
, height
);
2056 for (i
= 0; i
< size
; src
++, dst
++, i
++) {
2057 console_write_ch(&val
, VMEM2CHTYPE(*src
));
2065 for (; i
< size
; src
++, dst
++, i
++) {
2066 console_write_ch(&val
, VMEM2CHTYPE(*src
));
2073 if (c_min
<= c_max
) {
2074 i
= TEXTMODE_Y(c_min
);
2075 dpy_update(s
->ds
, 0, i
, width
, TEXTMODE_Y(c_max
) - i
+ 1);
2084 s
->get_resolution(s
, &width
, &height
);
2085 snprintf(msg_buffer
, sizeof(msg_buffer
), "%i x %i Graphic mode",
2093 snprintf(msg_buffer
, sizeof(msg_buffer
), "VGA Blank mode");
2097 /* Display a message */
2099 s
->last_height
= height
= 3;
2100 dpy_cursor(s
->ds
, -1, -1);
2101 s
->ds
->surface
->width
= s
->last_width
;
2102 s
->ds
->surface
->height
= height
;
2105 for (dst
= chardata
, i
= 0; i
< s
->last_width
* height
; i
++)
2106 console_write_ch(dst
++, ' ');
2108 size
= strlen(msg_buffer
);
2109 width
= (s
->last_width
- size
) / 2;
2110 dst
= chardata
+ s
->last_width
+ width
;
2111 for (i
= 0; i
< size
; i
++)
2112 console_write_ch(dst
++, 0x00200100 | msg_buffer
[i
]);
2114 dpy_update(s
->ds
, 0, 0, s
->last_width
, height
);
2117 static CPUReadMemoryFunc
* const vga_mem_read
[3] = {
2123 static CPUWriteMemoryFunc
* const vga_mem_write
[3] = {
2129 static void vga_save(QEMUFile
*f
, void *opaque
)
2131 VGAState
*s
= opaque
;
2135 pci_device_save(s
->pci_dev
, f
);
2137 qemu_put_be32s(f
, &s
->latch
);
2138 qemu_put_8s(f
, &s
->sr_index
);
2139 qemu_put_buffer(f
, s
->sr
, 8);
2140 qemu_put_8s(f
, &s
->gr_index
);
2141 qemu_put_buffer(f
, s
->gr
, 16);
2142 qemu_put_8s(f
, &s
->ar_index
);
2143 qemu_put_buffer(f
, s
->ar
, 21);
2144 qemu_put_be32(f
, s
->ar_flip_flop
);
2145 qemu_put_8s(f
, &s
->cr_index
);
2146 qemu_put_buffer(f
, s
->cr
, 256);
2147 qemu_put_8s(f
, &s
->msr
);
2148 qemu_put_8s(f
, &s
->fcr
);
2149 qemu_put_byte(f
, s
->st00
);
2150 qemu_put_8s(f
, &s
->st01
);
2152 qemu_put_8s(f
, &s
->dac_state
);
2153 qemu_put_8s(f
, &s
->dac_sub_index
);
2154 qemu_put_8s(f
, &s
->dac_read_index
);
2155 qemu_put_8s(f
, &s
->dac_write_index
);
2156 qemu_put_buffer(f
, s
->dac_cache
, 3);
2157 qemu_put_buffer(f
, s
->palette
, 768);
2159 qemu_put_be32(f
, s
->bank_offset
);
2160 #ifdef CONFIG_BOCHS_VBE
2161 qemu_put_byte(f
, 1);
2162 qemu_put_be16s(f
, &s
->vbe_index
);
2163 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
2164 qemu_put_be16s(f
, &s
->vbe_regs
[i
]);
2165 qemu_put_be32s(f
, &s
->vbe_start_addr
);
2166 qemu_put_be32s(f
, &s
->vbe_line_offset
);
2167 qemu_put_be32s(f
, &s
->vbe_bank_mask
);
2169 qemu_put_byte(f
, 0);
2173 static int vga_load(QEMUFile
*f
, void *opaque
, int version_id
)
2175 VGAState
*s
= opaque
;
2181 if (s
->pci_dev
&& version_id
>= 2) {
2182 ret
= pci_device_load(s
->pci_dev
, f
);
2187 qemu_get_be32s(f
, &s
->latch
);
2188 qemu_get_8s(f
, &s
->sr_index
);
2189 qemu_get_buffer(f
, s
->sr
, 8);
2190 qemu_get_8s(f
, &s
->gr_index
);
2191 qemu_get_buffer(f
, s
->gr
, 16);
2192 qemu_get_8s(f
, &s
->ar_index
);
2193 qemu_get_buffer(f
, s
->ar
, 21);
2194 s
->ar_flip_flop
=qemu_get_be32(f
);
2195 qemu_get_8s(f
, &s
->cr_index
);
2196 qemu_get_buffer(f
, s
->cr
, 256);
2197 qemu_get_8s(f
, &s
->msr
);
2198 qemu_get_8s(f
, &s
->fcr
);
2199 qemu_get_8s(f
, &s
->st00
);
2200 qemu_get_8s(f
, &s
->st01
);
2202 qemu_get_8s(f
, &s
->dac_state
);
2203 qemu_get_8s(f
, &s
->dac_sub_index
);
2204 qemu_get_8s(f
, &s
->dac_read_index
);
2205 qemu_get_8s(f
, &s
->dac_write_index
);
2206 qemu_get_buffer(f
, s
->dac_cache
, 3);
2207 qemu_get_buffer(f
, s
->palette
, 768);
2209 s
->bank_offset
=qemu_get_be32(f
);
2210 is_vbe
= qemu_get_byte(f
);
2211 #ifdef CONFIG_BOCHS_VBE
2214 qemu_get_be16s(f
, &s
->vbe_index
);
2215 for(i
= 0; i
< VBE_DISPI_INDEX_NB
; i
++)
2216 qemu_get_be16s(f
, &s
->vbe_regs
[i
]);
2217 qemu_get_be32s(f
, &s
->vbe_start_addr
);
2218 qemu_get_be32s(f
, &s
->vbe_line_offset
);
2219 qemu_get_be32s(f
, &s
->vbe_bank_mask
);
2226 s
->graphic_mode
= -1;
2230 typedef struct PCIVGAState
{
2235 void vga_dirty_log_start(VGAState
*s
)
2237 if (kvm_enabled() && s
->map_addr
)
2238 kvm_log_start(s
->map_addr
, s
->map_end
- s
->map_addr
);
2240 if (kvm_enabled() && s
->lfb_vram_mapped
) {
2241 kvm_log_start(isa_mem_base
+ 0xa0000, 0x8000);
2242 kvm_log_start(isa_mem_base
+ 0xa8000, 0x8000);
2246 static void vga_map(PCIDevice
*pci_dev
, int region_num
,
2247 uint32_t addr
, uint32_t size
, int type
)
2249 PCIVGAState
*d
= (PCIVGAState
*)pci_dev
;
2250 VGAState
*s
= &d
->vga
;
2251 if (region_num
== PCI_ROM_SLOT
) {
2252 cpu_register_physical_memory(addr
, s
->bios_size
, s
->bios_offset
);
2254 cpu_register_physical_memory(addr
, s
->vram_size
, s
->vram_offset
);
2256 s
->map_end
= addr
+ s
->vram_size
;
2257 vga_dirty_log_start(s
);
2261 void vga_common_init(VGACommonState
*s
, int vga_ram_size
)
2265 for(i
= 0;i
< 256; i
++) {
2267 for(j
= 0; j
< 8; j
++) {
2268 v
|= ((i
>> j
) & 1) << (j
* 4);
2273 for(j
= 0; j
< 4; j
++) {
2274 v
|= ((i
>> (2 * j
)) & 3) << (j
* 4);
2278 for(i
= 0; i
< 16; i
++) {
2280 for(j
= 0; j
< 4; j
++) {
2283 v
|= b
<< (2 * j
+ 1);
2288 s
->vram_offset
= qemu_ram_alloc(vga_ram_size
);
2289 s
->vram_ptr
= qemu_get_ram_ptr(s
->vram_offset
);
2290 s
->vram_size
= vga_ram_size
;
2291 s
->get_bpp
= vga_get_bpp
;
2292 s
->get_offsets
= vga_get_offsets
;
2293 s
->get_resolution
= vga_get_resolution
;
2294 s
->update
= vga_update_display
;
2295 s
->invalidate
= vga_invalidate_display
;
2296 s
->screen_dump
= vga_screen_dump
;
2297 s
->text_update
= vga_update_text
;
2298 switch (vga_retrace_method
) {
2299 case VGA_RETRACE_DUMB
:
2300 s
->retrace
= vga_dumb_retrace
;
2301 s
->update_retrace_info
= vga_dumb_update_retrace_info
;
2304 case VGA_RETRACE_PRECISE
:
2305 s
->retrace
= vga_precise_retrace
;
2306 s
->update_retrace_info
= vga_precise_update_retrace_info
;
2312 /* used by both ISA and PCI */
2313 void vga_init(VGAState
*s
)
2317 qemu_register_reset(vga_reset
, s
);
2318 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
2320 register_ioport_write(0x3c0, 16, 1, vga_ioport_write
, s
);
2322 register_ioport_write(0x3b4, 2, 1, vga_ioport_write
, s
);
2323 register_ioport_write(0x3d4, 2, 1, vga_ioport_write
, s
);
2324 register_ioport_write(0x3ba, 1, 1, vga_ioport_write
, s
);
2325 register_ioport_write(0x3da, 1, 1, vga_ioport_write
, s
);
2327 register_ioport_read(0x3c0, 16, 1, vga_ioport_read
, s
);
2329 register_ioport_read(0x3b4, 2, 1, vga_ioport_read
, s
);
2330 register_ioport_read(0x3d4, 2, 1, vga_ioport_read
, s
);
2331 register_ioport_read(0x3ba, 1, 1, vga_ioport_read
, s
);
2332 register_ioport_read(0x3da, 1, 1, vga_ioport_read
, s
);
2335 #ifdef CONFIG_BOCHS_VBE
2336 #if defined (TARGET_I386)
2337 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
2338 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data
, s
);
2340 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
2341 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data
, s
);
2343 /* old Bochs IO ports */
2344 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index
, s
);
2345 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data
, s
);
2347 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index
, s
);
2348 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data
, s
);
2350 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index
, s
);
2351 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data
, s
);
2353 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index
, s
);
2354 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data
, s
);
2356 #endif /* CONFIG_BOCHS_VBE */
2358 vga_io_memory
= cpu_register_io_memory(vga_mem_read
, vga_mem_write
, s
);
2359 cpu_register_physical_memory(isa_mem_base
+ 0x000a0000, 0x20000,
2361 qemu_register_coalesced_mmio(isa_mem_base
+ 0x000a0000, 0x20000);
2364 /* Memory mapped interface */
2365 static uint32_t vga_mm_readb (void *opaque
, target_phys_addr_t addr
)
2367 VGAState
*s
= opaque
;
2369 return vga_ioport_read(s
, addr
>> s
->it_shift
) & 0xff;
2372 static void vga_mm_writeb (void *opaque
,
2373 target_phys_addr_t addr
, uint32_t value
)
2375 VGAState
*s
= opaque
;
2377 vga_ioport_write(s
, addr
>> s
->it_shift
, value
& 0xff);
2380 static uint32_t vga_mm_readw (void *opaque
, target_phys_addr_t addr
)
2382 VGAState
*s
= opaque
;
2384 return vga_ioport_read(s
, addr
>> s
->it_shift
) & 0xffff;
2387 static void vga_mm_writew (void *opaque
,
2388 target_phys_addr_t addr
, uint32_t value
)
2390 VGAState
*s
= opaque
;
2392 vga_ioport_write(s
, addr
>> s
->it_shift
, value
& 0xffff);
2395 static uint32_t vga_mm_readl (void *opaque
, target_phys_addr_t addr
)
2397 VGAState
*s
= opaque
;
2399 return vga_ioport_read(s
, addr
>> s
->it_shift
);
2402 static void vga_mm_writel (void *opaque
,
2403 target_phys_addr_t addr
, uint32_t value
)
2405 VGAState
*s
= opaque
;
2407 vga_ioport_write(s
, addr
>> s
->it_shift
, value
);
2410 static CPUReadMemoryFunc
* const vga_mm_read_ctrl
[] = {
2416 static CPUWriteMemoryFunc
* const vga_mm_write_ctrl
[] = {
2422 static void vga_mm_init(VGAState
*s
, target_phys_addr_t vram_base
,
2423 target_phys_addr_t ctrl_base
, int it_shift
)
2425 int s_ioport_ctrl
, vga_io_memory
;
2427 s
->it_shift
= it_shift
;
2428 s_ioport_ctrl
= cpu_register_io_memory(vga_mm_read_ctrl
, vga_mm_write_ctrl
, s
);
2429 vga_io_memory
= cpu_register_io_memory(vga_mem_read
, vga_mem_write
, s
);
2431 register_savevm("vga", 0, 2, vga_save
, vga_load
, s
);
2433 cpu_register_physical_memory(ctrl_base
, 0x100000, s_ioport_ctrl
);
2435 cpu_register_physical_memory(vram_base
+ 0x000a0000, 0x20000, vga_io_memory
);
2436 qemu_register_coalesced_mmio(vram_base
+ 0x000a0000, 0x20000);
2439 int isa_vga_init(void)
2443 s
= qemu_mallocz(sizeof(VGAState
));
2445 vga_common_init(s
, VGA_RAM_SIZE
);
2448 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2449 s
->screen_dump
, s
->text_update
, s
);
2451 #ifdef CONFIG_BOCHS_VBE
2452 /* XXX: use optimized standard vga accesses */
2453 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
2454 VGA_RAM_SIZE
, s
->vram_offset
);
2459 int isa_vga_mm_init(target_phys_addr_t vram_base
,
2460 target_phys_addr_t ctrl_base
, int it_shift
)
2464 s
= qemu_mallocz(sizeof(VGAState
));
2466 vga_common_init(s
, VGA_RAM_SIZE
);
2467 vga_mm_init(s
, vram_base
, ctrl_base
, it_shift
);
2469 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2470 s
->screen_dump
, s
->text_update
, s
);
2472 #ifdef CONFIG_BOCHS_VBE
2473 /* XXX: use optimized standard vga accesses */
2474 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS
,
2475 VGA_RAM_SIZE
, s
->vram_offset
);
2480 static void pci_vga_write_config(PCIDevice
*d
,
2481 uint32_t address
, uint32_t val
, int len
)
2483 PCIVGAState
*pvs
= container_of(d
, PCIVGAState
, dev
);
2484 VGAState
*s
= &pvs
->vga
;
2486 pci_default_write_config(d
, address
, val
, len
);
2487 if (s
->map_addr
&& pvs
->dev
.io_regions
[0].addr
== -1)
2491 static int pci_vga_initfn(PCIDevice
*dev
)
2493 PCIVGAState
*d
= DO_UPCAST(PCIVGAState
, dev
, dev
);
2494 VGAState
*s
= &d
->vga
;
2495 uint8_t *pci_conf
= d
->dev
.config
;
2497 // vga + console init
2498 vga_common_init(s
, VGA_RAM_SIZE
);
2500 s
->pci_dev
= &d
->dev
;
2501 s
->ds
= graphic_console_init(s
->update
, s
->invalidate
,
2502 s
->screen_dump
, s
->text_update
, s
);
2504 // dummy VGA (same as Bochs ID)
2505 pci_config_set_vendor_id(pci_conf
, PCI_VENDOR_ID_QEMU
);
2506 pci_config_set_device_id(pci_conf
, PCI_DEVICE_ID_QEMU_VGA
);
2507 pci_config_set_class(pci_conf
, PCI_CLASS_DISPLAY_VGA
);
2508 pci_conf
[PCI_HEADER_TYPE
] = PCI_HEADER_TYPE_NORMAL
; // header_type
2510 /* XXX: VGA_RAM_SIZE must be a power of two */
2511 pci_register_bar(&d
->dev
, 0, VGA_RAM_SIZE
,
2512 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2515 unsigned int bios_total_size
;
2516 /* must be a power of two */
2517 bios_total_size
= 1;
2518 while (bios_total_size
< s
->bios_size
)
2519 bios_total_size
<<= 1;
2520 pci_register_bar(&d
->dev
, PCI_ROM_SLOT
, bios_total_size
,
2521 PCI_ADDRESS_SPACE_MEM_PREFETCH
, vga_map
);
2526 int pci_vga_init(PCIBus
*bus
,
2527 unsigned long vga_bios_offset
, int vga_bios_size
)
2531 dev
= pci_create("VGA", NULL
);
2532 qdev_prop_set_uint32(&dev
->qdev
, "bios-offset", vga_bios_offset
);
2533 qdev_prop_set_uint32(&dev
->qdev
, "bios-size", vga_bios_offset
);
2534 qdev_init(&dev
->qdev
);
2539 static PCIDeviceInfo vga_info
= {
2541 .qdev
.size
= sizeof(PCIVGAState
),
2542 .init
= pci_vga_initfn
,
2543 .config_write
= pci_vga_write_config
,
2544 .qdev
.props
= (Property
[]) {
2545 DEFINE_PROP_HEX32("bios-offset", PCIVGAState
, vga
.bios_offset
, 0),
2546 DEFINE_PROP_HEX32("bios-size", PCIVGAState
, vga
.bios_size
, 0),
2547 DEFINE_PROP_END_OF_LIST(),
2551 static void vga_register(void)
2553 pci_qdev_register(&vga_info
);
2555 device_init(vga_register
);
2557 /********************************************************/
2558 /* vga screen dump */
2560 static void vga_save_dpy_update(DisplayState
*ds
,
2561 int x
, int y
, int w
, int h
)
2563 if (screen_dump_filename
) {
2564 ppm_save(screen_dump_filename
, ds
->surface
);
2565 screen_dump_filename
= NULL
;
2569 static void vga_save_dpy_resize(DisplayState
*s
)
2573 static void vga_save_dpy_refresh(DisplayState
*s
)
2577 int ppm_save(const char *filename
, struct DisplaySurface
*ds
)
2585 f
= fopen(filename
, "wb");
2588 fprintf(f
, "P6\n%d %d\n%d\n",
2589 ds
->width
, ds
->height
, 255);
2591 for(y
= 0; y
< ds
->height
; y
++) {
2593 for(x
= 0; x
< ds
->width
; x
++) {
2594 if (ds
->pf
.bits_per_pixel
== 32)
2597 v
= (uint32_t) (*(uint16_t *)d
);
2598 r
= ((v
>> ds
->pf
.rshift
) & ds
->pf
.rmax
) * 256 /
2600 g
= ((v
>> ds
->pf
.gshift
) & ds
->pf
.gmax
) * 256 /
2602 b
= ((v
>> ds
->pf
.bshift
) & ds
->pf
.bmax
) * 256 /
2607 d
+= ds
->pf
.bytes_per_pixel
;
2615 static DisplayChangeListener
* vga_screen_dump_init(DisplayState
*ds
)
2617 DisplayChangeListener
*dcl
;
2619 dcl
= qemu_mallocz(sizeof(DisplayChangeListener
));
2620 dcl
->dpy_update
= vga_save_dpy_update
;
2621 dcl
->dpy_resize
= vga_save_dpy_resize
;
2622 dcl
->dpy_refresh
= vga_save_dpy_refresh
;
2623 register_displaychangelistener(ds
, dcl
);
2627 /* save the vga display in a PPM image even if no display is
2629 static void vga_screen_dump(void *opaque
, const char *filename
)
2631 VGAState
*s
= (VGAState
*)opaque
;
2633 if (!screen_dump_dcl
)
2634 screen_dump_dcl
= vga_screen_dump_init(s
->ds
);
2636 screen_dump_filename
= (char *)filename
;
2637 vga_invalidate_display(s
);