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