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