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