1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include "qemu/units.h"
27#include "sysemu/reset.h"
28#include "qapi/error.h"
29#include "hw/display/vga.h"
30#include "hw/pci/pci.h"
31#include "vga_int.h"
32#include "vga_regs.h"
33#include "ui/pixel_ops.h"
34#include "ui/console.h"
35#include "qemu/timer.h"
36#include "hw/xen/xen.h"
37#include "migration/vmstate.h"
38#include "trace.h"
39
40
41
42
43bool have_vga = true;
44
45
46#define VGA_TEXT_CURSOR_PERIOD_MS (1000 * 2 * 16 / 60)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61const uint8_t sr_mask[8] = {
62 0x03,
63 0x3d,
64 0x0f,
65 0x3f,
66 0x0e,
67 0x00,
68 0x00,
69 0xff,
70};
71
72const uint8_t gr_mask[16] = {
73 0x0f,
74 0x0f,
75 0x0f,
76 0x1f,
77 0x03,
78 0x7b,
79 0x0f,
80 0x0f,
81 0xff,
82 0x00,
83 0x00,
84 0x00,
85 0x00,
86 0x00,
87 0x00,
88 0x00,
89};
90
91#define cbswap_32(__x) \
92((uint32_t)( \
93 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
94 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
95 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
96 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
97
98#if HOST_BIG_ENDIAN
99#define PAT(x) cbswap_32(x)
100#else
101#define PAT(x) (x)
102#endif
103
104#if HOST_BIG_ENDIAN
105#define BIG 1
106#else
107#define BIG 0
108#endif
109
110#if HOST_BIG_ENDIAN
111#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
112#else
113#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
114#endif
115
116static const uint32_t mask16[16] = {
117 PAT(0x00000000),
118 PAT(0x000000ff),
119 PAT(0x0000ff00),
120 PAT(0x0000ffff),
121 PAT(0x00ff0000),
122 PAT(0x00ff00ff),
123 PAT(0x00ffff00),
124 PAT(0x00ffffff),
125 PAT(0xff000000),
126 PAT(0xff0000ff),
127 PAT(0xff00ff00),
128 PAT(0xff00ffff),
129 PAT(0xffff0000),
130 PAT(0xffff00ff),
131 PAT(0xffffff00),
132 PAT(0xffffffff),
133};
134
135#undef PAT
136
137#if HOST_BIG_ENDIAN
138#define PAT(x) (x)
139#else
140#define PAT(x) cbswap_32(x)
141#endif
142
143static uint32_t expand4[256];
144static uint16_t expand2[256];
145static uint8_t expand4to8[16];
146
147static void vbe_update_vgaregs(VGACommonState *s);
148
149static inline bool vbe_enabled(VGACommonState *s)
150{
151 return s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED;
152}
153
154static inline uint8_t sr(VGACommonState *s, int idx)
155{
156 return vbe_enabled(s) ? s->sr_vbe[idx] : s->sr[idx];
157}
158
159static void vga_update_memory_access(VGACommonState *s)
160{
161 hwaddr base, offset, size;
162
163 if (s->legacy_address_space == NULL) {
164 return;
165 }
166
167 if (s->has_chain4_alias) {
168 memory_region_del_subregion(s->legacy_address_space, &s->chain4_alias);
169 object_unparent(OBJECT(&s->chain4_alias));
170 s->has_chain4_alias = false;
171 s->plane_updated = 0xf;
172 }
173 if ((sr(s, VGA_SEQ_PLANE_WRITE) & VGA_SR02_ALL_PLANES) ==
174 VGA_SR02_ALL_PLANES && sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
175 offset = 0;
176 switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
177 case 0:
178 base = 0xa0000;
179 size = 0x20000;
180 break;
181 case 1:
182 base = 0xa0000;
183 size = 0x10000;
184 offset = s->bank_offset;
185 break;
186 case 2:
187 base = 0xb0000;
188 size = 0x8000;
189 break;
190 case 3:
191 default:
192 base = 0xb8000;
193 size = 0x8000;
194 break;
195 }
196 assert(offset + size <= s->vram_size);
197 memory_region_init_alias(&s->chain4_alias, memory_region_owner(&s->vram),
198 "vga.chain4", &s->vram, offset, size);
199 memory_region_add_subregion_overlap(s->legacy_address_space, base,
200 &s->chain4_alias, 2);
201 s->has_chain4_alias = true;
202 }
203}
204
205static void vga_dumb_update_retrace_info(VGACommonState *s)
206{
207 (void) s;
208}
209
210static void vga_precise_update_retrace_info(VGACommonState *s)
211{
212 int htotal_chars;
213 int hretr_start_char;
214 int hretr_skew_chars;
215 int hretr_end_char;
216
217 int vtotal_lines;
218 int vretr_start_line;
219 int vretr_end_line;
220
221 int dots;
222#if 0
223 int div2, sldiv2;
224#endif
225 int clocking_mode;
226 int clock_sel;
227 const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
228 int64_t chars_per_sec;
229 struct vga_precise_retrace *r = &s->retrace_info.precise;
230
231 htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
232 hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
233 hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
234 hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
235
236 vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
237 (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
238 ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
239 vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
240 ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
241 ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
242 vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
243
244 clocking_mode = (sr(s, VGA_SEQ_CLOCK_MODE) >> 3) & 1;
245 clock_sel = (s->msr >> 2) & 3;
246 dots = (s->msr & 1) ? 8 : 9;
247
248 chars_per_sec = clk_hz[clock_sel] / dots;
249
250 htotal_chars <<= clocking_mode;
251
252 r->total_chars = vtotal_lines * htotal_chars;
253 if (r->freq) {
254 r->ticks_per_char = NANOSECONDS_PER_SECOND / (r->total_chars * r->freq);
255 } else {
256 r->ticks_per_char = NANOSECONDS_PER_SECOND / chars_per_sec;
257 }
258
259 r->vstart = vretr_start_line;
260 r->vend = r->vstart + vretr_end_line + 1;
261
262 r->hstart = hretr_start_char + hretr_skew_chars;
263 r->hend = r->hstart + hretr_end_char + 1;
264 r->htotal = htotal_chars;
265
266#if 0
267 div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
268 sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
269 printf (
270 "hz=%f\n"
271 "htotal = %d\n"
272 "hretr_start = %d\n"
273 "hretr_skew = %d\n"
274 "hretr_end = %d\n"
275 "vtotal = %d\n"
276 "vretr_start = %d\n"
277 "vretr_end = %d\n"
278 "div2 = %d sldiv2 = %d\n"
279 "clocking_mode = %d\n"
280 "clock_sel = %d %d\n"
281 "dots = %d\n"
282 "ticks/char = %" PRId64 "\n"
283 "\n",
284 (double) NANOSECONDS_PER_SECOND / (r->ticks_per_char * r->total_chars),
285 htotal_chars,
286 hretr_start_char,
287 hretr_skew_chars,
288 hretr_end_char,
289 vtotal_lines,
290 vretr_start_line,
291 vretr_end_line,
292 div2, sldiv2,
293 clocking_mode,
294 clock_sel,
295 clk_hz[clock_sel],
296 dots,
297 r->ticks_per_char
298 );
299#endif
300}
301
302static uint8_t vga_precise_retrace(VGACommonState *s)
303{
304 struct vga_precise_retrace *r = &s->retrace_info.precise;
305 uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
306
307 if (r->total_chars) {
308 int cur_line, cur_line_char, cur_char;
309 int64_t cur_tick;
310
311 cur_tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
312
313 cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
314 cur_line = cur_char / r->htotal;
315
316 if (cur_line >= r->vstart && cur_line <= r->vend) {
317 val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
318 } else {
319 cur_line_char = cur_char % r->htotal;
320 if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
321 val |= ST01_DISP_ENABLE;
322 }
323 }
324
325 return val;
326 } else {
327 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
328 }
329}
330
331static uint8_t vga_dumb_retrace(VGACommonState *s)
332{
333 return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
334}
335
336int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
337{
338 if (s->msr & VGA_MIS_COLOR) {
339
340 return (addr >= 0x3b0 && addr <= 0x3bf);
341 } else {
342
343 return (addr >= 0x3d0 && addr <= 0x3df);
344 }
345}
346
347uint32_t vga_ioport_read(void *opaque, uint32_t addr)
348{
349 VGACommonState *s = opaque;
350 int val, index;
351
352 if (vga_ioport_invalid(s, addr)) {
353 val = 0xff;
354 } else {
355 switch(addr) {
356 case VGA_ATT_W:
357 if (s->ar_flip_flop == 0) {
358 val = s->ar_index;
359 } else {
360 val = 0;
361 }
362 break;
363 case VGA_ATT_R:
364 index = s->ar_index & 0x1f;
365 if (index < VGA_ATT_C) {
366 val = s->ar[index];
367 } else {
368 val = 0;
369 }
370 break;
371 case VGA_MIS_W:
372 val = s->st00;
373 break;
374 case VGA_SEQ_I:
375 val = s->sr_index;
376 break;
377 case VGA_SEQ_D:
378 val = s->sr[s->sr_index];
379#ifdef DEBUG_VGA_REG
380 printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
381#endif
382 break;
383 case VGA_PEL_IR:
384 val = s->dac_state;
385 break;
386 case VGA_PEL_IW:
387 val = s->dac_write_index;
388 break;
389 case VGA_PEL_D:
390 val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
391 if (++s->dac_sub_index == 3) {
392 s->dac_sub_index = 0;
393 s->dac_read_index++;
394 }
395 break;
396 case VGA_FTC_R:
397 val = s->fcr;
398 break;
399 case VGA_MIS_R:
400 val = s->msr;
401 break;
402 case VGA_GFX_I:
403 val = s->gr_index;
404 break;
405 case VGA_GFX_D:
406 val = s->gr[s->gr_index];
407#ifdef DEBUG_VGA_REG
408 printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
409#endif
410 break;
411 case VGA_CRT_IM:
412 case VGA_CRT_IC:
413 val = s->cr_index;
414 break;
415 case VGA_CRT_DM:
416 case VGA_CRT_DC:
417 val = s->cr[s->cr_index];
418#ifdef DEBUG_VGA_REG
419 printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
420#endif
421 break;
422 case VGA_IS1_RM:
423 case VGA_IS1_RC:
424
425 val = s->st01 = s->retrace(s);
426 s->ar_flip_flop = 0;
427 break;
428 default:
429 val = 0x00;
430 break;
431 }
432 }
433 trace_vga_std_read_io(addr, val);
434 return val;
435}
436
437void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
438{
439 VGACommonState *s = opaque;
440 int index;
441
442
443 if (vga_ioport_invalid(s, addr)) {
444 return;
445 }
446 trace_vga_std_write_io(addr, val);
447
448 switch(addr) {
449 case VGA_ATT_W:
450 if (s->ar_flip_flop == 0) {
451 val &= 0x3f;
452 s->ar_index = val;
453 } else {
454 index = s->ar_index & 0x1f;
455 switch(index) {
456 case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
457 s->ar[index] = val & 0x3f;
458 break;
459 case VGA_ATC_MODE:
460 s->ar[index] = val & ~0x10;
461 break;
462 case VGA_ATC_OVERSCAN:
463 s->ar[index] = val;
464 break;
465 case VGA_ATC_PLANE_ENABLE:
466 s->ar[index] = val & ~0xc0;
467 break;
468 case VGA_ATC_PEL:
469 s->ar[index] = val & ~0xf0;
470 break;
471 case VGA_ATC_COLOR_PAGE:
472 s->ar[index] = val & ~0xf0;
473 break;
474 default:
475 break;
476 }
477 }
478 s->ar_flip_flop ^= 1;
479 break;
480 case VGA_MIS_W:
481 s->msr = val & ~0x10;
482 s->update_retrace_info(s);
483 break;
484 case VGA_SEQ_I:
485 s->sr_index = val & 7;
486 break;
487 case VGA_SEQ_D:
488#ifdef DEBUG_VGA_REG
489 printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
490#endif
491 s->sr[s->sr_index] = val & sr_mask[s->sr_index];
492 if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
493 s->update_retrace_info(s);
494 }
495 vga_update_memory_access(s);
496 break;
497 case VGA_PEL_IR:
498 s->dac_read_index = val;
499 s->dac_sub_index = 0;
500 s->dac_state = 3;
501 break;
502 case VGA_PEL_IW:
503 s->dac_write_index = val;
504 s->dac_sub_index = 0;
505 s->dac_state = 0;
506 break;
507 case VGA_PEL_D:
508 s->dac_cache[s->dac_sub_index] = val;
509 if (++s->dac_sub_index == 3) {
510 memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
511 s->dac_sub_index = 0;
512 s->dac_write_index++;
513 }
514 break;
515 case VGA_GFX_I:
516 s->gr_index = val & 0x0f;
517 break;
518 case VGA_GFX_D:
519#ifdef DEBUG_VGA_REG
520 printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
521#endif
522 s->gr[s->gr_index] = val & gr_mask[s->gr_index];
523 vbe_update_vgaregs(s);
524 vga_update_memory_access(s);
525 break;
526 case VGA_CRT_IM:
527 case VGA_CRT_IC:
528 s->cr_index = val;
529 break;
530 case VGA_CRT_DM:
531 case VGA_CRT_DC:
532#ifdef DEBUG_VGA_REG
533 printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
534#endif
535
536 if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
537 s->cr_index <= VGA_CRTC_OVERFLOW) {
538
539 if (s->cr_index == VGA_CRTC_OVERFLOW) {
540 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
541 (val & 0x10);
542 vbe_update_vgaregs(s);
543 }
544 return;
545 }
546 s->cr[s->cr_index] = val;
547 vbe_update_vgaregs(s);
548
549 switch(s->cr_index) {
550 case VGA_CRTC_H_TOTAL:
551 case VGA_CRTC_H_SYNC_START:
552 case VGA_CRTC_H_SYNC_END:
553 case VGA_CRTC_V_TOTAL:
554 case VGA_CRTC_OVERFLOW:
555 case VGA_CRTC_V_SYNC_END:
556 case VGA_CRTC_MODE:
557 s->update_retrace_info(s);
558 break;
559 }
560 break;
561 case VGA_IS1_RM:
562 case VGA_IS1_RC:
563 s->fcr = val & 0x10;
564 break;
565 }
566}
567
568
569
570
571
572
573
574
575static void vbe_fixup_regs(VGACommonState *s)
576{
577 uint16_t *r = s->vbe_regs;
578 uint32_t bits, linelength, maxy, offset;
579
580 if (!vbe_enabled(s)) {
581
582 return;
583 }
584
585
586 switch (r[VBE_DISPI_INDEX_BPP]) {
587 case 4:
588 case 8:
589 case 16:
590 case 24:
591 case 32:
592 bits = r[VBE_DISPI_INDEX_BPP];
593 break;
594 case 15:
595 bits = 16;
596 break;
597 default:
598 bits = r[VBE_DISPI_INDEX_BPP] = 8;
599 break;
600 }
601
602
603 r[VBE_DISPI_INDEX_XRES] &= ~7u;
604 if (r[VBE_DISPI_INDEX_XRES] == 0) {
605 r[VBE_DISPI_INDEX_XRES] = 8;
606 }
607 if (r[VBE_DISPI_INDEX_XRES] > VBE_DISPI_MAX_XRES) {
608 r[VBE_DISPI_INDEX_XRES] = VBE_DISPI_MAX_XRES;
609 }
610 r[VBE_DISPI_INDEX_VIRT_WIDTH] &= ~7u;
611 if (r[VBE_DISPI_INDEX_VIRT_WIDTH] > VBE_DISPI_MAX_XRES) {
612 r[VBE_DISPI_INDEX_VIRT_WIDTH] = VBE_DISPI_MAX_XRES;
613 }
614 if (r[VBE_DISPI_INDEX_VIRT_WIDTH] < r[VBE_DISPI_INDEX_XRES]) {
615 r[VBE_DISPI_INDEX_VIRT_WIDTH] = r[VBE_DISPI_INDEX_XRES];
616 }
617
618
619 linelength = r[VBE_DISPI_INDEX_VIRT_WIDTH] * bits / 8;
620 maxy = s->vbe_size / linelength;
621 if (r[VBE_DISPI_INDEX_YRES] == 0) {
622 r[VBE_DISPI_INDEX_YRES] = 1;
623 }
624 if (r[VBE_DISPI_INDEX_YRES] > VBE_DISPI_MAX_YRES) {
625 r[VBE_DISPI_INDEX_YRES] = VBE_DISPI_MAX_YRES;
626 }
627 if (r[VBE_DISPI_INDEX_YRES] > maxy) {
628 r[VBE_DISPI_INDEX_YRES] = maxy;
629 }
630
631
632 if (r[VBE_DISPI_INDEX_X_OFFSET] > VBE_DISPI_MAX_XRES) {
633 r[VBE_DISPI_INDEX_X_OFFSET] = VBE_DISPI_MAX_XRES;
634 }
635 if (r[VBE_DISPI_INDEX_Y_OFFSET] > VBE_DISPI_MAX_YRES) {
636 r[VBE_DISPI_INDEX_Y_OFFSET] = VBE_DISPI_MAX_YRES;
637 }
638 offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8;
639 offset += r[VBE_DISPI_INDEX_Y_OFFSET] * linelength;
640 if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) {
641 r[VBE_DISPI_INDEX_Y_OFFSET] = 0;
642 offset = r[VBE_DISPI_INDEX_X_OFFSET] * bits / 8;
643 if (offset + r[VBE_DISPI_INDEX_YRES] * linelength > s->vbe_size) {
644 r[VBE_DISPI_INDEX_X_OFFSET] = 0;
645 offset = 0;
646 }
647 }
648
649
650 r[VBE_DISPI_INDEX_VIRT_HEIGHT] = maxy;
651 s->vbe_line_offset = linelength;
652 s->vbe_start_addr = offset / 4;
653}
654
655
656static void vbe_update_vgaregs(VGACommonState *s)
657{
658 int h, shift_control;
659
660 if (!vbe_enabled(s)) {
661
662 return;
663 }
664
665
666 s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
667 VGA_GR06_GRAPHICS_MODE;
668 s->cr[VGA_CRTC_MODE] |= 3;
669 s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
670
671 s->cr[VGA_CRTC_H_DISP] =
672 (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
673
674 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
675 s->cr[VGA_CRTC_V_DISP_END] = h;
676 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
677 ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
678
679 s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
680 s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
681 s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
682
683 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
684 shift_control = 0;
685 s->sr_vbe[VGA_SEQ_CLOCK_MODE] &= ~8;
686 } else {
687 shift_control = 2;
688
689 s->sr_vbe[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
690
691 s->sr_vbe[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
692 }
693 s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
694 (shift_control << 5);
695 s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f;
696}
697
698static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
699{
700 VGACommonState *s = opaque;
701 return s->vbe_index;
702}
703
704uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
705{
706 VGACommonState *s = opaque;
707 uint32_t val;
708
709 if (s->vbe_index < VBE_DISPI_INDEX_NB) {
710 if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
711 switch(s->vbe_index) {
712
713 case VBE_DISPI_INDEX_XRES:
714 val = VBE_DISPI_MAX_XRES;
715 break;
716 case VBE_DISPI_INDEX_YRES:
717 val = VBE_DISPI_MAX_YRES;
718 break;
719 case VBE_DISPI_INDEX_BPP:
720 val = VBE_DISPI_MAX_BPP;
721 break;
722 default:
723 val = s->vbe_regs[s->vbe_index];
724 break;
725 }
726 } else {
727 val = s->vbe_regs[s->vbe_index];
728 }
729 } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
730 val = s->vbe_size / (64 * KiB);
731 } else {
732 val = 0;
733 }
734 trace_vga_vbe_read(s->vbe_index, val);
735 return val;
736}
737
738void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
739{
740 VGACommonState *s = opaque;
741 s->vbe_index = val;
742}
743
744void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
745{
746 VGACommonState *s = opaque;
747
748 if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
749 trace_vga_vbe_write(s->vbe_index, val);
750 switch(s->vbe_index) {
751 case VBE_DISPI_INDEX_ID:
752 if (val == VBE_DISPI_ID0 ||
753 val == VBE_DISPI_ID1 ||
754 val == VBE_DISPI_ID2 ||
755 val == VBE_DISPI_ID3 ||
756 val == VBE_DISPI_ID4 ||
757 val == VBE_DISPI_ID5) {
758 s->vbe_regs[s->vbe_index] = val;
759 }
760 break;
761 case VBE_DISPI_INDEX_XRES:
762 case VBE_DISPI_INDEX_YRES:
763 case VBE_DISPI_INDEX_BPP:
764 case VBE_DISPI_INDEX_VIRT_WIDTH:
765 case VBE_DISPI_INDEX_X_OFFSET:
766 case VBE_DISPI_INDEX_Y_OFFSET:
767 s->vbe_regs[s->vbe_index] = val;
768 vbe_fixup_regs(s);
769 vbe_update_vgaregs(s);
770 break;
771 case VBE_DISPI_INDEX_BANK:
772 val &= s->vbe_bank_mask;
773 s->vbe_regs[s->vbe_index] = val;
774 s->bank_offset = (val << 16);
775 vga_update_memory_access(s);
776 break;
777 case VBE_DISPI_INDEX_ENABLE:
778 if ((val & VBE_DISPI_ENABLED) &&
779 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
780
781 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 0;
782 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
783 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
784 s->vbe_regs[VBE_DISPI_INDEX_ENABLE] |= VBE_DISPI_ENABLED;
785 vbe_fixup_regs(s);
786 vbe_update_vgaregs(s);
787
788
789 if (!(val & VBE_DISPI_NOCLEARMEM)) {
790 memset(s->vram_ptr, 0,
791 s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
792 }
793 } else {
794 s->bank_offset = 0;
795 }
796 s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
797 s->vbe_regs[s->vbe_index] = val;
798 vga_update_memory_access(s);
799 break;
800 default:
801 break;
802 }
803 }
804}
805
806
807uint32_t vga_mem_readb(VGACommonState *s, hwaddr addr)
808{
809 int memory_map_mode, plane;
810 uint32_t ret;
811
812
813 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
814 addr &= 0x1ffff;
815 switch(memory_map_mode) {
816 case 0:
817 break;
818 case 1:
819 if (addr >= 0x10000)
820 return 0xff;
821 addr += s->bank_offset;
822 break;
823 case 2:
824 addr -= 0x10000;
825 if (addr >= 0x8000)
826 return 0xff;
827 break;
828 default:
829 case 3:
830 addr -= 0x18000;
831 if (addr >= 0x8000)
832 return 0xff;
833 break;
834 }
835
836 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
837
838 assert(addr < s->vram_size);
839 ret = s->vram_ptr[addr];
840 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
841
842 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
843 addr = ((addr & ~1) << 1) | plane;
844 if (addr >= s->vram_size) {
845 return 0xff;
846 }
847 ret = s->vram_ptr[addr];
848 } else {
849
850 if (addr * sizeof(uint32_t) >= s->vram_size) {
851 return 0xff;
852 }
853 s->latch = ((uint32_t *)s->vram_ptr)[addr];
854
855 if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
856
857 plane = s->gr[VGA_GFX_PLANE_READ];
858 ret = GET_PLANE(s->latch, plane);
859 } else {
860
861 ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
862 mask16[s->gr[VGA_GFX_COMPARE_MASK]];
863 ret |= ret >> 16;
864 ret |= ret >> 8;
865 ret = (~ret) & 0xff;
866 }
867 }
868 return ret;
869}
870
871
872void vga_mem_writeb(VGACommonState *s, hwaddr addr, uint32_t val)
873{
874 int memory_map_mode, plane, write_mode, b, func_select, mask;
875 uint32_t write_mask, bit_mask, set_mask;
876
877#ifdef DEBUG_VGA_MEM
878 printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
879#endif
880
881 memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
882 addr &= 0x1ffff;
883 switch(memory_map_mode) {
884 case 0:
885 break;
886 case 1:
887 if (addr >= 0x10000)
888 return;
889 addr += s->bank_offset;
890 break;
891 case 2:
892 addr -= 0x10000;
893 if (addr >= 0x8000)
894 return;
895 break;
896 default:
897 case 3:
898 addr -= 0x18000;
899 if (addr >= 0x8000)
900 return;
901 break;
902 }
903
904 if (sr(s, VGA_SEQ_MEMORY_MODE) & VGA_SR04_CHN_4M) {
905
906 plane = addr & 3;
907 mask = (1 << plane);
908 if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
909 assert(addr < s->vram_size);
910 s->vram_ptr[addr] = val;
911#ifdef DEBUG_VGA_MEM
912 printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
913#endif
914 s->plane_updated |= mask;
915 memory_region_set_dirty(&s->vram, addr, 1);
916 }
917 } else if (s->gr[VGA_GFX_MODE] & 0x10) {
918
919 plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
920 mask = (1 << plane);
921 if (sr(s, VGA_SEQ_PLANE_WRITE) & mask) {
922 addr = ((addr & ~1) << 1) | plane;
923 if (addr >= s->vram_size) {
924 return;
925 }
926 s->vram_ptr[addr] = val;
927#ifdef DEBUG_VGA_MEM
928 printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
929#endif
930 s->plane_updated |= mask;
931 memory_region_set_dirty(&s->vram, addr, 1);
932 }
933 } else {
934
935 write_mode = s->gr[VGA_GFX_MODE] & 3;
936 switch(write_mode) {
937 default:
938 case 0:
939
940 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
941 val = ((val >> b) | (val << (8 - b))) & 0xff;
942 val |= val << 8;
943 val |= val << 16;
944
945
946 set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
947 val = (val & ~set_mask) |
948 (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
949 bit_mask = s->gr[VGA_GFX_BIT_MASK];
950 break;
951 case 1:
952 val = s->latch;
953 goto do_write;
954 case 2:
955 val = mask16[val & 0x0f];
956 bit_mask = s->gr[VGA_GFX_BIT_MASK];
957 break;
958 case 3:
959
960 b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
961 val = (val >> b) | (val << (8 - b));
962
963 bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
964 val = mask16[s->gr[VGA_GFX_SR_VALUE]];
965 break;
966 }
967
968
969 func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
970 switch(func_select) {
971 case 0:
972 default:
973
974 break;
975 case 1:
976
977 val &= s->latch;
978 break;
979 case 2:
980
981 val |= s->latch;
982 break;
983 case 3:
984
985 val ^= s->latch;
986 break;
987 }
988
989
990 bit_mask |= bit_mask << 8;
991 bit_mask |= bit_mask << 16;
992 val = (val & bit_mask) | (s->latch & ~bit_mask);
993
994 do_write:
995
996 mask = sr(s, VGA_SEQ_PLANE_WRITE);
997 s->plane_updated |= mask;
998 write_mask = mask16[mask];
999 if (addr * sizeof(uint32_t) >= s->vram_size) {
1000 return;
1001 }
1002 ((uint32_t *)s->vram_ptr)[addr] =
1003 (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
1004 (val & write_mask);
1005#ifdef DEBUG_VGA_MEM
1006 printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
1007 addr * 4, write_mask, val);
1008#endif
1009 memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
1010 }
1011}
1012
1013typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
1014 uint32_t srcaddr, int width);
1015
1016#include "vga-access.h"
1017#include "vga-helpers.h"
1018
1019
1020static int update_palette16(VGACommonState *s)
1021{
1022 int full_update, i;
1023 uint32_t v, col, *palette;
1024
1025 full_update = 0;
1026 palette = s->last_palette;
1027 for(i = 0; i < 16; i++) {
1028 v = s->ar[i];
1029 if (s->ar[VGA_ATC_MODE] & 0x80) {
1030 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
1031 } else {
1032 v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
1033 }
1034 v = v * 3;
1035 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1036 c6_to_8(s->palette[v + 1]),
1037 c6_to_8(s->palette[v + 2]));
1038 if (col != palette[i]) {
1039 full_update = 1;
1040 palette[i] = col;
1041 }
1042 }
1043 return full_update;
1044}
1045
1046
1047static int update_palette256(VGACommonState *s)
1048{
1049 int full_update, i;
1050 uint32_t v, col, *palette;
1051
1052 full_update = 0;
1053 palette = s->last_palette;
1054 v = 0;
1055 for(i = 0; i < 256; i++) {
1056 if (s->dac_8bit) {
1057 col = rgb_to_pixel32(s->palette[v],
1058 s->palette[v + 1],
1059 s->palette[v + 2]);
1060 } else {
1061 col = rgb_to_pixel32(c6_to_8(s->palette[v]),
1062 c6_to_8(s->palette[v + 1]),
1063 c6_to_8(s->palette[v + 2]));
1064 }
1065 if (col != palette[i]) {
1066 full_update = 1;
1067 palette[i] = col;
1068 }
1069 v += 3;
1070 }
1071 return full_update;
1072}
1073
1074static void vga_get_offsets(VGACommonState *s,
1075 uint32_t *pline_offset,
1076 uint32_t *pstart_addr,
1077 uint32_t *pline_compare)
1078{
1079 uint32_t start_addr, line_offset, line_compare;
1080
1081 if (vbe_enabled(s)) {
1082 line_offset = s->vbe_line_offset;
1083 start_addr = s->vbe_start_addr;
1084 line_compare = 65535;
1085 } else {
1086
1087 line_offset = s->cr[VGA_CRTC_OFFSET];
1088 line_offset <<= 3;
1089
1090
1091 start_addr = s->cr[VGA_CRTC_START_LO] |
1092 (s->cr[VGA_CRTC_START_HI] << 8);
1093
1094
1095 line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
1096 ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
1097 ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
1098 }
1099 *pline_offset = line_offset;
1100 *pstart_addr = start_addr;
1101 *pline_compare = line_compare;
1102}
1103
1104
1105static int update_basic_params(VGACommonState *s)
1106{
1107 int full_update;
1108 uint32_t start_addr, line_offset, line_compare;
1109
1110 full_update = 0;
1111
1112 s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1113
1114 if (line_offset != s->line_offset ||
1115 start_addr != s->start_addr ||
1116 line_compare != s->line_compare) {
1117 s->line_offset = line_offset;
1118 s->start_addr = start_addr;
1119 s->line_compare = line_compare;
1120 full_update = 1;
1121 }
1122 return full_update;
1123}
1124
1125
1126static const uint8_t cursor_glyph[32 * 4] = {
1127 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1128 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1129 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1130 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1131 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1132 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1133 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1134 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1135 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1136 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1137 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1138 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1139 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1140 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1141 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1142 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1143};
1144
1145static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1146 int *pcwidth, int *pcheight)
1147{
1148 int width, cwidth, height, cheight;
1149
1150
1151 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1152 cwidth = 8;
1153 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
1154 cwidth = 9;
1155 }
1156 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
1157 cwidth = 16;
1158 }
1159 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1160 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1161
1162 height = 100;
1163 } else {
1164 height = s->cr[VGA_CRTC_V_DISP_END] |
1165 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1166 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1167 height = (height + 1) / cheight;
1168 }
1169
1170 *pwidth = width;
1171 *pheight = height;
1172 *pcwidth = cwidth;
1173 *pcheight = cheight;
1174}
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184static void vga_draw_text(VGACommonState *s, int full_update)
1185{
1186 DisplaySurface *surface = qemu_console_surface(s->con);
1187 int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1188 int cx_min, cx_max, linesize, x_incr, line, line1;
1189 uint32_t offset, fgcol, bgcol, v, cursor_offset;
1190 uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1191 const uint8_t *font_ptr, *font_base[2];
1192 int dup9, line_offset;
1193 uint32_t *palette;
1194 uint32_t *ch_attr_ptr;
1195 int64_t now = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
1196
1197
1198 v = sr(s, VGA_SEQ_CHARACTER_MAP);
1199 offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1200 if (offset != s->font_offsets[0]) {
1201 s->font_offsets[0] = offset;
1202 full_update = 1;
1203 }
1204 font_base[0] = s->vram_ptr + offset;
1205
1206 offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1207 font_base[1] = s->vram_ptr + offset;
1208 if (offset != s->font_offsets[1]) {
1209 s->font_offsets[1] = offset;
1210 full_update = 1;
1211 }
1212 if (s->plane_updated & (1 << 2) || s->has_chain4_alias) {
1213
1214
1215 s->plane_updated = 0;
1216 full_update = 1;
1217 }
1218 full_update |= update_basic_params(s);
1219
1220 line_offset = s->line_offset;
1221
1222 vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1223 if ((height * width) <= 1) {
1224
1225 return;
1226 }
1227 if ((height * width) > CH_ATTR_SIZE) {
1228
1229 return;
1230 }
1231
1232 if (width != s->last_width || height != s->last_height ||
1233 cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1234 s->last_scr_width = width * cw;
1235 s->last_scr_height = height * cheight;
1236 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1237 surface = qemu_console_surface(s->con);
1238 dpy_text_resize(s->con, width, height);
1239 s->last_depth = 0;
1240 s->last_width = width;
1241 s->last_height = height;
1242 s->last_ch = cheight;
1243 s->last_cw = cw;
1244 full_update = 1;
1245 }
1246 full_update |= update_palette16(s);
1247 palette = s->last_palette;
1248 x_incr = cw * surface_bytes_per_pixel(surface);
1249
1250 if (full_update) {
1251 s->full_update_text = 1;
1252 }
1253 if (s->full_update_gfx) {
1254 s->full_update_gfx = 0;
1255 full_update |= 1;
1256 }
1257
1258 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1259 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1260 if (cursor_offset != s->cursor_offset ||
1261 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1262 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1263
1264
1265 if (s->cursor_offset < CH_ATTR_SIZE)
1266 s->last_ch_attr[s->cursor_offset] = -1;
1267 if (cursor_offset < CH_ATTR_SIZE)
1268 s->last_ch_attr[cursor_offset] = -1;
1269 s->cursor_offset = cursor_offset;
1270 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1271 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1272 }
1273 cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1274 if (now >= s->cursor_blink_time) {
1275 s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
1276 s->cursor_visible_phase = !s->cursor_visible_phase;
1277 }
1278
1279 dest = surface_data(surface);
1280 linesize = surface_stride(surface);
1281 ch_attr_ptr = s->last_ch_attr;
1282 line = 0;
1283 offset = s->start_addr * 4;
1284 for(cy = 0; cy < height; cy++) {
1285 d1 = dest;
1286 src = s->vram_ptr + offset;
1287 cx_min = width;
1288 cx_max = -1;
1289 for(cx = 0; cx < width; cx++) {
1290 if (src + sizeof(uint16_t) > s->vram_ptr + s->vram_size) {
1291 break;
1292 }
1293 ch_attr = *(uint16_t *)src;
1294 if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
1295 if (cx < cx_min)
1296 cx_min = cx;
1297 if (cx > cx_max)
1298 cx_max = cx;
1299 *ch_attr_ptr = ch_attr;
1300#if HOST_BIG_ENDIAN
1301 ch = ch_attr >> 8;
1302 cattr = ch_attr & 0xff;
1303#else
1304 ch = ch_attr & 0xff;
1305 cattr = ch_attr >> 8;
1306#endif
1307 font_ptr = font_base[(cattr >> 3) & 1];
1308 font_ptr += 32 * 4 * ch;
1309 bgcol = palette[cattr >> 4];
1310 fgcol = palette[cattr & 0x0f];
1311 if (cw == 16) {
1312 vga_draw_glyph16(d1, linesize,
1313 font_ptr, cheight, fgcol, bgcol);
1314 } else if (cw != 9) {
1315 vga_draw_glyph8(d1, linesize,
1316 font_ptr, cheight, fgcol, bgcol);
1317 } else {
1318 dup9 = 0;
1319 if (ch >= 0xb0 && ch <= 0xdf &&
1320 (s->ar[VGA_ATC_MODE] & 0x04)) {
1321 dup9 = 1;
1322 }
1323 vga_draw_glyph9(d1, linesize,
1324 font_ptr, cheight, fgcol, bgcol, dup9);
1325 }
1326 if (src == cursor_ptr &&
1327 !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1328 s->cursor_visible_phase) {
1329 int line_start, line_last, h;
1330
1331 line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1332 line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1333
1334 if (line_last > cheight - 1)
1335 line_last = cheight - 1;
1336 if (line_last >= line_start && line_start < cheight) {
1337 h = line_last - line_start + 1;
1338 d = d1 + linesize * line_start;
1339 if (cw == 16) {
1340 vga_draw_glyph16(d, linesize,
1341 cursor_glyph, h, fgcol, bgcol);
1342 } else if (cw != 9) {
1343 vga_draw_glyph8(d, linesize,
1344 cursor_glyph, h, fgcol, bgcol);
1345 } else {
1346 vga_draw_glyph9(d, linesize,
1347 cursor_glyph, h, fgcol, bgcol, 1);
1348 }
1349 }
1350 }
1351 }
1352 d1 += x_incr;
1353 src += 4;
1354 ch_attr_ptr++;
1355 }
1356 if (cx_max != -1) {
1357 dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
1358 (cx_max - cx_min + 1) * cw, cheight);
1359 }
1360 dest += linesize * cheight;
1361 line1 = line + cheight;
1362 offset += line_offset;
1363 if (line < s->line_compare && line1 >= s->line_compare) {
1364 offset = 0;
1365 }
1366 line = line1;
1367 }
1368}
1369
1370enum {
1371 VGA_DRAW_LINE2,
1372 VGA_DRAW_LINE2D2,
1373 VGA_DRAW_LINE4,
1374 VGA_DRAW_LINE4D2,
1375 VGA_DRAW_LINE8D2,
1376 VGA_DRAW_LINE8,
1377 VGA_DRAW_LINE15_LE,
1378 VGA_DRAW_LINE16_LE,
1379 VGA_DRAW_LINE24_LE,
1380 VGA_DRAW_LINE32_LE,
1381 VGA_DRAW_LINE15_BE,
1382 VGA_DRAW_LINE16_BE,
1383 VGA_DRAW_LINE24_BE,
1384 VGA_DRAW_LINE32_BE,
1385 VGA_DRAW_LINE_NB,
1386};
1387
1388static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
1389 vga_draw_line2,
1390 vga_draw_line2d2,
1391 vga_draw_line4,
1392 vga_draw_line4d2,
1393 vga_draw_line8d2,
1394 vga_draw_line8,
1395 vga_draw_line15_le,
1396 vga_draw_line16_le,
1397 vga_draw_line24_le,
1398 vga_draw_line32_le,
1399 vga_draw_line15_be,
1400 vga_draw_line16_be,
1401 vga_draw_line24_be,
1402 vga_draw_line32_be,
1403};
1404
1405static int vga_get_bpp(VGACommonState *s)
1406{
1407 int ret;
1408
1409 if (vbe_enabled(s)) {
1410 ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1411 } else {
1412 ret = 0;
1413 }
1414 return ret;
1415}
1416
1417static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1418{
1419 int width, height;
1420
1421 if (vbe_enabled(s)) {
1422 width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1423 height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1424 } else {
1425 width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1426 height = s->cr[VGA_CRTC_V_DISP_END] |
1427 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1428 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1429 height = (height + 1);
1430 }
1431 *pwidth = width;
1432 *pheight = height;
1433}
1434
1435void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1436{
1437 int y;
1438 if (y1 >= VGA_MAX_HEIGHT)
1439 return;
1440 if (y2 >= VGA_MAX_HEIGHT)
1441 y2 = VGA_MAX_HEIGHT;
1442 for(y = y1; y < y2; y++) {
1443 s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1444 }
1445}
1446
1447static bool vga_scanline_invalidated(VGACommonState *s, int y)
1448{
1449 if (y >= VGA_MAX_HEIGHT) {
1450 return false;
1451 }
1452 return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
1453}
1454
1455void vga_dirty_log_start(VGACommonState *s)
1456{
1457 memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1458}
1459
1460void vga_dirty_log_stop(VGACommonState *s)
1461{
1462 memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1463}
1464
1465
1466
1467
1468static void vga_draw_graphic(VGACommonState *s, int full_update)
1469{
1470 DisplaySurface *surface = qemu_console_surface(s->con);
1471 int y1, y, update, linesize, y_start, double_scan, mask, depth;
1472 int width, height, shift_control, bwidth, bits;
1473 ram_addr_t page0, page1, region_start, region_end;
1474 DirtyBitmapSnapshot *snap = NULL;
1475 int disp_width, multi_scan, multi_run;
1476 uint8_t *d;
1477 uint32_t v, addr1, addr;
1478 vga_draw_line_func *vga_draw_line = NULL;
1479 bool share_surface, force_shadow = false;
1480 pixman_format_code_t format;
1481#if HOST_BIG_ENDIAN
1482 bool byteswap = !s->big_endian_fb;
1483#else
1484 bool byteswap = s->big_endian_fb;
1485#endif
1486
1487 full_update |= update_basic_params(s);
1488
1489 s->get_resolution(s, &width, &height);
1490 disp_width = width;
1491 depth = s->get_bpp(s);
1492
1493 region_start = (s->start_addr * 4);
1494 region_end = region_start + (ram_addr_t)s->line_offset * height;
1495 region_end += width * depth / 8;
1496 region_end -= s->line_offset;
1497 if (region_end > s->vbe_size || depth == 0 || depth == 15) {
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513 region_start = 0;
1514 region_end = s->vbe_size;
1515 force_shadow = true;
1516 }
1517
1518
1519 shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1520 double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1521 if (s->cr[VGA_CRTC_MODE] & 1) {
1522 multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1523 - 1;
1524 } else {
1525
1526
1527 multi_scan = double_scan;
1528 }
1529 multi_run = multi_scan;
1530 if (shift_control != s->shift_control ||
1531 double_scan != s->double_scan) {
1532 full_update = 1;
1533 s->shift_control = shift_control;
1534 s->double_scan = double_scan;
1535 }
1536
1537 if (shift_control == 0) {
1538 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1539 disp_width <<= 1;
1540 }
1541 } else if (shift_control == 1) {
1542 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1543 disp_width <<= 1;
1544 }
1545 }
1546
1547
1548
1549
1550
1551
1552
1553 format = qemu_default_pixman_format(depth, !byteswap);
1554 if (format) {
1555 share_surface = dpy_gfx_check_format(s->con, format)
1556 && !s->force_shadow && !force_shadow;
1557 } else {
1558 share_surface = false;
1559 }
1560
1561 if (s->line_offset != s->last_line_offset ||
1562 disp_width != s->last_width ||
1563 height != s->last_height ||
1564 s->last_depth != depth ||
1565 s->last_byteswap != byteswap ||
1566 share_surface != is_buffer_shared(surface)) {
1567
1568 s->last_scr_width = disp_width;
1569 s->last_scr_height = height;
1570 s->last_width = disp_width;
1571 s->last_height = height;
1572 s->last_line_offset = s->line_offset;
1573 s->last_depth = depth;
1574 s->last_byteswap = byteswap;
1575 full_update = 1;
1576 }
1577 if (surface_data(surface) != s->vram_ptr + (s->start_addr * 4)
1578 && is_buffer_shared(surface)) {
1579
1580
1581 full_update = 1;
1582 }
1583
1584 if (full_update) {
1585 if (share_surface) {
1586 surface = qemu_create_displaysurface_from(disp_width,
1587 height, format, s->line_offset,
1588 s->vram_ptr + (s->start_addr * 4));
1589 dpy_gfx_replace_surface(s->con, surface);
1590 } else {
1591 qemu_console_resize(s->con, disp_width, height);
1592 surface = qemu_console_surface(s->con);
1593 }
1594 }
1595
1596 if (shift_control == 0) {
1597 full_update |= update_palette16(s);
1598 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1599 v = VGA_DRAW_LINE4D2;
1600 } else {
1601 v = VGA_DRAW_LINE4;
1602 }
1603 bits = 4;
1604 } else if (shift_control == 1) {
1605 full_update |= update_palette16(s);
1606 if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1607 v = VGA_DRAW_LINE2D2;
1608 } else {
1609 v = VGA_DRAW_LINE2;
1610 }
1611 bits = 4;
1612 } else {
1613 switch(s->get_bpp(s)) {
1614 default:
1615 case 0:
1616 full_update |= update_palette256(s);
1617 v = VGA_DRAW_LINE8D2;
1618 bits = 4;
1619 break;
1620 case 8:
1621 full_update |= update_palette256(s);
1622 v = VGA_DRAW_LINE8;
1623 bits = 8;
1624 break;
1625 case 15:
1626 v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
1627 bits = 16;
1628 break;
1629 case 16:
1630 v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
1631 bits = 16;
1632 break;
1633 case 24:
1634 v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
1635 bits = 24;
1636 break;
1637 case 32:
1638 v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
1639 bits = 32;
1640 break;
1641 }
1642 }
1643 vga_draw_line = vga_draw_line_table[v];
1644
1645 if (!is_buffer_shared(surface) && s->cursor_invalidate) {
1646 s->cursor_invalidate(s);
1647 }
1648
1649#if 0
1650 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",
1651 width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1652 s->line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
1653#endif
1654 addr1 = (s->start_addr * 4);
1655 bwidth = DIV_ROUND_UP(width * bits, 8);
1656 y_start = -1;
1657 d = surface_data(surface);
1658 linesize = surface_stride(surface);
1659 y1 = 0;
1660
1661 if (!full_update) {
1662 if (s->line_compare < height) {
1663
1664 region_start = 0;
1665 }
1666 snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
1667 region_end - region_start,
1668 DIRTY_MEMORY_VGA);
1669 }
1670
1671 for(y = 0; y < height; y++) {
1672 addr = addr1;
1673 if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1674 int shift;
1675
1676 shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1677 addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1678 }
1679 if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1680 addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1681 }
1682 page0 = addr & s->vbe_size_mask;
1683 page1 = (addr + bwidth - 1) & s->vbe_size_mask;
1684 if (full_update) {
1685 update = 1;
1686 } else if (page1 < page0) {
1687
1688 assert(force_shadow);
1689 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1690 page0, s->vbe_size - page0);
1691 update |= memory_region_snapshot_get_dirty(&s->vram, snap,
1692 0, page1);
1693 } else {
1694 update = memory_region_snapshot_get_dirty(&s->vram, snap,
1695 page0, page1 - page0);
1696 }
1697
1698 update |= vga_scanline_invalidated(s, y);
1699 if (update) {
1700 if (y_start < 0)
1701 y_start = y;
1702 if (!(is_buffer_shared(surface))) {
1703 vga_draw_line(s, d, addr, width);
1704 if (s->cursor_draw_line)
1705 s->cursor_draw_line(s, d, y);
1706 }
1707 } else {
1708 if (y_start >= 0) {
1709
1710 dpy_gfx_update(s->con, 0, y_start,
1711 disp_width, y - y_start);
1712 y_start = -1;
1713 }
1714 }
1715 if (!multi_run) {
1716 mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1717 if ((y1 & mask) == mask)
1718 addr1 += s->line_offset;
1719 y1++;
1720 multi_run = multi_scan;
1721 } else {
1722 multi_run--;
1723 }
1724
1725 if (y == s->line_compare)
1726 addr1 = 0;
1727 d += linesize;
1728 }
1729 if (y_start >= 0) {
1730
1731 dpy_gfx_update(s->con, 0, y_start,
1732 disp_width, y - y_start);
1733 }
1734 g_free(snap);
1735 memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
1736}
1737
1738static void vga_draw_blank(VGACommonState *s, int full_update)
1739{
1740 DisplaySurface *surface = qemu_console_surface(s->con);
1741 int i, w;
1742 uint8_t *d;
1743
1744 if (!full_update)
1745 return;
1746 if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1747 return;
1748
1749 w = s->last_scr_width * surface_bytes_per_pixel(surface);
1750 d = surface_data(surface);
1751 for(i = 0; i < s->last_scr_height; i++) {
1752 memset(d, 0, w);
1753 d += surface_stride(surface);
1754 }
1755 dpy_gfx_update_full(s->con);
1756}
1757
1758#define GMODE_TEXT 0
1759#define GMODE_GRAPH 1
1760#define GMODE_BLANK 2
1761
1762static void vga_update_display(void *opaque)
1763{
1764 VGACommonState *s = opaque;
1765 DisplaySurface *surface = qemu_console_surface(s->con);
1766 int full_update, graphic_mode;
1767
1768 qemu_flush_coalesced_mmio_buffer();
1769
1770 if (surface_bits_per_pixel(surface) == 0) {
1771
1772 } else {
1773 full_update = 0;
1774 if (!(s->ar_index & 0x20)) {
1775 graphic_mode = GMODE_BLANK;
1776 } else {
1777 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1778 }
1779 if (graphic_mode != s->graphic_mode) {
1780 s->graphic_mode = graphic_mode;
1781 s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
1782 full_update = 1;
1783 }
1784 switch(graphic_mode) {
1785 case GMODE_TEXT:
1786 vga_draw_text(s, full_update);
1787 break;
1788 case GMODE_GRAPH:
1789 vga_draw_graphic(s, full_update);
1790 break;
1791 case GMODE_BLANK:
1792 default:
1793 vga_draw_blank(s, full_update);
1794 break;
1795 }
1796 }
1797}
1798
1799
1800static void vga_invalidate_display(void *opaque)
1801{
1802 VGACommonState *s = opaque;
1803
1804 s->last_width = -1;
1805 s->last_height = -1;
1806}
1807
1808void vga_common_reset(VGACommonState *s)
1809{
1810 s->sr_index = 0;
1811 memset(s->sr, '\0', sizeof(s->sr));
1812 memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
1813 s->gr_index = 0;
1814 memset(s->gr, '\0', sizeof(s->gr));
1815 s->ar_index = 0;
1816 memset(s->ar, '\0', sizeof(s->ar));
1817 s->ar_flip_flop = 0;
1818 s->cr_index = 0;
1819 memset(s->cr, '\0', sizeof(s->cr));
1820 s->msr = 0;
1821 s->fcr = 0;
1822 s->st00 = 0;
1823 s->st01 = 0;
1824 s->dac_state = 0;
1825 s->dac_sub_index = 0;
1826 s->dac_read_index = 0;
1827 s->dac_write_index = 0;
1828 memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1829 s->dac_8bit = 0;
1830 memset(s->palette, '\0', sizeof(s->palette));
1831 s->bank_offset = 0;
1832 s->vbe_index = 0;
1833 memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1834 s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1835 s->vbe_start_addr = 0;
1836 s->vbe_line_offset = 0;
1837 s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1838 memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1839 s->graphic_mode = -1;
1840 s->shift_control = 0;
1841 s->double_scan = 0;
1842 s->line_offset = 0;
1843 s->line_compare = 0;
1844 s->start_addr = 0;
1845 s->plane_updated = 0;
1846 s->last_cw = 0;
1847 s->last_ch = 0;
1848 s->last_width = 0;
1849 s->last_height = 0;
1850 s->last_scr_width = 0;
1851 s->last_scr_height = 0;
1852 s->cursor_start = 0;
1853 s->cursor_end = 0;
1854 s->cursor_offset = 0;
1855 s->big_endian_fb = s->default_endian_fb;
1856 memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1857 memset(s->last_palette, '\0', sizeof(s->last_palette));
1858 memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1859 switch (vga_retrace_method) {
1860 case VGA_RETRACE_DUMB:
1861 break;
1862 case VGA_RETRACE_PRECISE:
1863 memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1864 break;
1865 }
1866 vga_update_memory_access(s);
1867}
1868
1869static void vga_reset(void *opaque)
1870{
1871 VGACommonState *s = opaque;
1872 vga_common_reset(s);
1873}
1874
1875#define TEXTMODE_X(x) ((x) % width)
1876#define TEXTMODE_Y(x) ((x) / width)
1877#define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1878 ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1879
1880
1881static void vga_update_text(void *opaque, console_ch_t *chardata)
1882{
1883 VGACommonState *s = opaque;
1884 int graphic_mode, i, cursor_offset, cursor_visible;
1885 int cw, cheight, width, height, size, c_min, c_max;
1886 uint32_t *src;
1887 console_ch_t *dst, val;
1888 char msg_buffer[80];
1889 int full_update = 0;
1890
1891 qemu_flush_coalesced_mmio_buffer();
1892
1893 if (!(s->ar_index & 0x20)) {
1894 graphic_mode = GMODE_BLANK;
1895 } else {
1896 graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1897 }
1898 if (graphic_mode != s->graphic_mode) {
1899 s->graphic_mode = graphic_mode;
1900 full_update = 1;
1901 }
1902 if (s->last_width == -1) {
1903 s->last_width = 0;
1904 full_update = 1;
1905 }
1906
1907 switch (graphic_mode) {
1908 case GMODE_TEXT:
1909
1910 full_update |= update_basic_params(s);
1911
1912
1913 cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1914 cw = 8;
1915 if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
1916 cw = 9;
1917 }
1918 if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
1919 cw = 16;
1920 }
1921 width = (s->cr[VGA_CRTC_H_DISP] + 1);
1922 if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1923
1924 height = 100;
1925 } else {
1926 height = s->cr[VGA_CRTC_V_DISP_END] |
1927 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1928 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1929 height = (height + 1) / cheight;
1930 }
1931
1932 size = (height * width);
1933 if (size > CH_ATTR_SIZE) {
1934 if (!full_update)
1935 return;
1936
1937 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1938 width, height);
1939 break;
1940 }
1941
1942 if (width != s->last_width || height != s->last_height ||
1943 cw != s->last_cw || cheight != s->last_ch) {
1944 s->last_scr_width = width * cw;
1945 s->last_scr_height = height * cheight;
1946 qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1947 dpy_text_resize(s->con, width, height);
1948 s->last_depth = 0;
1949 s->last_width = width;
1950 s->last_height = height;
1951 s->last_ch = cheight;
1952 s->last_cw = cw;
1953 full_update = 1;
1954 }
1955
1956 if (full_update) {
1957 s->full_update_gfx = 1;
1958 }
1959 if (s->full_update_text) {
1960 s->full_update_text = 0;
1961 full_update |= 1;
1962 }
1963
1964
1965 cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1966 s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1967 if (cursor_offset != s->cursor_offset ||
1968 s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1969 s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1970 cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
1971 if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1972 dpy_text_cursor(s->con,
1973 TEXTMODE_X(cursor_offset),
1974 TEXTMODE_Y(cursor_offset));
1975 else
1976 dpy_text_cursor(s->con, -1, -1);
1977 s->cursor_offset = cursor_offset;
1978 s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1979 s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1980 }
1981
1982 src = (uint32_t *) s->vram_ptr + s->start_addr;
1983 dst = chardata;
1984
1985 if (full_update) {
1986 for (i = 0; i < size; src ++, dst ++, i ++)
1987 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
1988
1989 dpy_text_update(s->con, 0, 0, width, height);
1990 } else {
1991 c_max = 0;
1992
1993 for (i = 0; i < size; src ++, dst ++, i ++) {
1994 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1995 if (*dst != val) {
1996 *dst = val;
1997 c_max = i;
1998 break;
1999 }
2000 }
2001 c_min = i;
2002 for (; i < size; src ++, dst ++, i ++) {
2003 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2004 if (*dst != val) {
2005 *dst = val;
2006 c_max = i;
2007 }
2008 }
2009
2010 if (c_min <= c_max) {
2011 i = TEXTMODE_Y(c_min);
2012 dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2013 }
2014 }
2015
2016 return;
2017 case GMODE_GRAPH:
2018 if (!full_update)
2019 return;
2020
2021 s->get_resolution(s, &width, &height);
2022 snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2023 width, height);
2024 break;
2025 case GMODE_BLANK:
2026 default:
2027 if (!full_update)
2028 return;
2029
2030 snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2031 break;
2032 }
2033
2034
2035 s->last_width = 60;
2036 s->last_height = height = 3;
2037 dpy_text_cursor(s->con, -1, -1);
2038 dpy_text_resize(s->con, s->last_width, height);
2039
2040 for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2041 console_write_ch(dst ++, ' ');
2042
2043 size = strlen(msg_buffer);
2044 width = (s->last_width - size) / 2;
2045 dst = chardata + s->last_width + width;
2046 for (i = 0; i < size; i ++)
2047 console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
2048 QEMU_COLOR_BLACK, 1));
2049
2050 dpy_text_update(s->con, 0, 0, s->last_width, height);
2051}
2052
2053static uint64_t vga_mem_read(void *opaque, hwaddr addr,
2054 unsigned size)
2055{
2056 VGACommonState *s = opaque;
2057
2058 return vga_mem_readb(s, addr);
2059}
2060
2061static void vga_mem_write(void *opaque, hwaddr addr,
2062 uint64_t data, unsigned size)
2063{
2064 VGACommonState *s = opaque;
2065
2066 vga_mem_writeb(s, addr, data);
2067}
2068
2069const MemoryRegionOps vga_mem_ops = {
2070 .read = vga_mem_read,
2071 .write = vga_mem_write,
2072 .endianness = DEVICE_LITTLE_ENDIAN,
2073 .impl = {
2074 .min_access_size = 1,
2075 .max_access_size = 1,
2076 },
2077};
2078
2079static int vga_common_post_load(void *opaque, int version_id)
2080{
2081 VGACommonState *s = opaque;
2082
2083
2084 s->graphic_mode = -1;
2085 vbe_update_vgaregs(s);
2086 vga_update_memory_access(s);
2087 return 0;
2088}
2089
2090static bool vga_endian_state_needed(void *opaque)
2091{
2092 VGACommonState *s = opaque;
2093
2094
2095
2096
2097
2098
2099 return s->default_endian_fb != s->big_endian_fb;
2100}
2101
2102static const VMStateDescription vmstate_vga_endian = {
2103 .name = "vga.endian",
2104 .version_id = 1,
2105 .minimum_version_id = 1,
2106 .needed = vga_endian_state_needed,
2107 .fields = (VMStateField[]) {
2108 VMSTATE_BOOL(big_endian_fb, VGACommonState),
2109 VMSTATE_END_OF_LIST()
2110 }
2111};
2112
2113const VMStateDescription vmstate_vga_common = {
2114 .name = "vga",
2115 .version_id = 2,
2116 .minimum_version_id = 2,
2117 .post_load = vga_common_post_load,
2118 .fields = (VMStateField[]) {
2119 VMSTATE_UINT32(latch, VGACommonState),
2120 VMSTATE_UINT8(sr_index, VGACommonState),
2121 VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2122 VMSTATE_UINT8(gr_index, VGACommonState),
2123 VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2124 VMSTATE_UINT8(ar_index, VGACommonState),
2125 VMSTATE_BUFFER(ar, VGACommonState),
2126 VMSTATE_INT32(ar_flip_flop, VGACommonState),
2127 VMSTATE_UINT8(cr_index, VGACommonState),
2128 VMSTATE_BUFFER(cr, VGACommonState),
2129 VMSTATE_UINT8(msr, VGACommonState),
2130 VMSTATE_UINT8(fcr, VGACommonState),
2131 VMSTATE_UINT8(st00, VGACommonState),
2132 VMSTATE_UINT8(st01, VGACommonState),
2133
2134 VMSTATE_UINT8(dac_state, VGACommonState),
2135 VMSTATE_UINT8(dac_sub_index, VGACommonState),
2136 VMSTATE_UINT8(dac_read_index, VGACommonState),
2137 VMSTATE_UINT8(dac_write_index, VGACommonState),
2138 VMSTATE_BUFFER(dac_cache, VGACommonState),
2139 VMSTATE_BUFFER(palette, VGACommonState),
2140
2141 VMSTATE_INT32(bank_offset, VGACommonState),
2142 VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState, NULL),
2143 VMSTATE_UINT16(vbe_index, VGACommonState),
2144 VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2145 VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2146 VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2147 VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2148 VMSTATE_END_OF_LIST()
2149 },
2150 .subsections = (const VMStateDescription*[]) {
2151 &vmstate_vga_endian,
2152 NULL
2153 }
2154};
2155
2156static const GraphicHwOps vga_ops = {
2157 .invalidate = vga_invalidate_display,
2158 .gfx_update = vga_update_display,
2159 .text_update = vga_update_text,
2160};
2161
2162static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
2163{
2164 if (val < vmin) {
2165 return vmin;
2166 }
2167 if (val > vmax) {
2168 return vmax;
2169 }
2170 return val;
2171}
2172
2173bool vga_common_init(VGACommonState *s, Object *obj, Error **errp)
2174{
2175 int i, j, v, b;
2176 Error *local_err = NULL;
2177
2178 for(i = 0;i < 256; i++) {
2179 v = 0;
2180 for(j = 0; j < 8; j++) {
2181 v |= ((i >> j) & 1) << (j * 4);
2182 }
2183 expand4[i] = v;
2184
2185 v = 0;
2186 for(j = 0; j < 4; j++) {
2187 v |= ((i >> (2 * j)) & 3) << (j * 4);
2188 }
2189 expand2[i] = v;
2190 }
2191 for(i = 0; i < 16; i++) {
2192 v = 0;
2193 for(j = 0; j < 4; j++) {
2194 b = ((i >> j) & 1);
2195 v |= b << (2 * j);
2196 v |= b << (2 * j + 1);
2197 }
2198 expand4to8[i] = v;
2199 }
2200
2201 s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
2202 s->vram_size_mb = pow2ceil(s->vram_size_mb);
2203 s->vram_size = s->vram_size_mb * MiB;
2204
2205 if (!s->vbe_size) {
2206 s->vbe_size = s->vram_size;
2207 }
2208 s->vbe_size_mask = s->vbe_size - 1;
2209
2210 s->is_vbe_vmstate = 1;
2211
2212 if (s->global_vmstate && qemu_ram_block_by_name("vga.vram")) {
2213 error_setg(errp, "Only one global VGA device can be used at a time");
2214 return false;
2215 }
2216
2217 memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size,
2218 &local_err);
2219 if (local_err) {
2220 error_propagate(errp, local_err);
2221 return false;
2222 }
2223 vmstate_register_ram(&s->vram, s->global_vmstate ? NULL : DEVICE(obj));
2224 xen_register_framebuffer(&s->vram);
2225 s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2226 s->get_bpp = vga_get_bpp;
2227 s->get_offsets = vga_get_offsets;
2228 s->get_resolution = vga_get_resolution;
2229 s->hw_ops = &vga_ops;
2230 switch (vga_retrace_method) {
2231 case VGA_RETRACE_DUMB:
2232 s->retrace = vga_dumb_retrace;
2233 s->update_retrace_info = vga_dumb_update_retrace_info;
2234 break;
2235
2236 case VGA_RETRACE_PRECISE:
2237 s->retrace = vga_precise_retrace;
2238 s->update_retrace_info = vga_precise_update_retrace_info;
2239 break;
2240 }
2241
2242
2243
2244
2245
2246
2247#if TARGET_BIG_ENDIAN
2248 s->default_endian_fb = true;
2249#else
2250 s->default_endian_fb = false;
2251#endif
2252 vga_dirty_log_start(s);
2253
2254 return true;
2255}
2256
2257static const MemoryRegionPortio vga_portio_list[] = {
2258 { 0x04, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write },
2259 { 0x0a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write },
2260 { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write },
2261 { 0x24, 2, 1, .read = vga_ioport_read, .write = vga_ioport_write },
2262 { 0x2a, 1, 1, .read = vga_ioport_read, .write = vga_ioport_write },
2263 PORTIO_END_OF_LIST(),
2264};
2265
2266static const MemoryRegionPortio vbe_portio_list[] = {
2267 { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2268# ifdef TARGET_I386
2269 { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2270# endif
2271 { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2272 PORTIO_END_OF_LIST(),
2273};
2274
2275
2276MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
2277 const MemoryRegionPortio **vga_ports,
2278 const MemoryRegionPortio **vbe_ports)
2279{
2280 MemoryRegion *vga_mem;
2281
2282 *vga_ports = vga_portio_list;
2283 *vbe_ports = vbe_portio_list;
2284
2285 vga_mem = g_malloc(sizeof(*vga_mem));
2286 memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
2287 "vga-lowmem", 0x20000);
2288 memory_region_set_flush_coalesced(vga_mem);
2289
2290 return vga_mem;
2291}
2292
2293void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
2294 MemoryRegion *address_space_io, bool init_vga_ports)
2295{
2296 MemoryRegion *vga_io_memory;
2297 const MemoryRegionPortio *vga_ports, *vbe_ports;
2298
2299 qemu_register_reset(vga_reset, s);
2300
2301 s->bank_offset = 0;
2302
2303 s->legacy_address_space = address_space;
2304
2305 vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
2306 memory_region_add_subregion_overlap(address_space,
2307 0x000a0000,
2308 vga_io_memory,
2309 1);
2310 memory_region_set_coalescing(vga_io_memory);
2311 if (init_vga_ports) {
2312 portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
2313 portio_list_set_flush_coalesced(&s->vga_port_list);
2314 portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
2315 }
2316 if (vbe_ports) {
2317 portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
2318 portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
2319 }
2320}
2321