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