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