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