|
|
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.8 root 1619: if (shift_control == 0) {
1620: if (s->sr[0x01] & 8) {
1621: disp_width <<= 1;
1622: }
1623: } else if (shift_control == 1) {
1624: if (s->sr[0x01] & 8) {
1625: disp_width <<= 1;
1626: }
1627: }
1628:
1.1.1.6 root 1629: depth = s->get_bpp(s);
1630: if (s->line_offset != s->last_line_offset ||
1631: disp_width != s->last_width ||
1632: height != s->last_height ||
1633: s->last_depth != depth) {
1634: #if defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1635: if (depth == 16 || depth == 32) {
1636: #else
1637: if (depth == 32) {
1638: #endif
1639: if (is_graphic_console()) {
1640: qemu_free_displaysurface(s->ds->surface);
1641: s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1642: s->line_offset,
1643: s->vram_ptr + (s->start_addr * 4));
1644: #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1645: s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1646: #endif
1647: dpy_resize(s->ds);
1648: } else {
1649: qemu_console_resize(s->ds, disp_width, height);
1650: }
1651: } else {
1652: qemu_console_resize(s->ds, disp_width, height);
1653: }
1654: s->last_scr_width = disp_width;
1655: s->last_scr_height = height;
1656: s->last_width = disp_width;
1657: s->last_height = height;
1658: s->last_line_offset = s->line_offset;
1659: s->last_depth = depth;
1660: full_update = 1;
1661: } else if (is_graphic_console() && is_buffer_shared(s->ds->surface) &&
1662: (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1663: s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1664: dpy_setdata(s->ds);
1665: }
1666:
1667: s->rgb_to_pixel =
1668: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1669:
1.1 root 1670: if (shift_control == 0) {
1671: full_update |= update_palette16(s);
1672: if (s->sr[0x01] & 8) {
1673: v = VGA_DRAW_LINE4D2;
1674: } else {
1675: v = VGA_DRAW_LINE4;
1676: }
1.1.1.6 root 1677: bits = 4;
1.1 root 1678: } else if (shift_control == 1) {
1679: full_update |= update_palette16(s);
1680: if (s->sr[0x01] & 8) {
1681: v = VGA_DRAW_LINE2D2;
1682: } else {
1683: v = VGA_DRAW_LINE2;
1684: }
1.1.1.6 root 1685: bits = 4;
1.1 root 1686: } else {
1687: switch(s->get_bpp(s)) {
1688: default:
1689: case 0:
1690: full_update |= update_palette256(s);
1691: v = VGA_DRAW_LINE8D2;
1.1.1.6 root 1692: bits = 4;
1.1 root 1693: break;
1694: case 8:
1695: full_update |= update_palette256(s);
1696: v = VGA_DRAW_LINE8;
1.1.1.6 root 1697: bits = 8;
1.1 root 1698: break;
1699: case 15:
1700: v = VGA_DRAW_LINE15;
1.1.1.6 root 1701: bits = 16;
1.1 root 1702: break;
1703: case 16:
1704: v = VGA_DRAW_LINE16;
1.1.1.6 root 1705: bits = 16;
1.1 root 1706: break;
1707: case 24:
1708: v = VGA_DRAW_LINE24;
1.1.1.6 root 1709: bits = 24;
1.1 root 1710: break;
1711: case 32:
1712: v = VGA_DRAW_LINE32;
1.1.1.6 root 1713: bits = 32;
1.1 root 1714: break;
1715: }
1716: }
1.1.1.3 root 1717: vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1.1 root 1718:
1.1.1.6 root 1719: if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1.1 root 1720: s->cursor_invalidate(s);
1.1.1.5 root 1721:
1.1 root 1722: line_offset = s->line_offset;
1723: #if 0
1724: 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",
1725: width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1726: #endif
1727: addr1 = (s->start_addr * 4);
1.1.1.6 root 1728: bwidth = (width * bits + 7) / 8;
1.1 root 1729: y_start = -1;
1730: page_min = 0x7fffffff;
1731: page_max = -1;
1.1.1.6 root 1732: d = ds_get_data(s->ds);
1733: linesize = ds_get_linesize(s->ds);
1.1 root 1734: y1 = 0;
1735: for(y = 0; y < height; y++) {
1736: addr = addr1;
1737: if (!(s->cr[0x17] & 1)) {
1738: int shift;
1739: /* CGA compatibility handling */
1740: shift = 14 + ((s->cr[0x17] >> 6) & 1);
1741: addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1742: }
1743: if (!(s->cr[0x17] & 2)) {
1744: addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1745: }
1746: page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1747: page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1.1.1.5 root 1748: update = full_update |
1.1 root 1749: cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1750: cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1751: if ((page1 - page0) > TARGET_PAGE_SIZE) {
1752: /* if wide line, can use another page */
1.1.1.5 root 1753: update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1.1 root 1754: VGA_DIRTY_FLAG);
1755: }
1756: /* explicit invalidation for the hardware cursor */
1757: update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1758: if (update) {
1759: if (y_start < 0)
1760: y_start = y;
1761: if (page0 < page_min)
1762: page_min = page0;
1763: if (page1 > page_max)
1764: page_max = page1;
1.1.1.6 root 1765: if (!(is_buffer_shared(s->ds->surface))) {
1766: vga_draw_line(s, d, s->vram_ptr + addr, width);
1767: if (s->cursor_draw_line)
1768: s->cursor_draw_line(s, d, y);
1769: }
1.1 root 1770: } else {
1771: if (y_start >= 0) {
1772: /* flush to display */
1.1.1.5 root 1773: dpy_update(s->ds, 0, y_start,
1.1 root 1774: disp_width, y - y_start);
1775: y_start = -1;
1776: }
1777: }
1778: if (!multi_run) {
1779: mask = (s->cr[0x17] & 3) ^ 3;
1780: if ((y1 & mask) == mask)
1781: addr1 += line_offset;
1782: y1++;
1783: multi_run = multi_scan;
1784: } else {
1785: multi_run--;
1786: }
1787: /* line compare acts on the displayed lines */
1788: if (y == s->line_compare)
1789: addr1 = 0;
1790: d += linesize;
1791: }
1792: if (y_start >= 0) {
1793: /* flush to display */
1.1.1.5 root 1794: dpy_update(s->ds, 0, y_start,
1.1 root 1795: disp_width, y - y_start);
1796: }
1797: /* reset modified pages */
1798: if (page_max != -1) {
1799: cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1800: VGA_DIRTY_FLAG);
1801: }
1802: memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1803: }
1804:
1805: static void vga_draw_blank(VGAState *s, int full_update)
1806: {
1807: int i, w, val;
1808: uint8_t *d;
1809:
1810: if (!full_update)
1811: return;
1812: if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1813: return;
1.1.1.6 root 1814: vga_dirty_log_stop(s);
1815:
1816: s->rgb_to_pixel =
1817: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1818: if (ds_get_bits_per_pixel(s->ds) == 8)
1.1 root 1819: val = s->rgb_to_pixel(0, 0, 0);
1820: else
1821: val = 0;
1.1.1.6 root 1822: w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1823: d = ds_get_data(s->ds);
1.1 root 1824: for(i = 0; i < s->last_scr_height; i++) {
1825: memset(d, val, w);
1.1.1.6 root 1826: d += ds_get_linesize(s->ds);
1.1 root 1827: }
1.1.1.5 root 1828: dpy_update(s->ds, 0, 0,
1.1 root 1829: s->last_scr_width, s->last_scr_height);
1830: }
1831:
1832: #define GMODE_TEXT 0
1833: #define GMODE_GRAPH 1
1.1.1.5 root 1834: #define GMODE_BLANK 2
1.1 root 1835:
1.1.1.2 root 1836: static void vga_update_display(void *opaque)
1.1 root 1837: {
1.1.1.2 root 1838: VGAState *s = (VGAState *)opaque;
1.1 root 1839: int full_update, graphic_mode;
1840:
1.1.1.6 root 1841: if (ds_get_bits_per_pixel(s->ds) == 0) {
1.1 root 1842: /* nothing to do */
1843: } else {
1844: full_update = 0;
1845: if (!(s->ar_index & 0x20)) {
1846: graphic_mode = GMODE_BLANK;
1847: } else {
1848: graphic_mode = s->gr[6] & 1;
1849: }
1850: if (graphic_mode != s->graphic_mode) {
1851: s->graphic_mode = graphic_mode;
1852: full_update = 1;
1853: }
1854: switch(graphic_mode) {
1855: case GMODE_TEXT:
1856: vga_draw_text(s, full_update);
1857: break;
1858: case GMODE_GRAPH:
1859: vga_draw_graphic(s, full_update);
1860: break;
1861: case GMODE_BLANK:
1862: default:
1863: vga_draw_blank(s, full_update);
1864: break;
1865: }
1866: }
1867: }
1868:
1869: /* force a full display refresh */
1.1.1.2 root 1870: static void vga_invalidate_display(void *opaque)
1.1 root 1871: {
1.1.1.2 root 1872: VGAState *s = (VGAState *)opaque;
1.1.1.5 root 1873:
1.1 root 1874: s->last_width = -1;
1875: s->last_height = -1;
1876: }
1877:
1.1.1.6 root 1878: void vga_reset(void *opaque)
1.1 root 1879: {
1.1.1.6 root 1880: VGAState *s = (VGAState *) opaque;
1881:
1882: s->lfb_addr = 0;
1883: s->lfb_end = 0;
1884: s->map_addr = 0;
1885: s->map_end = 0;
1886: s->lfb_vram_mapped = 0;
1887: s->bios_offset = 0;
1888: s->bios_size = 0;
1889: s->sr_index = 0;
1890: memset(s->sr, '\0', sizeof(s->sr));
1891: s->gr_index = 0;
1892: memset(s->gr, '\0', sizeof(s->gr));
1893: s->ar_index = 0;
1894: memset(s->ar, '\0', sizeof(s->ar));
1895: s->ar_flip_flop = 0;
1896: s->cr_index = 0;
1897: memset(s->cr, '\0', sizeof(s->cr));
1898: s->msr = 0;
1899: s->fcr = 0;
1900: s->st00 = 0;
1901: s->st01 = 0;
1902: s->dac_state = 0;
1903: s->dac_sub_index = 0;
1904: s->dac_read_index = 0;
1905: s->dac_write_index = 0;
1906: memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1907: s->dac_8bit = 0;
1908: memset(s->palette, '\0', sizeof(s->palette));
1909: s->bank_offset = 0;
1910: #ifdef CONFIG_BOCHS_VBE
1911: s->vbe_index = 0;
1912: memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1913: s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1914: s->vbe_start_addr = 0;
1915: s->vbe_line_offset = 0;
1916: s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1917: #endif
1918: memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1.1 root 1919: s->graphic_mode = -1; /* force full update */
1.1.1.6 root 1920: s->shift_control = 0;
1921: s->double_scan = 0;
1922: s->line_offset = 0;
1923: s->line_compare = 0;
1924: s->start_addr = 0;
1925: s->plane_updated = 0;
1926: s->last_cw = 0;
1927: s->last_ch = 0;
1928: s->last_width = 0;
1929: s->last_height = 0;
1930: s->last_scr_width = 0;
1931: s->last_scr_height = 0;
1932: s->cursor_start = 0;
1933: s->cursor_end = 0;
1934: s->cursor_offset = 0;
1935: memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1936: memset(s->last_palette, '\0', sizeof(s->last_palette));
1937: memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1938: switch (vga_retrace_method) {
1939: case VGA_RETRACE_DUMB:
1940: break;
1941: case VGA_RETRACE_PRECISE:
1942: memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1943: break;
1944: }
1945: }
1946:
1947: #define TEXTMODE_X(x) ((x) % width)
1948: #define TEXTMODE_Y(x) ((x) / width)
1949: #define VMEM2CHTYPE(v) ((v & 0xff0007ff) | \
1950: ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1951: /* relay text rendering to the display driver
1952: * instead of doing a full vga_update_display() */
1953: static void vga_update_text(void *opaque, console_ch_t *chardata)
1954: {
1955: VGAState *s = (VGAState *) opaque;
1956: int graphic_mode, i, cursor_offset, cursor_visible;
1957: int cw, cheight, width, height, size, c_min, c_max;
1958: uint32_t *src;
1959: console_ch_t *dst, val;
1960: char msg_buffer[80];
1961: int full_update = 0;
1962:
1963: if (!(s->ar_index & 0x20)) {
1964: graphic_mode = GMODE_BLANK;
1965: } else {
1966: graphic_mode = s->gr[6] & 1;
1967: }
1968: if (graphic_mode != s->graphic_mode) {
1969: s->graphic_mode = graphic_mode;
1970: full_update = 1;
1971: }
1972: if (s->last_width == -1) {
1973: s->last_width = 0;
1974: full_update = 1;
1975: }
1976:
1977: switch (graphic_mode) {
1978: case GMODE_TEXT:
1979: /* TODO: update palette */
1980: full_update |= update_basic_params(s);
1981:
1982: /* total width & height */
1983: cheight = (s->cr[9] & 0x1f) + 1;
1984: cw = 8;
1985: if (!(s->sr[1] & 0x01))
1986: cw = 9;
1987: if (s->sr[1] & 0x08)
1988: cw = 16; /* NOTE: no 18 pixel wide */
1989: width = (s->cr[0x01] + 1);
1990: if (s->cr[0x06] == 100) {
1991: /* ugly hack for CGA 160x100x16 - explain me the logic */
1992: height = 100;
1993: } else {
1994: height = s->cr[0x12] |
1995: ((s->cr[0x07] & 0x02) << 7) |
1996: ((s->cr[0x07] & 0x40) << 3);
1997: height = (height + 1) / cheight;
1998: }
1999:
2000: size = (height * width);
2001: if (size > CH_ATTR_SIZE) {
2002: if (!full_update)
2003: return;
2004:
2005: snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2006: width, height);
2007: break;
2008: }
2009:
2010: if (width != s->last_width || height != s->last_height ||
2011: cw != s->last_cw || cheight != s->last_ch) {
2012: s->last_scr_width = width * cw;
2013: s->last_scr_height = height * cheight;
2014: s->ds->surface->width = width;
2015: s->ds->surface->height = height;
2016: dpy_resize(s->ds);
2017: s->last_width = width;
2018: s->last_height = height;
2019: s->last_ch = cheight;
2020: s->last_cw = cw;
2021: full_update = 1;
2022: }
2023:
2024: /* Update "hardware" cursor */
2025: cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2026: if (cursor_offset != s->cursor_offset ||
2027: s->cr[0xa] != s->cursor_start ||
2028: s->cr[0xb] != s->cursor_end || full_update) {
2029: cursor_visible = !(s->cr[0xa] & 0x20);
2030: if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2031: dpy_cursor(s->ds,
2032: TEXTMODE_X(cursor_offset),
2033: TEXTMODE_Y(cursor_offset));
2034: else
2035: dpy_cursor(s->ds, -1, -1);
2036: s->cursor_offset = cursor_offset;
2037: s->cursor_start = s->cr[0xa];
2038: s->cursor_end = s->cr[0xb];
2039: }
2040:
2041: src = (uint32_t *) s->vram_ptr + s->start_addr;
2042: dst = chardata;
2043:
2044: if (full_update) {
2045: for (i = 0; i < size; src ++, dst ++, i ++)
2046: console_write_ch(dst, VMEM2CHTYPE(*src));
2047:
2048: dpy_update(s->ds, 0, 0, width, height);
2049: } else {
2050: c_max = 0;
2051:
2052: for (i = 0; i < size; src ++, dst ++, i ++) {
2053: console_write_ch(&val, VMEM2CHTYPE(*src));
2054: if (*dst != val) {
2055: *dst = val;
2056: c_max = i;
2057: break;
2058: }
2059: }
2060: c_min = i;
2061: for (; i < size; src ++, dst ++, i ++) {
2062: console_write_ch(&val, VMEM2CHTYPE(*src));
2063: if (*dst != val) {
2064: *dst = val;
2065: c_max = i;
2066: }
2067: }
2068:
2069: if (c_min <= c_max) {
2070: i = TEXTMODE_Y(c_min);
2071: dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2072: }
2073: }
2074:
2075: return;
2076: case GMODE_GRAPH:
2077: if (!full_update)
2078: return;
2079:
2080: s->get_resolution(s, &width, &height);
2081: snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2082: width, height);
2083: break;
2084: case GMODE_BLANK:
2085: default:
2086: if (!full_update)
2087: return;
2088:
2089: snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2090: break;
2091: }
2092:
2093: /* Display a message */
2094: s->last_width = 60;
2095: s->last_height = height = 3;
2096: dpy_cursor(s->ds, -1, -1);
2097: s->ds->surface->width = s->last_width;
2098: s->ds->surface->height = height;
2099: dpy_resize(s->ds);
2100:
2101: for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2102: console_write_ch(dst ++, ' ');
2103:
2104: size = strlen(msg_buffer);
2105: width = (s->last_width - size) / 2;
2106: dst = chardata + s->last_width + width;
2107: for (i = 0; i < size; i ++)
2108: console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2109:
2110: dpy_update(s->ds, 0, 0, s->last_width, height);
1.1 root 2111: }
2112:
2113: static CPUReadMemoryFunc *vga_mem_read[3] = {
2114: vga_mem_readb,
2115: vga_mem_readw,
2116: vga_mem_readl,
2117: };
2118:
2119: static CPUWriteMemoryFunc *vga_mem_write[3] = {
2120: vga_mem_writeb,
2121: vga_mem_writew,
2122: vga_mem_writel,
2123: };
2124:
2125: static void vga_save(QEMUFile *f, void *opaque)
2126: {
2127: VGAState *s = opaque;
2128: int i;
2129:
1.1.1.4 root 2130: if (s->pci_dev)
2131: pci_device_save(s->pci_dev, f);
2132:
1.1 root 2133: qemu_put_be32s(f, &s->latch);
2134: qemu_put_8s(f, &s->sr_index);
2135: qemu_put_buffer(f, s->sr, 8);
2136: qemu_put_8s(f, &s->gr_index);
2137: qemu_put_buffer(f, s->gr, 16);
2138: qemu_put_8s(f, &s->ar_index);
2139: qemu_put_buffer(f, s->ar, 21);
1.1.1.5 root 2140: qemu_put_be32(f, s->ar_flip_flop);
1.1 root 2141: qemu_put_8s(f, &s->cr_index);
2142: qemu_put_buffer(f, s->cr, 256);
2143: qemu_put_8s(f, &s->msr);
2144: qemu_put_8s(f, &s->fcr);
1.1.1.5 root 2145: qemu_put_byte(f, s->st00);
1.1 root 2146: qemu_put_8s(f, &s->st01);
2147:
2148: qemu_put_8s(f, &s->dac_state);
2149: qemu_put_8s(f, &s->dac_sub_index);
2150: qemu_put_8s(f, &s->dac_read_index);
2151: qemu_put_8s(f, &s->dac_write_index);
2152: qemu_put_buffer(f, s->dac_cache, 3);
2153: qemu_put_buffer(f, s->palette, 768);
2154:
1.1.1.5 root 2155: qemu_put_be32(f, s->bank_offset);
1.1 root 2156: #ifdef CONFIG_BOCHS_VBE
2157: qemu_put_byte(f, 1);
2158: qemu_put_be16s(f, &s->vbe_index);
2159: for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2160: qemu_put_be16s(f, &s->vbe_regs[i]);
2161: qemu_put_be32s(f, &s->vbe_start_addr);
2162: qemu_put_be32s(f, &s->vbe_line_offset);
2163: qemu_put_be32s(f, &s->vbe_bank_mask);
2164: #else
2165: qemu_put_byte(f, 0);
2166: #endif
2167: }
2168:
2169: static int vga_load(QEMUFile *f, void *opaque, int version_id)
2170: {
2171: VGAState *s = opaque;
1.1.1.4 root 2172: int is_vbe, i, ret;
1.1 root 2173:
1.1.1.4 root 2174: if (version_id > 2)
1.1 root 2175: return -EINVAL;
2176:
1.1.1.4 root 2177: if (s->pci_dev && version_id >= 2) {
2178: ret = pci_device_load(s->pci_dev, f);
2179: if (ret < 0)
2180: return ret;
2181: }
2182:
1.1 root 2183: qemu_get_be32s(f, &s->latch);
2184: qemu_get_8s(f, &s->sr_index);
2185: qemu_get_buffer(f, s->sr, 8);
2186: qemu_get_8s(f, &s->gr_index);
2187: qemu_get_buffer(f, s->gr, 16);
2188: qemu_get_8s(f, &s->ar_index);
2189: qemu_get_buffer(f, s->ar, 21);
1.1.1.5 root 2190: s->ar_flip_flop=qemu_get_be32(f);
1.1 root 2191: qemu_get_8s(f, &s->cr_index);
2192: qemu_get_buffer(f, s->cr, 256);
2193: qemu_get_8s(f, &s->msr);
2194: qemu_get_8s(f, &s->fcr);
2195: qemu_get_8s(f, &s->st00);
2196: qemu_get_8s(f, &s->st01);
2197:
2198: qemu_get_8s(f, &s->dac_state);
2199: qemu_get_8s(f, &s->dac_sub_index);
2200: qemu_get_8s(f, &s->dac_read_index);
2201: qemu_get_8s(f, &s->dac_write_index);
2202: qemu_get_buffer(f, s->dac_cache, 3);
2203: qemu_get_buffer(f, s->palette, 768);
2204:
1.1.1.5 root 2205: s->bank_offset=qemu_get_be32(f);
1.1 root 2206: is_vbe = qemu_get_byte(f);
2207: #ifdef CONFIG_BOCHS_VBE
2208: if (!is_vbe)
2209: return -EINVAL;
2210: qemu_get_be16s(f, &s->vbe_index);
2211: for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2212: qemu_get_be16s(f, &s->vbe_regs[i]);
2213: qemu_get_be32s(f, &s->vbe_start_addr);
2214: qemu_get_be32s(f, &s->vbe_line_offset);
2215: qemu_get_be32s(f, &s->vbe_bank_mask);
2216: #else
2217: if (is_vbe)
2218: return -EINVAL;
2219: #endif
2220:
2221: /* force refresh */
2222: s->graphic_mode = -1;
2223: return 0;
2224: }
2225:
1.1.1.4 root 2226: typedef struct PCIVGAState {
2227: PCIDevice dev;
2228: VGAState vga_state;
2229: } PCIVGAState;
2230:
1.1.1.6 root 2231: void vga_dirty_log_start(VGAState *s)
2232: {
2233: if (kvm_enabled() && s->map_addr)
2234: kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2235:
2236: if (kvm_enabled() && s->lfb_vram_mapped) {
2237: kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2238: kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2239: }
2240: }
2241:
2242: void vga_dirty_log_stop(VGAState *s)
2243: {
2244: if (kvm_enabled() && s->map_addr)
2245: kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2246:
2247: if (kvm_enabled() && s->lfb_vram_mapped) {
2248: kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2249: kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2250: }
2251: }
2252:
1.1.1.5 root 2253: static void vga_map(PCIDevice *pci_dev, int region_num,
1.1 root 2254: uint32_t addr, uint32_t size, int type)
2255: {
1.1.1.4 root 2256: PCIVGAState *d = (PCIVGAState *)pci_dev;
2257: VGAState *s = &d->vga_state;
1.1 root 2258: if (region_num == PCI_ROM_SLOT) {
2259: cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2260: } else {
2261: cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2262: }
1.1.1.6 root 2263:
2264: s->map_addr = addr;
2265: s->map_end = addr + VGA_RAM_SIZE;
2266:
2267: vga_dirty_log_start(s);
1.1 root 2268: }
2269:
1.1.1.6 root 2270: void vga_common_init(VGAState *s, uint8_t *vga_ram_base,
2271: ram_addr_t vga_ram_offset, int vga_ram_size)
1.1 root 2272: {
2273: int i, j, v, b;
2274:
2275: for(i = 0;i < 256; i++) {
2276: v = 0;
2277: for(j = 0; j < 8; j++) {
2278: v |= ((i >> j) & 1) << (j * 4);
2279: }
2280: expand4[i] = v;
2281:
2282: v = 0;
2283: for(j = 0; j < 4; j++) {
2284: v |= ((i >> (2 * j)) & 3) << (j * 4);
2285: }
2286: expand2[i] = v;
2287: }
2288: for(i = 0; i < 16; i++) {
2289: v = 0;
2290: for(j = 0; j < 4; j++) {
2291: b = ((i >> j) & 1);
2292: v |= b << (2 * j);
2293: v |= b << (2 * j + 1);
2294: }
2295: expand4to8[i] = v;
2296: }
2297:
2298: s->vram_ptr = vga_ram_base;
2299: s->vram_offset = vga_ram_offset;
2300: s->vram_size = vga_ram_size;
2301: s->get_bpp = vga_get_bpp;
2302: s->get_offsets = vga_get_offsets;
2303: s->get_resolution = vga_get_resolution;
1.1.1.5 root 2304: s->update = vga_update_display;
2305: s->invalidate = vga_invalidate_display;
2306: s->screen_dump = vga_screen_dump;
1.1.1.6 root 2307: s->text_update = vga_update_text;
2308: switch (vga_retrace_method) {
2309: case VGA_RETRACE_DUMB:
2310: s->retrace = vga_dumb_retrace;
2311: s->update_retrace_info = vga_dumb_update_retrace_info;
2312: break;
2313:
2314: case VGA_RETRACE_PRECISE:
2315: s->retrace = vga_precise_retrace;
2316: s->update_retrace_info = vga_precise_update_retrace_info;
2317: break;
2318: }
2319: vga_reset(s);
1.1 root 2320: }
2321:
1.1.1.4 root 2322: /* used by both ISA and PCI */
1.1.1.5 root 2323: void vga_init(VGAState *s)
1.1 root 2324: {
1.1.1.4 root 2325: int vga_io_memory;
1.1 root 2326:
1.1.1.6 root 2327: qemu_register_reset(vga_reset, s);
1.1.1.4 root 2328: register_savevm("vga", 0, 2, vga_save, vga_load, s);
1.1 root 2329:
2330: register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2331:
2332: register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2333: register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2334: register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2335: register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2336:
2337: register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2338:
2339: register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2340: register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2341: register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2342: register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2343: s->bank_offset = 0;
2344:
2345: #ifdef CONFIG_BOCHS_VBE
2346: #if defined (TARGET_I386)
2347: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2348: register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2349:
2350: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2351: register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2352:
2353: /* old Bochs IO ports */
2354: register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2355: register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2356:
2357: register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1.1.1.5 root 2358: register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1.1 root 2359: #else
2360: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2361: register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2362:
2363: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2364: register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2365: #endif
2366: #endif /* CONFIG_BOCHS_VBE */
2367:
2368: vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1.1.1.5 root 2369: cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1.1 root 2370: vga_io_memory);
1.1.1.6 root 2371: qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
1.1.1.4 root 2372: }
1.1 root 2373:
1.1.1.5 root 2374: /* Memory mapped interface */
2375: static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2376: {
2377: VGAState *s = opaque;
2378:
1.1.1.6 root 2379: return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
1.1.1.5 root 2380: }
2381:
2382: static void vga_mm_writeb (void *opaque,
2383: target_phys_addr_t addr, uint32_t value)
2384: {
2385: VGAState *s = opaque;
2386:
1.1.1.6 root 2387: vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
1.1.1.5 root 2388: }
2389:
2390: static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2391: {
2392: VGAState *s = opaque;
2393:
1.1.1.6 root 2394: return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
1.1.1.5 root 2395: }
2396:
2397: static void vga_mm_writew (void *opaque,
2398: target_phys_addr_t addr, uint32_t value)
2399: {
2400: VGAState *s = opaque;
2401:
1.1.1.6 root 2402: vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
1.1.1.5 root 2403: }
2404:
2405: static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2406: {
2407: VGAState *s = opaque;
2408:
1.1.1.6 root 2409: return vga_ioport_read(s, addr >> s->it_shift);
1.1.1.5 root 2410: }
2411:
2412: static void vga_mm_writel (void *opaque,
2413: target_phys_addr_t addr, uint32_t value)
2414: {
2415: VGAState *s = opaque;
2416:
1.1.1.6 root 2417: vga_ioport_write(s, addr >> s->it_shift, value);
1.1.1.5 root 2418: }
2419:
2420: static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2421: &vga_mm_readb,
2422: &vga_mm_readw,
2423: &vga_mm_readl,
2424: };
2425:
2426: static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2427: &vga_mm_writeb,
2428: &vga_mm_writew,
2429: &vga_mm_writel,
2430: };
2431:
2432: static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2433: target_phys_addr_t ctrl_base, int it_shift)
2434: {
2435: int s_ioport_ctrl, vga_io_memory;
2436:
2437: s->it_shift = it_shift;
2438: s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2439: vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2440:
2441: register_savevm("vga", 0, 2, vga_save, vga_load, s);
2442:
2443: cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2444: s->bank_offset = 0;
2445: cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
1.1.1.6 root 2446: qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
1.1.1.5 root 2447: }
2448:
1.1.1.6 root 2449: int isa_vga_init(uint8_t *vga_ram_base,
1.1.1.4 root 2450: unsigned long vga_ram_offset, int vga_ram_size)
2451: {
2452: VGAState *s;
2453:
2454: s = qemu_mallocz(sizeof(VGAState));
2455:
1.1.1.6 root 2456: vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
1.1.1.4 root 2457: vga_init(s);
1.1 root 2458:
1.1.1.6 root 2459: s->ds = graphic_console_init(s->update, s->invalidate,
2460: s->screen_dump, s->text_update, s);
1.1.1.5 root 2461:
1.1 root 2462: #ifdef CONFIG_BOCHS_VBE
1.1.1.4 root 2463: /* XXX: use optimized standard vga accesses */
1.1.1.5 root 2464: cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1.1.1.4 root 2465: vga_ram_size, vga_ram_offset);
1.1 root 2466: #endif
1.1.1.4 root 2467: return 0;
2468: }
2469:
1.1.1.6 root 2470: int isa_vga_mm_init(uint8_t *vga_ram_base,
1.1.1.5 root 2471: unsigned long vga_ram_offset, int vga_ram_size,
2472: target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2473: int it_shift)
2474: {
2475: VGAState *s;
2476:
2477: s = qemu_mallocz(sizeof(VGAState));
2478:
1.1.1.6 root 2479: vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
1.1.1.5 root 2480: vga_mm_init(s, vram_base, ctrl_base, it_shift);
2481:
1.1.1.6 root 2482: s->ds = graphic_console_init(s->update, s->invalidate,
2483: s->screen_dump, s->text_update, s);
1.1.1.5 root 2484:
2485: #ifdef CONFIG_BOCHS_VBE
2486: /* XXX: use optimized standard vga accesses */
2487: cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2488: vga_ram_size, vga_ram_offset);
2489: #endif
2490: return 0;
2491: }
2492:
1.1.1.7 root 2493: static void pci_vga_write_config(PCIDevice *d,
2494: uint32_t address, uint32_t val, int len)
2495: {
2496: PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2497: VGAState *s = &pvs->vga_state;
2498:
2499: vga_dirty_log_stop(s);
2500: pci_default_write_config(d, address, val, len);
2501: vga_dirty_log_start(s);
2502: }
2503:
1.1.1.6 root 2504: int pci_vga_init(PCIBus *bus, uint8_t *vga_ram_base,
1.1.1.4 root 2505: unsigned long vga_ram_offset, int vga_ram_size,
2506: unsigned long vga_bios_offset, int vga_bios_size)
2507: {
2508: PCIVGAState *d;
2509: VGAState *s;
2510: uint8_t *pci_conf;
1.1.1.5 root 2511:
2512: d = (PCIVGAState *)pci_register_device(bus, "VGA",
1.1.1.4 root 2513: sizeof(PCIVGAState),
1.1.1.7 root 2514: -1, NULL, pci_vga_write_config);
1.1.1.4 root 2515: if (!d)
2516: return -1;
2517: s = &d->vga_state;
1.1.1.5 root 2518:
1.1.1.6 root 2519: vga_common_init(s, vga_ram_base, vga_ram_offset, vga_ram_size);
1.1.1.4 root 2520: vga_init(s);
1.1.1.5 root 2521:
1.1.1.6 root 2522: s->ds = graphic_console_init(s->update, s->invalidate,
2523: s->screen_dump, s->text_update, s);
1.1.1.5 root 2524:
1.1.1.4 root 2525: s->pci_dev = &d->dev;
1.1.1.5 root 2526:
1.1.1.4 root 2527: pci_conf = d->dev.config;
1.1.1.6 root 2528: // dummy VGA (same as Bochs ID)
2529: pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2530: pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2531: pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
1.1.1.4 root 2532: pci_conf[0x0e] = 0x00; // header_type
1.1.1.5 root 2533:
1.1.1.4 root 2534: /* XXX: vga_ram_size must be a power of two */
1.1.1.5 root 2535: pci_register_io_region(&d->dev, 0, vga_ram_size,
1.1.1.4 root 2536: PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2537: if (vga_bios_size != 0) {
2538: unsigned int bios_total_size;
2539: s->bios_offset = vga_bios_offset;
2540: s->bios_size = vga_bios_size;
2541: /* must be a power of two */
2542: bios_total_size = 1;
2543: while (bios_total_size < vga_bios_size)
2544: bios_total_size <<= 1;
1.1.1.5 root 2545: pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
1.1.1.4 root 2546: PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1.1 root 2547: }
2548: return 0;
2549: }
2550:
2551: /********************************************************/
2552: /* vga screen dump */
2553:
1.1.1.5 root 2554: static void vga_save_dpy_update(DisplayState *s,
1.1 root 2555: int x, int y, int w, int h)
2556: {
2557: }
2558:
1.1.1.6 root 2559: static void vga_save_dpy_resize(DisplayState *s)
1.1 root 2560: {
2561: }
2562:
2563: static void vga_save_dpy_refresh(DisplayState *s)
2564: {
2565: }
2566:
1.1.1.6 root 2567: int ppm_save(const char *filename, struct DisplaySurface *ds)
1.1 root 2568: {
2569: FILE *f;
2570: uint8_t *d, *d1;
1.1.1.6 root 2571: uint32_t v;
1.1 root 2572: int y, x;
1.1.1.6 root 2573: uint8_t r, g, b;
1.1 root 2574:
2575: f = fopen(filename, "wb");
2576: if (!f)
2577: return -1;
2578: fprintf(f, "P6\n%d %d\n%d\n",
1.1.1.6 root 2579: ds->width, ds->height, 255);
2580: d1 = ds->data;
2581: for(y = 0; y < ds->height; y++) {
1.1 root 2582: d = d1;
1.1.1.6 root 2583: for(x = 0; x < ds->width; x++) {
2584: if (ds->pf.bits_per_pixel == 32)
2585: v = *(uint32_t *)d;
2586: else
2587: v = (uint32_t) (*(uint16_t *)d);
2588: r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2589: (ds->pf.rmax + 1);
2590: g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2591: (ds->pf.gmax + 1);
2592: b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2593: (ds->pf.bmax + 1);
2594: fputc(r, f);
2595: fputc(g, f);
2596: fputc(b, f);
2597: d += ds->pf.bytes_per_pixel;
1.1 root 2598: }
1.1.1.6 root 2599: d1 += ds->linesize;
1.1 root 2600: }
2601: fclose(f);
2602: return 0;
2603: }
2604:
1.1.1.6 root 2605: static void vga_screen_dump_blank(VGAState *s, const char *filename)
2606: {
2607: FILE *f;
2608: unsigned int y, x, w, h;
2609:
2610: w = s->last_scr_width * sizeof(uint32_t);
2611: h = s->last_scr_height;
2612:
2613: f = fopen(filename, "wb");
2614: if (!f)
2615: return;
2616: fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
2617: for (y = 0; y < h; y++) {
2618: for (x = 0; x < w; x++) {
2619: fputc(0, f);
2620: }
2621: }
2622: fclose(f);
2623: }
2624:
2625: static void vga_screen_dump_common(VGAState *s, const char *filename,
2626: int w, int h)
1.1 root 2627: {
2628: DisplayState *saved_ds, ds1, *ds = &ds1;
1.1.1.6 root 2629: DisplayChangeListener dcl;
1.1.1.5 root 2630:
1.1 root 2631: /* XXX: this is a little hackish */
1.1.1.2 root 2632: vga_invalidate_display(s);
1.1 root 2633: saved_ds = s->ds;
2634:
2635: memset(ds, 0, sizeof(DisplayState));
1.1.1.6 root 2636: memset(&dcl, 0, sizeof(DisplayChangeListener));
2637: dcl.dpy_update = vga_save_dpy_update;
2638: dcl.dpy_resize = vga_save_dpy_resize;
2639: dcl.dpy_refresh = vga_save_dpy_refresh;
2640: register_displaychangelistener(ds, &dcl);
2641: ds->surface = qemu_create_displaysurface(w, h, 32, 4 * w);
1.1 root 2642:
2643: s->ds = ds;
2644: s->graphic_mode = -1;
1.1.1.2 root 2645: vga_update_display(s);
1.1.1.5 root 2646:
1.1.1.6 root 2647: ppm_save(filename, ds->surface);
2648:
2649: qemu_free_displaysurface(ds->surface);
1.1 root 2650: s->ds = saved_ds;
2651: }
1.1.1.6 root 2652:
2653: static void vga_screen_dump_graphic(VGAState *s, const char *filename)
2654: {
2655: int w, h;
2656:
2657: s->get_resolution(s, &w, &h);
2658: vga_screen_dump_common(s, filename, w, h);
2659: }
2660:
2661: static void vga_screen_dump_text(VGAState *s, const char *filename)
2662: {
2663: int w, h, cwidth, cheight;
2664:
2665: vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
2666: vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
2667: }
2668:
2669: /* save the vga display in a PPM image even if no display is
2670: available */
2671: static void vga_screen_dump(void *opaque, const char *filename)
2672: {
2673: VGAState *s = (VGAState *)opaque;
2674:
2675: if (!(s->ar_index & 0x20))
2676: vga_screen_dump_blank(s, filename);
2677: else if (s->gr[6] & 1)
2678: vga_screen_dump_graphic(s, filename);
2679: else
2680: vga_screen_dump_text(s, filename);
1.1.1.9 ! root 2681: vga_invalidate_display(s);
1.1.1.6 root 2682: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.