|
|
1.1 root 1: /*
2: * QEMU VGA Emulator.
1.1.1.5 root 3: *
1.1 root 4: * Copyright (c) 2003 Fabrice Bellard
1.1.1.5 root 5: *
1.1 root 6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
1.1.1.5 root 24: #include "hw.h"
25: #include "console.h"
26: #include "pc.h"
27: #include "pci.h"
1.1 root 28: #include "vga_int.h"
1.1.1.5 root 29: #include "pixel_ops.h"
1.1.1.6 root 30: #include "qemu-timer.h"
31: #include "kvm.h"
1.1 root 32:
33: //#define DEBUG_VGA
34: //#define DEBUG_VGA_MEM
35: //#define DEBUG_VGA_REG
36:
37: //#define DEBUG_BOCHS_VBE
38:
39: /* force some bits to zero */
40: const uint8_t sr_mask[8] = {
1.1.1.10 root 41: 0x03,
42: 0x3d,
43: 0x0f,
44: 0x3f,
45: 0x0e,
46: 0x00,
47: 0x00,
48: 0xff,
1.1 root 49: };
50:
51: const uint8_t gr_mask[16] = {
1.1.1.10 root 52: 0x0f, /* 0x00 */
53: 0x0f, /* 0x01 */
54: 0x0f, /* 0x02 */
55: 0x1f, /* 0x03 */
56: 0x03, /* 0x04 */
57: 0x7b, /* 0x05 */
58: 0x0f, /* 0x06 */
59: 0x0f, /* 0x07 */
60: 0xff, /* 0x08 */
61: 0x00, /* 0x09 */
62: 0x00, /* 0x0a */
63: 0x00, /* 0x0b */
64: 0x00, /* 0x0c */
65: 0x00, /* 0x0d */
66: 0x00, /* 0x0e */
67: 0x00, /* 0x0f */
1.1 root 68: };
69:
70: #define cbswap_32(__x) \
71: ((uint32_t)( \
72: (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73: (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
74: (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
75: (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
76:
1.1.1.12 root 77: #ifdef HOST_WORDS_BIGENDIAN
1.1 root 78: #define PAT(x) cbswap_32(x)
79: #else
80: #define PAT(x) (x)
81: #endif
82:
1.1.1.12 root 83: #ifdef HOST_WORDS_BIGENDIAN
1.1 root 84: #define BIG 1
85: #else
86: #define BIG 0
87: #endif
88:
1.1.1.12 root 89: #ifdef HOST_WORDS_BIGENDIAN
1.1 root 90: #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
91: #else
92: #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93: #endif
94:
95: static const uint32_t mask16[16] = {
96: PAT(0x00000000),
97: PAT(0x000000ff),
98: PAT(0x0000ff00),
99: PAT(0x0000ffff),
100: PAT(0x00ff0000),
101: PAT(0x00ff00ff),
102: PAT(0x00ffff00),
103: PAT(0x00ffffff),
104: PAT(0xff000000),
105: PAT(0xff0000ff),
106: PAT(0xff00ff00),
107: PAT(0xff00ffff),
108: PAT(0xffff0000),
109: PAT(0xffff00ff),
110: PAT(0xffffff00),
111: PAT(0xffffffff),
112: };
113:
114: #undef PAT
115:
1.1.1.12 root 116: #ifdef HOST_WORDS_BIGENDIAN
1.1 root 117: #define PAT(x) (x)
118: #else
119: #define PAT(x) cbswap_32(x)
120: #endif
121:
122: static const uint32_t dmask16[16] = {
123: PAT(0x00000000),
124: PAT(0x000000ff),
125: PAT(0x0000ff00),
126: PAT(0x0000ffff),
127: PAT(0x00ff0000),
128: PAT(0x00ff00ff),
129: PAT(0x00ffff00),
130: PAT(0x00ffffff),
131: PAT(0xff000000),
132: PAT(0xff0000ff),
133: PAT(0xff00ff00),
134: PAT(0xff00ffff),
135: PAT(0xffff0000),
136: PAT(0xffff00ff),
137: PAT(0xffffff00),
138: PAT(0xffffffff),
139: };
140:
141: static const uint32_t dmask4[4] = {
142: PAT(0x00000000),
143: PAT(0x0000ffff),
144: PAT(0xffff0000),
145: PAT(0xffffffff),
146: };
147:
148: static uint32_t expand4[256];
149: static uint16_t expand2[256];
150: static uint8_t expand4to8[16];
151:
1.1.1.2 root 152: static void vga_screen_dump(void *opaque, const char *filename);
1.1.1.10 root 153: static char *screen_dump_filename;
154: static DisplayChangeListener *screen_dump_dcl;
1.1.1.2 root 155:
1.1.1.12 root 156: static void vga_dumb_update_retrace_info(VGACommonState *s)
1.1.1.6 root 157: {
158: (void) s;
159: }
160:
1.1.1.12 root 161: static void vga_precise_update_retrace_info(VGACommonState *s)
1.1.1.6 root 162: {
163: int htotal_chars;
164: int hretr_start_char;
165: int hretr_skew_chars;
166: int hretr_end_char;
167:
168: int vtotal_lines;
169: int vretr_start_line;
170: int vretr_end_line;
171:
1.1.1.13! root 172: int dots;
! 173: #if 0
! 174: int div2, sldiv2;
! 175: #endif
1.1.1.6 root 176: int clocking_mode;
177: int clock_sel;
178: const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
179: int64_t chars_per_sec;
180: struct vga_precise_retrace *r = &s->retrace_info.precise;
181:
182: htotal_chars = s->cr[0x00] + 5;
183: hretr_start_char = s->cr[0x04];
184: hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
185: hretr_end_char = s->cr[0x05] & 0x1f;
186:
187: vtotal_lines = (s->cr[0x06]
188: | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
189: ;
190: vretr_start_line = s->cr[0x10]
191: | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
192: ;
193: vretr_end_line = s->cr[0x11] & 0xf;
194:
195:
196:
197: clocking_mode = (s->sr[0x01] >> 3) & 1;
198: clock_sel = (s->msr >> 2) & 3;
199: dots = (s->msr & 1) ? 8 : 9;
200:
201: chars_per_sec = clk_hz[clock_sel] / dots;
202:
203: htotal_chars <<= clocking_mode;
204:
205: r->total_chars = vtotal_lines * htotal_chars;
206: if (r->freq) {
1.1.1.12 root 207: r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
1.1.1.6 root 208: } else {
1.1.1.12 root 209: r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
1.1.1.6 root 210: }
211:
212: r->vstart = vretr_start_line;
213: r->vend = r->vstart + vretr_end_line + 1;
214:
215: r->hstart = hretr_start_char + hretr_skew_chars;
216: r->hend = r->hstart + hretr_end_char + 1;
217: r->htotal = htotal_chars;
218:
219: #if 0
1.1.1.13! root 220: div2 = (s->cr[0x17] >> 2) & 1;
! 221: sldiv2 = (s->cr[0x17] >> 3) & 1;
1.1.1.6 root 222: printf (
223: "hz=%f\n"
224: "htotal = %d\n"
225: "hretr_start = %d\n"
226: "hretr_skew = %d\n"
227: "hretr_end = %d\n"
228: "vtotal = %d\n"
229: "vretr_start = %d\n"
230: "vretr_end = %d\n"
231: "div2 = %d sldiv2 = %d\n"
232: "clocking_mode = %d\n"
233: "clock_sel = %d %d\n"
234: "dots = %d\n"
1.1.1.13! root 235: "ticks/char = %" PRId64 "\n"
1.1.1.6 root 236: "\n",
1.1.1.12 root 237: (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
1.1.1.6 root 238: htotal_chars,
239: hretr_start_char,
240: hretr_skew_chars,
241: hretr_end_char,
242: vtotal_lines,
243: vretr_start_line,
244: vretr_end_line,
245: div2, sldiv2,
246: clocking_mode,
247: clock_sel,
248: clk_hz[clock_sel],
249: dots,
250: r->ticks_per_char
251: );
252: #endif
253: }
254:
1.1.1.12 root 255: static uint8_t vga_precise_retrace(VGACommonState *s)
1.1.1.6 root 256: {
257: struct vga_precise_retrace *r = &s->retrace_info.precise;
258: uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
259:
260: if (r->total_chars) {
261: int cur_line, cur_line_char, cur_char;
262: int64_t cur_tick;
263:
264: cur_tick = qemu_get_clock(vm_clock);
265:
266: cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
267: cur_line = cur_char / r->htotal;
268:
269: if (cur_line >= r->vstart && cur_line <= r->vend) {
270: val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
271: } else {
272: cur_line_char = cur_char % r->htotal;
273: if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
274: val |= ST01_DISP_ENABLE;
275: }
276: }
277:
278: return val;
279: } else {
280: return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
281: }
282: }
283:
1.1.1.12 root 284: static uint8_t vga_dumb_retrace(VGACommonState *s)
1.1.1.6 root 285: {
286: return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
287: }
288:
1.1.1.12 root 289: int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
1.1 root 290: {
1.1.1.12 root 291: if (s->msr & MSR_COLOR_EMULATION) {
292: /* Color */
293: return (addr >= 0x3b0 && addr <= 0x3bf);
294: } else {
295: /* Monochrome */
296: return (addr >= 0x3d0 && addr <= 0x3df);
297: }
298: }
299:
300: uint32_t vga_ioport_read(void *opaque, uint32_t addr)
301: {
302: VGACommonState *s = opaque;
1.1 root 303: int val, index;
304:
1.1.1.12 root 305: if (vga_ioport_invalid(s, addr)) {
1.1 root 306: val = 0xff;
307: } else {
308: switch(addr) {
309: case 0x3c0:
310: if (s->ar_flip_flop == 0) {
311: val = s->ar_index;
312: } else {
313: val = 0;
314: }
315: break;
316: case 0x3c1:
317: index = s->ar_index & 0x1f;
1.1.1.5 root 318: if (index < 21)
1.1 root 319: val = s->ar[index];
320: else
321: val = 0;
322: break;
323: case 0x3c2:
324: val = s->st00;
325: break;
326: case 0x3c4:
327: val = s->sr_index;
328: break;
329: case 0x3c5:
330: val = s->sr[s->sr_index];
331: #ifdef DEBUG_VGA_REG
332: printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
333: #endif
334: break;
335: case 0x3c7:
336: val = s->dac_state;
337: break;
1.1.1.12 root 338: case 0x3c8:
339: val = s->dac_write_index;
340: break;
1.1 root 341: case 0x3c9:
342: val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
343: if (++s->dac_sub_index == 3) {
344: s->dac_sub_index = 0;
345: s->dac_read_index++;
346: }
347: break;
348: case 0x3ca:
349: val = s->fcr;
350: break;
351: case 0x3cc:
352: val = s->msr;
353: break;
354: case 0x3ce:
355: val = s->gr_index;
356: break;
357: case 0x3cf:
358: val = s->gr[s->gr_index];
359: #ifdef DEBUG_VGA_REG
360: printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
361: #endif
362: break;
363: case 0x3b4:
364: case 0x3d4:
365: val = s->cr_index;
366: break;
367: case 0x3b5:
368: case 0x3d5:
369: val = s->cr[s->cr_index];
370: #ifdef DEBUG_VGA_REG
371: printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
372: #endif
373: break;
374: case 0x3ba:
375: case 0x3da:
376: /* just toggle to fool polling */
1.1.1.6 root 377: val = s->st01 = s->retrace(s);
1.1 root 378: s->ar_flip_flop = 0;
379: break;
380: default:
381: val = 0x00;
382: break;
383: }
384: }
385: #if defined(DEBUG_VGA)
386: printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
387: #endif
388: return val;
389: }
390:
1.1.1.12 root 391: void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
1.1 root 392: {
1.1.1.12 root 393: VGACommonState *s = opaque;
1.1 root 394: int index;
395:
396: /* check port range access depending on color/monochrome mode */
1.1.1.12 root 397: if (vga_ioport_invalid(s, addr)) {
1.1 root 398: return;
1.1.1.12 root 399: }
1.1 root 400: #ifdef DEBUG_VGA
401: printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
402: #endif
403:
404: switch(addr) {
405: case 0x3c0:
406: if (s->ar_flip_flop == 0) {
407: val &= 0x3f;
408: s->ar_index = val;
409: } else {
410: index = s->ar_index & 0x1f;
411: switch(index) {
412: case 0x00 ... 0x0f:
413: s->ar[index] = val & 0x3f;
414: break;
415: case 0x10:
416: s->ar[index] = val & ~0x10;
417: break;
418: case 0x11:
419: s->ar[index] = val;
420: break;
421: case 0x12:
422: s->ar[index] = val & ~0xc0;
423: break;
424: case 0x13:
425: s->ar[index] = val & ~0xf0;
426: break;
427: case 0x14:
428: s->ar[index] = val & ~0xf0;
429: break;
430: default:
431: break;
432: }
433: }
434: s->ar_flip_flop ^= 1;
435: break;
436: case 0x3c2:
437: s->msr = val & ~0x10;
1.1.1.6 root 438: s->update_retrace_info(s);
1.1 root 439: break;
440: case 0x3c4:
441: s->sr_index = val & 7;
442: break;
443: case 0x3c5:
444: #ifdef DEBUG_VGA_REG
445: printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
446: #endif
447: s->sr[s->sr_index] = val & sr_mask[s->sr_index];
1.1.1.6 root 448: if (s->sr_index == 1) s->update_retrace_info(s);
1.1 root 449: break;
450: case 0x3c7:
451: s->dac_read_index = val;
452: s->dac_sub_index = 0;
453: s->dac_state = 3;
454: break;
455: case 0x3c8:
456: s->dac_write_index = val;
457: s->dac_sub_index = 0;
458: s->dac_state = 0;
459: break;
460: case 0x3c9:
461: s->dac_cache[s->dac_sub_index] = val;
462: if (++s->dac_sub_index == 3) {
463: memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
464: s->dac_sub_index = 0;
465: s->dac_write_index++;
466: }
467: break;
468: case 0x3ce:
469: s->gr_index = val & 0x0f;
470: break;
471: case 0x3cf:
472: #ifdef DEBUG_VGA_REG
473: printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
474: #endif
475: s->gr[s->gr_index] = val & gr_mask[s->gr_index];
476: break;
477: case 0x3b4:
478: case 0x3d4:
479: s->cr_index = val;
480: break;
481: case 0x3b5:
482: case 0x3d5:
483: #ifdef DEBUG_VGA_REG
484: printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
485: #endif
486: /* handle CR0-7 protection */
487: if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
488: /* can always write bit 4 of CR7 */
489: if (s->cr_index == 7)
490: s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
491: return;
492: }
1.1.1.12 root 493: s->cr[s->cr_index] = val;
1.1.1.6 root 494:
495: switch(s->cr_index) {
496: case 0x00:
497: case 0x04:
498: case 0x05:
499: case 0x06:
500: case 0x07:
501: case 0x11:
502: case 0x17:
503: s->update_retrace_info(s);
504: break;
505: }
1.1 root 506: break;
507: case 0x3ba:
508: case 0x3da:
509: s->fcr = val & 0x10;
510: break;
511: }
512: }
513:
514: #ifdef CONFIG_BOCHS_VBE
515: static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
516: {
1.1.1.12 root 517: VGACommonState *s = opaque;
1.1 root 518: uint32_t val;
519: val = s->vbe_index;
520: return val;
521: }
522:
523: static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
524: {
1.1.1.12 root 525: VGACommonState *s = opaque;
1.1 root 526: uint32_t val;
527:
1.1.1.13! root 528: if (s->vbe_index < VBE_DISPI_INDEX_NB) {
1.1.1.3 root 529: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
530: switch(s->vbe_index) {
531: /* XXX: do not hardcode ? */
532: case VBE_DISPI_INDEX_XRES:
533: val = VBE_DISPI_MAX_XRES;
534: break;
535: case VBE_DISPI_INDEX_YRES:
536: val = VBE_DISPI_MAX_YRES;
537: break;
538: case VBE_DISPI_INDEX_BPP:
539: val = VBE_DISPI_MAX_BPP;
540: break;
541: default:
1.1.1.5 root 542: val = s->vbe_regs[s->vbe_index];
1.1.1.3 root 543: break;
544: }
545: } else {
1.1.1.5 root 546: val = s->vbe_regs[s->vbe_index];
1.1.1.3 root 547: }
1.1.1.13! root 548: } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
! 549: val = s->vram_size / (64 * 1024);
1.1.1.3 root 550: } else {
1.1 root 551: val = 0;
1.1.1.3 root 552: }
1.1 root 553: #ifdef DEBUG_BOCHS_VBE
554: printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
555: #endif
556: return val;
557: }
558:
559: static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
560: {
1.1.1.12 root 561: VGACommonState *s = opaque;
1.1 root 562: s->vbe_index = val;
563: }
564:
565: static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
566: {
1.1.1.12 root 567: VGACommonState *s = opaque;
1.1 root 568:
569: if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
570: #ifdef DEBUG_BOCHS_VBE
571: printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
572: #endif
573: switch(s->vbe_index) {
574: case VBE_DISPI_INDEX_ID:
575: if (val == VBE_DISPI_ID0 ||
576: val == VBE_DISPI_ID1 ||
1.1.1.4 root 577: val == VBE_DISPI_ID2 ||
578: val == VBE_DISPI_ID3 ||
579: val == VBE_DISPI_ID4) {
1.1 root 580: s->vbe_regs[s->vbe_index] = val;
581: }
582: break;
583: case VBE_DISPI_INDEX_XRES:
584: if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
585: s->vbe_regs[s->vbe_index] = val;
586: }
587: break;
588: case VBE_DISPI_INDEX_YRES:
589: if (val <= VBE_DISPI_MAX_YRES) {
590: s->vbe_regs[s->vbe_index] = val;
591: }
592: break;
593: case VBE_DISPI_INDEX_BPP:
594: if (val == 0)
595: val = 8;
1.1.1.5 root 596: if (val == 4 || val == 8 || val == 15 ||
1.1 root 597: val == 16 || val == 24 || val == 32) {
598: s->vbe_regs[s->vbe_index] = val;
599: }
600: break;
601: case VBE_DISPI_INDEX_BANK:
1.1.1.4 root 602: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
603: val &= (s->vbe_bank_mask >> 2);
604: } else {
605: val &= s->vbe_bank_mask;
606: }
1.1 root 607: s->vbe_regs[s->vbe_index] = val;
608: s->bank_offset = (val << 16);
609: break;
610: case VBE_DISPI_INDEX_ENABLE:
1.1.1.3 root 611: if ((val & VBE_DISPI_ENABLED) &&
612: !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
1.1 root 613: int h, shift_control;
614:
1.1.1.5 root 615: s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
1.1 root 616: s->vbe_regs[VBE_DISPI_INDEX_XRES];
1.1.1.5 root 617: s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
1.1 root 618: s->vbe_regs[VBE_DISPI_INDEX_YRES];
619: s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
620: s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
1.1.1.5 root 621:
1.1 root 622: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
623: s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
624: else
1.1.1.5 root 625: s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
1.1 root 626: ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
627: s->vbe_start_addr = 0;
1.1.1.3 root 628:
1.1 root 629: /* clear the screen (should be done in BIOS) */
630: if (!(val & VBE_DISPI_NOCLEARMEM)) {
1.1.1.5 root 631: memset(s->vram_ptr, 0,
1.1 root 632: s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
633: }
1.1.1.5 root 634:
1.1 root 635: /* we initialize the VGA graphic mode (should be done
636: in BIOS) */
637: s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
638: s->cr[0x17] |= 3; /* no CGA modes */
639: s->cr[0x13] = s->vbe_line_offset >> 3;
640: /* width */
641: s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
1.1.1.3 root 642: /* height (only meaningful if < 1024) */
1.1 root 643: h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
644: s->cr[0x12] = h;
1.1.1.5 root 645: s->cr[0x07] = (s->cr[0x07] & ~0x42) |
1.1 root 646: ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
647: /* line compare to 1023 */
648: s->cr[0x18] = 0xff;
649: s->cr[0x07] |= 0x10;
650: s->cr[0x09] |= 0x40;
1.1.1.5 root 651:
1.1 root 652: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
653: shift_control = 0;
654: s->sr[0x01] &= ~8; /* no double line */
655: } else {
656: shift_control = 2;
657: s->sr[4] |= 0x08; /* set chain 4 mode */
658: s->sr[2] |= 0x0f; /* activate all planes */
659: }
660: s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
661: s->cr[0x09] &= ~0x9f; /* no double scan */
662: } else {
663: /* XXX: the bios should do that */
664: s->bank_offset = 0;
665: }
1.1.1.4 root 666: s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
1.1 root 667: s->vbe_regs[s->vbe_index] = val;
668: break;
669: case VBE_DISPI_INDEX_VIRT_WIDTH:
670: {
671: int w, h, line_offset;
672:
673: if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
674: return;
675: w = val;
676: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
677: line_offset = w >> 1;
678: else
679: line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
680: h = s->vram_size / line_offset;
681: /* XXX: support weird bochs semantics ? */
682: if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
683: return;
684: s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
685: s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
686: s->vbe_line_offset = line_offset;
687: }
688: break;
689: case VBE_DISPI_INDEX_X_OFFSET:
690: case VBE_DISPI_INDEX_Y_OFFSET:
691: {
692: int x;
693: s->vbe_regs[s->vbe_index] = val;
694: s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
695: x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
696: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
697: s->vbe_start_addr += x >> 1;
698: else
699: s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
700: s->vbe_start_addr >>= 2;
701: }
702: break;
703: default:
704: break;
705: }
706: }
707: }
708: #endif
709:
710: /* called for accesses between 0xa0000 and 0xc0000 */
711: uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
712: {
1.1.1.12 root 713: VGACommonState *s = opaque;
1.1 root 714: int memory_map_mode, plane;
715: uint32_t ret;
1.1.1.5 root 716:
1.1 root 717: /* convert to VGA memory offset */
718: memory_map_mode = (s->gr[6] >> 2) & 3;
719: addr &= 0x1ffff;
720: switch(memory_map_mode) {
721: case 0:
722: break;
723: case 1:
724: if (addr >= 0x10000)
725: return 0xff;
726: addr += s->bank_offset;
727: break;
728: case 2:
729: addr -= 0x10000;
730: if (addr >= 0x8000)
731: return 0xff;
732: break;
733: default:
734: case 3:
735: addr -= 0x18000;
736: if (addr >= 0x8000)
737: return 0xff;
738: break;
739: }
1.1.1.5 root 740:
1.1 root 741: if (s->sr[4] & 0x08) {
742: /* chain 4 mode : simplest access */
743: ret = s->vram_ptr[addr];
744: } else if (s->gr[5] & 0x10) {
745: /* odd/even mode (aka text mode mapping) */
746: plane = (s->gr[4] & 2) | (addr & 1);
747: ret = s->vram_ptr[((addr & ~1) << 1) | plane];
748: } else {
749: /* standard VGA latched access */
750: s->latch = ((uint32_t *)s->vram_ptr)[addr];
751:
752: if (!(s->gr[5] & 0x08)) {
753: /* read mode 0 */
754: plane = s->gr[4];
755: ret = GET_PLANE(s->latch, plane);
756: } else {
757: /* read mode 1 */
758: ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
759: ret |= ret >> 16;
760: ret |= ret >> 8;
761: ret = (~ret) & 0xff;
762: }
763: }
764: return ret;
765: }
766:
767: static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
768: {
769: uint32_t v;
770: #ifdef TARGET_WORDS_BIGENDIAN
771: v = vga_mem_readb(opaque, addr) << 8;
772: v |= vga_mem_readb(opaque, addr + 1);
773: #else
774: v = vga_mem_readb(opaque, addr);
775: v |= vga_mem_readb(opaque, addr + 1) << 8;
776: #endif
777: return v;
778: }
779:
780: static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
781: {
782: uint32_t v;
783: #ifdef TARGET_WORDS_BIGENDIAN
784: v = vga_mem_readb(opaque, addr) << 24;
785: v |= vga_mem_readb(opaque, addr + 1) << 16;
786: v |= vga_mem_readb(opaque, addr + 2) << 8;
787: v |= vga_mem_readb(opaque, addr + 3);
788: #else
789: v = vga_mem_readb(opaque, addr);
790: v |= vga_mem_readb(opaque, addr + 1) << 8;
791: v |= vga_mem_readb(opaque, addr + 2) << 16;
792: v |= vga_mem_readb(opaque, addr + 3) << 24;
793: #endif
794: return v;
795: }
796:
797: /* called for accesses between 0xa0000 and 0xc0000 */
798: void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
799: {
1.1.1.12 root 800: VGACommonState *s = opaque;
1.1 root 801: int memory_map_mode, plane, write_mode, b, func_select, mask;
802: uint32_t write_mask, bit_mask, set_mask;
803:
804: #ifdef DEBUG_VGA_MEM
1.1.1.10 root 805: printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
1.1 root 806: #endif
807: /* convert to VGA memory offset */
808: memory_map_mode = (s->gr[6] >> 2) & 3;
809: addr &= 0x1ffff;
810: switch(memory_map_mode) {
811: case 0:
812: break;
813: case 1:
814: if (addr >= 0x10000)
815: return;
816: addr += s->bank_offset;
817: break;
818: case 2:
819: addr -= 0x10000;
820: if (addr >= 0x8000)
821: return;
822: break;
823: default:
824: case 3:
825: addr -= 0x18000;
826: if (addr >= 0x8000)
827: return;
828: break;
829: }
1.1.1.5 root 830:
1.1 root 831: if (s->sr[4] & 0x08) {
832: /* chain 4 mode : simplest access */
833: plane = addr & 3;
834: mask = (1 << plane);
835: if (s->sr[2] & mask) {
836: s->vram_ptr[addr] = val;
837: #ifdef DEBUG_VGA_MEM
1.1.1.10 root 838: printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
1.1 root 839: #endif
840: s->plane_updated |= mask; /* only used to detect font change */
841: cpu_physical_memory_set_dirty(s->vram_offset + addr);
842: }
843: } else if (s->gr[5] & 0x10) {
844: /* odd/even mode (aka text mode mapping) */
845: plane = (s->gr[4] & 2) | (addr & 1);
846: mask = (1 << plane);
847: if (s->sr[2] & mask) {
848: addr = ((addr & ~1) << 1) | plane;
849: s->vram_ptr[addr] = val;
850: #ifdef DEBUG_VGA_MEM
1.1.1.10 root 851: printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
1.1 root 852: #endif
853: s->plane_updated |= mask; /* only used to detect font change */
854: cpu_physical_memory_set_dirty(s->vram_offset + addr);
855: }
856: } else {
857: /* standard VGA latched access */
858: write_mode = s->gr[5] & 3;
859: switch(write_mode) {
860: default:
861: case 0:
862: /* rotate */
863: b = s->gr[3] & 7;
864: val = ((val >> b) | (val << (8 - b))) & 0xff;
865: val |= val << 8;
866: val |= val << 16;
867:
868: /* apply set/reset mask */
869: set_mask = mask16[s->gr[1]];
870: val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
871: bit_mask = s->gr[8];
872: break;
873: case 1:
874: val = s->latch;
875: goto do_write;
876: case 2:
877: val = mask16[val & 0x0f];
878: bit_mask = s->gr[8];
879: break;
880: case 3:
881: /* rotate */
882: b = s->gr[3] & 7;
883: val = (val >> b) | (val << (8 - b));
884:
885: bit_mask = s->gr[8] & val;
886: val = mask16[s->gr[0]];
887: break;
888: }
889:
890: /* apply logical operation */
891: func_select = s->gr[3] >> 3;
892: switch(func_select) {
893: case 0:
894: default:
895: /* nothing to do */
896: break;
897: case 1:
898: /* and */
899: val &= s->latch;
900: break;
901: case 2:
902: /* or */
903: val |= s->latch;
904: break;
905: case 3:
906: /* xor */
907: val ^= s->latch;
908: break;
909: }
910:
911: /* apply bit mask */
912: bit_mask |= bit_mask << 8;
913: bit_mask |= bit_mask << 16;
914: val = (val & bit_mask) | (s->latch & ~bit_mask);
915:
916: do_write:
917: /* mask data according to sr[2] */
918: mask = s->sr[2];
919: s->plane_updated |= mask; /* only used to detect font change */
920: write_mask = mask16[mask];
1.1.1.5 root 921: ((uint32_t *)s->vram_ptr)[addr] =
922: (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
1.1 root 923: (val & write_mask);
924: #ifdef DEBUG_VGA_MEM
1.1.1.10 root 925: printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
926: addr * 4, write_mask, val);
1.1 root 927: #endif
1.1.1.10 root 928: cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
1.1 root 929: }
930: }
931:
932: static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
933: {
934: #ifdef TARGET_WORDS_BIGENDIAN
935: vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
936: vga_mem_writeb(opaque, addr + 1, val & 0xff);
937: #else
938: vga_mem_writeb(opaque, addr, val & 0xff);
939: vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
940: #endif
941: }
942:
943: static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
944: {
945: #ifdef TARGET_WORDS_BIGENDIAN
946: vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
947: vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
948: vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
949: vga_mem_writeb(opaque, addr + 3, val & 0xff);
950: #else
951: vga_mem_writeb(opaque, addr, val & 0xff);
952: vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
953: vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
954: vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
955: #endif
956: }
957:
958: typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
959: const uint8_t *font_ptr, int h,
960: uint32_t fgcol, uint32_t bgcol);
961: typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
1.1.1.5 root 962: const uint8_t *font_ptr, int h,
1.1 root 963: uint32_t fgcol, uint32_t bgcol, int dup9);
1.1.1.12 root 964: typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
1.1 root 965: const uint8_t *s, int width);
966:
967: #define DEPTH 8
968: #include "vga_template.h"
969:
970: #define DEPTH 15
971: #include "vga_template.h"
972:
1.1.1.5 root 973: #define BGR_FORMAT
974: #define DEPTH 15
975: #include "vga_template.h"
976:
977: #define DEPTH 16
978: #include "vga_template.h"
979:
980: #define BGR_FORMAT
1.1 root 981: #define DEPTH 16
982: #include "vga_template.h"
983:
984: #define DEPTH 32
985: #include "vga_template.h"
986:
1.1.1.3 root 987: #define BGR_FORMAT
988: #define DEPTH 32
989: #include "vga_template.h"
990:
1.1 root 991: static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
992: {
993: unsigned int col;
994: col = rgb_to_pixel8(r, g, b);
995: col |= col << 8;
996: col |= col << 16;
997: return col;
998: }
999:
1000: static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1001: {
1002: unsigned int col;
1003: col = rgb_to_pixel15(r, g, b);
1004: col |= col << 16;
1005: return col;
1006: }
1007:
1.1.1.5 root 1008: static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1009: unsigned int b)
1010: {
1011: unsigned int col;
1012: col = rgb_to_pixel15bgr(r, g, b);
1013: col |= col << 16;
1014: return col;
1015: }
1016:
1.1 root 1017: static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1018: {
1019: unsigned int col;
1020: col = rgb_to_pixel16(r, g, b);
1021: col |= col << 16;
1022: return col;
1023: }
1024:
1.1.1.5 root 1025: static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1026: unsigned int b)
1027: {
1028: unsigned int col;
1029: col = rgb_to_pixel16bgr(r, g, b);
1030: col |= col << 16;
1031: return col;
1032: }
1033:
1.1 root 1034: static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1035: {
1036: unsigned int col;
1037: col = rgb_to_pixel32(r, g, b);
1038: return col;
1039: }
1040:
1.1.1.3 root 1041: static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1042: {
1043: unsigned int col;
1044: col = rgb_to_pixel32bgr(r, g, b);
1045: return col;
1046: }
1047:
1.1 root 1048: /* return true if the palette was modified */
1.1.1.12 root 1049: static int update_palette16(VGACommonState *s)
1.1 root 1050: {
1051: int full_update, i;
1052: uint32_t v, col, *palette;
1053:
1054: full_update = 0;
1055: palette = s->last_palette;
1056: for(i = 0; i < 16; i++) {
1057: v = s->ar[i];
1058: if (s->ar[0x10] & 0x80)
1059: v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1060: else
1061: v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1062: v = v * 3;
1.1.1.5 root 1063: col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1064: c6_to_8(s->palette[v + 1]),
1.1 root 1065: c6_to_8(s->palette[v + 2]));
1066: if (col != palette[i]) {
1067: full_update = 1;
1068: palette[i] = col;
1069: }
1070: }
1071: return full_update;
1072: }
1073:
1074: /* return true if the palette was modified */
1.1.1.12 root 1075: static int update_palette256(VGACommonState *s)
1.1 root 1076: {
1077: int full_update, i;
1078: uint32_t v, col, *palette;
1079:
1080: full_update = 0;
1081: palette = s->last_palette;
1082: v = 0;
1083: for(i = 0; i < 256; i++) {
1.1.1.4 root 1084: if (s->dac_8bit) {
1.1.1.5 root 1085: col = s->rgb_to_pixel(s->palette[v],
1086: s->palette[v + 1],
1.1.1.4 root 1087: s->palette[v + 2]);
1088: } else {
1.1.1.5 root 1089: col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1090: c6_to_8(s->palette[v + 1]),
1.1.1.4 root 1091: c6_to_8(s->palette[v + 2]));
1092: }
1.1 root 1093: if (col != palette[i]) {
1094: full_update = 1;
1095: palette[i] = col;
1096: }
1097: v += 3;
1098: }
1099: return full_update;
1100: }
1101:
1.1.1.12 root 1102: static void vga_get_offsets(VGACommonState *s,
1.1.1.5 root 1103: uint32_t *pline_offset,
1.1.1.4 root 1104: uint32_t *pstart_addr,
1105: uint32_t *pline_compare)
1.1 root 1106: {
1.1.1.4 root 1107: uint32_t start_addr, line_offset, line_compare;
1.1 root 1108: #ifdef CONFIG_BOCHS_VBE
1109: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1110: line_offset = s->vbe_line_offset;
1111: start_addr = s->vbe_start_addr;
1.1.1.4 root 1112: line_compare = 65535;
1.1 root 1113: } else
1114: #endif
1.1.1.5 root 1115: {
1.1 root 1116: /* compute line_offset in bytes */
1117: line_offset = s->cr[0x13];
1118: line_offset <<= 3;
1119:
1120: /* starting address */
1121: start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1.1.1.4 root 1122:
1123: /* line compare */
1.1.1.5 root 1124: line_compare = s->cr[0x18] |
1.1.1.4 root 1125: ((s->cr[0x07] & 0x10) << 4) |
1126: ((s->cr[0x09] & 0x40) << 3);
1.1 root 1127: }
1128: *pline_offset = line_offset;
1129: *pstart_addr = start_addr;
1.1.1.4 root 1130: *pline_compare = line_compare;
1.1 root 1131: }
1132:
1133: /* update start_addr and line_offset. Return TRUE if modified */
1.1.1.12 root 1134: static int update_basic_params(VGACommonState *s)
1.1 root 1135: {
1136: int full_update;
1137: uint32_t start_addr, line_offset, line_compare;
1.1.1.5 root 1138:
1.1 root 1139: full_update = 0;
1140:
1.1.1.4 root 1141: s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1.1 root 1142:
1143: if (line_offset != s->line_offset ||
1144: start_addr != s->start_addr ||
1145: line_compare != s->line_compare) {
1146: s->line_offset = line_offset;
1147: s->start_addr = start_addr;
1148: s->line_compare = line_compare;
1149: full_update = 1;
1150: }
1151: return full_update;
1152: }
1153:
1.1.1.5 root 1154: #define NB_DEPTHS 7
1.1.1.3 root 1155:
1156: static inline int get_depth_index(DisplayState *s)
1.1 root 1157: {
1.1.1.6 root 1158: switch(ds_get_bits_per_pixel(s)) {
1.1 root 1159: default:
1160: case 8:
1161: return 0;
1162: case 15:
1.1.1.6 root 1163: return 1;
1.1 root 1164: case 16:
1.1.1.6 root 1165: return 2;
1.1 root 1166: case 32:
1.1.1.10 root 1167: if (is_surface_bgr(s->surface))
1168: return 4;
1169: else
1170: return 3;
1.1 root 1171: }
1172: }
1173:
1.1.1.13! root 1174: static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1.1 root 1175: vga_draw_glyph8_8,
1176: vga_draw_glyph8_16,
1177: vga_draw_glyph8_16,
1178: vga_draw_glyph8_32,
1.1.1.3 root 1179: vga_draw_glyph8_32,
1.1.1.5 root 1180: vga_draw_glyph8_16,
1181: vga_draw_glyph8_16,
1.1 root 1182: };
1183:
1.1.1.13! root 1184: static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1.1 root 1185: vga_draw_glyph16_8,
1186: vga_draw_glyph16_16,
1187: vga_draw_glyph16_16,
1188: vga_draw_glyph16_32,
1.1.1.3 root 1189: vga_draw_glyph16_32,
1.1.1.5 root 1190: vga_draw_glyph16_16,
1191: vga_draw_glyph16_16,
1.1 root 1192: };
1193:
1.1.1.13! root 1194: static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1.1 root 1195: vga_draw_glyph9_8,
1196: vga_draw_glyph9_16,
1197: vga_draw_glyph9_16,
1198: vga_draw_glyph9_32,
1.1.1.3 root 1199: vga_draw_glyph9_32,
1.1.1.5 root 1200: vga_draw_glyph9_16,
1201: vga_draw_glyph9_16,
1.1 root 1202: };
1.1.1.5 root 1203:
1.1 root 1204: static const uint8_t cursor_glyph[32 * 4] = {
1205: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1.1.1.5 root 1221: };
1.1 root 1222:
1.1.1.12 root 1223: static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1.1.1.6 root 1224: int *pcwidth, int *pcheight)
1225: {
1226: int width, cwidth, height, cheight;
1227:
1228: /* total width & height */
1229: cheight = (s->cr[9] & 0x1f) + 1;
1230: cwidth = 8;
1231: if (!(s->sr[1] & 0x01))
1232: cwidth = 9;
1233: if (s->sr[1] & 0x08)
1234: cwidth = 16; /* NOTE: no 18 pixel wide */
1235: width = (s->cr[0x01] + 1);
1236: if (s->cr[0x06] == 100) {
1237: /* ugly hack for CGA 160x100x16 - explain me the logic */
1238: height = 100;
1239: } else {
1240: height = s->cr[0x12] |
1241: ((s->cr[0x07] & 0x02) << 7) |
1242: ((s->cr[0x07] & 0x40) << 3);
1243: height = (height + 1) / cheight;
1244: }
1245:
1246: *pwidth = width;
1247: *pheight = height;
1248: *pcwidth = cwidth;
1249: *pcheight = cheight;
1250: }
1251:
1252: typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1253:
1.1.1.13! root 1254: static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1.1.1.6 root 1255: rgb_to_pixel8_dup,
1256: rgb_to_pixel15_dup,
1257: rgb_to_pixel16_dup,
1258: rgb_to_pixel32_dup,
1259: rgb_to_pixel32bgr_dup,
1260: rgb_to_pixel15bgr_dup,
1261: rgb_to_pixel16bgr_dup,
1262: };
1263:
1.1.1.5 root 1264: /*
1265: * Text mode update
1.1 root 1266: * Missing:
1267: * - double scan
1.1.1.5 root 1268: * - double width
1.1 root 1269: * - underline
1270: * - flashing
1271: */
1.1.1.12 root 1272: static void vga_draw_text(VGACommonState *s, int full_update)
1.1 root 1273: {
1274: int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1.1.1.12 root 1275: int cx_min, cx_max, linesize, x_incr, line, line1;
1.1 root 1276: uint32_t offset, fgcol, bgcol, v, cursor_offset;
1.1.1.12 root 1277: uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1.1 root 1278: const uint8_t *font_ptr, *font_base[2];
1279: int dup9, line_offset, depth_index;
1280: uint32_t *palette;
1281: uint32_t *ch_attr_ptr;
1282: vga_draw_glyph8_func *vga_draw_glyph8;
1283: vga_draw_glyph9_func *vga_draw_glyph9;
1284:
1285: /* compute font data address (in plane 2) */
1286: v = s->sr[3];
1287: offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1288: if (offset != s->font_offsets[0]) {
1289: s->font_offsets[0] = offset;
1290: full_update = 1;
1291: }
1292: font_base[0] = s->vram_ptr + offset;
1293:
1294: offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1295: font_base[1] = s->vram_ptr + offset;
1296: if (offset != s->font_offsets[1]) {
1297: s->font_offsets[1] = offset;
1298: full_update = 1;
1299: }
1300: if (s->plane_updated & (1 << 2)) {
1301: /* if the plane 2 was modified since the last display, it
1302: indicates the font may have been modified */
1303: s->plane_updated = 0;
1304: full_update = 1;
1305: }
1306: full_update |= update_basic_params(s);
1307:
1308: line_offset = s->line_offset;
1309:
1.1.1.6 root 1310: vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1.1 root 1311: if ((height * width) > CH_ATTR_SIZE) {
1312: /* better than nothing: exit if transient size is too big */
1313: return;
1314: }
1315:
1316: if (width != s->last_width || height != s->last_height ||
1.1.1.6 root 1317: cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1.1 root 1318: s->last_scr_width = width * cw;
1319: s->last_scr_height = height * cheight;
1.1.1.6 root 1320: qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1321: s->last_depth = 0;
1.1 root 1322: s->last_width = width;
1323: s->last_height = height;
1324: s->last_ch = cheight;
1325: s->last_cw = cw;
1326: full_update = 1;
1327: }
1.1.1.6 root 1328: s->rgb_to_pixel =
1329: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1330: full_update |= update_palette16(s);
1331: palette = s->last_palette;
1332: x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1333:
1.1 root 1334: cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1335: if (cursor_offset != s->cursor_offset ||
1336: s->cr[0xa] != s->cursor_start ||
1337: s->cr[0xb] != s->cursor_end) {
1338: /* if the cursor position changed, we update the old and new
1339: chars */
1340: if (s->cursor_offset < CH_ATTR_SIZE)
1341: s->last_ch_attr[s->cursor_offset] = -1;
1342: if (cursor_offset < CH_ATTR_SIZE)
1343: s->last_ch_attr[cursor_offset] = -1;
1344: s->cursor_offset = cursor_offset;
1345: s->cursor_start = s->cr[0xa];
1346: s->cursor_end = s->cr[0xb];
1347: }
1348: cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1.1.1.5 root 1349:
1.1.1.3 root 1350: depth_index = get_depth_index(s->ds);
1.1 root 1351: if (cw == 16)
1352: vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1353: else
1354: vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1355: vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1.1.1.5 root 1356:
1.1.1.6 root 1357: dest = ds_get_data(s->ds);
1358: linesize = ds_get_linesize(s->ds);
1.1 root 1359: ch_attr_ptr = s->last_ch_attr;
1.1.1.12 root 1360: line = 0;
1361: offset = s->start_addr * 4;
1.1 root 1362: for(cy = 0; cy < height; cy++) {
1363: d1 = dest;
1.1.1.12 root 1364: src = s->vram_ptr + offset;
1.1 root 1365: cx_min = width;
1366: cx_max = -1;
1367: for(cx = 0; cx < width; cx++) {
1368: ch_attr = *(uint16_t *)src;
1369: if (full_update || ch_attr != *ch_attr_ptr) {
1370: if (cx < cx_min)
1371: cx_min = cx;
1372: if (cx > cx_max)
1373: cx_max = cx;
1374: *ch_attr_ptr = ch_attr;
1.1.1.12 root 1375: #ifdef HOST_WORDS_BIGENDIAN
1.1 root 1376: ch = ch_attr >> 8;
1377: cattr = ch_attr & 0xff;
1378: #else
1379: ch = ch_attr & 0xff;
1380: cattr = ch_attr >> 8;
1381: #endif
1382: font_ptr = font_base[(cattr >> 3) & 1];
1383: font_ptr += 32 * 4 * ch;
1384: bgcol = palette[cattr >> 4];
1385: fgcol = palette[cattr & 0x0f];
1386: if (cw != 9) {
1.1.1.5 root 1387: vga_draw_glyph8(d1, linesize,
1.1 root 1388: font_ptr, cheight, fgcol, bgcol);
1389: } else {
1390: dup9 = 0;
1391: if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1392: dup9 = 1;
1.1.1.5 root 1393: vga_draw_glyph9(d1, linesize,
1.1 root 1394: font_ptr, cheight, fgcol, bgcol, dup9);
1395: }
1396: if (src == cursor_ptr &&
1397: !(s->cr[0x0a] & 0x20)) {
1398: int line_start, line_last, h;
1399: /* draw the cursor */
1400: line_start = s->cr[0x0a] & 0x1f;
1401: line_last = s->cr[0x0b] & 0x1f;
1402: /* XXX: check that */
1403: if (line_last > cheight - 1)
1404: line_last = cheight - 1;
1405: if (line_last >= line_start && line_start < cheight) {
1406: h = line_last - line_start + 1;
1407: d = d1 + linesize * line_start;
1408: if (cw != 9) {
1.1.1.5 root 1409: vga_draw_glyph8(d, linesize,
1.1 root 1410: cursor_glyph, h, fgcol, bgcol);
1411: } else {
1.1.1.5 root 1412: vga_draw_glyph9(d, linesize,
1.1 root 1413: cursor_glyph, h, fgcol, bgcol, 1);
1414: }
1415: }
1416: }
1417: }
1418: d1 += x_incr;
1419: src += 4;
1420: ch_attr_ptr++;
1421: }
1422: if (cx_max != -1) {
1.1.1.5 root 1423: dpy_update(s->ds, cx_min * cw, cy * cheight,
1.1 root 1424: (cx_max - cx_min + 1) * cw, cheight);
1425: }
1426: dest += linesize * cheight;
1.1.1.12 root 1427: line1 = line + cheight;
1428: offset += line_offset;
1429: if (line < s->line_compare && line1 >= s->line_compare) {
1430: offset = 0;
1431: }
1432: line = line1;
1.1 root 1433: }
1434: }
1435:
1436: enum {
1437: VGA_DRAW_LINE2,
1438: VGA_DRAW_LINE2D2,
1439: VGA_DRAW_LINE4,
1440: VGA_DRAW_LINE4D2,
1441: VGA_DRAW_LINE8D2,
1442: VGA_DRAW_LINE8,
1443: VGA_DRAW_LINE15,
1444: VGA_DRAW_LINE16,
1445: VGA_DRAW_LINE24,
1446: VGA_DRAW_LINE32,
1447: VGA_DRAW_LINE_NB,
1448: };
1449:
1.1.1.13! root 1450: static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1.1 root 1451: vga_draw_line2_8,
1452: vga_draw_line2_16,
1453: vga_draw_line2_16,
1454: vga_draw_line2_32,
1.1.1.3 root 1455: vga_draw_line2_32,
1.1.1.5 root 1456: vga_draw_line2_16,
1457: vga_draw_line2_16,
1.1 root 1458:
1459: vga_draw_line2d2_8,
1460: vga_draw_line2d2_16,
1461: vga_draw_line2d2_16,
1462: vga_draw_line2d2_32,
1.1.1.3 root 1463: vga_draw_line2d2_32,
1.1.1.5 root 1464: vga_draw_line2d2_16,
1465: vga_draw_line2d2_16,
1.1 root 1466:
1467: vga_draw_line4_8,
1468: vga_draw_line4_16,
1469: vga_draw_line4_16,
1470: vga_draw_line4_32,
1.1.1.3 root 1471: vga_draw_line4_32,
1.1.1.5 root 1472: vga_draw_line4_16,
1473: vga_draw_line4_16,
1.1 root 1474:
1475: vga_draw_line4d2_8,
1476: vga_draw_line4d2_16,
1477: vga_draw_line4d2_16,
1478: vga_draw_line4d2_32,
1.1.1.3 root 1479: vga_draw_line4d2_32,
1.1.1.5 root 1480: vga_draw_line4d2_16,
1481: vga_draw_line4d2_16,
1.1 root 1482:
1483: vga_draw_line8d2_8,
1484: vga_draw_line8d2_16,
1485: vga_draw_line8d2_16,
1486: vga_draw_line8d2_32,
1.1.1.3 root 1487: vga_draw_line8d2_32,
1.1.1.5 root 1488: vga_draw_line8d2_16,
1489: vga_draw_line8d2_16,
1.1 root 1490:
1491: vga_draw_line8_8,
1492: vga_draw_line8_16,
1493: vga_draw_line8_16,
1494: vga_draw_line8_32,
1.1.1.3 root 1495: vga_draw_line8_32,
1.1.1.5 root 1496: vga_draw_line8_16,
1497: vga_draw_line8_16,
1.1 root 1498:
1499: vga_draw_line15_8,
1500: vga_draw_line15_15,
1501: vga_draw_line15_16,
1502: vga_draw_line15_32,
1.1.1.3 root 1503: vga_draw_line15_32bgr,
1.1.1.5 root 1504: vga_draw_line15_15bgr,
1505: vga_draw_line15_16bgr,
1.1 root 1506:
1507: vga_draw_line16_8,
1508: vga_draw_line16_15,
1509: vga_draw_line16_16,
1510: vga_draw_line16_32,
1.1.1.3 root 1511: vga_draw_line16_32bgr,
1.1.1.5 root 1512: vga_draw_line16_15bgr,
1513: vga_draw_line16_16bgr,
1.1 root 1514:
1515: vga_draw_line24_8,
1516: vga_draw_line24_15,
1517: vga_draw_line24_16,
1518: vga_draw_line24_32,
1.1.1.3 root 1519: vga_draw_line24_32bgr,
1.1.1.5 root 1520: vga_draw_line24_15bgr,
1521: vga_draw_line24_16bgr,
1.1 root 1522:
1523: vga_draw_line32_8,
1524: vga_draw_line32_15,
1525: vga_draw_line32_16,
1526: vga_draw_line32_32,
1.1.1.3 root 1527: vga_draw_line32_32bgr,
1.1.1.5 root 1528: vga_draw_line32_15bgr,
1529: vga_draw_line32_16bgr,
1.1.1.3 root 1530: };
1531:
1.1.1.12 root 1532: static int vga_get_bpp(VGACommonState *s)
1.1 root 1533: {
1534: int ret;
1535: #ifdef CONFIG_BOCHS_VBE
1536: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1537: ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1.1.1.5 root 1538: } else
1.1 root 1539: #endif
1540: {
1541: ret = 0;
1542: }
1543: return ret;
1544: }
1545:
1.1.1.12 root 1546: static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1.1 root 1547: {
1548: int width, height;
1.1.1.5 root 1549:
1.1.1.3 root 1550: #ifdef CONFIG_BOCHS_VBE
1551: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1552: width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1553: height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1.1.1.5 root 1554: } else
1.1.1.3 root 1555: #endif
1556: {
1557: width = (s->cr[0x01] + 1) * 8;
1.1.1.5 root 1558: height = s->cr[0x12] |
1559: ((s->cr[0x07] & 0x02) << 7) |
1.1.1.3 root 1560: ((s->cr[0x07] & 0x40) << 3);
1561: height = (height + 1);
1562: }
1.1 root 1563: *pwidth = width;
1564: *pheight = height;
1565: }
1566:
1.1.1.12 root 1567: void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1.1 root 1568: {
1569: int y;
1570: if (y1 >= VGA_MAX_HEIGHT)
1571: return;
1572: if (y2 >= VGA_MAX_HEIGHT)
1573: y2 = VGA_MAX_HEIGHT;
1574: for(y = y1; y < y2; y++) {
1575: s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1576: }
1577: }
1578:
1.1.1.12 root 1579: static void vga_sync_dirty_bitmap(VGACommonState *s)
1.1.1.6 root 1580: {
1581: if (s->map_addr)
1582: cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1583:
1584: if (s->lfb_vram_mapped) {
1585: cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1586: cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1587: }
1.1.1.12 root 1588:
1589: #ifdef CONFIG_BOCHS_VBE
1590: if (s->vbe_mapped) {
1591: cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1592: VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1593: }
1594: #endif
1595:
1596: }
1597:
1598: void vga_dirty_log_start(VGACommonState *s)
1599: {
1600: if (kvm_enabled() && s->map_addr)
1601: kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1602:
1603: if (kvm_enabled() && s->lfb_vram_mapped) {
1604: kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1605: kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1606: }
1607:
1608: #ifdef CONFIG_BOCHS_VBE
1609: if (kvm_enabled() && s->vbe_mapped) {
1610: kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1611: }
1612: #endif
1613: }
1614:
1615: void vga_dirty_log_stop(VGACommonState *s)
1616: {
1617: if (kvm_enabled() && s->map_addr)
1618: kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
1619:
1620: if (kvm_enabled() && s->lfb_vram_mapped) {
1.1.1.13! root 1621: kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
! 1622: kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
1.1.1.12 root 1623: }
1624:
1625: #ifdef CONFIG_BOCHS_VBE
1626: if (kvm_enabled() && s->vbe_mapped) {
1627: kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1628: }
1629: #endif
1630: }
1631:
1632: void vga_dirty_log_restart(VGACommonState *s)
1633: {
1634: vga_dirty_log_stop(s);
1635: vga_dirty_log_start(s);
1.1.1.6 root 1636: }
1637:
1.1.1.5 root 1638: /*
1.1 root 1639: * graphic modes
1640: */
1.1.1.12 root 1641: static void vga_draw_graphic(VGACommonState *s, int full_update)
1.1 root 1642: {
1.1.1.10 root 1643: int y1, y, update, linesize, y_start, double_scan, mask, depth;
1644: int width, height, shift_control, line_offset, bwidth, bits;
1645: ram_addr_t page0, page1, page_min, page_max;
1.1 root 1646: int disp_width, multi_scan, multi_run;
1647: uint8_t *d;
1648: uint32_t v, addr1, addr;
1649: vga_draw_line_func *vga_draw_line;
1.1.1.5 root 1650:
1.1 root 1651: full_update |= update_basic_params(s);
1652:
1.1.1.6 root 1653: if (!full_update)
1654: vga_sync_dirty_bitmap(s);
1655:
1.1 root 1656: s->get_resolution(s, &width, &height);
1657: disp_width = width;
1658:
1659: shift_control = (s->gr[0x05] >> 5) & 3;
1660: double_scan = (s->cr[0x09] >> 7);
1661: if (shift_control != 1) {
1662: multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1663: } else {
1664: /* in CGA modes, multi_scan is ignored */
1665: /* XXX: is it correct ? */
1666: multi_scan = double_scan;
1667: }
1668: multi_run = multi_scan;
1669: if (shift_control != s->shift_control ||
1670: double_scan != s->double_scan) {
1671: full_update = 1;
1672: s->shift_control = shift_control;
1673: s->double_scan = double_scan;
1674: }
1.1.1.5 root 1675:
1.1.1.8 root 1676: if (shift_control == 0) {
1677: if (s->sr[0x01] & 8) {
1678: disp_width <<= 1;
1679: }
1680: } else if (shift_control == 1) {
1681: if (s->sr[0x01] & 8) {
1682: disp_width <<= 1;
1683: }
1684: }
1685:
1.1.1.6 root 1686: depth = s->get_bpp(s);
1687: if (s->line_offset != s->last_line_offset ||
1688: disp_width != s->last_width ||
1689: height != s->last_height ||
1690: s->last_depth != depth) {
1.1.1.12 root 1691: #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1.1.1.6 root 1692: if (depth == 16 || depth == 32) {
1693: #else
1694: if (depth == 32) {
1695: #endif
1.1.1.10 root 1696: qemu_free_displaysurface(s->ds);
1697: s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1698: s->line_offset,
1699: s->vram_ptr + (s->start_addr * 4));
1.1.1.12 root 1700: #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1.1.1.10 root 1701: s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1.1.1.6 root 1702: #endif
1.1.1.10 root 1703: dpy_resize(s->ds);
1.1.1.6 root 1704: } else {
1705: qemu_console_resize(s->ds, disp_width, height);
1706: }
1707: s->last_scr_width = disp_width;
1708: s->last_scr_height = height;
1709: s->last_width = disp_width;
1710: s->last_height = height;
1711: s->last_line_offset = s->line_offset;
1712: s->last_depth = depth;
1713: full_update = 1;
1.1.1.10 root 1714: } else if (is_buffer_shared(s->ds->surface) &&
1.1.1.6 root 1715: (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1716: s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1717: dpy_setdata(s->ds);
1718: }
1719:
1720: s->rgb_to_pixel =
1721: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1722:
1.1 root 1723: if (shift_control == 0) {
1724: full_update |= update_palette16(s);
1725: if (s->sr[0x01] & 8) {
1726: v = VGA_DRAW_LINE4D2;
1727: } else {
1728: v = VGA_DRAW_LINE4;
1729: }
1.1.1.6 root 1730: bits = 4;
1.1 root 1731: } else if (shift_control == 1) {
1732: full_update |= update_palette16(s);
1733: if (s->sr[0x01] & 8) {
1734: v = VGA_DRAW_LINE2D2;
1735: } else {
1736: v = VGA_DRAW_LINE2;
1737: }
1.1.1.6 root 1738: bits = 4;
1.1 root 1739: } else {
1740: switch(s->get_bpp(s)) {
1741: default:
1742: case 0:
1743: full_update |= update_palette256(s);
1744: v = VGA_DRAW_LINE8D2;
1.1.1.6 root 1745: bits = 4;
1.1 root 1746: break;
1747: case 8:
1748: full_update |= update_palette256(s);
1749: v = VGA_DRAW_LINE8;
1.1.1.6 root 1750: bits = 8;
1.1 root 1751: break;
1752: case 15:
1753: v = VGA_DRAW_LINE15;
1.1.1.6 root 1754: bits = 16;
1.1 root 1755: break;
1756: case 16:
1757: v = VGA_DRAW_LINE16;
1.1.1.6 root 1758: bits = 16;
1.1 root 1759: break;
1760: case 24:
1761: v = VGA_DRAW_LINE24;
1.1.1.6 root 1762: bits = 24;
1.1 root 1763: break;
1764: case 32:
1765: v = VGA_DRAW_LINE32;
1.1.1.6 root 1766: bits = 32;
1.1 root 1767: break;
1768: }
1769: }
1.1.1.3 root 1770: vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1.1 root 1771:
1.1.1.6 root 1772: if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1.1 root 1773: s->cursor_invalidate(s);
1.1.1.5 root 1774:
1.1 root 1775: line_offset = s->line_offset;
1776: #if 0
1777: 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",
1778: width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1779: #endif
1780: addr1 = (s->start_addr * 4);
1.1.1.6 root 1781: bwidth = (width * bits + 7) / 8;
1.1 root 1782: y_start = -1;
1.1.1.10 root 1783: page_min = -1;
1784: page_max = 0;
1.1.1.6 root 1785: d = ds_get_data(s->ds);
1786: linesize = ds_get_linesize(s->ds);
1.1 root 1787: y1 = 0;
1788: for(y = 0; y < height; y++) {
1789: addr = addr1;
1790: if (!(s->cr[0x17] & 1)) {
1791: int shift;
1792: /* CGA compatibility handling */
1793: shift = 14 + ((s->cr[0x17] >> 6) & 1);
1794: addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1795: }
1796: if (!(s->cr[0x17] & 2)) {
1797: addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1798: }
1799: page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1800: page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1.1.1.5 root 1801: update = full_update |
1.1 root 1802: cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1803: cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1804: if ((page1 - page0) > TARGET_PAGE_SIZE) {
1805: /* if wide line, can use another page */
1.1.1.5 root 1806: update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1.1 root 1807: VGA_DIRTY_FLAG);
1808: }
1809: /* explicit invalidation for the hardware cursor */
1810: update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1811: if (update) {
1812: if (y_start < 0)
1813: y_start = y;
1814: if (page0 < page_min)
1815: page_min = page0;
1816: if (page1 > page_max)
1817: page_max = page1;
1.1.1.6 root 1818: if (!(is_buffer_shared(s->ds->surface))) {
1819: vga_draw_line(s, d, s->vram_ptr + addr, width);
1820: if (s->cursor_draw_line)
1821: s->cursor_draw_line(s, d, y);
1822: }
1.1 root 1823: } else {
1824: if (y_start >= 0) {
1825: /* flush to display */
1.1.1.5 root 1826: dpy_update(s->ds, 0, y_start,
1.1 root 1827: disp_width, y - y_start);
1828: y_start = -1;
1829: }
1830: }
1831: if (!multi_run) {
1832: mask = (s->cr[0x17] & 3) ^ 3;
1833: if ((y1 & mask) == mask)
1834: addr1 += line_offset;
1835: y1++;
1836: multi_run = multi_scan;
1837: } else {
1838: multi_run--;
1839: }
1840: /* line compare acts on the displayed lines */
1841: if (y == s->line_compare)
1842: addr1 = 0;
1843: d += linesize;
1844: }
1845: if (y_start >= 0) {
1846: /* flush to display */
1.1.1.5 root 1847: dpy_update(s->ds, 0, y_start,
1.1 root 1848: disp_width, y - y_start);
1849: }
1850: /* reset modified pages */
1.1.1.10 root 1851: if (page_max >= page_min) {
1.1 root 1852: cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1853: VGA_DIRTY_FLAG);
1854: }
1855: memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1856: }
1857:
1.1.1.12 root 1858: static void vga_draw_blank(VGACommonState *s, int full_update)
1.1 root 1859: {
1860: int i, w, val;
1861: uint8_t *d;
1862:
1863: if (!full_update)
1864: return;
1865: if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1866: return;
1.1.1.6 root 1867:
1868: s->rgb_to_pixel =
1869: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1870: if (ds_get_bits_per_pixel(s->ds) == 8)
1.1 root 1871: val = s->rgb_to_pixel(0, 0, 0);
1872: else
1873: val = 0;
1.1.1.6 root 1874: w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1875: d = ds_get_data(s->ds);
1.1 root 1876: for(i = 0; i < s->last_scr_height; i++) {
1877: memset(d, val, w);
1.1.1.6 root 1878: d += ds_get_linesize(s->ds);
1.1 root 1879: }
1.1.1.5 root 1880: dpy_update(s->ds, 0, 0,
1.1 root 1881: s->last_scr_width, s->last_scr_height);
1882: }
1883:
1884: #define GMODE_TEXT 0
1885: #define GMODE_GRAPH 1
1.1.1.5 root 1886: #define GMODE_BLANK 2
1.1 root 1887:
1.1.1.2 root 1888: static void vga_update_display(void *opaque)
1.1 root 1889: {
1.1.1.12 root 1890: VGACommonState *s = opaque;
1.1 root 1891: int full_update, graphic_mode;
1892:
1.1.1.6 root 1893: if (ds_get_bits_per_pixel(s->ds) == 0) {
1.1 root 1894: /* nothing to do */
1895: } else {
1.1.1.11 root 1896: full_update = 0;
1.1 root 1897: if (!(s->ar_index & 0x20)) {
1898: graphic_mode = GMODE_BLANK;
1899: } else {
1900: graphic_mode = s->gr[6] & 1;
1901: }
1902: if (graphic_mode != s->graphic_mode) {
1903: s->graphic_mode = graphic_mode;
1904: full_update = 1;
1905: }
1906: switch(graphic_mode) {
1907: case GMODE_TEXT:
1908: vga_draw_text(s, full_update);
1909: break;
1910: case GMODE_GRAPH:
1911: vga_draw_graphic(s, full_update);
1912: break;
1913: case GMODE_BLANK:
1914: default:
1915: vga_draw_blank(s, full_update);
1916: break;
1917: }
1918: }
1919: }
1920:
1921: /* force a full display refresh */
1.1.1.2 root 1922: static void vga_invalidate_display(void *opaque)
1.1 root 1923: {
1.1.1.12 root 1924: VGACommonState *s = opaque;
1.1.1.5 root 1925:
1.1.1.11 root 1926: s->last_width = -1;
1927: s->last_height = -1;
1.1 root 1928: }
1929:
1.1.1.12 root 1930: void vga_common_reset(VGACommonState *s)
1.1 root 1931: {
1.1.1.6 root 1932: s->lfb_addr = 0;
1933: s->lfb_end = 0;
1934: s->map_addr = 0;
1935: s->map_end = 0;
1936: s->lfb_vram_mapped = 0;
1937: s->bios_offset = 0;
1938: s->bios_size = 0;
1939: s->sr_index = 0;
1940: memset(s->sr, '\0', sizeof(s->sr));
1941: s->gr_index = 0;
1942: memset(s->gr, '\0', sizeof(s->gr));
1943: s->ar_index = 0;
1944: memset(s->ar, '\0', sizeof(s->ar));
1945: s->ar_flip_flop = 0;
1946: s->cr_index = 0;
1947: memset(s->cr, '\0', sizeof(s->cr));
1948: s->msr = 0;
1949: s->fcr = 0;
1950: s->st00 = 0;
1951: s->st01 = 0;
1952: s->dac_state = 0;
1953: s->dac_sub_index = 0;
1954: s->dac_read_index = 0;
1955: s->dac_write_index = 0;
1956: memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1957: s->dac_8bit = 0;
1958: memset(s->palette, '\0', sizeof(s->palette));
1959: s->bank_offset = 0;
1960: #ifdef CONFIG_BOCHS_VBE
1961: s->vbe_index = 0;
1962: memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1.1.1.13! root 1963: s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1.1.1.6 root 1964: s->vbe_start_addr = 0;
1965: s->vbe_line_offset = 0;
1966: s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1967: #endif
1968: memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1.1 root 1969: s->graphic_mode = -1; /* force full update */
1.1.1.6 root 1970: s->shift_control = 0;
1971: s->double_scan = 0;
1972: s->line_offset = 0;
1973: s->line_compare = 0;
1974: s->start_addr = 0;
1975: s->plane_updated = 0;
1976: s->last_cw = 0;
1977: s->last_ch = 0;
1978: s->last_width = 0;
1979: s->last_height = 0;
1980: s->last_scr_width = 0;
1981: s->last_scr_height = 0;
1982: s->cursor_start = 0;
1983: s->cursor_end = 0;
1984: s->cursor_offset = 0;
1985: memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1986: memset(s->last_palette, '\0', sizeof(s->last_palette));
1987: memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1988: switch (vga_retrace_method) {
1989: case VGA_RETRACE_DUMB:
1990: break;
1991: case VGA_RETRACE_PRECISE:
1992: memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1993: break;
1994: }
1995: }
1996:
1.1.1.12 root 1997: static void vga_reset(void *opaque)
1998: {
1999: VGACommonState *s = opaque;
2000: vga_common_reset(s);
2001: }
2002:
1.1.1.6 root 2003: #define TEXTMODE_X(x) ((x) % width)
2004: #define TEXTMODE_Y(x) ((x) / width)
2005: #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
2006: ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2007: /* relay text rendering to the display driver
2008: * instead of doing a full vga_update_display() */
2009: static void vga_update_text(void *opaque, console_ch_t *chardata)
2010: {
1.1.1.12 root 2011: VGACommonState *s = opaque;
1.1.1.6 root 2012: int graphic_mode, i, cursor_offset, cursor_visible;
2013: int cw, cheight, width, height, size, c_min, c_max;
2014: uint32_t *src;
2015: console_ch_t *dst, val;
2016: char msg_buffer[80];
2017: int full_update = 0;
2018:
2019: if (!(s->ar_index & 0x20)) {
2020: graphic_mode = GMODE_BLANK;
2021: } else {
2022: graphic_mode = s->gr[6] & 1;
2023: }
2024: if (graphic_mode != s->graphic_mode) {
2025: s->graphic_mode = graphic_mode;
2026: full_update = 1;
2027: }
2028: if (s->last_width == -1) {
2029: s->last_width = 0;
2030: full_update = 1;
2031: }
2032:
2033: switch (graphic_mode) {
2034: case GMODE_TEXT:
2035: /* TODO: update palette */
2036: full_update |= update_basic_params(s);
2037:
2038: /* total width & height */
2039: cheight = (s->cr[9] & 0x1f) + 1;
2040: cw = 8;
2041: if (!(s->sr[1] & 0x01))
2042: cw = 9;
2043: if (s->sr[1] & 0x08)
2044: cw = 16; /* NOTE: no 18 pixel wide */
2045: width = (s->cr[0x01] + 1);
2046: if (s->cr[0x06] == 100) {
2047: /* ugly hack for CGA 160x100x16 - explain me the logic */
2048: height = 100;
2049: } else {
2050: height = s->cr[0x12] |
2051: ((s->cr[0x07] & 0x02) << 7) |
2052: ((s->cr[0x07] & 0x40) << 3);
2053: height = (height + 1) / cheight;
2054: }
2055:
2056: size = (height * width);
2057: if (size > CH_ATTR_SIZE) {
2058: if (!full_update)
2059: return;
2060:
2061: snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2062: width, height);
2063: break;
2064: }
2065:
2066: if (width != s->last_width || height != s->last_height ||
2067: cw != s->last_cw || cheight != s->last_ch) {
2068: s->last_scr_width = width * cw;
2069: s->last_scr_height = height * cheight;
2070: s->ds->surface->width = width;
2071: s->ds->surface->height = height;
2072: dpy_resize(s->ds);
2073: s->last_width = width;
2074: s->last_height = height;
2075: s->last_ch = cheight;
2076: s->last_cw = cw;
2077: full_update = 1;
2078: }
2079:
2080: /* Update "hardware" cursor */
2081: cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2082: if (cursor_offset != s->cursor_offset ||
2083: s->cr[0xa] != s->cursor_start ||
2084: s->cr[0xb] != s->cursor_end || full_update) {
2085: cursor_visible = !(s->cr[0xa] & 0x20);
2086: if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2087: dpy_cursor(s->ds,
2088: TEXTMODE_X(cursor_offset),
2089: TEXTMODE_Y(cursor_offset));
2090: else
2091: dpy_cursor(s->ds, -1, -1);
2092: s->cursor_offset = cursor_offset;
2093: s->cursor_start = s->cr[0xa];
2094: s->cursor_end = s->cr[0xb];
2095: }
2096:
2097: src = (uint32_t *) s->vram_ptr + s->start_addr;
2098: dst = chardata;
2099:
2100: if (full_update) {
2101: for (i = 0; i < size; src ++, dst ++, i ++)
2102: console_write_ch(dst, VMEM2CHTYPE(*src));
2103:
2104: dpy_update(s->ds, 0, 0, width, height);
2105: } else {
2106: c_max = 0;
2107:
2108: for (i = 0; i < size; src ++, dst ++, i ++) {
2109: console_write_ch(&val, VMEM2CHTYPE(*src));
2110: if (*dst != val) {
2111: *dst = val;
2112: c_max = i;
2113: break;
2114: }
2115: }
2116: c_min = i;
2117: for (; i < size; src ++, dst ++, i ++) {
2118: console_write_ch(&val, VMEM2CHTYPE(*src));
2119: if (*dst != val) {
2120: *dst = val;
2121: c_max = i;
2122: }
2123: }
2124:
2125: if (c_min <= c_max) {
2126: i = TEXTMODE_Y(c_min);
2127: dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2128: }
2129: }
2130:
2131: return;
2132: case GMODE_GRAPH:
2133: if (!full_update)
2134: return;
2135:
2136: s->get_resolution(s, &width, &height);
2137: snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2138: width, height);
2139: break;
2140: case GMODE_BLANK:
2141: default:
2142: if (!full_update)
2143: return;
2144:
2145: snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2146: break;
2147: }
2148:
2149: /* Display a message */
2150: s->last_width = 60;
2151: s->last_height = height = 3;
2152: dpy_cursor(s->ds, -1, -1);
2153: s->ds->surface->width = s->last_width;
2154: s->ds->surface->height = height;
2155: dpy_resize(s->ds);
2156:
2157: for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2158: console_write_ch(dst ++, ' ');
2159:
2160: size = strlen(msg_buffer);
2161: width = (s->last_width - size) / 2;
2162: dst = chardata + s->last_width + width;
2163: for (i = 0; i < size; i ++)
2164: console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2165:
2166: dpy_update(s->ds, 0, 0, s->last_width, height);
1.1 root 2167: }
2168:
1.1.1.12 root 2169: CPUReadMemoryFunc * const vga_mem_read[3] = {
1.1 root 2170: vga_mem_readb,
2171: vga_mem_readw,
2172: vga_mem_readl,
2173: };
2174:
1.1.1.12 root 2175: CPUWriteMemoryFunc * const vga_mem_write[3] = {
1.1 root 2176: vga_mem_writeb,
2177: vga_mem_writew,
2178: vga_mem_writel,
2179: };
2180:
1.1.1.12 root 2181: static int vga_common_post_load(void *opaque, int version_id)
1.1 root 2182: {
1.1.1.12 root 2183: VGACommonState *s = opaque;
1.1 root 2184:
2185: /* force refresh */
2186: s->graphic_mode = -1;
2187: return 0;
2188: }
2189:
1.1.1.12 root 2190: const VMStateDescription vmstate_vga_common = {
2191: .name = "vga",
2192: .version_id = 2,
2193: .minimum_version_id = 2,
2194: .minimum_version_id_old = 2,
2195: .post_load = vga_common_post_load,
2196: .fields = (VMStateField []) {
2197: VMSTATE_UINT32(latch, VGACommonState),
2198: VMSTATE_UINT8(sr_index, VGACommonState),
2199: VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2200: VMSTATE_UINT8(gr_index, VGACommonState),
2201: VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2202: VMSTATE_UINT8(ar_index, VGACommonState),
2203: VMSTATE_BUFFER(ar, VGACommonState),
2204: VMSTATE_INT32(ar_flip_flop, VGACommonState),
2205: VMSTATE_UINT8(cr_index, VGACommonState),
2206: VMSTATE_BUFFER(cr, VGACommonState),
2207: VMSTATE_UINT8(msr, VGACommonState),
2208: VMSTATE_UINT8(fcr, VGACommonState),
2209: VMSTATE_UINT8(st00, VGACommonState),
2210: VMSTATE_UINT8(st01, VGACommonState),
2211:
2212: VMSTATE_UINT8(dac_state, VGACommonState),
2213: VMSTATE_UINT8(dac_sub_index, VGACommonState),
2214: VMSTATE_UINT8(dac_read_index, VGACommonState),
2215: VMSTATE_UINT8(dac_write_index, VGACommonState),
2216: VMSTATE_BUFFER(dac_cache, VGACommonState),
2217: VMSTATE_BUFFER(palette, VGACommonState),
1.1.1.4 root 2218:
1.1.1.12 root 2219: VMSTATE_INT32(bank_offset, VGACommonState),
2220: VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2221: #ifdef CONFIG_BOCHS_VBE
2222: VMSTATE_UINT16(vbe_index, VGACommonState),
2223: VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2224: VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2225: VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2226: VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2227: #endif
2228: VMSTATE_END_OF_LIST()
1.1 root 2229: }
1.1.1.12 root 2230: };
1.1 root 2231:
1.1.1.12 root 2232: void vga_common_init(VGACommonState *s, int vga_ram_size)
1.1 root 2233: {
2234: int i, j, v, b;
2235:
2236: for(i = 0;i < 256; i++) {
2237: v = 0;
2238: for(j = 0; j < 8; j++) {
2239: v |= ((i >> j) & 1) << (j * 4);
2240: }
2241: expand4[i] = v;
2242:
2243: v = 0;
2244: for(j = 0; j < 4; j++) {
2245: v |= ((i >> (2 * j)) & 3) << (j * 4);
2246: }
2247: expand2[i] = v;
2248: }
2249: for(i = 0; i < 16; i++) {
2250: v = 0;
2251: for(j = 0; j < 4; j++) {
2252: b = ((i >> j) & 1);
2253: v |= b << (2 * j);
2254: v |= b << (2 * j + 1);
2255: }
2256: expand4to8[i] = v;
2257: }
2258:
1.1.1.12 root 2259: #ifdef CONFIG_BOCHS_VBE
2260: s->is_vbe_vmstate = 1;
2261: #else
2262: s->is_vbe_vmstate = 0;
2263: #endif
1.1.1.13! root 2264: s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
1.1.1.10 root 2265: s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
1.1 root 2266: s->vram_size = vga_ram_size;
2267: s->get_bpp = vga_get_bpp;
2268: s->get_offsets = vga_get_offsets;
2269: s->get_resolution = vga_get_resolution;
1.1.1.5 root 2270: s->update = vga_update_display;
2271: s->invalidate = vga_invalidate_display;
2272: s->screen_dump = vga_screen_dump;
1.1.1.6 root 2273: s->text_update = vga_update_text;
2274: switch (vga_retrace_method) {
2275: case VGA_RETRACE_DUMB:
2276: s->retrace = vga_dumb_retrace;
2277: s->update_retrace_info = vga_dumb_update_retrace_info;
2278: break;
2279:
2280: case VGA_RETRACE_PRECISE:
2281: s->retrace = vga_precise_retrace;
2282: s->update_retrace_info = vga_precise_update_retrace_info;
2283: break;
2284: }
1.1 root 2285: }
2286:
1.1.1.4 root 2287: /* used by both ISA and PCI */
1.1.1.12 root 2288: void vga_init(VGACommonState *s)
1.1 root 2289: {
1.1.1.4 root 2290: int vga_io_memory;
1.1 root 2291:
1.1.1.6 root 2292: qemu_register_reset(vga_reset, s);
1.1 root 2293:
2294: register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2295:
2296: register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2297: register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2298: register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2299: register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2300:
2301: register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2302:
2303: register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2304: register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2305: register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2306: register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2307: s->bank_offset = 0;
2308:
2309: #ifdef CONFIG_BOCHS_VBE
2310: #if defined (TARGET_I386)
2311: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2312: register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2313:
2314: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2315: register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2316:
2317: /* old Bochs IO ports */
2318: register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2319: register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2320:
2321: register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1.1.1.5 root 2322: register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1.1 root 2323: #else
2324: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2325: register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2326:
2327: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2328: register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2329: #endif
2330: #endif /* CONFIG_BOCHS_VBE */
2331:
1.1.1.10 root 2332: vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
1.1.1.5 root 2333: cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1.1 root 2334: vga_io_memory);
1.1.1.6 root 2335: qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
1.1.1.4 root 2336: }
1.1 root 2337:
1.1.1.12 root 2338: void vga_init_vbe(VGACommonState *s)
1.1.1.4 root 2339: {
1.1 root 2340: #ifdef CONFIG_BOCHS_VBE
1.1.1.4 root 2341: /* XXX: use optimized standard vga accesses */
1.1.1.5 root 2342: cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1.1.1.10 root 2343: VGA_RAM_SIZE, s->vram_offset);
1.1.1.12 root 2344: s->vbe_mapped = 1;
2345: #endif
1.1.1.4 root 2346: }
1.1 root 2347: /********************************************************/
2348: /* vga screen dump */
2349:
1.1.1.10 root 2350: static void vga_save_dpy_update(DisplayState *ds,
1.1 root 2351: int x, int y, int w, int h)
2352: {
1.1.1.10 root 2353: if (screen_dump_filename) {
2354: ppm_save(screen_dump_filename, ds->surface);
2355: screen_dump_filename = NULL;
2356: }
1.1 root 2357: }
2358:
1.1.1.6 root 2359: static void vga_save_dpy_resize(DisplayState *s)
1.1 root 2360: {
2361: }
2362:
2363: static void vga_save_dpy_refresh(DisplayState *s)
2364: {
2365: }
2366:
1.1.1.6 root 2367: int ppm_save(const char *filename, struct DisplaySurface *ds)
1.1 root 2368: {
2369: FILE *f;
2370: uint8_t *d, *d1;
1.1.1.6 root 2371: uint32_t v;
1.1 root 2372: int y, x;
1.1.1.6 root 2373: uint8_t r, g, b;
1.1 root 2374:
2375: f = fopen(filename, "wb");
2376: if (!f)
2377: return -1;
2378: fprintf(f, "P6\n%d %d\n%d\n",
1.1.1.6 root 2379: ds->width, ds->height, 255);
2380: d1 = ds->data;
2381: for(y = 0; y < ds->height; y++) {
1.1 root 2382: d = d1;
1.1.1.6 root 2383: for(x = 0; x < ds->width; x++) {
2384: if (ds->pf.bits_per_pixel == 32)
2385: v = *(uint32_t *)d;
2386: else
2387: v = (uint32_t) (*(uint16_t *)d);
2388: r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2389: (ds->pf.rmax + 1);
2390: g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2391: (ds->pf.gmax + 1);
2392: b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2393: (ds->pf.bmax + 1);
2394: fputc(r, f);
2395: fputc(g, f);
2396: fputc(b, f);
2397: d += ds->pf.bytes_per_pixel;
1.1 root 2398: }
1.1.1.6 root 2399: d1 += ds->linesize;
1.1 root 2400: }
2401: fclose(f);
2402: return 0;
2403: }
2404:
1.1.1.10 root 2405: static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
1.1.1.6 root 2406: {
1.1.1.10 root 2407: DisplayChangeListener *dcl;
1.1.1.6 root 2408:
1.1.1.10 root 2409: dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2410: dcl->dpy_update = vga_save_dpy_update;
2411: dcl->dpy_resize = vga_save_dpy_resize;
2412: dcl->dpy_refresh = vga_save_dpy_refresh;
2413: register_displaychangelistener(ds, dcl);
2414: return dcl;
1.1.1.6 root 2415: }
2416:
2417: /* save the vga display in a PPM image even if no display is
2418: available */
2419: static void vga_screen_dump(void *opaque, const char *filename)
2420: {
1.1.1.12 root 2421: VGACommonState *s = opaque;
1.1.1.6 root 2422:
1.1.1.10 root 2423: if (!screen_dump_dcl)
2424: screen_dump_dcl = vga_screen_dump_init(s->ds);
2425:
2426: screen_dump_filename = (char *)filename;
1.1.1.9 root 2427: vga_invalidate_display(s);
1.1.1.10 root 2428: vga_hw_update();
1.1.1.6 root 2429: }
1.1.1.10 root 2430:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.