Clean up KVM/QEMU interaction
[qemu-kvm/fedora.git] / hw / vga.c
blob222a39c16610e30d2eed8a0a9e645496321930cb
1 /*
2 * QEMU VGA Emulator.
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
22 * THE SOFTWARE.
24 #include "hw.h"
25 #include "console.h"
26 #include "pc.h"
27 #include "pci.h"
28 #include "vga_int.h"
29 #include "pixel_ops.h"
30 #include "qemu-kvm.h"
32 #include <sys/mman.h>
34 //#define DEBUG_VGA
35 //#define DEBUG_VGA_MEM
36 //#define DEBUG_VGA_REG
38 //#define DEBUG_BOCHS_VBE
40 /* force some bits to zero */
41 const uint8_t sr_mask[8] = {
42 (uint8_t)~0xfc,
43 (uint8_t)~0xc2,
44 (uint8_t)~0xf0,
45 (uint8_t)~0xc0,
46 (uint8_t)~0xf1,
47 (uint8_t)~0xff,
48 (uint8_t)~0xff,
49 (uint8_t)~0x00,
52 const uint8_t gr_mask[16] = {
53 (uint8_t)~0xf0, /* 0x00 */
54 (uint8_t)~0xf0, /* 0x01 */
55 (uint8_t)~0xf0, /* 0x02 */
56 (uint8_t)~0xe0, /* 0x03 */
57 (uint8_t)~0xfc, /* 0x04 */
58 (uint8_t)~0x84, /* 0x05 */
59 (uint8_t)~0xf0, /* 0x06 */
60 (uint8_t)~0xf0, /* 0x07 */
61 (uint8_t)~0x00, /* 0x08 */
62 (uint8_t)~0xff, /* 0x09 */
63 (uint8_t)~0xff, /* 0x0a */
64 (uint8_t)~0xff, /* 0x0b */
65 (uint8_t)~0xff, /* 0x0c */
66 (uint8_t)~0xff, /* 0x0d */
67 (uint8_t)~0xff, /* 0x0e */
68 (uint8_t)~0xff, /* 0x0f */
71 #define cbswap_32(__x) \
72 ((uint32_t)( \
73 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
74 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
75 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
76 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
78 #ifdef WORDS_BIGENDIAN
79 #define PAT(x) cbswap_32(x)
80 #else
81 #define PAT(x) (x)
82 #endif
84 #ifdef WORDS_BIGENDIAN
85 #define BIG 1
86 #else
87 #define BIG 0
88 #endif
90 #ifdef WORDS_BIGENDIAN
91 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
92 #else
93 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
94 #endif
96 static const uint32_t mask16[16] = {
97 PAT(0x00000000),
98 PAT(0x000000ff),
99 PAT(0x0000ff00),
100 PAT(0x0000ffff),
101 PAT(0x00ff0000),
102 PAT(0x00ff00ff),
103 PAT(0x00ffff00),
104 PAT(0x00ffffff),
105 PAT(0xff000000),
106 PAT(0xff0000ff),
107 PAT(0xff00ff00),
108 PAT(0xff00ffff),
109 PAT(0xffff0000),
110 PAT(0xffff00ff),
111 PAT(0xffffff00),
112 PAT(0xffffffff),
115 #undef PAT
117 #ifdef WORDS_BIGENDIAN
118 #define PAT(x) (x)
119 #else
120 #define PAT(x) cbswap_32(x)
121 #endif
123 static const uint32_t dmask16[16] = {
124 PAT(0x00000000),
125 PAT(0x000000ff),
126 PAT(0x0000ff00),
127 PAT(0x0000ffff),
128 PAT(0x00ff0000),
129 PAT(0x00ff00ff),
130 PAT(0x00ffff00),
131 PAT(0x00ffffff),
132 PAT(0xff000000),
133 PAT(0xff0000ff),
134 PAT(0xff00ff00),
135 PAT(0xff00ffff),
136 PAT(0xffff0000),
137 PAT(0xffff00ff),
138 PAT(0xffffff00),
139 PAT(0xffffffff),
142 static const uint32_t dmask4[4] = {
143 PAT(0x00000000),
144 PAT(0x0000ffff),
145 PAT(0xffff0000),
146 PAT(0xffffffff),
149 static uint32_t expand4[256];
150 static uint16_t expand2[256];
151 static uint8_t expand4to8[16];
153 static void vga_screen_dump(void *opaque, const char *filename);
155 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
157 VGAState *s = opaque;
158 int val, index;
160 /* check port range access depending on color/monochrome mode */
161 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
162 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
163 val = 0xff;
164 } else {
165 switch(addr) {
166 case 0x3c0:
167 if (s->ar_flip_flop == 0) {
168 val = s->ar_index;
169 } else {
170 val = 0;
172 break;
173 case 0x3c1:
174 index = s->ar_index & 0x1f;
175 if (index < 21)
176 val = s->ar[index];
177 else
178 val = 0;
179 break;
180 case 0x3c2:
181 val = s->st00;
182 break;
183 case 0x3c4:
184 val = s->sr_index;
185 break;
186 case 0x3c5:
187 val = s->sr[s->sr_index];
188 #ifdef DEBUG_VGA_REG
189 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
190 #endif
191 break;
192 case 0x3c7:
193 val = s->dac_state;
194 break;
195 case 0x3c8:
196 val = s->dac_write_index;
197 break;
198 case 0x3c9:
199 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
200 if (++s->dac_sub_index == 3) {
201 s->dac_sub_index = 0;
202 s->dac_read_index++;
204 break;
205 case 0x3ca:
206 val = s->fcr;
207 break;
208 case 0x3cc:
209 val = s->msr;
210 break;
211 case 0x3ce:
212 val = s->gr_index;
213 break;
214 case 0x3cf:
215 val = s->gr[s->gr_index];
216 #ifdef DEBUG_VGA_REG
217 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
218 #endif
219 break;
220 case 0x3b4:
221 case 0x3d4:
222 val = s->cr_index;
223 break;
224 case 0x3b5:
225 case 0x3d5:
226 val = s->cr[s->cr_index];
227 #ifdef DEBUG_VGA_REG
228 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
229 #endif
230 break;
231 case 0x3ba:
232 case 0x3da:
233 /* just toggle to fool polling */
234 s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
235 val = s->st01;
236 s->ar_flip_flop = 0;
237 break;
238 default:
239 val = 0x00;
240 break;
243 #if defined(DEBUG_VGA)
244 printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
245 #endif
246 return val;
249 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
251 VGAState *s = opaque;
252 int index;
254 /* check port range access depending on color/monochrome mode */
255 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
256 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
257 return;
259 #ifdef DEBUG_VGA
260 printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
261 #endif
263 switch(addr) {
264 case 0x3c0:
265 if (s->ar_flip_flop == 0) {
266 val &= 0x3f;
267 s->ar_index = val;
268 } else {
269 index = s->ar_index & 0x1f;
270 switch(index) {
271 case 0x00 ... 0x0f:
272 s->ar[index] = val & 0x3f;
273 break;
274 case 0x10:
275 s->ar[index] = val & ~0x10;
276 break;
277 case 0x11:
278 s->ar[index] = val;
279 break;
280 case 0x12:
281 s->ar[index] = val & ~0xc0;
282 break;
283 case 0x13:
284 s->ar[index] = val & ~0xf0;
285 break;
286 case 0x14:
287 s->ar[index] = val & ~0xf0;
288 break;
289 default:
290 break;
293 s->ar_flip_flop ^= 1;
294 break;
295 case 0x3c2:
296 s->msr = val & ~0x10;
297 break;
298 case 0x3c4:
299 s->sr_index = val & 7;
300 break;
301 case 0x3c5:
302 #ifdef DEBUG_VGA_REG
303 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
304 #endif
305 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
306 break;
307 case 0x3c7:
308 s->dac_read_index = val;
309 s->dac_sub_index = 0;
310 s->dac_state = 3;
311 break;
312 case 0x3c8:
313 s->dac_write_index = val;
314 s->dac_sub_index = 0;
315 s->dac_state = 0;
316 break;
317 case 0x3c9:
318 s->dac_cache[s->dac_sub_index] = val;
319 if (++s->dac_sub_index == 3) {
320 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
321 s->dac_sub_index = 0;
322 s->dac_write_index++;
324 break;
325 case 0x3ce:
326 s->gr_index = val & 0x0f;
327 break;
328 case 0x3cf:
329 #ifdef DEBUG_VGA_REG
330 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
331 #endif
332 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
333 break;
334 case 0x3b4:
335 case 0x3d4:
336 s->cr_index = val;
337 break;
338 case 0x3b5:
339 case 0x3d5:
340 #ifdef DEBUG_VGA_REG
341 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
342 #endif
343 /* handle CR0-7 protection */
344 if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
345 /* can always write bit 4 of CR7 */
346 if (s->cr_index == 7)
347 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
348 return;
350 switch(s->cr_index) {
351 case 0x01: /* horizontal display end */
352 case 0x07:
353 case 0x09:
354 case 0x0c:
355 case 0x0d:
356 case 0x12: /* vertical display end */
357 s->cr[s->cr_index] = val;
358 break;
359 default:
360 s->cr[s->cr_index] = val;
361 break;
363 break;
364 case 0x3ba:
365 case 0x3da:
366 s->fcr = val & 0x10;
367 break;
371 #ifdef CONFIG_BOCHS_VBE
372 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
374 VGAState *s = opaque;
375 uint32_t val;
376 val = s->vbe_index;
377 return val;
380 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
382 VGAState *s = opaque;
383 uint32_t val;
385 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
386 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
387 switch(s->vbe_index) {
388 /* XXX: do not hardcode ? */
389 case VBE_DISPI_INDEX_XRES:
390 val = VBE_DISPI_MAX_XRES;
391 break;
392 case VBE_DISPI_INDEX_YRES:
393 val = VBE_DISPI_MAX_YRES;
394 break;
395 case VBE_DISPI_INDEX_BPP:
396 val = VBE_DISPI_MAX_BPP;
397 break;
398 default:
399 val = s->vbe_regs[s->vbe_index];
400 break;
402 } else {
403 val = s->vbe_regs[s->vbe_index];
405 } else {
406 val = 0;
408 #ifdef DEBUG_BOCHS_VBE
409 printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
410 #endif
411 return val;
414 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
416 VGAState *s = opaque;
417 s->vbe_index = val;
420 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
422 VGAState *s = opaque;
424 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
425 #ifdef DEBUG_BOCHS_VBE
426 printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
427 #endif
428 switch(s->vbe_index) {
429 case VBE_DISPI_INDEX_ID:
430 if (val == VBE_DISPI_ID0 ||
431 val == VBE_DISPI_ID1 ||
432 val == VBE_DISPI_ID2 ||
433 val == VBE_DISPI_ID3 ||
434 val == VBE_DISPI_ID4) {
435 s->vbe_regs[s->vbe_index] = val;
437 break;
438 case VBE_DISPI_INDEX_XRES:
439 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
440 s->vbe_regs[s->vbe_index] = val;
442 break;
443 case VBE_DISPI_INDEX_YRES:
444 if (val <= VBE_DISPI_MAX_YRES) {
445 s->vbe_regs[s->vbe_index] = val;
447 break;
448 case VBE_DISPI_INDEX_BPP:
449 if (val == 0)
450 val = 8;
451 if (val == 4 || val == 8 || val == 15 ||
452 val == 16 || val == 24 || val == 32) {
453 s->vbe_regs[s->vbe_index] = val;
455 break;
456 case VBE_DISPI_INDEX_BANK:
457 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
458 val &= (s->vbe_bank_mask >> 2);
459 } else {
460 val &= s->vbe_bank_mask;
462 s->vbe_regs[s->vbe_index] = val;
463 s->bank_offset = (val << 16);
464 break;
465 case VBE_DISPI_INDEX_ENABLE:
466 if ((val & VBE_DISPI_ENABLED) &&
467 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
468 int h, shift_control;
470 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
471 s->vbe_regs[VBE_DISPI_INDEX_XRES];
472 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
473 s->vbe_regs[VBE_DISPI_INDEX_YRES];
474 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
475 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
477 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
478 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
479 else
480 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
481 ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
482 s->vbe_start_addr = 0;
484 /* clear the screen (should be done in BIOS) */
485 if (!(val & VBE_DISPI_NOCLEARMEM)) {
486 memset(s->vram_ptr, 0,
487 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
490 /* we initialize the VGA graphic mode (should be done
491 in BIOS) */
492 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
493 s->cr[0x17] |= 3; /* no CGA modes */
494 s->cr[0x13] = s->vbe_line_offset >> 3;
495 /* width */
496 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
497 /* height (only meaningful if < 1024) */
498 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
499 s->cr[0x12] = h;
500 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
501 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
502 /* line compare to 1023 */
503 s->cr[0x18] = 0xff;
504 s->cr[0x07] |= 0x10;
505 s->cr[0x09] |= 0x40;
507 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
508 shift_control = 0;
509 s->sr[0x01] &= ~8; /* no double line */
510 } else {
511 shift_control = 2;
512 s->sr[4] |= 0x08; /* set chain 4 mode */
513 s->sr[2] |= 0x0f; /* activate all planes */
515 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
516 s->cr[0x09] &= ~0x9f; /* no double scan */
517 } else {
518 /* XXX: the bios should do that */
519 s->bank_offset = 0;
521 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
522 s->vbe_regs[s->vbe_index] = val;
523 break;
524 case VBE_DISPI_INDEX_VIRT_WIDTH:
526 int w, h, line_offset;
528 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
529 return;
530 w = val;
531 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
532 line_offset = w >> 1;
533 else
534 line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
535 h = s->vram_size / line_offset;
536 /* XXX: support weird bochs semantics ? */
537 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
538 return;
539 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
540 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
541 s->vbe_line_offset = line_offset;
543 break;
544 case VBE_DISPI_INDEX_X_OFFSET:
545 case VBE_DISPI_INDEX_Y_OFFSET:
547 int x;
548 s->vbe_regs[s->vbe_index] = val;
549 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
550 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
551 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
552 s->vbe_start_addr += x >> 1;
553 else
554 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
555 s->vbe_start_addr >>= 2;
557 break;
558 default:
559 break;
563 #endif
565 /* called for accesses between 0xa0000 and 0xc0000 */
566 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
568 VGAState *s = opaque;
569 int memory_map_mode, plane;
570 uint32_t ret;
572 /* convert to VGA memory offset */
573 memory_map_mode = (s->gr[6] >> 2) & 3;
574 addr &= 0x1ffff;
575 switch(memory_map_mode) {
576 case 0:
577 break;
578 case 1:
579 if (addr >= 0x10000)
580 return 0xff;
581 addr += s->bank_offset;
582 break;
583 case 2:
584 addr -= 0x10000;
585 if (addr >= 0x8000)
586 return 0xff;
587 break;
588 default:
589 case 3:
590 addr -= 0x18000;
591 if (addr >= 0x8000)
592 return 0xff;
593 break;
596 if (s->sr[4] & 0x08) {
597 /* chain 4 mode : simplest access */
598 ret = s->vram_ptr[addr];
599 } else if (s->gr[5] & 0x10) {
600 /* odd/even mode (aka text mode mapping) */
601 plane = (s->gr[4] & 2) | (addr & 1);
602 ret = s->vram_ptr[((addr & ~1) << 1) | plane];
603 } else {
604 /* standard VGA latched access */
605 s->latch = ((uint32_t *)s->vram_ptr)[addr];
607 if (!(s->gr[5] & 0x08)) {
608 /* read mode 0 */
609 plane = s->gr[4];
610 ret = GET_PLANE(s->latch, plane);
611 } else {
612 /* read mode 1 */
613 ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
614 ret |= ret >> 16;
615 ret |= ret >> 8;
616 ret = (~ret) & 0xff;
619 return ret;
622 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
624 uint32_t v;
625 #ifdef TARGET_WORDS_BIGENDIAN
626 v = vga_mem_readb(opaque, addr) << 8;
627 v |= vga_mem_readb(opaque, addr + 1);
628 #else
629 v = vga_mem_readb(opaque, addr);
630 v |= vga_mem_readb(opaque, addr + 1) << 8;
631 #endif
632 return v;
635 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
637 uint32_t v;
638 #ifdef TARGET_WORDS_BIGENDIAN
639 v = vga_mem_readb(opaque, addr) << 24;
640 v |= vga_mem_readb(opaque, addr + 1) << 16;
641 v |= vga_mem_readb(opaque, addr + 2) << 8;
642 v |= vga_mem_readb(opaque, addr + 3);
643 #else
644 v = vga_mem_readb(opaque, addr);
645 v |= vga_mem_readb(opaque, addr + 1) << 8;
646 v |= vga_mem_readb(opaque, addr + 2) << 16;
647 v |= vga_mem_readb(opaque, addr + 3) << 24;
648 #endif
649 return v;
652 /* called for accesses between 0xa0000 and 0xc0000 */
653 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
655 VGAState *s = opaque;
656 int memory_map_mode, plane, write_mode, b, func_select, mask;
657 uint32_t write_mask, bit_mask, set_mask;
659 #ifdef DEBUG_VGA_MEM
660 printf("vga: [0x%x] = 0x%02x\n", addr, val);
661 #endif
662 /* convert to VGA memory offset */
663 memory_map_mode = (s->gr[6] >> 2) & 3;
664 addr &= 0x1ffff;
665 switch(memory_map_mode) {
666 case 0:
667 break;
668 case 1:
669 if (addr >= 0x10000)
670 return;
671 addr += s->bank_offset;
672 break;
673 case 2:
674 addr -= 0x10000;
675 if (addr >= 0x8000)
676 return;
677 break;
678 default:
679 case 3:
680 addr -= 0x18000;
681 if (addr >= 0x8000)
682 return;
683 break;
686 if (s->sr[4] & 0x08) {
687 /* chain 4 mode : simplest access */
688 plane = addr & 3;
689 mask = (1 << plane);
690 if (s->sr[2] & mask) {
691 s->vram_ptr[addr] = val;
692 #ifdef DEBUG_VGA_MEM
693 printf("vga: chain4: [0x%x]\n", addr);
694 #endif
695 s->plane_updated |= mask; /* only used to detect font change */
696 cpu_physical_memory_set_dirty(s->vram_offset + addr);
698 } else if (s->gr[5] & 0x10) {
699 /* odd/even mode (aka text mode mapping) */
700 plane = (s->gr[4] & 2) | (addr & 1);
701 mask = (1 << plane);
702 if (s->sr[2] & mask) {
703 addr = ((addr & ~1) << 1) | plane;
704 s->vram_ptr[addr] = val;
705 #ifdef DEBUG_VGA_MEM
706 printf("vga: odd/even: [0x%x]\n", addr);
707 #endif
708 s->plane_updated |= mask; /* only used to detect font change */
709 cpu_physical_memory_set_dirty(s->vram_offset + addr);
711 } else {
712 /* standard VGA latched access */
713 write_mode = s->gr[5] & 3;
714 switch(write_mode) {
715 default:
716 case 0:
717 /* rotate */
718 b = s->gr[3] & 7;
719 val = ((val >> b) | (val << (8 - b))) & 0xff;
720 val |= val << 8;
721 val |= val << 16;
723 /* apply set/reset mask */
724 set_mask = mask16[s->gr[1]];
725 val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
726 bit_mask = s->gr[8];
727 break;
728 case 1:
729 val = s->latch;
730 goto do_write;
731 case 2:
732 val = mask16[val & 0x0f];
733 bit_mask = s->gr[8];
734 break;
735 case 3:
736 /* rotate */
737 b = s->gr[3] & 7;
738 val = (val >> b) | (val << (8 - b));
740 bit_mask = s->gr[8] & val;
741 val = mask16[s->gr[0]];
742 break;
745 /* apply logical operation */
746 func_select = s->gr[3] >> 3;
747 switch(func_select) {
748 case 0:
749 default:
750 /* nothing to do */
751 break;
752 case 1:
753 /* and */
754 val &= s->latch;
755 break;
756 case 2:
757 /* or */
758 val |= s->latch;
759 break;
760 case 3:
761 /* xor */
762 val ^= s->latch;
763 break;
766 /* apply bit mask */
767 bit_mask |= bit_mask << 8;
768 bit_mask |= bit_mask << 16;
769 val = (val & bit_mask) | (s->latch & ~bit_mask);
771 do_write:
772 /* mask data according to sr[2] */
773 mask = s->sr[2];
774 s->plane_updated |= mask; /* only used to detect font change */
775 write_mask = mask16[mask];
776 ((uint32_t *)s->vram_ptr)[addr] =
777 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
778 (val & write_mask);
779 #ifdef DEBUG_VGA_MEM
780 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
781 addr * 4, write_mask, val);
782 #endif
783 cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
787 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
789 #ifdef TARGET_WORDS_BIGENDIAN
790 vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
791 vga_mem_writeb(opaque, addr + 1, val & 0xff);
792 #else
793 vga_mem_writeb(opaque, addr, val & 0xff);
794 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
795 #endif
798 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
800 #ifdef TARGET_WORDS_BIGENDIAN
801 vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
802 vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
803 vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
804 vga_mem_writeb(opaque, addr + 3, val & 0xff);
805 #else
806 vga_mem_writeb(opaque, addr, val & 0xff);
807 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
808 vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
809 vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
810 #endif
813 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
814 const uint8_t *font_ptr, int h,
815 uint32_t fgcol, uint32_t bgcol);
816 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
817 const uint8_t *font_ptr, int h,
818 uint32_t fgcol, uint32_t bgcol, int dup9);
819 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
820 const uint8_t *s, int width);
822 #define DEPTH 8
823 #include "vga_template.h"
825 #define DEPTH 15
826 #include "vga_template.h"
828 #define BGR_FORMAT
829 #define DEPTH 15
830 #include "vga_template.h"
832 #define DEPTH 16
833 #include "vga_template.h"
835 #define BGR_FORMAT
836 #define DEPTH 16
837 #include "vga_template.h"
839 #define DEPTH 32
840 #include "vga_template.h"
842 #define BGR_FORMAT
843 #define DEPTH 32
844 #include "vga_template.h"
846 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
848 unsigned int col;
849 col = rgb_to_pixel8(r, g, b);
850 col |= col << 8;
851 col |= col << 16;
852 return col;
855 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
857 unsigned int col;
858 col = rgb_to_pixel15(r, g, b);
859 col |= col << 16;
860 return col;
863 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
864 unsigned int b)
866 unsigned int col;
867 col = rgb_to_pixel15bgr(r, g, b);
868 col |= col << 16;
869 return col;
872 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
874 unsigned int col;
875 col = rgb_to_pixel16(r, g, b);
876 col |= col << 16;
877 return col;
880 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
881 unsigned int b)
883 unsigned int col;
884 col = rgb_to_pixel16bgr(r, g, b);
885 col |= col << 16;
886 return col;
889 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
891 unsigned int col;
892 col = rgb_to_pixel32(r, g, b);
893 return col;
896 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
898 unsigned int col;
899 col = rgb_to_pixel32bgr(r, g, b);
900 return col;
903 /* return true if the palette was modified */
904 static int update_palette16(VGAState *s)
906 int full_update, i;
907 uint32_t v, col, *palette;
909 full_update = 0;
910 palette = s->last_palette;
911 for(i = 0; i < 16; i++) {
912 v = s->ar[i];
913 if (s->ar[0x10] & 0x80)
914 v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
915 else
916 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
917 v = v * 3;
918 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
919 c6_to_8(s->palette[v + 1]),
920 c6_to_8(s->palette[v + 2]));
921 if (col != palette[i]) {
922 full_update = 1;
923 palette[i] = col;
926 return full_update;
929 /* return true if the palette was modified */
930 static int update_palette256(VGAState *s)
932 int full_update, i;
933 uint32_t v, col, *palette;
935 full_update = 0;
936 palette = s->last_palette;
937 v = 0;
938 for(i = 0; i < 256; i++) {
939 if (s->dac_8bit) {
940 col = s->rgb_to_pixel(s->palette[v],
941 s->palette[v + 1],
942 s->palette[v + 2]);
943 } else {
944 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
945 c6_to_8(s->palette[v + 1]),
946 c6_to_8(s->palette[v + 2]));
948 if (col != palette[i]) {
949 full_update = 1;
950 palette[i] = col;
952 v += 3;
954 return full_update;
957 static void vga_get_offsets(VGAState *s,
958 uint32_t *pline_offset,
959 uint32_t *pstart_addr,
960 uint32_t *pline_compare)
962 uint32_t start_addr, line_offset, line_compare;
963 #ifdef CONFIG_BOCHS_VBE
964 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
965 line_offset = s->vbe_line_offset;
966 start_addr = s->vbe_start_addr;
967 line_compare = 65535;
968 } else
969 #endif
971 /* compute line_offset in bytes */
972 line_offset = s->cr[0x13];
973 line_offset <<= 3;
975 /* starting address */
976 start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
978 /* line compare */
979 line_compare = s->cr[0x18] |
980 ((s->cr[0x07] & 0x10) << 4) |
981 ((s->cr[0x09] & 0x40) << 3);
983 *pline_offset = line_offset;
984 *pstart_addr = start_addr;
985 *pline_compare = line_compare;
988 /* update start_addr and line_offset. Return TRUE if modified */
989 static int update_basic_params(VGAState *s)
991 int full_update;
992 uint32_t start_addr, line_offset, line_compare;
994 full_update = 0;
996 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
998 if (line_offset != s->line_offset ||
999 start_addr != s->start_addr ||
1000 line_compare != s->line_compare) {
1001 s->line_offset = line_offset;
1002 s->start_addr = start_addr;
1003 s->line_compare = line_compare;
1004 full_update = 1;
1006 return full_update;
1009 #define NB_DEPTHS 7
1011 static inline int get_depth_index(DisplayState *s)
1013 switch(s->depth) {
1014 default:
1015 case 8:
1016 return 0;
1017 case 15:
1018 if (s->bgr)
1019 return 5;
1020 else
1021 return 1;
1022 case 16:
1023 if (s->bgr)
1024 return 6;
1025 else
1026 return 2;
1027 case 32:
1028 if (s->bgr)
1029 return 4;
1030 else
1031 return 3;
1035 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1036 vga_draw_glyph8_8,
1037 vga_draw_glyph8_16,
1038 vga_draw_glyph8_16,
1039 vga_draw_glyph8_32,
1040 vga_draw_glyph8_32,
1041 vga_draw_glyph8_16,
1042 vga_draw_glyph8_16,
1045 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1046 vga_draw_glyph16_8,
1047 vga_draw_glyph16_16,
1048 vga_draw_glyph16_16,
1049 vga_draw_glyph16_32,
1050 vga_draw_glyph16_32,
1051 vga_draw_glyph16_16,
1052 vga_draw_glyph16_16,
1055 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1056 vga_draw_glyph9_8,
1057 vga_draw_glyph9_16,
1058 vga_draw_glyph9_16,
1059 vga_draw_glyph9_32,
1060 vga_draw_glyph9_32,
1061 vga_draw_glyph9_16,
1062 vga_draw_glyph9_16,
1065 static const uint8_t cursor_glyph[32 * 4] = {
1066 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1067 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1068 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1070 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1071 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1072 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1073 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1075 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1076 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1077 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1078 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1079 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1080 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1081 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1085 * Text mode update
1086 * Missing:
1087 * - double scan
1088 * - double width
1089 * - underline
1090 * - flashing
1092 static void vga_draw_text(VGAState *s, int full_update)
1094 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1095 int cx_min, cx_max, linesize, x_incr;
1096 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1097 uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1098 const uint8_t *font_ptr, *font_base[2];
1099 int dup9, line_offset, depth_index;
1100 uint32_t *palette;
1101 uint32_t *ch_attr_ptr;
1102 vga_draw_glyph8_func *vga_draw_glyph8;
1103 vga_draw_glyph9_func *vga_draw_glyph9;
1105 full_update |= update_palette16(s);
1106 palette = s->last_palette;
1108 /* compute font data address (in plane 2) */
1109 v = s->sr[3];
1110 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1111 if (offset != s->font_offsets[0]) {
1112 s->font_offsets[0] = offset;
1113 full_update = 1;
1115 font_base[0] = s->vram_ptr + offset;
1117 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1118 font_base[1] = s->vram_ptr + offset;
1119 if (offset != s->font_offsets[1]) {
1120 s->font_offsets[1] = offset;
1121 full_update = 1;
1123 if (s->plane_updated & (1 << 2)) {
1124 /* if the plane 2 was modified since the last display, it
1125 indicates the font may have been modified */
1126 s->plane_updated = 0;
1127 full_update = 1;
1129 full_update |= update_basic_params(s);
1131 line_offset = s->line_offset;
1132 s1 = s->vram_ptr + (s->start_addr * 4);
1134 /* total width & height */
1135 cheight = (s->cr[9] & 0x1f) + 1;
1136 cw = 8;
1137 if (!(s->sr[1] & 0x01))
1138 cw = 9;
1139 if (s->sr[1] & 0x08)
1140 cw = 16; /* NOTE: no 18 pixel wide */
1141 x_incr = cw * ((s->ds->depth + 7) >> 3);
1142 width = (s->cr[0x01] + 1);
1143 if (s->cr[0x06] == 100) {
1144 /* ugly hack for CGA 160x100x16 - explain me the logic */
1145 height = 100;
1146 } else {
1147 height = s->cr[0x12] |
1148 ((s->cr[0x07] & 0x02) << 7) |
1149 ((s->cr[0x07] & 0x40) << 3);
1150 height = (height + 1) / cheight;
1152 if ((height * width) > CH_ATTR_SIZE) {
1153 /* better than nothing: exit if transient size is too big */
1154 return;
1157 if (width != s->last_width || height != s->last_height ||
1158 cw != s->last_cw || cheight != s->last_ch) {
1159 s->last_scr_width = width * cw;
1160 s->last_scr_height = height * cheight;
1161 dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1162 s->last_width = width;
1163 s->last_height = height;
1164 s->last_ch = cheight;
1165 s->last_cw = cw;
1166 full_update = 1;
1168 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1169 if (cursor_offset != s->cursor_offset ||
1170 s->cr[0xa] != s->cursor_start ||
1171 s->cr[0xb] != s->cursor_end) {
1172 /* if the cursor position changed, we update the old and new
1173 chars */
1174 if (s->cursor_offset < CH_ATTR_SIZE)
1175 s->last_ch_attr[s->cursor_offset] = -1;
1176 if (cursor_offset < CH_ATTR_SIZE)
1177 s->last_ch_attr[cursor_offset] = -1;
1178 s->cursor_offset = cursor_offset;
1179 s->cursor_start = s->cr[0xa];
1180 s->cursor_end = s->cr[0xb];
1182 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1184 depth_index = get_depth_index(s->ds);
1185 if (cw == 16)
1186 vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1187 else
1188 vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1189 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1191 dest = s->ds->data;
1192 linesize = s->ds->linesize;
1193 ch_attr_ptr = s->last_ch_attr;
1194 for(cy = 0; cy < height; cy++) {
1195 d1 = dest;
1196 src = s1;
1197 cx_min = width;
1198 cx_max = -1;
1199 for(cx = 0; cx < width; cx++) {
1200 ch_attr = *(uint16_t *)src;
1201 if (full_update || ch_attr != *ch_attr_ptr) {
1202 if (cx < cx_min)
1203 cx_min = cx;
1204 if (cx > cx_max)
1205 cx_max = cx;
1206 *ch_attr_ptr = ch_attr;
1207 #ifdef WORDS_BIGENDIAN
1208 ch = ch_attr >> 8;
1209 cattr = ch_attr & 0xff;
1210 #else
1211 ch = ch_attr & 0xff;
1212 cattr = ch_attr >> 8;
1213 #endif
1214 font_ptr = font_base[(cattr >> 3) & 1];
1215 font_ptr += 32 * 4 * ch;
1216 bgcol = palette[cattr >> 4];
1217 fgcol = palette[cattr & 0x0f];
1218 if (cw != 9) {
1219 vga_draw_glyph8(d1, linesize,
1220 font_ptr, cheight, fgcol, bgcol);
1221 } else {
1222 dup9 = 0;
1223 if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1224 dup9 = 1;
1225 vga_draw_glyph9(d1, linesize,
1226 font_ptr, cheight, fgcol, bgcol, dup9);
1228 if (src == cursor_ptr &&
1229 !(s->cr[0x0a] & 0x20)) {
1230 int line_start, line_last, h;
1231 /* draw the cursor */
1232 line_start = s->cr[0x0a] & 0x1f;
1233 line_last = s->cr[0x0b] & 0x1f;
1234 /* XXX: check that */
1235 if (line_last > cheight - 1)
1236 line_last = cheight - 1;
1237 if (line_last >= line_start && line_start < cheight) {
1238 h = line_last - line_start + 1;
1239 d = d1 + linesize * line_start;
1240 if (cw != 9) {
1241 vga_draw_glyph8(d, linesize,
1242 cursor_glyph, h, fgcol, bgcol);
1243 } else {
1244 vga_draw_glyph9(d, linesize,
1245 cursor_glyph, h, fgcol, bgcol, 1);
1250 d1 += x_incr;
1251 src += 4;
1252 ch_attr_ptr++;
1254 if (cx_max != -1) {
1255 dpy_update(s->ds, cx_min * cw, cy * cheight,
1256 (cx_max - cx_min + 1) * cw, cheight);
1258 dest += linesize * cheight;
1259 s1 += line_offset;
1263 enum {
1264 VGA_DRAW_LINE2,
1265 VGA_DRAW_LINE2D2,
1266 VGA_DRAW_LINE4,
1267 VGA_DRAW_LINE4D2,
1268 VGA_DRAW_LINE8D2,
1269 VGA_DRAW_LINE8,
1270 VGA_DRAW_LINE15,
1271 VGA_DRAW_LINE16,
1272 VGA_DRAW_LINE24,
1273 VGA_DRAW_LINE32,
1274 VGA_DRAW_LINE_NB,
1277 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1278 vga_draw_line2_8,
1279 vga_draw_line2_16,
1280 vga_draw_line2_16,
1281 vga_draw_line2_32,
1282 vga_draw_line2_32,
1283 vga_draw_line2_16,
1284 vga_draw_line2_16,
1286 vga_draw_line2d2_8,
1287 vga_draw_line2d2_16,
1288 vga_draw_line2d2_16,
1289 vga_draw_line2d2_32,
1290 vga_draw_line2d2_32,
1291 vga_draw_line2d2_16,
1292 vga_draw_line2d2_16,
1294 vga_draw_line4_8,
1295 vga_draw_line4_16,
1296 vga_draw_line4_16,
1297 vga_draw_line4_32,
1298 vga_draw_line4_32,
1299 vga_draw_line4_16,
1300 vga_draw_line4_16,
1302 vga_draw_line4d2_8,
1303 vga_draw_line4d2_16,
1304 vga_draw_line4d2_16,
1305 vga_draw_line4d2_32,
1306 vga_draw_line4d2_32,
1307 vga_draw_line4d2_16,
1308 vga_draw_line4d2_16,
1310 vga_draw_line8d2_8,
1311 vga_draw_line8d2_16,
1312 vga_draw_line8d2_16,
1313 vga_draw_line8d2_32,
1314 vga_draw_line8d2_32,
1315 vga_draw_line8d2_16,
1316 vga_draw_line8d2_16,
1318 vga_draw_line8_8,
1319 vga_draw_line8_16,
1320 vga_draw_line8_16,
1321 vga_draw_line8_32,
1322 vga_draw_line8_32,
1323 vga_draw_line8_16,
1324 vga_draw_line8_16,
1326 vga_draw_line15_8,
1327 vga_draw_line15_15,
1328 vga_draw_line15_16,
1329 vga_draw_line15_32,
1330 vga_draw_line15_32bgr,
1331 vga_draw_line15_15bgr,
1332 vga_draw_line15_16bgr,
1334 vga_draw_line16_8,
1335 vga_draw_line16_15,
1336 vga_draw_line16_16,
1337 vga_draw_line16_32,
1338 vga_draw_line16_32bgr,
1339 vga_draw_line16_15bgr,
1340 vga_draw_line16_16bgr,
1342 vga_draw_line24_8,
1343 vga_draw_line24_15,
1344 vga_draw_line24_16,
1345 vga_draw_line24_32,
1346 vga_draw_line24_32bgr,
1347 vga_draw_line24_15bgr,
1348 vga_draw_line24_16bgr,
1350 vga_draw_line32_8,
1351 vga_draw_line32_15,
1352 vga_draw_line32_16,
1353 vga_draw_line32_32,
1354 vga_draw_line32_32bgr,
1355 vga_draw_line32_15bgr,
1356 vga_draw_line32_16bgr,
1359 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1361 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1362 rgb_to_pixel8_dup,
1363 rgb_to_pixel15_dup,
1364 rgb_to_pixel16_dup,
1365 rgb_to_pixel32_dup,
1366 rgb_to_pixel32bgr_dup,
1367 rgb_to_pixel15bgr_dup,
1368 rgb_to_pixel16bgr_dup,
1371 static int vga_get_bpp(VGAState *s)
1373 int ret;
1374 #ifdef CONFIG_BOCHS_VBE
1375 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1376 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1377 } else
1378 #endif
1380 ret = 0;
1382 return ret;
1385 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1387 int width, height;
1389 #ifdef CONFIG_BOCHS_VBE
1390 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1391 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1392 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1393 } else
1394 #endif
1396 width = (s->cr[0x01] + 1) * 8;
1397 height = s->cr[0x12] |
1398 ((s->cr[0x07] & 0x02) << 7) |
1399 ((s->cr[0x07] & 0x40) << 3);
1400 height = (height + 1);
1402 *pwidth = width;
1403 *pheight = height;
1406 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1408 int y;
1409 if (y1 >= VGA_MAX_HEIGHT)
1410 return;
1411 if (y2 >= VGA_MAX_HEIGHT)
1412 y2 = VGA_MAX_HEIGHT;
1413 for(y = y1; y < y2; y++) {
1414 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1418 static int bitmap_get_dirty(unsigned long *bitmap, unsigned nr)
1420 unsigned word = nr / ((sizeof bitmap[0]) * 8);
1421 unsigned bit = nr % ((sizeof bitmap[0]) * 8);
1423 //printf("%x -> %ld\n", nr, (bitmap[word] >> bit) & 1);
1424 return (bitmap[word] >> bit) & 1;
1429 * graphic modes
1431 static void vga_draw_graphic(VGAState *s, int full_update)
1433 int y1, y, update, linesize, y_start, double_scan, mask;
1434 int width, height, shift_control, line_offset, bwidth;
1435 int disp_width, multi_scan, multi_run;
1436 uint8_t *d;
1437 uint32_t v, addr1, addr;
1438 long page0, page1, page_min, page_max;
1439 vga_draw_line_func *vga_draw_line;
1440 /* HACK ALERT */
1441 #define VGA_BITMAP_SIZE ((8*1024*1024) / 4096 / 8 / sizeof(long))
1442 unsigned long bitmap[VGA_BITMAP_SIZE];
1443 #ifndef TARGET_IA64
1444 int r;
1445 if (kvm_enabled()) {
1446 r = qemu_kvm_get_dirty_pages(s->map_addr, &bitmap);
1447 if (r < 0)
1448 fprintf(stderr, "kvm: get_dirty_pages returned %d\n", r);
1450 #else
1451 memset(bitmap, 0xff, VGA_BITMAP_SIZE*sizeof(long));
1452 //FIXME:Always flush full screen before log dirty ready!!
1453 #endif
1455 full_update |= update_basic_params(s);
1457 s->get_resolution(s, &width, &height);
1458 disp_width = width;
1460 shift_control = (s->gr[0x05] >> 5) & 3;
1461 double_scan = (s->cr[0x09] >> 7);
1462 if (shift_control != 1) {
1463 multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1464 } else {
1465 /* in CGA modes, multi_scan is ignored */
1466 /* XXX: is it correct ? */
1467 multi_scan = double_scan;
1469 multi_run = multi_scan;
1470 if (shift_control != s->shift_control ||
1471 double_scan != s->double_scan) {
1472 full_update = 1;
1473 s->shift_control = shift_control;
1474 s->double_scan = double_scan;
1477 if (shift_control == 0) {
1478 full_update |= update_palette16(s);
1479 if (s->sr[0x01] & 8) {
1480 v = VGA_DRAW_LINE4D2;
1481 disp_width <<= 1;
1482 } else {
1483 v = VGA_DRAW_LINE4;
1485 } else if (shift_control == 1) {
1486 full_update |= update_palette16(s);
1487 if (s->sr[0x01] & 8) {
1488 v = VGA_DRAW_LINE2D2;
1489 disp_width <<= 1;
1490 } else {
1491 v = VGA_DRAW_LINE2;
1493 } else {
1494 switch(s->get_bpp(s)) {
1495 default:
1496 case 0:
1497 full_update |= update_palette256(s);
1498 v = VGA_DRAW_LINE8D2;
1499 break;
1500 case 8:
1501 full_update |= update_palette256(s);
1502 v = VGA_DRAW_LINE8;
1503 break;
1504 case 15:
1505 v = VGA_DRAW_LINE15;
1506 break;
1507 case 16:
1508 v = VGA_DRAW_LINE16;
1509 break;
1510 case 24:
1511 v = VGA_DRAW_LINE24;
1512 break;
1513 case 32:
1514 v = VGA_DRAW_LINE32;
1515 break;
1518 vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1520 if (disp_width != s->last_width ||
1521 height != s->last_height) {
1522 dpy_resize(s->ds, disp_width, height);
1523 s->last_scr_width = disp_width;
1524 s->last_scr_height = height;
1525 s->last_width = disp_width;
1526 s->last_height = height;
1527 full_update = 1;
1529 if (s->cursor_invalidate)
1530 s->cursor_invalidate(s);
1532 line_offset = s->line_offset;
1533 #if 0
1534 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",
1535 width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1536 #endif
1537 addr1 = (s->start_addr * 4);
1538 bwidth = width * 4;
1539 y_start = -1;
1540 page_min = 0x7fffffff;
1541 page_max = -1;
1542 d = s->ds->data;
1543 linesize = s->ds->linesize;
1544 y1 = 0;
1545 for(y = 0; y < height; y++) {
1546 addr = addr1;
1547 if (!(s->cr[0x17] & 1)) {
1548 int shift;
1549 /* CGA compatibility handling */
1550 shift = 14 + ((s->cr[0x17] >> 6) & 1);
1551 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1553 if (!(s->cr[0x17] & 2)) {
1554 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1556 page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1557 page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1558 update = full_update |
1559 cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1560 cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1561 if (kvm_enabled()) {
1562 update |= bitmap_get_dirty(bitmap, (page0 - s->vram_offset) >> TARGET_PAGE_BITS);
1563 update |= bitmap_get_dirty(bitmap, (page1 - s->vram_offset) >> TARGET_PAGE_BITS);
1566 if ((page1 - page0) > TARGET_PAGE_SIZE) {
1567 /* if wide line, can use another page */
1568 update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1569 VGA_DIRTY_FLAG);
1570 if (kvm_enabled())
1571 update |= bitmap_get_dirty(bitmap, (page0 - s->vram_offset) >> TARGET_PAGE_BITS);
1573 /* explicit invalidation for the hardware cursor */
1574 update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1575 if (update) {
1576 if (y_start < 0)
1577 y_start = y;
1578 if (page0 < page_min)
1579 page_min = page0;
1580 if (page1 > page_max)
1581 page_max = page1;
1582 vga_draw_line(s, d, s->vram_ptr + addr, width);
1583 if (s->cursor_draw_line)
1584 s->cursor_draw_line(s, d, y);
1585 } else {
1586 if (y_start >= 0) {
1587 /* flush to display */
1588 dpy_update(s->ds, 0, y_start,
1589 disp_width, y - y_start);
1590 y_start = -1;
1593 if (!multi_run) {
1594 mask = (s->cr[0x17] & 3) ^ 3;
1595 if ((y1 & mask) == mask)
1596 addr1 += line_offset;
1597 y1++;
1598 multi_run = multi_scan;
1599 } else {
1600 multi_run--;
1602 /* line compare acts on the displayed lines */
1603 if (y == s->line_compare)
1604 addr1 = 0;
1605 d += linesize;
1607 if (y_start >= 0) {
1608 /* flush to display */
1609 dpy_update(s->ds, 0, y_start,
1610 disp_width, y - y_start);
1612 /* reset modified pages */
1613 if (page_max != -1) {
1614 cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1615 VGA_DIRTY_FLAG);
1617 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1620 static void vga_draw_blank(VGAState *s, int full_update)
1622 int i, w, val;
1623 uint8_t *d;
1625 if (!full_update)
1626 return;
1627 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1628 return;
1629 if (s->ds->depth == 8)
1630 val = s->rgb_to_pixel(0, 0, 0);
1631 else
1632 val = 0;
1633 w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1634 d = s->ds->data;
1635 for(i = 0; i < s->last_scr_height; i++) {
1636 memset(d, val, w);
1637 d += s->ds->linesize;
1639 dpy_update(s->ds, 0, 0,
1640 s->last_scr_width, s->last_scr_height);
1643 #define GMODE_TEXT 0
1644 #define GMODE_GRAPH 1
1645 #define GMODE_BLANK 2
1647 static void vga_update_display(void *opaque)
1649 VGAState *s = (VGAState *)opaque;
1650 int full_update, graphic_mode;
1652 if (s->ds->depth == 0) {
1653 /* nothing to do */
1654 } else {
1655 s->rgb_to_pixel =
1656 rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1658 full_update = 0;
1659 if (!(s->ar_index & 0x20)) {
1660 graphic_mode = GMODE_BLANK;
1661 } else {
1662 graphic_mode = s->gr[6] & 1;
1664 if (graphic_mode != s->graphic_mode) {
1665 s->graphic_mode = graphic_mode;
1666 full_update = 1;
1668 switch(graphic_mode) {
1669 case GMODE_TEXT:
1670 vga_draw_text(s, full_update);
1671 break;
1672 case GMODE_GRAPH:
1673 vga_draw_graphic(s, full_update);
1674 break;
1675 case GMODE_BLANK:
1676 default:
1677 vga_draw_blank(s, full_update);
1678 break;
1683 /* force a full display refresh */
1684 static void vga_invalidate_display(void *opaque)
1686 VGAState *s = (VGAState *)opaque;
1688 s->last_width = -1;
1689 s->last_height = -1;
1692 static void vga_reset(VGAState *s)
1694 memset(s, 0, sizeof(VGAState));
1695 s->graphic_mode = -1; /* force full update */
1698 static CPUReadMemoryFunc *vga_mem_read[3] = {
1699 vga_mem_readb,
1700 vga_mem_readw,
1701 vga_mem_readl,
1704 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1705 vga_mem_writeb,
1706 vga_mem_writew,
1707 vga_mem_writel,
1710 static void vga_save(QEMUFile *f, void *opaque)
1712 VGAState *s = opaque;
1713 int i;
1715 if (s->pci_dev)
1716 pci_device_save(s->pci_dev, f);
1718 qemu_put_be32s(f, &s->latch);
1719 qemu_put_8s(f, &s->sr_index);
1720 qemu_put_buffer(f, s->sr, 8);
1721 qemu_put_8s(f, &s->gr_index);
1722 qemu_put_buffer(f, s->gr, 16);
1723 qemu_put_8s(f, &s->ar_index);
1724 qemu_put_buffer(f, s->ar, 21);
1725 qemu_put_be32(f, s->ar_flip_flop);
1726 qemu_put_8s(f, &s->cr_index);
1727 qemu_put_buffer(f, s->cr, 256);
1728 qemu_put_8s(f, &s->msr);
1729 qemu_put_8s(f, &s->fcr);
1730 qemu_put_byte(f, s->st00);
1731 qemu_put_8s(f, &s->st01);
1733 qemu_put_8s(f, &s->dac_state);
1734 qemu_put_8s(f, &s->dac_sub_index);
1735 qemu_put_8s(f, &s->dac_read_index);
1736 qemu_put_8s(f, &s->dac_write_index);
1737 qemu_put_buffer(f, s->dac_cache, 3);
1738 qemu_put_buffer(f, s->palette, 768);
1740 qemu_put_be32(f, s->bank_offset);
1741 #ifdef CONFIG_BOCHS_VBE
1742 qemu_put_byte(f, 1);
1743 qemu_put_be16s(f, &s->vbe_index);
1744 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1745 qemu_put_be16s(f, &s->vbe_regs[i]);
1746 qemu_put_be32s(f, &s->vbe_start_addr);
1747 qemu_put_be32s(f, &s->vbe_line_offset);
1748 qemu_put_be32s(f, &s->vbe_bank_mask);
1749 #else
1750 qemu_put_byte(f, 0);
1751 #endif
1754 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1756 VGAState *s = opaque;
1757 int is_vbe, i, ret;
1759 if (version_id > 2)
1760 return -EINVAL;
1762 if (s->pci_dev && version_id >= 2) {
1763 ret = pci_device_load(s->pci_dev, f);
1764 if (ret < 0)
1765 return ret;
1768 qemu_get_be32s(f, &s->latch);
1769 qemu_get_8s(f, &s->sr_index);
1770 qemu_get_buffer(f, s->sr, 8);
1771 qemu_get_8s(f, &s->gr_index);
1772 qemu_get_buffer(f, s->gr, 16);
1773 qemu_get_8s(f, &s->ar_index);
1774 qemu_get_buffer(f, s->ar, 21);
1775 s->ar_flip_flop=qemu_get_be32(f);
1776 qemu_get_8s(f, &s->cr_index);
1777 qemu_get_buffer(f, s->cr, 256);
1778 qemu_get_8s(f, &s->msr);
1779 qemu_get_8s(f, &s->fcr);
1780 qemu_get_8s(f, &s->st00);
1781 qemu_get_8s(f, &s->st01);
1783 qemu_get_8s(f, &s->dac_state);
1784 qemu_get_8s(f, &s->dac_sub_index);
1785 qemu_get_8s(f, &s->dac_read_index);
1786 qemu_get_8s(f, &s->dac_write_index);
1787 qemu_get_buffer(f, s->dac_cache, 3);
1788 qemu_get_buffer(f, s->palette, 768);
1790 s->bank_offset=qemu_get_be32(f);
1791 is_vbe = qemu_get_byte(f);
1792 #ifdef CONFIG_BOCHS_VBE
1793 if (!is_vbe)
1794 return -EINVAL;
1795 qemu_get_be16s(f, &s->vbe_index);
1796 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1797 qemu_get_be16s(f, &s->vbe_regs[i]);
1798 qemu_get_be32s(f, &s->vbe_start_addr);
1799 qemu_get_be32s(f, &s->vbe_line_offset);
1800 qemu_get_be32s(f, &s->vbe_bank_mask);
1801 #else
1802 if (is_vbe)
1803 return -EINVAL;
1804 #endif
1806 /* force refresh */
1807 s->graphic_mode = -1;
1808 return 0;
1811 typedef struct PCIVGAState {
1812 PCIDevice dev;
1813 VGAState vga_state;
1814 } PCIVGAState;
1816 static void vga_map(PCIDevice *pci_dev, int region_num,
1817 uint32_t addr, uint32_t size, int type)
1819 PCIVGAState *d = (PCIVGAState *)pci_dev;
1820 VGAState *s = &d->vga_state;
1821 if (region_num == PCI_ROM_SLOT) {
1822 cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1823 } else {
1824 cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1825 if (kvm_enabled()) {
1826 unsigned long vga_ram_begin, vga_ram_end;
1827 void *vram_pointer, *old_vram;
1829 vga_ram_begin = addr;
1830 vga_ram_end = addr + VGA_RAM_SIZE;
1832 if (vga_ram_begin == s->map_addr &&
1833 vga_ram_end == s->map_end) {
1834 return;
1837 if (s->map_addr && s->map_end)
1838 unset_vram_mapping(s->map_addr, s->map_end);
1840 vram_pointer = set_vram_mapping(vga_ram_begin, vga_ram_end);
1841 if (!vram_pointer) {
1842 fprintf(stderr, "set_vram_mapping failed\n");
1843 s->map_addr = s->map_end = 0;
1845 else {
1846 old_vram = vga_update_vram((VGAState *)s, vram_pointer,
1847 VGA_RAM_SIZE);
1848 if (s->map_addr && s->map_end)
1849 munmap(old_vram, s->map_end - s->map_addr);
1850 else
1851 qemu_free(old_vram);
1852 s->map_addr = vga_ram_begin;
1853 s->map_end = vga_ram_end;
1859 #ifdef TARGET_IA64
1860 /* do the same job as vgabios before vgabios get ready - yeah */
1861 void vga_bios_init(VGAState *s)
1863 uint8_t palette_model[192] = {
1864 0, 0, 0, 0, 0, 170, 0, 170,
1865 0, 0, 170, 170, 170, 0, 0, 170,
1866 0, 170, 170, 85, 0, 170, 170, 170,
1867 85, 85, 85, 85, 85, 255, 85, 255,
1868 85, 85, 255, 255, 255, 85, 85, 255,
1869 85, 255, 255, 255, 85, 255, 255, 255,
1870 0, 21, 0, 0, 21, 42, 0, 63,
1871 0, 0, 63, 42, 42, 21, 0, 42,
1872 21, 42, 42, 63, 0, 42, 63, 42,
1873 0, 21, 21, 0, 21, 63, 0, 63,
1874 21, 0, 63, 63, 42, 21, 21, 42,
1875 21, 63, 42, 63, 21, 42, 63, 63,
1876 21, 0, 0, 21, 0, 42, 21, 42,
1877 0, 21, 42, 42, 63, 0, 0, 63,
1878 0, 42, 63, 42, 0, 63, 42, 42,
1879 21, 0, 21, 21, 0, 63, 21, 42,
1880 21, 21, 42, 63, 63, 0, 21, 63,
1881 0, 63, 63, 42, 21, 63, 42, 63,
1882 21, 21, 0, 21, 21, 42, 21, 63,
1883 0, 21, 63, 42, 63, 21, 0, 63,
1884 21, 42, 63, 63, 0, 63, 63, 42,
1885 21, 21, 21, 21, 21, 63, 21, 63,
1886 21, 21, 63, 63, 63, 21, 21, 63,
1887 21, 63, 63, 63, 21, 63, 63, 63
1890 s->latch = 0;
1892 s->sr_index = 3;
1893 s->sr[0] = 3;
1894 s->sr[1] = 0;
1895 s->sr[2] = 3;
1896 s->sr[3] = 0;
1897 s->sr[4] = 2;
1898 s->sr[5] = 0;
1899 s->sr[6] = 0;
1900 s->sr[7] = 0;
1902 s->gr_index = 5;
1903 s->gr[0] = 0;
1904 s->gr[1] = 0;
1905 s->gr[2] = 0;
1906 s->gr[3] = 0;
1907 s->gr[4] = 0;
1908 s->gr[5] = 16;
1909 s->gr[6] = 14;
1910 s->gr[7] = 15;
1911 s->gr[8] = 255;
1913 /* changed by out 0x03c0 */
1914 s->ar_index = 32;
1915 s->ar[0] = 0;
1916 s->ar[1] = 1;
1917 s->ar[2] = 2;
1918 s->ar[3] = 3;
1919 s->ar[4] = 4;
1920 s->ar[5] = 5;
1921 s->ar[6] = 6;
1922 s->ar[7] = 7;
1923 s->ar[8] = 8;
1924 s->ar[9] = 9;
1925 s->ar[10] = 10;
1926 s->ar[11] = 11;
1927 s->ar[12] = 12;
1928 s->ar[13] = 13;
1929 s->ar[14] = 14;
1930 s->ar[15] = 15;
1931 s->ar[16] = 12;
1932 s->ar[17] = 0;
1933 s->ar[18] = 15;
1934 s->ar[19] = 8;
1935 s->ar[20] = 0;
1937 s->ar_flip_flop = 1;
1939 s->cr_index = 15;
1940 s->cr[0] = 95;
1941 s->cr[1] = 79;
1942 s->cr[2] = 80;
1943 s->cr[3] = 130;
1944 s->cr[4] = 85;
1945 s->cr[5] = 129;
1946 s->cr[6] = 191;
1947 s->cr[7] = 31;
1948 s->cr[8] = 0;
1949 s->cr[9] = 79;
1950 s->cr[10] = 14;
1951 s->cr[11] = 15;
1952 s->cr[12] = 0;
1953 s->cr[13] = 0;
1954 s->cr[14] = 5;
1955 s->cr[15] = 160;
1956 s->cr[16] = 156;
1957 s->cr[17] = 142;
1958 s->cr[18] = 143;
1959 s->cr[19] = 40;
1960 s->cr[20] = 31;
1961 s->cr[21] = 150;
1962 s->cr[22] = 185;
1963 s->cr[23] = 163;
1964 s->cr[24] = 255;
1966 s->msr = 103;
1967 s->fcr = 0;
1968 s->st00 = 0;
1969 s->st01 = 0;
1971 /* dac_* & palette will be initialized by os through out 0x03c8 &
1972 * out 0c03c9(1:3) */
1973 s->dac_state = 0;
1974 s->dac_sub_index = 0;
1975 s->dac_read_index = 0;
1976 s->dac_write_index = 16;
1977 s->dac_cache[0] = 255;
1978 s->dac_cache[1] = 255;
1979 s->dac_cache[2] = 255;
1981 /* palette */
1982 memcpy(s->palette, palette_model, 192);
1984 s->bank_offset = 0;
1985 s->graphic_mode = -1;
1987 /* TODO: add vbe support if enabled */
1989 #endif
1991 /* when used on xen/kvm environment, the vga_ram_base is not used */
1992 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1993 unsigned long vga_ram_offset, int vga_ram_size)
1995 int i, j, v, b;
1997 for(i = 0;i < 256; i++) {
1998 v = 0;
1999 for(j = 0; j < 8; j++) {
2000 v |= ((i >> j) & 1) << (j * 4);
2002 expand4[i] = v;
2004 v = 0;
2005 for(j = 0; j < 4; j++) {
2006 v |= ((i >> (2 * j)) & 3) << (j * 4);
2008 expand2[i] = v;
2010 for(i = 0; i < 16; i++) {
2011 v = 0;
2012 for(j = 0; j < 4; j++) {
2013 b = ((i >> j) & 1);
2014 v |= b << (2 * j);
2015 v |= b << (2 * j + 1);
2017 expand4to8[i] = v;
2020 vga_reset(s);
2022 if (kvm_enabled())
2023 s->vram_ptr = qemu_malloc(vga_ram_size);
2024 else
2025 s->vram_ptr = vga_ram_base;
2026 s->vram_offset = vga_ram_offset;
2027 s->vram_size = vga_ram_size;
2028 s->ds = ds;
2029 s->get_bpp = vga_get_bpp;
2030 s->get_offsets = vga_get_offsets;
2031 s->get_resolution = vga_get_resolution;
2032 s->update = vga_update_display;
2033 s->invalidate = vga_invalidate_display;
2034 s->screen_dump = vga_screen_dump;
2035 #ifdef TARGET_IA64
2036 vga_bios_init(s);
2037 #endif
2040 /* used by both ISA and PCI */
2041 void vga_init(VGAState *s)
2043 int vga_io_memory;
2045 register_savevm("vga", 0, 2, vga_save, vga_load, s);
2047 register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2049 register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2050 register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2051 register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2052 register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2054 register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2056 register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2057 register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2058 register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2059 register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2060 s->bank_offset = 0;
2062 #ifdef CONFIG_BOCHS_VBE
2063 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
2064 s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
2065 #if defined (TARGET_I386)
2066 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2067 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2069 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2070 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2072 /* old Bochs IO ports */
2073 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2074 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2076 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2077 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2078 #else
2079 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2080 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2082 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2083 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2084 #endif
2085 #endif /* CONFIG_BOCHS_VBE */
2087 vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2088 cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2089 vga_io_memory);
2092 /* Memory mapped interface */
2093 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2095 VGAState *s = opaque;
2097 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
2100 static void vga_mm_writeb (void *opaque,
2101 target_phys_addr_t addr, uint32_t value)
2103 VGAState *s = opaque;
2105 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
2108 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2110 VGAState *s = opaque;
2112 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
2115 static void vga_mm_writew (void *opaque,
2116 target_phys_addr_t addr, uint32_t value)
2118 VGAState *s = opaque;
2120 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
2123 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2125 VGAState *s = opaque;
2127 return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
2130 static void vga_mm_writel (void *opaque,
2131 target_phys_addr_t addr, uint32_t value)
2133 VGAState *s = opaque;
2135 vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
2138 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2139 &vga_mm_readb,
2140 &vga_mm_readw,
2141 &vga_mm_readl,
2144 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2145 &vga_mm_writeb,
2146 &vga_mm_writew,
2147 &vga_mm_writel,
2150 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2151 target_phys_addr_t ctrl_base, int it_shift)
2153 int s_ioport_ctrl, vga_io_memory;
2155 s->base_ctrl = ctrl_base;
2156 s->it_shift = it_shift;
2157 s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2158 vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2160 register_savevm("vga", 0, 2, vga_save, vga_load, s);
2162 cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2163 s->bank_offset = 0;
2164 cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2167 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2168 unsigned long vga_ram_offset, int vga_ram_size)
2170 VGAState *s;
2172 s = qemu_mallocz(sizeof(VGAState));
2173 if (!s)
2174 return -1;
2176 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2177 vga_init(s);
2179 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
2181 #ifdef CONFIG_BOCHS_VBE
2182 /* XXX: use optimized standard vga accesses */
2183 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2184 vga_ram_size, vga_ram_offset);
2185 #endif
2186 return 0;
2189 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2190 unsigned long vga_ram_offset, int vga_ram_size,
2191 target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2192 int it_shift)
2194 VGAState *s;
2196 s = qemu_mallocz(sizeof(VGAState));
2197 if (!s)
2198 return -1;
2200 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2201 vga_mm_init(s, vram_base, ctrl_base, it_shift);
2203 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
2205 #ifdef CONFIG_BOCHS_VBE
2206 /* XXX: use optimized standard vga accesses */
2207 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2208 vga_ram_size, vga_ram_offset);
2209 #endif
2210 return 0;
2213 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2214 unsigned long vga_ram_offset, int vga_ram_size,
2215 unsigned long vga_bios_offset, int vga_bios_size)
2217 PCIVGAState *d;
2218 VGAState *s;
2219 uint8_t *pci_conf;
2221 d = (PCIVGAState *)pci_register_device(bus, "VGA",
2222 sizeof(PCIVGAState),
2223 -1, NULL, NULL);
2224 if (!d)
2225 return -1;
2226 s = &d->vga_state;
2228 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2229 vga_init(s);
2231 graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
2233 s->pci_dev = &d->dev;
2235 pci_conf = d->dev.config;
2236 pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2237 pci_conf[0x01] = 0x12;
2238 pci_conf[0x02] = 0x11;
2239 pci_conf[0x03] = 0x11;
2240 pci_conf[0x0a] = 0x00; // VGA controller
2241 pci_conf[0x0b] = 0x03;
2242 pci_conf[0x0e] = 0x00; // header_type
2244 /* XXX: vga_ram_size must be a power of two */
2245 pci_register_io_region(&d->dev, 0, vga_ram_size,
2246 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2247 if (vga_bios_size != 0) {
2248 unsigned int bios_total_size;
2249 s->bios_offset = vga_bios_offset;
2250 s->bios_size = vga_bios_size;
2251 /* must be a power of two */
2252 bios_total_size = 1;
2253 while (bios_total_size < vga_bios_size)
2254 bios_total_size <<= 1;
2255 pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2256 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2258 return 0;
2261 void *vga_update_vram(VGAState *s, void *vga_ram_base, int vga_ram_size)
2263 uint8_t *old_pointer;
2265 if (s->vram_size != vga_ram_size) {
2266 fprintf(stderr, "No support to change vga_ram_size\n");
2267 return NULL;
2270 if (!vga_ram_base) {
2271 vga_ram_base = qemu_malloc(vga_ram_size);
2272 if (!vga_ram_base) {
2273 fprintf(stderr, "reallocate error\n");
2274 return NULL;
2278 /* XXX lock needed? */
2279 memcpy(vga_ram_base, s->vram_ptr, vga_ram_size);
2280 old_pointer = s->vram_ptr;
2281 s->vram_ptr = vga_ram_base;
2283 return old_pointer;
2286 /********************************************************/
2287 /* vga screen dump */
2289 static int vga_save_w, vga_save_h;
2291 static void vga_save_dpy_update(DisplayState *s,
2292 int x, int y, int w, int h)
2296 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2298 s->linesize = w * 4;
2299 s->data = qemu_malloc(h * s->linesize);
2300 vga_save_w = w;
2301 vga_save_h = h;
2304 static void vga_save_dpy_refresh(DisplayState *s)
2308 int ppm_save(const char *filename, uint8_t *data,
2309 int w, int h, int linesize)
2311 FILE *f;
2312 uint8_t *d, *d1;
2313 unsigned int v;
2314 int y, x;
2316 f = fopen(filename, "wb");
2317 if (!f)
2318 return -1;
2319 fprintf(f, "P6\n%d %d\n%d\n",
2320 w, h, 255);
2321 d1 = data;
2322 for(y = 0; y < h; y++) {
2323 d = d1;
2324 for(x = 0; x < w; x++) {
2325 v = *(uint32_t *)d;
2326 fputc((v >> 16) & 0xff, f);
2327 fputc((v >> 8) & 0xff, f);
2328 fputc((v) & 0xff, f);
2329 d += 4;
2331 d1 += linesize;
2333 fclose(f);
2334 return 0;
2337 /* save the vga display in a PPM image even if no display is
2338 available */
2339 static void vga_screen_dump(void *opaque, const char *filename)
2341 VGAState *s = (VGAState *)opaque;
2342 DisplayState *saved_ds, ds1, *ds = &ds1;
2344 /* XXX: this is a little hackish */
2345 vga_invalidate_display(s);
2346 saved_ds = s->ds;
2348 memset(ds, 0, sizeof(DisplayState));
2349 ds->dpy_update = vga_save_dpy_update;
2350 ds->dpy_resize = vga_save_dpy_resize;
2351 ds->dpy_refresh = vga_save_dpy_refresh;
2352 ds->depth = 32;
2354 s->ds = ds;
2355 s->graphic_mode = -1;
2356 vga_update_display(s);
2358 if (ds->data) {
2359 ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2360 s->ds->linesize);
2361 qemu_free(ds->data);
2363 s->ds = saved_ds;