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