]> git.proxmox.com Git - qemu.git/blob - hw/vga.c
2a0a9c3d01021f63e36a615fa2d2ea5a36ecbf87
[qemu.git] / hw / vga.c
1 /*
2 * QEMU VGA Emulator.
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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.
23 */
24 #include "vl.h"
25 #include "vga_int.h"
26
27 //#define DEBUG_VGA
28 //#define DEBUG_VGA_MEM
29 //#define DEBUG_VGA_REG
30
31 //#define DEBUG_S3
32 //#define DEBUG_BOCHS_VBE
33
34 /* S3 VGA is deprecated - another graphic card will be emulated */
35 //#define CONFIG_S3VGA
36
37 /* force some bits to zero */
38 const uint8_t sr_mask[8] = {
39 (uint8_t)~0xfc,
40 (uint8_t)~0xc2,
41 (uint8_t)~0xf0,
42 (uint8_t)~0xc0,
43 (uint8_t)~0xf1,
44 (uint8_t)~0xff,
45 (uint8_t)~0xff,
46 (uint8_t)~0x00,
47 };
48
49 const uint8_t gr_mask[16] = {
50 (uint8_t)~0xf0, /* 0x00 */
51 (uint8_t)~0xf0, /* 0x01 */
52 (uint8_t)~0xf0, /* 0x02 */
53 (uint8_t)~0xe0, /* 0x03 */
54 (uint8_t)~0xfc, /* 0x04 */
55 (uint8_t)~0x84, /* 0x05 */
56 (uint8_t)~0xf0, /* 0x06 */
57 (uint8_t)~0xf0, /* 0x07 */
58 (uint8_t)~0x00, /* 0x08 */
59 (uint8_t)~0xff, /* 0x09 */
60 (uint8_t)~0xff, /* 0x0a */
61 (uint8_t)~0xff, /* 0x0b */
62 (uint8_t)~0xff, /* 0x0c */
63 (uint8_t)~0xff, /* 0x0d */
64 (uint8_t)~0xff, /* 0x0e */
65 (uint8_t)~0xff, /* 0x0f */
66 };
67
68 #define cbswap_32(__x) \
69 ((uint32_t)( \
70 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
71 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
72 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
73 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
74
75 #ifdef WORDS_BIGENDIAN
76 #define PAT(x) cbswap_32(x)
77 #else
78 #define PAT(x) (x)
79 #endif
80
81 #ifdef WORDS_BIGENDIAN
82 #define BIG 1
83 #else
84 #define BIG 0
85 #endif
86
87 #ifdef WORDS_BIGENDIAN
88 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
89 #else
90 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
91 #endif
92
93 static const uint32_t mask16[16] = {
94 PAT(0x00000000),
95 PAT(0x000000ff),
96 PAT(0x0000ff00),
97 PAT(0x0000ffff),
98 PAT(0x00ff0000),
99 PAT(0x00ff00ff),
100 PAT(0x00ffff00),
101 PAT(0x00ffffff),
102 PAT(0xff000000),
103 PAT(0xff0000ff),
104 PAT(0xff00ff00),
105 PAT(0xff00ffff),
106 PAT(0xffff0000),
107 PAT(0xffff00ff),
108 PAT(0xffffff00),
109 PAT(0xffffffff),
110 };
111
112 #undef PAT
113
114 #ifdef WORDS_BIGENDIAN
115 #define PAT(x) (x)
116 #else
117 #define PAT(x) cbswap_32(x)
118 #endif
119
120 static const uint32_t dmask16[16] = {
121 PAT(0x00000000),
122 PAT(0x000000ff),
123 PAT(0x0000ff00),
124 PAT(0x0000ffff),
125 PAT(0x00ff0000),
126 PAT(0x00ff00ff),
127 PAT(0x00ffff00),
128 PAT(0x00ffffff),
129 PAT(0xff000000),
130 PAT(0xff0000ff),
131 PAT(0xff00ff00),
132 PAT(0xff00ffff),
133 PAT(0xffff0000),
134 PAT(0xffff00ff),
135 PAT(0xffffff00),
136 PAT(0xffffffff),
137 };
138
139 static const uint32_t dmask4[4] = {
140 PAT(0x00000000),
141 PAT(0x0000ffff),
142 PAT(0xffff0000),
143 PAT(0xffffffff),
144 };
145
146 static uint32_t expand4[256];
147 static uint16_t expand2[256];
148 static uint8_t expand4to8[16];
149
150 VGAState *vga_state;
151 int vga_io_memory;
152
153 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
154 {
155 VGAState *s = opaque;
156 int val, index;
157
158 /* check port range access depending on color/monochrome mode */
159 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
160 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
161 val = 0xff;
162 } else {
163 switch(addr) {
164 case 0x3c0:
165 if (s->ar_flip_flop == 0) {
166 val = s->ar_index;
167 } else {
168 val = 0;
169 }
170 break;
171 case 0x3c1:
172 index = s->ar_index & 0x1f;
173 if (index < 21)
174 val = s->ar[index];
175 else
176 val = 0;
177 break;
178 case 0x3c2:
179 val = s->st00;
180 break;
181 case 0x3c4:
182 val = s->sr_index;
183 break;
184 case 0x3c5:
185 val = s->sr[s->sr_index];
186 #ifdef DEBUG_VGA_REG
187 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
188 #endif
189 break;
190 case 0x3c7:
191 val = s->dac_state;
192 break;
193 case 0x3c8:
194 val = s->dac_write_index;
195 break;
196 case 0x3c9:
197 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
198 if (++s->dac_sub_index == 3) {
199 s->dac_sub_index = 0;
200 s->dac_read_index++;
201 }
202 break;
203 case 0x3ca:
204 val = s->fcr;
205 break;
206 case 0x3cc:
207 val = s->msr;
208 break;
209 case 0x3ce:
210 val = s->gr_index;
211 break;
212 case 0x3cf:
213 val = s->gr[s->gr_index];
214 #ifdef DEBUG_VGA_REG
215 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
216 #endif
217 break;
218 case 0x3b4:
219 case 0x3d4:
220 val = s->cr_index;
221 break;
222 case 0x3b5:
223 case 0x3d5:
224 val = s->cr[s->cr_index];
225 #ifdef DEBUG_VGA_REG
226 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
227 #endif
228 #ifdef DEBUG_S3
229 if (s->cr_index >= 0x20)
230 printf("S3: CR read index=0x%x val=0x%x\n",
231 s->cr_index, val);
232 #endif
233 break;
234 case 0x3ba:
235 case 0x3da:
236 /* just toggle to fool polling */
237 s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
238 val = s->st01;
239 s->ar_flip_flop = 0;
240 break;
241 default:
242 val = 0x00;
243 break;
244 }
245 }
246 #if defined(DEBUG_VGA)
247 printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
248 #endif
249 return val;
250 }
251
252 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
253 {
254 VGAState *s = opaque;
255 int index;
256
257 /* check port range access depending on color/monochrome mode */
258 if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
259 (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
260 return;
261
262 #ifdef DEBUG_VGA
263 printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
264 #endif
265
266 switch(addr) {
267 case 0x3c0:
268 if (s->ar_flip_flop == 0) {
269 val &= 0x3f;
270 s->ar_index = val;
271 } else {
272 index = s->ar_index & 0x1f;
273 switch(index) {
274 case 0x00 ... 0x0f:
275 s->ar[index] = val & 0x3f;
276 break;
277 case 0x10:
278 s->ar[index] = val & ~0x10;
279 break;
280 case 0x11:
281 s->ar[index] = val;
282 break;
283 case 0x12:
284 s->ar[index] = val & ~0xc0;
285 break;
286 case 0x13:
287 s->ar[index] = val & ~0xf0;
288 break;
289 case 0x14:
290 s->ar[index] = val & ~0xf0;
291 break;
292 default:
293 break;
294 }
295 }
296 s->ar_flip_flop ^= 1;
297 break;
298 case 0x3c2:
299 s->msr = val & ~0x10;
300 break;
301 case 0x3c4:
302 s->sr_index = val & 7;
303 break;
304 case 0x3c5:
305 #ifdef DEBUG_VGA_REG
306 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
307 #endif
308 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
309 break;
310 case 0x3c7:
311 s->dac_read_index = val;
312 s->dac_sub_index = 0;
313 s->dac_state = 3;
314 break;
315 case 0x3c8:
316 s->dac_write_index = val;
317 s->dac_sub_index = 0;
318 s->dac_state = 0;
319 break;
320 case 0x3c9:
321 s->dac_cache[s->dac_sub_index] = val;
322 if (++s->dac_sub_index == 3) {
323 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
324 s->dac_sub_index = 0;
325 s->dac_write_index++;
326 }
327 break;
328 case 0x3ce:
329 s->gr_index = val & 0x0f;
330 break;
331 case 0x3cf:
332 #ifdef DEBUG_VGA_REG
333 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
334 #endif
335 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
336 break;
337 case 0x3b4:
338 case 0x3d4:
339 s->cr_index = val;
340 break;
341 case 0x3b5:
342 case 0x3d5:
343 #ifdef DEBUG_VGA_REG
344 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
345 #endif
346 /* handle CR0-7 protection */
347 if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
348 /* can always write bit 4 of CR7 */
349 if (s->cr_index == 7)
350 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
351 return;
352 }
353 switch(s->cr_index) {
354 case 0x01: /* horizontal display end */
355 case 0x07:
356 case 0x09:
357 case 0x0c:
358 case 0x0d:
359 case 0x12: /* veritcal display end */
360 s->cr[s->cr_index] = val;
361 break;
362
363 #ifdef CONFIG_S3VGA
364 /* S3 registers */
365 case 0x2d:
366 case 0x2e:
367 case 0x2f:
368 case 0x30:
369 /* chip ID, cannot write */
370 break;
371 case 0x31:
372 /* update start address */
373 {
374 int v;
375 s->cr[s->cr_index] = val;
376 v = (val >> 4) & 3;
377 s->cr[0x69] = (s->cr[69] & ~0x03) | v;
378 }
379 break;
380 case 0x51:
381 /* update start address */
382 {
383 int v;
384 s->cr[s->cr_index] = val;
385 v = val & 3;
386 s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
387 }
388 break;
389 #endif
390 default:
391 s->cr[s->cr_index] = val;
392 break;
393 }
394 #ifdef DEBUG_S3
395 if (s->cr_index >= 0x20)
396 printf("S3: CR write index=0x%x val=0x%x\n",
397 s->cr_index, val);
398 #endif
399 break;
400 case 0x3ba:
401 case 0x3da:
402 s->fcr = val & 0x10;
403 break;
404 }
405 }
406
407 #ifdef CONFIG_BOCHS_VBE
408 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
409 {
410 VGAState *s = opaque;
411 uint32_t val;
412 val = s->vbe_index;
413 return val;
414 }
415
416 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
417 {
418 VGAState *s = opaque;
419 uint32_t val;
420
421 if (s->vbe_index <= VBE_DISPI_INDEX_NB)
422 val = s->vbe_regs[s->vbe_index];
423 else
424 val = 0;
425 #ifdef DEBUG_BOCHS_VBE
426 printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
427 #endif
428 return val;
429 }
430
431 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
432 {
433 VGAState *s = opaque;
434 s->vbe_index = val;
435 }
436
437 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
438 {
439 VGAState *s = opaque;
440
441 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
442 #ifdef DEBUG_BOCHS_VBE
443 printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
444 #endif
445 switch(s->vbe_index) {
446 case VBE_DISPI_INDEX_ID:
447 if (val == VBE_DISPI_ID0 ||
448 val == VBE_DISPI_ID1 ||
449 val == VBE_DISPI_ID2) {
450 s->vbe_regs[s->vbe_index] = val;
451 }
452 break;
453 case VBE_DISPI_INDEX_XRES:
454 if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
455 s->vbe_regs[s->vbe_index] = val;
456 }
457 break;
458 case VBE_DISPI_INDEX_YRES:
459 if (val <= VBE_DISPI_MAX_YRES) {
460 s->vbe_regs[s->vbe_index] = val;
461 }
462 break;
463 case VBE_DISPI_INDEX_BPP:
464 if (val == 0)
465 val = 8;
466 if (val == 4 || val == 8 || val == 15 ||
467 val == 16 || val == 24 || val == 32) {
468 s->vbe_regs[s->vbe_index] = val;
469 }
470 break;
471 case VBE_DISPI_INDEX_BANK:
472 val &= s->vbe_bank_mask;
473 s->vbe_regs[s->vbe_index] = val;
474 s->bank_offset = (val << 16);
475 break;
476 case VBE_DISPI_INDEX_ENABLE:
477 if (val & VBE_DISPI_ENABLED) {
478 int h, shift_control;
479
480 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
481 s->vbe_regs[VBE_DISPI_INDEX_XRES];
482 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
483 s->vbe_regs[VBE_DISPI_INDEX_YRES];
484 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
485 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
486
487 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
488 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
489 else
490 s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
491 ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
492 s->vbe_start_addr = 0;
493
494 /* clear the screen (should be done in BIOS) */
495 if (!(val & VBE_DISPI_NOCLEARMEM)) {
496 memset(s->vram_ptr, 0,
497 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
498 }
499
500 /* we initialize the VGA graphic mode (should be done
501 in BIOS) */
502 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
503 s->cr[0x17] |= 3; /* no CGA modes */
504 s->cr[0x13] = s->vbe_line_offset >> 3;
505 /* width */
506 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
507 /* height */
508 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
509 s->cr[0x12] = h;
510 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
511 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
512 /* line compare to 1023 */
513 s->cr[0x18] = 0xff;
514 s->cr[0x07] |= 0x10;
515 s->cr[0x09] |= 0x40;
516
517 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
518 shift_control = 0;
519 s->sr[0x01] &= ~8; /* no double line */
520 } else {
521 shift_control = 2;
522 s->sr[4] |= 0x08; /* set chain 4 mode */
523 s->sr[2] |= 0x0f; /* activate all planes */
524 }
525 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
526 s->cr[0x09] &= ~0x9f; /* no double scan */
527 } else {
528 /* XXX: the bios should do that */
529 s->bank_offset = 0;
530 }
531 s->vbe_regs[s->vbe_index] = val;
532 break;
533 case VBE_DISPI_INDEX_VIRT_WIDTH:
534 {
535 int w, h, line_offset;
536
537 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
538 return;
539 w = val;
540 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
541 line_offset = w >> 1;
542 else
543 line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
544 h = s->vram_size / line_offset;
545 /* XXX: support weird bochs semantics ? */
546 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
547 return;
548 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
549 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
550 s->vbe_line_offset = line_offset;
551 }
552 break;
553 case VBE_DISPI_INDEX_X_OFFSET:
554 case VBE_DISPI_INDEX_Y_OFFSET:
555 {
556 int x;
557 s->vbe_regs[s->vbe_index] = val;
558 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
559 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
560 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
561 s->vbe_start_addr += x >> 1;
562 else
563 s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
564 s->vbe_start_addr >>= 2;
565 }
566 break;
567 default:
568 break;
569 }
570 }
571 }
572 #endif
573
574 /* called for accesses between 0xa0000 and 0xc0000 */
575 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
576 {
577 VGAState *s = opaque;
578 int memory_map_mode, plane;
579 uint32_t ret;
580
581 /* convert to VGA memory offset */
582 memory_map_mode = (s->gr[6] >> 2) & 3;
583 addr &= 0x1ffff;
584 switch(memory_map_mode) {
585 case 0:
586 break;
587 case 1:
588 if (addr >= 0x10000)
589 return 0xff;
590 addr += s->bank_offset;
591 break;
592 case 2:
593 addr -= 0x10000;
594 if (addr >= 0x8000)
595 return 0xff;
596 break;
597 default:
598 case 3:
599 addr -= 0x18000;
600 if (addr >= 0x8000)
601 return 0xff;
602 break;
603 }
604
605 if (s->sr[4] & 0x08) {
606 /* chain 4 mode : simplest access */
607 ret = s->vram_ptr[addr];
608 } else if (s->gr[5] & 0x10) {
609 /* odd/even mode (aka text mode mapping) */
610 plane = (s->gr[4] & 2) | (addr & 1);
611 ret = s->vram_ptr[((addr & ~1) << 1) | plane];
612 } else {
613 /* standard VGA latched access */
614 s->latch = ((uint32_t *)s->vram_ptr)[addr];
615
616 if (!(s->gr[5] & 0x08)) {
617 /* read mode 0 */
618 plane = s->gr[4];
619 ret = GET_PLANE(s->latch, plane);
620 } else {
621 /* read mode 1 */
622 ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
623 ret |= ret >> 16;
624 ret |= ret >> 8;
625 ret = (~ret) & 0xff;
626 }
627 }
628 return ret;
629 }
630
631 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
632 {
633 uint32_t v;
634 #ifdef TARGET_WORDS_BIGENDIAN
635 v = vga_mem_readb(opaque, addr) << 8;
636 v |= vga_mem_readb(opaque, addr + 1);
637 #else
638 v = vga_mem_readb(opaque, addr);
639 v |= vga_mem_readb(opaque, addr + 1) << 8;
640 #endif
641 return v;
642 }
643
644 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
645 {
646 uint32_t v;
647 #ifdef TARGET_WORDS_BIGENDIAN
648 v = vga_mem_readb(opaque, addr) << 24;
649 v |= vga_mem_readb(opaque, addr + 1) << 16;
650 v |= vga_mem_readb(opaque, addr + 2) << 8;
651 v |= vga_mem_readb(opaque, addr + 3);
652 #else
653 v = vga_mem_readb(opaque, addr);
654 v |= vga_mem_readb(opaque, addr + 1) << 8;
655 v |= vga_mem_readb(opaque, addr + 2) << 16;
656 v |= vga_mem_readb(opaque, addr + 3) << 24;
657 #endif
658 return v;
659 }
660
661 /* called for accesses between 0xa0000 and 0xc0000 */
662 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
663 {
664 VGAState *s = opaque;
665 int memory_map_mode, plane, write_mode, b, func_select;
666 uint32_t write_mask, bit_mask, set_mask;
667
668 #ifdef DEBUG_VGA_MEM
669 printf("vga: [0x%x] = 0x%02x\n", addr, val);
670 #endif
671 /* convert to VGA memory offset */
672 memory_map_mode = (s->gr[6] >> 2) & 3;
673 addr &= 0x1ffff;
674 switch(memory_map_mode) {
675 case 0:
676 break;
677 case 1:
678 if (addr >= 0x10000)
679 return;
680 addr += s->bank_offset;
681 break;
682 case 2:
683 addr -= 0x10000;
684 if (addr >= 0x8000)
685 return;
686 break;
687 default:
688 case 3:
689 addr -= 0x18000;
690 if (addr >= 0x8000)
691 return;
692 break;
693 }
694
695 if (s->sr[4] & 0x08) {
696 /* chain 4 mode : simplest access */
697 plane = addr & 3;
698 if (s->sr[2] & (1 << plane)) {
699 s->vram_ptr[addr] = val;
700 #ifdef DEBUG_VGA_MEM
701 printf("vga: chain4: [0x%x]\n", addr);
702 #endif
703 cpu_physical_memory_set_dirty(s->vram_offset + addr);
704 }
705 } else if (s->gr[5] & 0x10) {
706 /* odd/even mode (aka text mode mapping) */
707 plane = (s->gr[4] & 2) | (addr & 1);
708 if (s->sr[2] & (1 << plane)) {
709 addr = ((addr & ~1) << 1) | plane;
710 s->vram_ptr[addr] = val;
711 #ifdef DEBUG_VGA_MEM
712 printf("vga: odd/even: [0x%x]\n", addr);
713 #endif
714 cpu_physical_memory_set_dirty(s->vram_offset + addr);
715 }
716 } else {
717 /* standard VGA latched access */
718 write_mode = s->gr[5] & 3;
719 switch(write_mode) {
720 default:
721 case 0:
722 /* rotate */
723 b = s->gr[3] & 7;
724 val = ((val >> b) | (val << (8 - b))) & 0xff;
725 val |= val << 8;
726 val |= val << 16;
727
728 /* apply set/reset mask */
729 set_mask = mask16[s->gr[1]];
730 val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
731 bit_mask = s->gr[8];
732 break;
733 case 1:
734 val = s->latch;
735 goto do_write;
736 case 2:
737 val = mask16[val & 0x0f];
738 bit_mask = s->gr[8];
739 break;
740 case 3:
741 /* rotate */
742 b = s->gr[3] & 7;
743 val = (val >> b) | (val << (8 - b));
744
745 bit_mask = s->gr[8] & val;
746 val = mask16[s->gr[0]];
747 break;
748 }
749
750 /* apply logical operation */
751 func_select = s->gr[3] >> 3;
752 switch(func_select) {
753 case 0:
754 default:
755 /* nothing to do */
756 break;
757 case 1:
758 /* and */
759 val &= s->latch;
760 break;
761 case 2:
762 /* or */
763 val |= s->latch;
764 break;
765 case 3:
766 /* xor */
767 val ^= s->latch;
768 break;
769 }
770
771 /* apply bit mask */
772 bit_mask |= bit_mask << 8;
773 bit_mask |= bit_mask << 16;
774 val = (val & bit_mask) | (s->latch & ~bit_mask);
775
776 do_write:
777 /* mask data according to sr[2] */
778 write_mask = mask16[s->sr[2]];
779 ((uint32_t *)s->vram_ptr)[addr] =
780 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
781 (val & write_mask);
782 #ifdef DEBUG_VGA_MEM
783 printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
784 addr * 4, write_mask, val);
785 #endif
786 cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
787 }
788 }
789
790 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
791 {
792 #ifdef TARGET_WORDS_BIGENDIAN
793 vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
794 vga_mem_writeb(opaque, addr + 1, val & 0xff);
795 #else
796 vga_mem_writeb(opaque, addr, val & 0xff);
797 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
798 #endif
799 }
800
801 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
802 {
803 #ifdef TARGET_WORDS_BIGENDIAN
804 vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
805 vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
806 vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
807 vga_mem_writeb(opaque, addr + 3, val & 0xff);
808 #else
809 vga_mem_writeb(opaque, addr, val & 0xff);
810 vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
811 vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
812 vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
813 #endif
814 }
815
816 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
817 const uint8_t *font_ptr, int h,
818 uint32_t fgcol, uint32_t bgcol);
819 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
820 const uint8_t *font_ptr, int h,
821 uint32_t fgcol, uint32_t bgcol, int dup9);
822 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
823 const uint8_t *s, int width);
824
825 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
826 {
827 /* XXX: TODO */
828 return 0;
829 }
830
831 static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
832 {
833 return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
834 }
835
836 static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
837 {
838 return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
839 }
840
841 static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
842 {
843 return (r << 16) | (g << 8) | b;
844 }
845
846 #define DEPTH 8
847 #include "vga_template.h"
848
849 #define DEPTH 15
850 #include "vga_template.h"
851
852 #define DEPTH 16
853 #include "vga_template.h"
854
855 #define DEPTH 32
856 #include "vga_template.h"
857
858 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
859 {
860 unsigned int col;
861 col = rgb_to_pixel8(r, g, b);
862 col |= col << 8;
863 col |= col << 16;
864 return col;
865 }
866
867 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
868 {
869 unsigned int col;
870 col = rgb_to_pixel15(r, g, b);
871 col |= col << 16;
872 return col;
873 }
874
875 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
876 {
877 unsigned int col;
878 col = rgb_to_pixel16(r, g, b);
879 col |= col << 16;
880 return col;
881 }
882
883 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
884 {
885 unsigned int col;
886 col = rgb_to_pixel32(r, g, b);
887 return col;
888 }
889
890 /* return true if the palette was modified */
891 static int update_palette16(VGAState *s)
892 {
893 int full_update, i;
894 uint32_t v, col, *palette;
895
896 full_update = 0;
897 palette = s->last_palette;
898 for(i = 0; i < 16; i++) {
899 v = s->ar[i];
900 if (s->ar[0x10] & 0x80)
901 v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
902 else
903 v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
904 v = v * 3;
905 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
906 c6_to_8(s->palette[v + 1]),
907 c6_to_8(s->palette[v + 2]));
908 if (col != palette[i]) {
909 full_update = 1;
910 palette[i] = col;
911 }
912 }
913 return full_update;
914 }
915
916 /* return true if the palette was modified */
917 static int update_palette256(VGAState *s)
918 {
919 int full_update, i;
920 uint32_t v, col, *palette;
921
922 full_update = 0;
923 palette = s->last_palette;
924 v = 0;
925 for(i = 0; i < 256; i++) {
926 col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
927 c6_to_8(s->palette[v + 1]),
928 c6_to_8(s->palette[v + 2]));
929 if (col != palette[i]) {
930 full_update = 1;
931 palette[i] = col;
932 }
933 v += 3;
934 }
935 return full_update;
936 }
937
938 static void vga_get_offsets(VGAState *s,
939 uint32_t *pline_offset,
940 uint32_t *pstart_addr)
941 {
942 uint32_t start_addr, line_offset;
943 #ifdef CONFIG_BOCHS_VBE
944 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
945 line_offset = s->vbe_line_offset;
946 start_addr = s->vbe_start_addr;
947 } else
948 #endif
949 {
950 /* compute line_offset in bytes */
951 line_offset = s->cr[0x13];
952 #ifdef CONFIG_S3VGA
953 {
954 uinr32_t v;
955 v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
956 if (v == 0)
957 v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
958 line_offset |= (v << 8);
959 }
960 #endif
961 line_offset <<= 3;
962
963 /* starting address */
964 start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
965 #ifdef CONFIG_S3VGA
966 start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
967 #endif
968 }
969 *pline_offset = line_offset;
970 *pstart_addr = start_addr;
971 }
972
973 /* update start_addr and line_offset. Return TRUE if modified */
974 static int update_basic_params(VGAState *s)
975 {
976 int full_update;
977 uint32_t start_addr, line_offset, line_compare;
978
979 full_update = 0;
980
981 s->get_offsets(s, &line_offset, &start_addr);
982 /* line compare */
983 line_compare = s->cr[0x18] |
984 ((s->cr[0x07] & 0x10) << 4) |
985 ((s->cr[0x09] & 0x40) << 3);
986
987 if (line_offset != s->line_offset ||
988 start_addr != s->start_addr ||
989 line_compare != s->line_compare) {
990 s->line_offset = line_offset;
991 s->start_addr = start_addr;
992 s->line_compare = line_compare;
993 full_update = 1;
994 }
995 return full_update;
996 }
997
998 static inline int get_depth_index(int depth)
999 {
1000 switch(depth) {
1001 default:
1002 case 8:
1003 return 0;
1004 case 15:
1005 return 1;
1006 case 16:
1007 return 2;
1008 case 32:
1009 return 3;
1010 }
1011 }
1012
1013 static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1014 vga_draw_glyph8_8,
1015 vga_draw_glyph8_16,
1016 vga_draw_glyph8_16,
1017 vga_draw_glyph8_32,
1018 };
1019
1020 static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1021 vga_draw_glyph16_8,
1022 vga_draw_glyph16_16,
1023 vga_draw_glyph16_16,
1024 vga_draw_glyph16_32,
1025 };
1026
1027 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1028 vga_draw_glyph9_8,
1029 vga_draw_glyph9_16,
1030 vga_draw_glyph9_16,
1031 vga_draw_glyph9_32,
1032 };
1033
1034 static const uint8_t cursor_glyph[32 * 4] = {
1035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1036 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1040 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1041 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1043 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1044 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1045 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1046 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1047 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1048 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1049 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1050 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1051 };
1052
1053 /*
1054 * Text mode update
1055 * Missing:
1056 * - double scan
1057 * - double width
1058 * - underline
1059 * - flashing
1060 */
1061 static void vga_draw_text(VGAState *s, int full_update)
1062 {
1063 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1064 int cx_min, cx_max, linesize, x_incr;
1065 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1066 uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1067 const uint8_t *font_ptr, *font_base[2];
1068 int dup9, line_offset, depth_index;
1069 uint32_t *palette;
1070 uint32_t *ch_attr_ptr;
1071 vga_draw_glyph8_func *vga_draw_glyph8;
1072 vga_draw_glyph9_func *vga_draw_glyph9;
1073
1074 full_update |= update_palette16(s);
1075 palette = s->last_palette;
1076
1077 /* compute font data address (in plane 2) */
1078 v = s->sr[3];
1079 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1080 if (offset != s->font_offsets[0]) {
1081 s->font_offsets[0] = offset;
1082 full_update = 1;
1083 }
1084 font_base[0] = s->vram_ptr + offset;
1085
1086 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1087 font_base[1] = s->vram_ptr + offset;
1088 if (offset != s->font_offsets[1]) {
1089 s->font_offsets[1] = offset;
1090 full_update = 1;
1091 }
1092
1093 full_update |= update_basic_params(s);
1094
1095 line_offset = s->line_offset;
1096 s1 = s->vram_ptr + (s->start_addr * 4);
1097
1098 /* total width & height */
1099 cheight = (s->cr[9] & 0x1f) + 1;
1100 cw = 8;
1101 if (!(s->sr[1] & 0x01))
1102 cw = 9;
1103 if (s->sr[1] & 0x08)
1104 cw = 16; /* NOTE: no 18 pixel wide */
1105 x_incr = cw * ((s->ds->depth + 7) >> 3);
1106 width = (s->cr[0x01] + 1);
1107 if (s->cr[0x06] == 100) {
1108 /* ugly hack for CGA 160x100x16 - explain me the logic */
1109 height = 100;
1110 } else {
1111 height = s->cr[0x12] |
1112 ((s->cr[0x07] & 0x02) << 7) |
1113 ((s->cr[0x07] & 0x40) << 3);
1114 height = (height + 1) / cheight;
1115 }
1116 if ((height * width) > CH_ATTR_SIZE) {
1117 /* better than nothing: exit if transient size is too big */
1118 return;
1119 }
1120
1121 if (width != s->last_width || height != s->last_height ||
1122 cw != s->last_cw || cheight != s->last_ch) {
1123 s->last_scr_width = width * cw;
1124 s->last_scr_height = height * cheight;
1125 dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1126 s->last_width = width;
1127 s->last_height = height;
1128 s->last_ch = cheight;
1129 s->last_cw = cw;
1130 full_update = 1;
1131 }
1132 cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1133 if (cursor_offset != s->cursor_offset ||
1134 s->cr[0xa] != s->cursor_start ||
1135 s->cr[0xb] != s->cursor_end) {
1136 /* if the cursor position changed, we update the old and new
1137 chars */
1138 if (s->cursor_offset < CH_ATTR_SIZE)
1139 s->last_ch_attr[s->cursor_offset] = -1;
1140 if (cursor_offset < CH_ATTR_SIZE)
1141 s->last_ch_attr[cursor_offset] = -1;
1142 s->cursor_offset = cursor_offset;
1143 s->cursor_start = s->cr[0xa];
1144 s->cursor_end = s->cr[0xb];
1145 }
1146 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1147
1148 depth_index = get_depth_index(s->ds->depth);
1149 if (cw == 16)
1150 vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1151 else
1152 vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1153 vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1154
1155 dest = s->ds->data;
1156 linesize = s->ds->linesize;
1157 ch_attr_ptr = s->last_ch_attr;
1158 for(cy = 0; cy < height; cy++) {
1159 d1 = dest;
1160 src = s1;
1161 cx_min = width;
1162 cx_max = -1;
1163 for(cx = 0; cx < width; cx++) {
1164 ch_attr = *(uint16_t *)src;
1165 if (full_update || ch_attr != *ch_attr_ptr) {
1166 if (cx < cx_min)
1167 cx_min = cx;
1168 if (cx > cx_max)
1169 cx_max = cx;
1170 *ch_attr_ptr = ch_attr;
1171 #ifdef WORDS_BIGENDIAN
1172 ch = ch_attr >> 8;
1173 cattr = ch_attr & 0xff;
1174 #else
1175 ch = ch_attr & 0xff;
1176 cattr = ch_attr >> 8;
1177 #endif
1178 font_ptr = font_base[(cattr >> 3) & 1];
1179 font_ptr += 32 * 4 * ch;
1180 bgcol = palette[cattr >> 4];
1181 fgcol = palette[cattr & 0x0f];
1182 if (cw != 9) {
1183 vga_draw_glyph8(d1, linesize,
1184 font_ptr, cheight, fgcol, bgcol);
1185 } else {
1186 dup9 = 0;
1187 if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1188 dup9 = 1;
1189 vga_draw_glyph9(d1, linesize,
1190 font_ptr, cheight, fgcol, bgcol, dup9);
1191 }
1192 if (src == cursor_ptr &&
1193 !(s->cr[0x0a] & 0x20)) {
1194 int line_start, line_last, h;
1195 /* draw the cursor */
1196 line_start = s->cr[0x0a] & 0x1f;
1197 line_last = s->cr[0x0b] & 0x1f;
1198 /* XXX: check that */
1199 if (line_last > cheight - 1)
1200 line_last = cheight - 1;
1201 if (line_last >= line_start && line_start < cheight) {
1202 h = line_last - line_start + 1;
1203 d = d1 + linesize * line_start;
1204 if (cw != 9) {
1205 vga_draw_glyph8(d, linesize,
1206 cursor_glyph, h, fgcol, bgcol);
1207 } else {
1208 vga_draw_glyph9(d, linesize,
1209 cursor_glyph, h, fgcol, bgcol, 1);
1210 }
1211 }
1212 }
1213 }
1214 d1 += x_incr;
1215 src += 4;
1216 ch_attr_ptr++;
1217 }
1218 if (cx_max != -1) {
1219 dpy_update(s->ds, cx_min * cw, cy * cheight,
1220 (cx_max - cx_min + 1) * cw, cheight);
1221 }
1222 dest += linesize * cheight;
1223 s1 += line_offset;
1224 }
1225 }
1226
1227 enum {
1228 VGA_DRAW_LINE2,
1229 VGA_DRAW_LINE2D2,
1230 VGA_DRAW_LINE4,
1231 VGA_DRAW_LINE4D2,
1232 VGA_DRAW_LINE8D2,
1233 VGA_DRAW_LINE8,
1234 VGA_DRAW_LINE15,
1235 VGA_DRAW_LINE16,
1236 VGA_DRAW_LINE24,
1237 VGA_DRAW_LINE32,
1238 VGA_DRAW_LINE_NB,
1239 };
1240
1241 static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1242 vga_draw_line2_8,
1243 vga_draw_line2_16,
1244 vga_draw_line2_16,
1245 vga_draw_line2_32,
1246
1247 vga_draw_line2d2_8,
1248 vga_draw_line2d2_16,
1249 vga_draw_line2d2_16,
1250 vga_draw_line2d2_32,
1251
1252 vga_draw_line4_8,
1253 vga_draw_line4_16,
1254 vga_draw_line4_16,
1255 vga_draw_line4_32,
1256
1257 vga_draw_line4d2_8,
1258 vga_draw_line4d2_16,
1259 vga_draw_line4d2_16,
1260 vga_draw_line4d2_32,
1261
1262 vga_draw_line8d2_8,
1263 vga_draw_line8d2_16,
1264 vga_draw_line8d2_16,
1265 vga_draw_line8d2_32,
1266
1267 vga_draw_line8_8,
1268 vga_draw_line8_16,
1269 vga_draw_line8_16,
1270 vga_draw_line8_32,
1271
1272 vga_draw_line15_8,
1273 vga_draw_line15_15,
1274 vga_draw_line15_16,
1275 vga_draw_line15_32,
1276
1277 vga_draw_line16_8,
1278 vga_draw_line16_15,
1279 vga_draw_line16_16,
1280 vga_draw_line16_32,
1281
1282 vga_draw_line24_8,
1283 vga_draw_line24_15,
1284 vga_draw_line24_16,
1285 vga_draw_line24_32,
1286
1287 vga_draw_line32_8,
1288 vga_draw_line32_15,
1289 vga_draw_line32_16,
1290 vga_draw_line32_32,
1291 };
1292
1293 static int vga_get_bpp(VGAState *s)
1294 {
1295 int ret;
1296 #ifdef CONFIG_BOCHS_VBE
1297 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1298 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1299 } else
1300 #endif
1301 {
1302 ret = 0;
1303 }
1304 return ret;
1305 }
1306
1307 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1308 {
1309 int width, height;
1310
1311 width = (s->cr[0x01] + 1) * 8;
1312 height = s->cr[0x12] |
1313 ((s->cr[0x07] & 0x02) << 7) |
1314 ((s->cr[0x07] & 0x40) << 3);
1315 height = (height + 1);
1316 *pwidth = width;
1317 *pheight = height;
1318 }
1319
1320 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1321 {
1322 int y;
1323 if (y1 >= VGA_MAX_HEIGHT)
1324 return;
1325 if (y2 >= VGA_MAX_HEIGHT)
1326 y2 = VGA_MAX_HEIGHT;
1327 for(y = y1; y < y2; y++) {
1328 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1329 }
1330 }
1331
1332 /*
1333 * graphic modes
1334 */
1335 static void vga_draw_graphic(VGAState *s, int full_update)
1336 {
1337 int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1338 int width, height, shift_control, line_offset, page0, page1, bwidth;
1339 int disp_width, multi_scan, multi_run;
1340 uint8_t *d;
1341 uint32_t v, addr1, addr;
1342 vga_draw_line_func *vga_draw_line;
1343
1344 full_update |= update_basic_params(s);
1345
1346 s->get_resolution(s, &width, &height);
1347 disp_width = width;
1348
1349 shift_control = (s->gr[0x05] >> 5) & 3;
1350 double_scan = (s->cr[0x09] & 0x80);
1351 if (shift_control > 1) {
1352 multi_scan = (s->cr[0x09] & 0x1f);
1353 } else {
1354 multi_scan = 0;
1355 }
1356 multi_run = multi_scan;
1357 if (shift_control != s->shift_control ||
1358 double_scan != s->double_scan) {
1359 full_update = 1;
1360 s->shift_control = shift_control;
1361 s->double_scan = double_scan;
1362 }
1363
1364 if (shift_control == 0) {
1365 full_update |= update_palette16(s);
1366 if (s->sr[0x01] & 8) {
1367 v = VGA_DRAW_LINE4D2;
1368 disp_width <<= 1;
1369 } else {
1370 v = VGA_DRAW_LINE4;
1371 }
1372 } else if (shift_control == 1) {
1373 full_update |= update_palette16(s);
1374 if (s->sr[0x01] & 8) {
1375 v = VGA_DRAW_LINE2D2;
1376 disp_width <<= 1;
1377 } else {
1378 v = VGA_DRAW_LINE2;
1379 }
1380 } else {
1381 switch(s->get_bpp(s)) {
1382 default:
1383 case 0:
1384 full_update |= update_palette256(s);
1385 v = VGA_DRAW_LINE8D2;
1386 break;
1387 case 8:
1388 full_update |= update_palette256(s);
1389 v = VGA_DRAW_LINE8;
1390 break;
1391 case 15:
1392 v = VGA_DRAW_LINE15;
1393 break;
1394 case 16:
1395 v = VGA_DRAW_LINE16;
1396 break;
1397 case 24:
1398 v = VGA_DRAW_LINE24;
1399 break;
1400 case 32:
1401 v = VGA_DRAW_LINE32;
1402 break;
1403 }
1404 }
1405 vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1406
1407 if (disp_width != s->last_width ||
1408 height != s->last_height) {
1409 dpy_resize(s->ds, disp_width, height);
1410 s->last_scr_width = disp_width;
1411 s->last_scr_height = height;
1412 s->last_width = disp_width;
1413 s->last_height = height;
1414 full_update = 1;
1415 }
1416 if (s->cursor_invalidate)
1417 s->cursor_invalidate(s);
1418
1419 line_offset = s->line_offset;
1420 #if 0
1421 printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1422 width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1423 #endif
1424 addr1 = (s->start_addr * 4);
1425 bwidth = width * 4;
1426 y_start = -1;
1427 page_min = 0x7fffffff;
1428 page_max = -1;
1429 d = s->ds->data;
1430 linesize = s->ds->linesize;
1431 y1 = 0;
1432 for(y = 0; y < height; y++) {
1433 addr = addr1;
1434 if (!(s->cr[0x17] & 1)) {
1435 int shift;
1436 /* CGA compatibility handling */
1437 shift = 14 + ((s->cr[0x17] >> 6) & 1);
1438 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1439 }
1440 if (!(s->cr[0x17] & 2)) {
1441 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1442 }
1443 page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1444 page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1445 update = full_update | cpu_physical_memory_is_dirty(page0) |
1446 cpu_physical_memory_is_dirty(page1);
1447 if ((page1 - page0) > TARGET_PAGE_SIZE) {
1448 /* if wide line, can use another page */
1449 update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1450 }
1451 /* explicit invalidation for the hardware cursor */
1452 update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1453 if (update) {
1454 if (y_start < 0)
1455 y_start = y;
1456 if (page0 < page_min)
1457 page_min = page0;
1458 if (page1 > page_max)
1459 page_max = page1;
1460 vga_draw_line(s, d, s->vram_ptr + addr, width);
1461 if (s->cursor_draw_line)
1462 s->cursor_draw_line(s, d, y);
1463 } else {
1464 if (y_start >= 0) {
1465 /* flush to display */
1466 dpy_update(s->ds, 0, y_start,
1467 disp_width, y - y_start);
1468 y_start = -1;
1469 }
1470 }
1471 if (!multi_run) {
1472 if (!double_scan || (y & 1) != 0) {
1473 if (y1 == s->line_compare) {
1474 addr1 = 0;
1475 } else {
1476 mask = (s->cr[0x17] & 3) ^ 3;
1477 if ((y1 & mask) == mask)
1478 addr1 += line_offset;
1479 }
1480 y1++;
1481 }
1482 multi_run = multi_scan;
1483 } else {
1484 multi_run--;
1485 y1++;
1486 }
1487 d += linesize;
1488 }
1489 if (y_start >= 0) {
1490 /* flush to display */
1491 dpy_update(s->ds, 0, y_start,
1492 disp_width, y - y_start);
1493 }
1494 /* reset modified pages */
1495 if (page_max != -1) {
1496 cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1497 }
1498 memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1499 }
1500
1501 static void vga_draw_blank(VGAState *s, int full_update)
1502 {
1503 int i, w, val;
1504 uint8_t *d;
1505
1506 if (!full_update)
1507 return;
1508 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1509 return;
1510 if (s->ds->depth == 8)
1511 val = s->rgb_to_pixel(0, 0, 0);
1512 else
1513 val = 0;
1514 w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1515 d = s->ds->data;
1516 for(i = 0; i < s->last_scr_height; i++) {
1517 memset(d, val, w);
1518 d += s->ds->linesize;
1519 }
1520 dpy_update(s->ds, 0, 0,
1521 s->last_scr_width, s->last_scr_height);
1522 }
1523
1524 #define GMODE_TEXT 0
1525 #define GMODE_GRAPH 1
1526 #define GMODE_BLANK 2
1527
1528 void vga_update_display(void)
1529 {
1530 VGAState *s = vga_state;
1531 int full_update, graphic_mode;
1532
1533 if (s->ds->depth == 0) {
1534 /* nothing to do */
1535 } else {
1536 switch(s->ds->depth) {
1537 case 8:
1538 s->rgb_to_pixel = rgb_to_pixel8_dup;
1539 break;
1540 case 15:
1541 s->rgb_to_pixel = rgb_to_pixel15_dup;
1542 break;
1543 default:
1544 case 16:
1545 s->rgb_to_pixel = rgb_to_pixel16_dup;
1546 break;
1547 case 32:
1548 s->rgb_to_pixel = rgb_to_pixel32_dup;
1549 break;
1550 }
1551
1552 full_update = 0;
1553 if (!(s->ar_index & 0x20)) {
1554 graphic_mode = GMODE_BLANK;
1555 } else {
1556 graphic_mode = s->gr[6] & 1;
1557 }
1558 if (graphic_mode != s->graphic_mode) {
1559 s->graphic_mode = graphic_mode;
1560 full_update = 1;
1561 }
1562 switch(graphic_mode) {
1563 case GMODE_TEXT:
1564 vga_draw_text(s, full_update);
1565 break;
1566 case GMODE_GRAPH:
1567 vga_draw_graphic(s, full_update);
1568 break;
1569 case GMODE_BLANK:
1570 default:
1571 vga_draw_blank(s, full_update);
1572 break;
1573 }
1574 }
1575 }
1576
1577 /* force a full display refresh */
1578 void vga_invalidate_display(void)
1579 {
1580 VGAState *s = vga_state;
1581
1582 s->last_width = -1;
1583 s->last_height = -1;
1584 }
1585
1586 static void vga_reset(VGAState *s)
1587 {
1588 memset(s, 0, sizeof(VGAState));
1589 #ifdef CONFIG_S3VGA
1590 /* chip ID for 8c968 */
1591 s->cr[0x2d] = 0x88;
1592 s->cr[0x2e] = 0xb0;
1593 s->cr[0x2f] = 0x01; /* XXX: check revision code */
1594 s->cr[0x30] = 0xe1;
1595 #endif
1596 s->graphic_mode = -1; /* force full update */
1597 }
1598
1599 static CPUReadMemoryFunc *vga_mem_read[3] = {
1600 vga_mem_readb,
1601 vga_mem_readw,
1602 vga_mem_readl,
1603 };
1604
1605 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1606 vga_mem_writeb,
1607 vga_mem_writew,
1608 vga_mem_writel,
1609 };
1610
1611 static void vga_save(QEMUFile *f, void *opaque)
1612 {
1613 VGAState *s = opaque;
1614 int i;
1615
1616 qemu_put_be32s(f, &s->latch);
1617 qemu_put_8s(f, &s->sr_index);
1618 qemu_put_buffer(f, s->sr, 8);
1619 qemu_put_8s(f, &s->gr_index);
1620 qemu_put_buffer(f, s->gr, 16);
1621 qemu_put_8s(f, &s->ar_index);
1622 qemu_put_buffer(f, s->ar, 21);
1623 qemu_put_be32s(f, &s->ar_flip_flop);
1624 qemu_put_8s(f, &s->cr_index);
1625 qemu_put_buffer(f, s->cr, 256);
1626 qemu_put_8s(f, &s->msr);
1627 qemu_put_8s(f, &s->fcr);
1628 qemu_put_8s(f, &s->st00);
1629 qemu_put_8s(f, &s->st01);
1630
1631 qemu_put_8s(f, &s->dac_state);
1632 qemu_put_8s(f, &s->dac_sub_index);
1633 qemu_put_8s(f, &s->dac_read_index);
1634 qemu_put_8s(f, &s->dac_write_index);
1635 qemu_put_buffer(f, s->dac_cache, 3);
1636 qemu_put_buffer(f, s->palette, 768);
1637
1638 qemu_put_be32s(f, &s->bank_offset);
1639 #ifdef CONFIG_BOCHS_VBE
1640 qemu_put_byte(f, 1);
1641 qemu_put_be16s(f, &s->vbe_index);
1642 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1643 qemu_put_be16s(f, &s->vbe_regs[i]);
1644 qemu_put_be32s(f, &s->vbe_start_addr);
1645 qemu_put_be32s(f, &s->vbe_line_offset);
1646 qemu_put_be32s(f, &s->vbe_bank_mask);
1647 #else
1648 qemu_put_byte(f, 0);
1649 #endif
1650 }
1651
1652 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1653 {
1654 VGAState *s = opaque;
1655 int is_vbe, i;
1656
1657 if (version_id != 1)
1658 return -EINVAL;
1659
1660 qemu_get_be32s(f, &s->latch);
1661 qemu_get_8s(f, &s->sr_index);
1662 qemu_get_buffer(f, s->sr, 8);
1663 qemu_get_8s(f, &s->gr_index);
1664 qemu_get_buffer(f, s->gr, 16);
1665 qemu_get_8s(f, &s->ar_index);
1666 qemu_get_buffer(f, s->ar, 21);
1667 qemu_get_be32s(f, &s->ar_flip_flop);
1668 qemu_get_8s(f, &s->cr_index);
1669 qemu_get_buffer(f, s->cr, 256);
1670 qemu_get_8s(f, &s->msr);
1671 qemu_get_8s(f, &s->fcr);
1672 qemu_get_8s(f, &s->st00);
1673 qemu_get_8s(f, &s->st01);
1674
1675 qemu_get_8s(f, &s->dac_state);
1676 qemu_get_8s(f, &s->dac_sub_index);
1677 qemu_get_8s(f, &s->dac_read_index);
1678 qemu_get_8s(f, &s->dac_write_index);
1679 qemu_get_buffer(f, s->dac_cache, 3);
1680 qemu_get_buffer(f, s->palette, 768);
1681
1682 qemu_get_be32s(f, &s->bank_offset);
1683 is_vbe = qemu_get_byte(f);
1684 #ifdef CONFIG_BOCHS_VBE
1685 if (!is_vbe)
1686 return -EINVAL;
1687 qemu_get_be16s(f, &s->vbe_index);
1688 for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1689 qemu_get_be16s(f, &s->vbe_regs[i]);
1690 qemu_get_be32s(f, &s->vbe_start_addr);
1691 qemu_get_be32s(f, &s->vbe_line_offset);
1692 qemu_get_be32s(f, &s->vbe_bank_mask);
1693 #else
1694 if (is_vbe)
1695 return -EINVAL;
1696 #endif
1697
1698 /* force refresh */
1699 s->graphic_mode = -1;
1700 return 0;
1701 }
1702
1703 static void vga_map(PCIDevice *pci_dev, int region_num,
1704 uint32_t addr, uint32_t size, int type)
1705 {
1706 VGAState *s = vga_state;
1707
1708 cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1709 }
1710
1711 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1712 unsigned long vga_ram_offset, int vga_ram_size)
1713 {
1714 int i, j, v, b;
1715
1716 for(i = 0;i < 256; i++) {
1717 v = 0;
1718 for(j = 0; j < 8; j++) {
1719 v |= ((i >> j) & 1) << (j * 4);
1720 }
1721 expand4[i] = v;
1722
1723 v = 0;
1724 for(j = 0; j < 4; j++) {
1725 v |= ((i >> (2 * j)) & 3) << (j * 4);
1726 }
1727 expand2[i] = v;
1728 }
1729 for(i = 0; i < 16; i++) {
1730 v = 0;
1731 for(j = 0; j < 4; j++) {
1732 b = ((i >> j) & 1);
1733 v |= b << (2 * j);
1734 v |= b << (2 * j + 1);
1735 }
1736 expand4to8[i] = v;
1737 }
1738
1739 vga_reset(s);
1740
1741 s->vram_ptr = vga_ram_base;
1742 s->vram_offset = vga_ram_offset;
1743 s->vram_size = vga_ram_size;
1744 s->ds = ds;
1745 s->get_bpp = vga_get_bpp;
1746 s->get_offsets = vga_get_offsets;
1747 s->get_resolution = vga_get_resolution;
1748 /* XXX: currently needed for display */
1749 vga_state = s;
1750 }
1751
1752
1753 int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
1754 unsigned long vga_ram_offset, int vga_ram_size)
1755 {
1756 VGAState *s;
1757
1758 s = qemu_mallocz(sizeof(VGAState));
1759 if (!s)
1760 return -1;
1761
1762 vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1763
1764 register_savevm("vga", 0, 1, vga_save, vga_load, s);
1765
1766 register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1767
1768 register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1769 register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1770 register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1771 register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1772
1773 register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1774
1775 register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1776 register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1777 register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1778 register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1779 s->bank_offset = 0;
1780
1781 #ifdef CONFIG_BOCHS_VBE
1782 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1783 s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1784 #if defined (TARGET_I386)
1785 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1786 register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1787
1788 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1789 register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1790
1791 /* old Bochs IO ports */
1792 register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1793 register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1794
1795 register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1796 register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1797 #else
1798 register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1799 register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1800
1801 register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1802 register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1803 #endif
1804 #endif /* CONFIG_BOCHS_VBE */
1805
1806 vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1807 cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1808 vga_io_memory);
1809
1810 if (bus) {
1811 PCIDevice *d;
1812 uint8_t *pci_conf;
1813
1814 d = pci_register_device(bus, "VGA",
1815 sizeof(PCIDevice),
1816 -1, NULL, NULL);
1817 pci_conf = d->config;
1818 pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1819 pci_conf[0x01] = 0x12;
1820 pci_conf[0x02] = 0x11;
1821 pci_conf[0x03] = 0x11;
1822 pci_conf[0x0a] = 0x00; // VGA controller
1823 pci_conf[0x0b] = 0x03;
1824 pci_conf[0x0e] = 0x00; // header_type
1825
1826 /* XXX: vga_ram_size must be a power of two */
1827 pci_register_io_region(d, 0, vga_ram_size,
1828 PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1829 } else {
1830 #ifdef CONFIG_BOCHS_VBE
1831 /* XXX: use optimized standard vga accesses */
1832 cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1833 vga_ram_size, vga_ram_offset);
1834 #endif
1835 }
1836 return 0;
1837 }
1838
1839 /********************************************************/
1840 /* vga screen dump */
1841
1842 static int vga_save_w, vga_save_h;
1843
1844 static void vga_save_dpy_update(DisplayState *s,
1845 int x, int y, int w, int h)
1846 {
1847 }
1848
1849 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1850 {
1851 s->linesize = w * 4;
1852 s->data = qemu_malloc(h * s->linesize);
1853 vga_save_w = w;
1854 vga_save_h = h;
1855 }
1856
1857 static void vga_save_dpy_refresh(DisplayState *s)
1858 {
1859 }
1860
1861 static int ppm_save(const char *filename, uint8_t *data,
1862 int w, int h, int linesize)
1863 {
1864 FILE *f;
1865 uint8_t *d, *d1;
1866 unsigned int v;
1867 int y, x;
1868
1869 f = fopen(filename, "wb");
1870 if (!f)
1871 return -1;
1872 fprintf(f, "P6\n%d %d\n%d\n",
1873 w, h, 255);
1874 d1 = data;
1875 for(y = 0; y < h; y++) {
1876 d = d1;
1877 for(x = 0; x < w; x++) {
1878 v = *(uint32_t *)d;
1879 fputc((v >> 16) & 0xff, f);
1880 fputc((v >> 8) & 0xff, f);
1881 fputc((v) & 0xff, f);
1882 d += 4;
1883 }
1884 d1 += linesize;
1885 }
1886 fclose(f);
1887 return 0;
1888 }
1889
1890 /* save the vga display in a PPM image even if no display is
1891 available */
1892 void vga_screen_dump(const char *filename)
1893 {
1894 VGAState *s = vga_state;
1895 DisplayState *saved_ds, ds1, *ds = &ds1;
1896
1897 /* XXX: this is a little hackish */
1898 vga_invalidate_display();
1899 saved_ds = s->ds;
1900
1901 memset(ds, 0, sizeof(DisplayState));
1902 ds->dpy_update = vga_save_dpy_update;
1903 ds->dpy_resize = vga_save_dpy_resize;
1904 ds->dpy_refresh = vga_save_dpy_refresh;
1905 ds->depth = 32;
1906
1907 s->ds = ds;
1908 s->graphic_mode = -1;
1909 vga_update_display();
1910
1911 if (ds->data) {
1912 ppm_save(filename, ds->data, vga_save_w, vga_save_h,
1913 s->ds->linesize);
1914 qemu_free(ds->data);
1915 }
1916 s->ds = saved_ds;
1917 }