Revision 798b0c25 hw/vga.c
b/hw/vga.c | ||
---|---|---|
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 | 24 |
#include "vl.h" |
25 |
#include "vga_int.h" |
|
25 | 26 |
|
26 | 27 |
//#define DEBUG_VGA |
27 | 28 |
//#define DEBUG_VGA_MEM |
... | ... | |
33 | 34 |
/* S3 VGA is deprecated - another graphic card will be emulated */ |
34 | 35 |
//#define CONFIG_S3VGA |
35 | 36 |
|
36 |
#define MSR_COLOR_EMULATION 0x01 |
|
37 |
#define MSR_PAGE_SELECT 0x20 |
|
38 |
|
|
39 |
#define ST01_V_RETRACE 0x08 |
|
40 |
#define ST01_DISP_ENABLE 0x01 |
|
41 |
|
|
42 |
/* bochs VBE support */ |
|
43 |
#define CONFIG_BOCHS_VBE |
|
44 |
|
|
45 |
#define VBE_DISPI_MAX_XRES 1024 |
|
46 |
#define VBE_DISPI_MAX_YRES 768 |
|
47 |
|
|
48 |
#define VBE_DISPI_INDEX_ID 0x0 |
|
49 |
#define VBE_DISPI_INDEX_XRES 0x1 |
|
50 |
#define VBE_DISPI_INDEX_YRES 0x2 |
|
51 |
#define VBE_DISPI_INDEX_BPP 0x3 |
|
52 |
#define VBE_DISPI_INDEX_ENABLE 0x4 |
|
53 |
#define VBE_DISPI_INDEX_BANK 0x5 |
|
54 |
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 |
|
55 |
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 |
|
56 |
#define VBE_DISPI_INDEX_X_OFFSET 0x8 |
|
57 |
#define VBE_DISPI_INDEX_Y_OFFSET 0x9 |
|
58 |
#define VBE_DISPI_INDEX_NB 0xa |
|
59 |
|
|
60 |
#define VBE_DISPI_ID0 0xB0C0 |
|
61 |
#define VBE_DISPI_ID1 0xB0C1 |
|
62 |
#define VBE_DISPI_ID2 0xB0C2 |
|
63 |
|
|
64 |
#define VBE_DISPI_DISABLED 0x00 |
|
65 |
#define VBE_DISPI_ENABLED 0x01 |
|
66 |
#define VBE_DISPI_LFB_ENABLED 0x40 |
|
67 |
#define VBE_DISPI_NOCLEARMEM 0x80 |
|
68 |
|
|
69 |
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 |
|
70 |
|
|
71 |
typedef struct VGAState { |
|
72 |
uint8_t *vram_ptr; |
|
73 |
unsigned long vram_offset; |
|
74 |
unsigned int vram_size; |
|
75 |
uint32_t latch; |
|
76 |
uint8_t sr_index; |
|
77 |
uint8_t sr[8]; |
|
78 |
uint8_t gr_index; |
|
79 |
uint8_t gr[16]; |
|
80 |
uint8_t ar_index; |
|
81 |
uint8_t ar[21]; |
|
82 |
int ar_flip_flop; |
|
83 |
uint8_t cr_index; |
|
84 |
uint8_t cr[256]; /* CRT registers */ |
|
85 |
uint8_t msr; /* Misc Output Register */ |
|
86 |
uint8_t fcr; /* Feature Control Register */ |
|
87 |
uint8_t st00; /* status 0 */ |
|
88 |
uint8_t st01; /* status 1 */ |
|
89 |
uint8_t dac_state; |
|
90 |
uint8_t dac_sub_index; |
|
91 |
uint8_t dac_read_index; |
|
92 |
uint8_t dac_write_index; |
|
93 |
uint8_t dac_cache[3]; /* used when writing */ |
|
94 |
uint8_t palette[768]; |
|
95 |
int32_t bank_offset; |
|
96 |
#ifdef CONFIG_BOCHS_VBE |
|
97 |
uint16_t vbe_index; |
|
98 |
uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; |
|
99 |
uint32_t vbe_start_addr; |
|
100 |
uint32_t vbe_line_offset; |
|
101 |
uint32_t vbe_bank_mask; |
|
102 |
#endif |
|
103 |
/* display refresh support */ |
|
104 |
DisplayState *ds; |
|
105 |
uint32_t font_offsets[2]; |
|
106 |
int graphic_mode; |
|
107 |
uint8_t shift_control; |
|
108 |
uint8_t double_scan; |
|
109 |
uint32_t line_offset; |
|
110 |
uint32_t line_compare; |
|
111 |
uint32_t start_addr; |
|
112 |
uint8_t last_cw, last_ch; |
|
113 |
uint32_t last_width, last_height; /* in chars or pixels */ |
|
114 |
uint32_t last_scr_width, last_scr_height; /* in pixels */ |
|
115 |
uint8_t cursor_start, cursor_end; |
|
116 |
uint32_t cursor_offset; |
|
117 |
unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b); |
|
118 |
/* tell for each page if it has been updated since the last time */ |
|
119 |
uint32_t last_palette[256]; |
|
120 |
#define CH_ATTR_SIZE (160 * 100) |
|
121 |
uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ |
|
122 |
} VGAState; |
|
123 |
|
|
124 | 37 |
/* force some bits to zero */ |
125 |
static const uint8_t sr_mask[8] = {
|
|
38 |
const uint8_t sr_mask[8] = { |
|
126 | 39 |
(uint8_t)~0xfc, |
127 | 40 |
(uint8_t)~0xc2, |
128 | 41 |
(uint8_t)~0xf0, |
... | ... | |
133 | 46 |
(uint8_t)~0x00, |
134 | 47 |
}; |
135 | 48 |
|
136 |
static const uint8_t gr_mask[16] = {
|
|
49 |
const uint8_t gr_mask[16] = { |
|
137 | 50 |
(uint8_t)~0xf0, /* 0x00 */ |
138 | 51 |
(uint8_t)~0xf0, /* 0x01 */ |
139 | 52 |
(uint8_t)~0xf0, /* 0x02 */ |
... | ... | |
656 | 569 |
#endif |
657 | 570 |
|
658 | 571 |
/* called for accesses between 0xa0000 and 0xc0000 */ |
659 |
static uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
|
|
572 |
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr) |
|
660 | 573 |
{ |
661 | 574 |
VGAState *s = opaque; |
662 | 575 |
int memory_map_mode, plane; |
... | ... | |
743 | 656 |
} |
744 | 657 |
|
745 | 658 |
/* called for accesses between 0xa0000 and 0xc0000 */ |
746 |
static void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
|
|
659 |
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
|
747 | 660 |
{ |
748 | 661 |
VGAState *s = opaque; |
749 | 662 |
int memory_map_mode, plane, write_mode, b, func_select; |
... | ... | |
1027 | 940 |
return full_update; |
1028 | 941 |
} |
1029 | 942 |
|
1030 |
/* update start_addr and line_offset. Return TRUE if modified */ |
|
1031 |
static int update_basic_params(VGAState *s) |
|
943 |
static void vga_get_offsets(VGAState *s, |
|
944 |
uint32_t *pline_offset, |
|
945 |
uint32_t *pstart_addr) |
|
1032 | 946 |
{ |
1033 |
int full_update; |
|
1034 |
uint32_t start_addr, line_offset, line_compare; |
|
1035 |
|
|
1036 |
full_update = 0; |
|
1037 |
|
|
947 |
uint32_t start_addr, line_offset; |
|
1038 | 948 |
#ifdef CONFIG_BOCHS_VBE |
1039 | 949 |
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { |
1040 | 950 |
line_offset = s->vbe_line_offset; |
... | ... | |
1061 | 971 |
start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */ |
1062 | 972 |
#endif |
1063 | 973 |
} |
974 |
*pline_offset = line_offset; |
|
975 |
*pstart_addr = start_addr; |
|
976 |
} |
|
977 |
|
|
978 |
/* update start_addr and line_offset. Return TRUE if modified */ |
|
979 |
static int update_basic_params(VGAState *s) |
|
980 |
{ |
|
981 |
int full_update; |
|
982 |
uint32_t start_addr, line_offset, line_compare; |
|
1064 | 983 |
|
984 |
full_update = 0; |
|
985 |
|
|
986 |
s->get_offsets(s, &line_offset, &start_addr); |
|
1065 | 987 |
/* line compare */ |
1066 | 988 |
line_compare = s->cr[0x18] | |
1067 | 989 |
((s->cr[0x07] & 0x10) << 4) | |
... | ... | |
1373 | 1295 |
vga_draw_line32_32, |
1374 | 1296 |
}; |
1375 | 1297 |
|
1298 |
static int vga_get_bpp(VGAState *s) |
|
1299 |
{ |
|
1300 |
int ret; |
|
1301 |
#ifdef CONFIG_BOCHS_VBE |
|
1302 |
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { |
|
1303 |
ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; |
|
1304 |
} else |
|
1305 |
#endif |
|
1306 |
{ |
|
1307 |
ret = 0; |
|
1308 |
} |
|
1309 |
return ret; |
|
1310 |
} |
|
1311 |
|
|
1376 | 1312 |
/* |
1377 | 1313 |
* graphic modes |
1378 | 1314 |
* Missing: |
... | ... | |
1429 | 1365 |
v = VGA_DRAW_LINE2; |
1430 | 1366 |
} |
1431 | 1367 |
} else { |
1432 |
#ifdef CONFIG_BOCHS_VBE |
|
1433 |
if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { |
|
1434 |
switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) { |
|
1435 |
default: |
|
1436 |
case 8: |
|
1437 |
full_update |= update_palette256(s); |
|
1438 |
v = VGA_DRAW_LINE8; |
|
1439 |
break; |
|
1440 |
case 15: |
|
1441 |
v = VGA_DRAW_LINE15; |
|
1442 |
break; |
|
1443 |
case 16: |
|
1444 |
v = VGA_DRAW_LINE16; |
|
1445 |
break; |
|
1446 |
case 24: |
|
1447 |
v = VGA_DRAW_LINE24; |
|
1448 |
break; |
|
1449 |
case 32: |
|
1450 |
v = VGA_DRAW_LINE32; |
|
1451 |
break; |
|
1452 |
} |
|
1453 |
} else |
|
1454 |
#endif |
|
1455 |
{ |
|
1368 |
switch(s->get_bpp(s)) { |
|
1369 |
default: |
|
1370 |
case 0: |
|
1456 | 1371 |
full_update |= update_palette256(s); |
1457 | 1372 |
v = VGA_DRAW_LINE8D2; |
1373 |
break; |
|
1374 |
case 8: |
|
1375 |
full_update |= update_palette256(s); |
|
1376 |
v = VGA_DRAW_LINE8; |
|
1377 |
break; |
|
1378 |
case 15: |
|
1379 |
v = VGA_DRAW_LINE15; |
|
1380 |
break; |
|
1381 |
case 16: |
|
1382 |
v = VGA_DRAW_LINE16; |
|
1383 |
break; |
|
1384 |
case 24: |
|
1385 |
v = VGA_DRAW_LINE24; |
|
1386 |
break; |
|
1387 |
case 32: |
|
1388 |
v = VGA_DRAW_LINE32; |
|
1389 |
break; |
|
1458 | 1390 |
} |
1459 | 1391 |
} |
1460 | 1392 |
vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)]; |
... | ... | |
1747 | 1679 |
cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); |
1748 | 1680 |
} |
1749 | 1681 |
|
1750 |
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, |
|
1751 |
unsigned long vga_ram_offset, int vga_ram_size, |
|
1752 |
int is_pci) |
|
1682 |
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, |
|
1683 |
unsigned long vga_ram_offset, int vga_ram_size) |
|
1753 | 1684 |
{ |
1754 |
VGAState *s = &vga_state; |
|
1755 | 1685 |
int i, j, v, b; |
1756 | 1686 |
|
1757 | 1687 |
for(i = 0;i < 256; i++) { |
... | ... | |
1783 | 1713 |
s->vram_offset = vga_ram_offset; |
1784 | 1714 |
s->vram_size = vga_ram_size; |
1785 | 1715 |
s->ds = ds; |
1716 |
s->get_bpp = vga_get_bpp; |
|
1717 |
s->get_offsets = vga_get_offsets; |
|
1718 |
} |
|
1719 |
|
|
1720 |
|
|
1721 |
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, |
|
1722 |
unsigned long vga_ram_offset, int vga_ram_size, |
|
1723 |
int is_pci) |
|
1724 |
{ |
|
1725 |
VGAState *s = &vga_state; |
|
1726 |
|
|
1727 |
vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); |
|
1786 | 1728 |
|
1787 | 1729 |
register_savevm("vga", 0, 1, vga_save, vga_load, s); |
1788 | 1730 |
|
Also available in: Unified diff