|
|
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 root 30:
31: //#define DEBUG_VGA
32: //#define DEBUG_VGA_MEM
33: //#define DEBUG_VGA_REG
34:
35: //#define DEBUG_BOCHS_VBE
36:
37: /* force some bits to zero */
38: const uint8_t sr_mask[8] = {
39: (uint8_t)~0xfc,
40: (uint8_t)~0xc2,
41: (uint8_t)~0xf0,
42: (uint8_t)~0xc0,
43: (uint8_t)~0xf1,
44: (uint8_t)~0xff,
45: (uint8_t)~0xff,
46: (uint8_t)~0x00,
47: };
48:
49: const uint8_t gr_mask[16] = {
50: (uint8_t)~0xf0, /* 0x00 */
51: (uint8_t)~0xf0, /* 0x01 */
52: (uint8_t)~0xf0, /* 0x02 */
53: (uint8_t)~0xe0, /* 0x03 */
54: (uint8_t)~0xfc, /* 0x04 */
55: (uint8_t)~0x84, /* 0x05 */
56: (uint8_t)~0xf0, /* 0x06 */
57: (uint8_t)~0xf0, /* 0x07 */
58: (uint8_t)~0x00, /* 0x08 */
59: (uint8_t)~0xff, /* 0x09 */
60: (uint8_t)~0xff, /* 0x0a */
61: (uint8_t)~0xff, /* 0x0b */
62: (uint8_t)~0xff, /* 0x0c */
63: (uint8_t)~0xff, /* 0x0d */
64: (uint8_t)~0xff, /* 0x0e */
65: (uint8_t)~0xff, /* 0x0f */
66: };
67:
68: #define cbswap_32(__x) \
69: ((uint32_t)( \
70: (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
71: (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
72: (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
73: (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
74:
75: #ifdef WORDS_BIGENDIAN
76: #define PAT(x) cbswap_32(x)
77: #else
78: #define PAT(x) (x)
79: #endif
80:
81: #ifdef WORDS_BIGENDIAN
82: #define BIG 1
83: #else
84: #define BIG 0
85: #endif
86:
87: #ifdef WORDS_BIGENDIAN
88: #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
89: #else
90: #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
91: #endif
92:
93: static const uint32_t mask16[16] = {
94: PAT(0x00000000),
95: PAT(0x000000ff),
96: PAT(0x0000ff00),
97: PAT(0x0000ffff),
98: PAT(0x00ff0000),
99: PAT(0x00ff00ff),
100: PAT(0x00ffff00),
101: PAT(0x00ffffff),
102: PAT(0xff000000),
103: PAT(0xff0000ff),
104: PAT(0xff00ff00),
105: PAT(0xff00ffff),
106: PAT(0xffff0000),
107: PAT(0xffff00ff),
108: PAT(0xffffff00),
109: PAT(0xffffffff),
110: };
111:
112: #undef PAT
113:
114: #ifdef WORDS_BIGENDIAN
115: #define PAT(x) (x)
116: #else
117: #define PAT(x) cbswap_32(x)
118: #endif
119:
120: static const uint32_t dmask16[16] = {
121: PAT(0x00000000),
122: PAT(0x000000ff),
123: PAT(0x0000ff00),
124: PAT(0x0000ffff),
125: PAT(0x00ff0000),
126: PAT(0x00ff00ff),
127: PAT(0x00ffff00),
128: PAT(0x00ffffff),
129: PAT(0xff000000),
130: PAT(0xff0000ff),
131: PAT(0xff00ff00),
132: PAT(0xff00ffff),
133: PAT(0xffff0000),
134: PAT(0xffff00ff),
135: PAT(0xffffff00),
136: PAT(0xffffffff),
137: };
138:
139: static const uint32_t dmask4[4] = {
140: PAT(0x00000000),
141: PAT(0x0000ffff),
142: PAT(0xffff0000),
143: PAT(0xffffffff),
144: };
145:
146: static uint32_t expand4[256];
147: static uint16_t expand2[256];
148: static uint8_t expand4to8[16];
149:
1.1.1.2 root 150: static void vga_screen_dump(void *opaque, const char *filename);
151:
1.1 root 152: static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
153: {
154: VGAState *s = opaque;
155: int val, index;
156:
157: /* check port range access depending on color/monochrome mode */
158: if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
159: (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
160: val = 0xff;
161: } else {
162: switch(addr) {
163: case 0x3c0:
164: if (s->ar_flip_flop == 0) {
165: val = s->ar_index;
166: } else {
167: val = 0;
168: }
169: break;
170: case 0x3c1:
171: index = s->ar_index & 0x1f;
1.1.1.5 ! root 172: if (index < 21)
1.1 root 173: val = s->ar[index];
174: else
175: val = 0;
176: break;
177: case 0x3c2:
178: val = s->st00;
179: break;
180: case 0x3c4:
181: val = s->sr_index;
182: break;
183: case 0x3c5:
184: val = s->sr[s->sr_index];
185: #ifdef DEBUG_VGA_REG
186: printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
187: #endif
188: break;
189: case 0x3c7:
190: val = s->dac_state;
191: break;
192: case 0x3c8:
193: val = s->dac_write_index;
194: break;
195: case 0x3c9:
196: val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
197: if (++s->dac_sub_index == 3) {
198: s->dac_sub_index = 0;
199: s->dac_read_index++;
200: }
201: break;
202: case 0x3ca:
203: val = s->fcr;
204: break;
205: case 0x3cc:
206: val = s->msr;
207: break;
208: case 0x3ce:
209: val = s->gr_index;
210: break;
211: case 0x3cf:
212: val = s->gr[s->gr_index];
213: #ifdef DEBUG_VGA_REG
214: printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
215: #endif
216: break;
217: case 0x3b4:
218: case 0x3d4:
219: val = s->cr_index;
220: break;
221: case 0x3b5:
222: case 0x3d5:
223: val = s->cr[s->cr_index];
224: #ifdef DEBUG_VGA_REG
225: printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
226: #endif
227: break;
228: case 0x3ba:
229: case 0x3da:
230: /* just toggle to fool polling */
231: s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
232: val = s->st01;
233: s->ar_flip_flop = 0;
234: break;
235: default:
236: val = 0x00;
237: break;
238: }
239: }
240: #if defined(DEBUG_VGA)
241: printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
242: #endif
243: return val;
244: }
245:
246: static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
247: {
248: VGAState *s = opaque;
249: int index;
250:
251: /* check port range access depending on color/monochrome mode */
252: if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
253: (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
254: return;
255:
256: #ifdef DEBUG_VGA
257: printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
258: #endif
259:
260: switch(addr) {
261: case 0x3c0:
262: if (s->ar_flip_flop == 0) {
263: val &= 0x3f;
264: s->ar_index = val;
265: } else {
266: index = s->ar_index & 0x1f;
267: switch(index) {
268: case 0x00 ... 0x0f:
269: s->ar[index] = val & 0x3f;
270: break;
271: case 0x10:
272: s->ar[index] = val & ~0x10;
273: break;
274: case 0x11:
275: s->ar[index] = val;
276: break;
277: case 0x12:
278: s->ar[index] = val & ~0xc0;
279: break;
280: case 0x13:
281: s->ar[index] = val & ~0xf0;
282: break;
283: case 0x14:
284: s->ar[index] = val & ~0xf0;
285: break;
286: default:
287: break;
288: }
289: }
290: s->ar_flip_flop ^= 1;
291: break;
292: case 0x3c2:
293: s->msr = val & ~0x10;
294: break;
295: case 0x3c4:
296: s->sr_index = val & 7;
297: break;
298: case 0x3c5:
299: #ifdef DEBUG_VGA_REG
300: printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
301: #endif
302: s->sr[s->sr_index] = val & sr_mask[s->sr_index];
303: break;
304: case 0x3c7:
305: s->dac_read_index = val;
306: s->dac_sub_index = 0;
307: s->dac_state = 3;
308: break;
309: case 0x3c8:
310: s->dac_write_index = val;
311: s->dac_sub_index = 0;
312: s->dac_state = 0;
313: break;
314: case 0x3c9:
315: s->dac_cache[s->dac_sub_index] = val;
316: if (++s->dac_sub_index == 3) {
317: memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
318: s->dac_sub_index = 0;
319: s->dac_write_index++;
320: }
321: break;
322: case 0x3ce:
323: s->gr_index = val & 0x0f;
324: break;
325: case 0x3cf:
326: #ifdef DEBUG_VGA_REG
327: printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
328: #endif
329: s->gr[s->gr_index] = val & gr_mask[s->gr_index];
330: break;
331: case 0x3b4:
332: case 0x3d4:
333: s->cr_index = val;
334: break;
335: case 0x3b5:
336: case 0x3d5:
337: #ifdef DEBUG_VGA_REG
338: printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
339: #endif
340: /* handle CR0-7 protection */
341: if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
342: /* can always write bit 4 of CR7 */
343: if (s->cr_index == 7)
344: s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
345: return;
346: }
347: switch(s->cr_index) {
348: case 0x01: /* horizontal display end */
349: case 0x07:
350: case 0x09:
351: case 0x0c:
352: case 0x0d:
1.1.1.5 ! root 353: case 0x12: /* vertical display end */
1.1 root 354: s->cr[s->cr_index] = val;
355: break;
356: default:
357: s->cr[s->cr_index] = val;
358: break;
359: }
360: break;
361: case 0x3ba:
362: case 0x3da:
363: s->fcr = val & 0x10;
364: break;
365: }
366: }
367:
368: #ifdef CONFIG_BOCHS_VBE
369: static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
370: {
371: VGAState *s = opaque;
372: uint32_t val;
373: val = s->vbe_index;
374: return val;
375: }
376:
377: static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
378: {
379: VGAState *s = opaque;
380: uint32_t val;
381:
1.1.1.3 root 382: if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
383: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
384: switch(s->vbe_index) {
385: /* XXX: do not hardcode ? */
386: case VBE_DISPI_INDEX_XRES:
387: val = VBE_DISPI_MAX_XRES;
388: break;
389: case VBE_DISPI_INDEX_YRES:
390: val = VBE_DISPI_MAX_YRES;
391: break;
392: case VBE_DISPI_INDEX_BPP:
393: val = VBE_DISPI_MAX_BPP;
394: break;
395: default:
1.1.1.5 ! root 396: val = s->vbe_regs[s->vbe_index];
1.1.1.3 root 397: break;
398: }
399: } else {
1.1.1.5 ! root 400: val = s->vbe_regs[s->vbe_index];
1.1.1.3 root 401: }
402: } else {
1.1 root 403: val = 0;
1.1.1.3 root 404: }
1.1 root 405: #ifdef DEBUG_BOCHS_VBE
406: printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
407: #endif
408: return val;
409: }
410:
411: static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
412: {
413: VGAState *s = opaque;
414: s->vbe_index = val;
415: }
416:
417: static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
418: {
419: VGAState *s = opaque;
420:
421: if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
422: #ifdef DEBUG_BOCHS_VBE
423: printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
424: #endif
425: switch(s->vbe_index) {
426: case VBE_DISPI_INDEX_ID:
427: if (val == VBE_DISPI_ID0 ||
428: val == VBE_DISPI_ID1 ||
1.1.1.4 root 429: val == VBE_DISPI_ID2 ||
430: val == VBE_DISPI_ID3 ||
431: val == VBE_DISPI_ID4) {
1.1 root 432: s->vbe_regs[s->vbe_index] = val;
433: }
434: break;
435: case VBE_DISPI_INDEX_XRES:
436: if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
437: s->vbe_regs[s->vbe_index] = val;
438: }
439: break;
440: case VBE_DISPI_INDEX_YRES:
441: if (val <= VBE_DISPI_MAX_YRES) {
442: s->vbe_regs[s->vbe_index] = val;
443: }
444: break;
445: case VBE_DISPI_INDEX_BPP:
446: if (val == 0)
447: val = 8;
1.1.1.5 ! root 448: if (val == 4 || val == 8 || val == 15 ||
1.1 root 449: val == 16 || val == 24 || val == 32) {
450: s->vbe_regs[s->vbe_index] = val;
451: }
452: break;
453: case VBE_DISPI_INDEX_BANK:
1.1.1.4 root 454: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
455: val &= (s->vbe_bank_mask >> 2);
456: } else {
457: val &= s->vbe_bank_mask;
458: }
1.1 root 459: s->vbe_regs[s->vbe_index] = val;
460: s->bank_offset = (val << 16);
461: break;
462: case VBE_DISPI_INDEX_ENABLE:
1.1.1.3 root 463: if ((val & VBE_DISPI_ENABLED) &&
464: !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
1.1 root 465: int h, shift_control;
466:
1.1.1.5 ! root 467: s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
1.1 root 468: s->vbe_regs[VBE_DISPI_INDEX_XRES];
1.1.1.5 ! root 469: s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
1.1 root 470: s->vbe_regs[VBE_DISPI_INDEX_YRES];
471: s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
472: s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
1.1.1.5 ! root 473:
1.1 root 474: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
475: s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
476: else
1.1.1.5 ! root 477: s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
1.1 root 478: ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
479: s->vbe_start_addr = 0;
1.1.1.3 root 480:
1.1 root 481: /* clear the screen (should be done in BIOS) */
482: if (!(val & VBE_DISPI_NOCLEARMEM)) {
1.1.1.5 ! root 483: memset(s->vram_ptr, 0,
1.1 root 484: s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
485: }
1.1.1.5 ! root 486:
1.1 root 487: /* we initialize the VGA graphic mode (should be done
488: in BIOS) */
489: s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
490: s->cr[0x17] |= 3; /* no CGA modes */
491: s->cr[0x13] = s->vbe_line_offset >> 3;
492: /* width */
493: s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
1.1.1.3 root 494: /* height (only meaningful if < 1024) */
1.1 root 495: h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
496: s->cr[0x12] = h;
1.1.1.5 ! root 497: s->cr[0x07] = (s->cr[0x07] & ~0x42) |
1.1 root 498: ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
499: /* line compare to 1023 */
500: s->cr[0x18] = 0xff;
501: s->cr[0x07] |= 0x10;
502: s->cr[0x09] |= 0x40;
1.1.1.5 ! root 503:
1.1 root 504: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
505: shift_control = 0;
506: s->sr[0x01] &= ~8; /* no double line */
507: } else {
508: shift_control = 2;
509: s->sr[4] |= 0x08; /* set chain 4 mode */
510: s->sr[2] |= 0x0f; /* activate all planes */
511: }
512: s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
513: s->cr[0x09] &= ~0x9f; /* no double scan */
514: } else {
515: /* XXX: the bios should do that */
516: s->bank_offset = 0;
517: }
1.1.1.4 root 518: s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
1.1 root 519: s->vbe_regs[s->vbe_index] = val;
520: break;
521: case VBE_DISPI_INDEX_VIRT_WIDTH:
522: {
523: int w, h, line_offset;
524:
525: if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
526: return;
527: w = val;
528: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
529: line_offset = w >> 1;
530: else
531: line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
532: h = s->vram_size / line_offset;
533: /* XXX: support weird bochs semantics ? */
534: if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
535: return;
536: s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
537: s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
538: s->vbe_line_offset = line_offset;
539: }
540: break;
541: case VBE_DISPI_INDEX_X_OFFSET:
542: case VBE_DISPI_INDEX_Y_OFFSET:
543: {
544: int x;
545: s->vbe_regs[s->vbe_index] = val;
546: s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
547: x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
548: if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
549: s->vbe_start_addr += x >> 1;
550: else
551: s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
552: s->vbe_start_addr >>= 2;
553: }
554: break;
555: default:
556: break;
557: }
558: }
559: }
560: #endif
561:
562: /* called for accesses between 0xa0000 and 0xc0000 */
563: uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
564: {
565: VGAState *s = opaque;
566: int memory_map_mode, plane;
567: uint32_t ret;
1.1.1.5 ! root 568:
1.1 root 569: /* convert to VGA memory offset */
570: memory_map_mode = (s->gr[6] >> 2) & 3;
571: addr &= 0x1ffff;
572: switch(memory_map_mode) {
573: case 0:
574: break;
575: case 1:
576: if (addr >= 0x10000)
577: return 0xff;
578: addr += s->bank_offset;
579: break;
580: case 2:
581: addr -= 0x10000;
582: if (addr >= 0x8000)
583: return 0xff;
584: break;
585: default:
586: case 3:
587: addr -= 0x18000;
588: if (addr >= 0x8000)
589: return 0xff;
590: break;
591: }
1.1.1.5 ! root 592:
1.1 root 593: if (s->sr[4] & 0x08) {
594: /* chain 4 mode : simplest access */
595: ret = s->vram_ptr[addr];
596: } else if (s->gr[5] & 0x10) {
597: /* odd/even mode (aka text mode mapping) */
598: plane = (s->gr[4] & 2) | (addr & 1);
599: ret = s->vram_ptr[((addr & ~1) << 1) | plane];
600: } else {
601: /* standard VGA latched access */
602: s->latch = ((uint32_t *)s->vram_ptr)[addr];
603:
604: if (!(s->gr[5] & 0x08)) {
605: /* read mode 0 */
606: plane = s->gr[4];
607: ret = GET_PLANE(s->latch, plane);
608: } else {
609: /* read mode 1 */
610: ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
611: ret |= ret >> 16;
612: ret |= ret >> 8;
613: ret = (~ret) & 0xff;
614: }
615: }
616: return ret;
617: }
618:
619: static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
620: {
621: uint32_t v;
622: #ifdef TARGET_WORDS_BIGENDIAN
623: v = vga_mem_readb(opaque, addr) << 8;
624: v |= vga_mem_readb(opaque, addr + 1);
625: #else
626: v = vga_mem_readb(opaque, addr);
627: v |= vga_mem_readb(opaque, addr + 1) << 8;
628: #endif
629: return v;
630: }
631:
632: static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
633: {
634: uint32_t v;
635: #ifdef TARGET_WORDS_BIGENDIAN
636: v = vga_mem_readb(opaque, addr) << 24;
637: v |= vga_mem_readb(opaque, addr + 1) << 16;
638: v |= vga_mem_readb(opaque, addr + 2) << 8;
639: v |= vga_mem_readb(opaque, addr + 3);
640: #else
641: v = vga_mem_readb(opaque, addr);
642: v |= vga_mem_readb(opaque, addr + 1) << 8;
643: v |= vga_mem_readb(opaque, addr + 2) << 16;
644: v |= vga_mem_readb(opaque, addr + 3) << 24;
645: #endif
646: return v;
647: }
648:
649: /* called for accesses between 0xa0000 and 0xc0000 */
650: void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
651: {
652: VGAState *s = opaque;
653: int memory_map_mode, plane, write_mode, b, func_select, mask;
654: uint32_t write_mask, bit_mask, set_mask;
655:
656: #ifdef DEBUG_VGA_MEM
657: printf("vga: [0x%x] = 0x%02x\n", addr, val);
658: #endif
659: /* convert to VGA memory offset */
660: memory_map_mode = (s->gr[6] >> 2) & 3;
661: addr &= 0x1ffff;
662: switch(memory_map_mode) {
663: case 0:
664: break;
665: case 1:
666: if (addr >= 0x10000)
667: return;
668: addr += s->bank_offset;
669: break;
670: case 2:
671: addr -= 0x10000;
672: if (addr >= 0x8000)
673: return;
674: break;
675: default:
676: case 3:
677: addr -= 0x18000;
678: if (addr >= 0x8000)
679: return;
680: break;
681: }
1.1.1.5 ! root 682:
1.1 root 683: if (s->sr[4] & 0x08) {
684: /* chain 4 mode : simplest access */
685: plane = addr & 3;
686: mask = (1 << plane);
687: if (s->sr[2] & mask) {
688: s->vram_ptr[addr] = val;
689: #ifdef DEBUG_VGA_MEM
690: printf("vga: chain4: [0x%x]\n", addr);
691: #endif
692: s->plane_updated |= mask; /* only used to detect font change */
693: cpu_physical_memory_set_dirty(s->vram_offset + addr);
694: }
695: } else if (s->gr[5] & 0x10) {
696: /* odd/even mode (aka text mode mapping) */
697: plane = (s->gr[4] & 2) | (addr & 1);
698: mask = (1 << plane);
699: if (s->sr[2] & mask) {
700: addr = ((addr & ~1) << 1) | plane;
701: s->vram_ptr[addr] = val;
702: #ifdef DEBUG_VGA_MEM
703: printf("vga: odd/even: [0x%x]\n", addr);
704: #endif
705: s->plane_updated |= mask; /* only used to detect font change */
706: cpu_physical_memory_set_dirty(s->vram_offset + addr);
707: }
708: } else {
709: /* standard VGA latched access */
710: write_mode = s->gr[5] & 3;
711: switch(write_mode) {
712: default:
713: case 0:
714: /* rotate */
715: b = s->gr[3] & 7;
716: val = ((val >> b) | (val << (8 - b))) & 0xff;
717: val |= val << 8;
718: val |= val << 16;
719:
720: /* apply set/reset mask */
721: set_mask = mask16[s->gr[1]];
722: val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
723: bit_mask = s->gr[8];
724: break;
725: case 1:
726: val = s->latch;
727: goto do_write;
728: case 2:
729: val = mask16[val & 0x0f];
730: bit_mask = s->gr[8];
731: break;
732: case 3:
733: /* rotate */
734: b = s->gr[3] & 7;
735: val = (val >> b) | (val << (8 - b));
736:
737: bit_mask = s->gr[8] & val;
738: val = mask16[s->gr[0]];
739: break;
740: }
741:
742: /* apply logical operation */
743: func_select = s->gr[3] >> 3;
744: switch(func_select) {
745: case 0:
746: default:
747: /* nothing to do */
748: break;
749: case 1:
750: /* and */
751: val &= s->latch;
752: break;
753: case 2:
754: /* or */
755: val |= s->latch;
756: break;
757: case 3:
758: /* xor */
759: val ^= s->latch;
760: break;
761: }
762:
763: /* apply bit mask */
764: bit_mask |= bit_mask << 8;
765: bit_mask |= bit_mask << 16;
766: val = (val & bit_mask) | (s->latch & ~bit_mask);
767:
768: do_write:
769: /* mask data according to sr[2] */
770: mask = s->sr[2];
771: s->plane_updated |= mask; /* only used to detect font change */
772: write_mask = mask16[mask];
1.1.1.5 ! root 773: ((uint32_t *)s->vram_ptr)[addr] =
! 774: (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
1.1 root 775: (val & write_mask);
776: #ifdef DEBUG_VGA_MEM
1.1.1.5 ! root 777: printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
1.1 root 778: addr * 4, write_mask, val);
779: #endif
780: cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
781: }
782: }
783:
784: static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
785: {
786: #ifdef TARGET_WORDS_BIGENDIAN
787: vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
788: vga_mem_writeb(opaque, addr + 1, val & 0xff);
789: #else
790: vga_mem_writeb(opaque, addr, val & 0xff);
791: vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
792: #endif
793: }
794:
795: static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
796: {
797: #ifdef TARGET_WORDS_BIGENDIAN
798: vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
799: vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
800: vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
801: vga_mem_writeb(opaque, addr + 3, val & 0xff);
802: #else
803: vga_mem_writeb(opaque, addr, val & 0xff);
804: vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
805: vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
806: vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
807: #endif
808: }
809:
810: typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
811: const uint8_t *font_ptr, int h,
812: uint32_t fgcol, uint32_t bgcol);
813: typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
1.1.1.5 ! root 814: const uint8_t *font_ptr, int h,
1.1 root 815: uint32_t fgcol, uint32_t bgcol, int dup9);
1.1.1.5 ! root 816: typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
1.1 root 817: const uint8_t *s, int width);
818:
819: #define DEPTH 8
820: #include "vga_template.h"
821:
822: #define DEPTH 15
823: #include "vga_template.h"
824:
1.1.1.5 ! root 825: #define BGR_FORMAT
! 826: #define DEPTH 15
! 827: #include "vga_template.h"
! 828:
! 829: #define DEPTH 16
! 830: #include "vga_template.h"
! 831:
! 832: #define BGR_FORMAT
1.1 root 833: #define DEPTH 16
834: #include "vga_template.h"
835:
836: #define DEPTH 32
837: #include "vga_template.h"
838:
1.1.1.3 root 839: #define BGR_FORMAT
840: #define DEPTH 32
841: #include "vga_template.h"
842:
1.1 root 843: static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
844: {
845: unsigned int col;
846: col = rgb_to_pixel8(r, g, b);
847: col |= col << 8;
848: col |= col << 16;
849: return col;
850: }
851:
852: static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
853: {
854: unsigned int col;
855: col = rgb_to_pixel15(r, g, b);
856: col |= col << 16;
857: return col;
858: }
859:
1.1.1.5 ! root 860: static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
! 861: unsigned int b)
! 862: {
! 863: unsigned int col;
! 864: col = rgb_to_pixel15bgr(r, g, b);
! 865: col |= col << 16;
! 866: return col;
! 867: }
! 868:
1.1 root 869: static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
870: {
871: unsigned int col;
872: col = rgb_to_pixel16(r, g, b);
873: col |= col << 16;
874: return col;
875: }
876:
1.1.1.5 ! root 877: static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
! 878: unsigned int b)
! 879: {
! 880: unsigned int col;
! 881: col = rgb_to_pixel16bgr(r, g, b);
! 882: col |= col << 16;
! 883: return col;
! 884: }
! 885:
1.1 root 886: static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
887: {
888: unsigned int col;
889: col = rgb_to_pixel32(r, g, b);
890: return col;
891: }
892:
1.1.1.3 root 893: static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
894: {
895: unsigned int col;
896: col = rgb_to_pixel32bgr(r, g, b);
897: return col;
898: }
899:
1.1 root 900: /* return true if the palette was modified */
901: static int update_palette16(VGAState *s)
902: {
903: int full_update, i;
904: uint32_t v, col, *palette;
905:
906: full_update = 0;
907: palette = s->last_palette;
908: for(i = 0; i < 16; i++) {
909: v = s->ar[i];
910: if (s->ar[0x10] & 0x80)
911: v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
912: else
913: v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
914: v = v * 3;
1.1.1.5 ! root 915: col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
! 916: c6_to_8(s->palette[v + 1]),
1.1 root 917: c6_to_8(s->palette[v + 2]));
918: if (col != palette[i]) {
919: full_update = 1;
920: palette[i] = col;
921: }
922: }
923: return full_update;
924: }
925:
926: /* return true if the palette was modified */
927: static int update_palette256(VGAState *s)
928: {
929: int full_update, i;
930: uint32_t v, col, *palette;
931:
932: full_update = 0;
933: palette = s->last_palette;
934: v = 0;
935: for(i = 0; i < 256; i++) {
1.1.1.4 root 936: if (s->dac_8bit) {
1.1.1.5 ! root 937: col = s->rgb_to_pixel(s->palette[v],
! 938: s->palette[v + 1],
1.1.1.4 root 939: s->palette[v + 2]);
940: } else {
1.1.1.5 ! root 941: col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
! 942: c6_to_8(s->palette[v + 1]),
1.1.1.4 root 943: c6_to_8(s->palette[v + 2]));
944: }
1.1 root 945: if (col != palette[i]) {
946: full_update = 1;
947: palette[i] = col;
948: }
949: v += 3;
950: }
951: return full_update;
952: }
953:
1.1.1.5 ! root 954: static void vga_get_offsets(VGAState *s,
! 955: uint32_t *pline_offset,
1.1.1.4 root 956: uint32_t *pstart_addr,
957: uint32_t *pline_compare)
1.1 root 958: {
1.1.1.4 root 959: uint32_t start_addr, line_offset, line_compare;
1.1 root 960: #ifdef CONFIG_BOCHS_VBE
961: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
962: line_offset = s->vbe_line_offset;
963: start_addr = s->vbe_start_addr;
1.1.1.4 root 964: line_compare = 65535;
1.1 root 965: } else
966: #endif
1.1.1.5 ! root 967: {
1.1 root 968: /* compute line_offset in bytes */
969: line_offset = s->cr[0x13];
970: line_offset <<= 3;
971:
972: /* starting address */
973: start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1.1.1.4 root 974:
975: /* line compare */
1.1.1.5 ! root 976: line_compare = s->cr[0x18] |
1.1.1.4 root 977: ((s->cr[0x07] & 0x10) << 4) |
978: ((s->cr[0x09] & 0x40) << 3);
1.1 root 979: }
980: *pline_offset = line_offset;
981: *pstart_addr = start_addr;
1.1.1.4 root 982: *pline_compare = line_compare;
1.1 root 983: }
984:
985: /* update start_addr and line_offset. Return TRUE if modified */
986: static int update_basic_params(VGAState *s)
987: {
988: int full_update;
989: uint32_t start_addr, line_offset, line_compare;
1.1.1.5 ! root 990:
1.1 root 991: full_update = 0;
992:
1.1.1.4 root 993: s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1.1 root 994:
995: if (line_offset != s->line_offset ||
996: start_addr != s->start_addr ||
997: line_compare != s->line_compare) {
998: s->line_offset = line_offset;
999: s->start_addr = start_addr;
1000: s->line_compare = line_compare;
1001: full_update = 1;
1002: }
1003: return full_update;
1004: }
1005:
1.1.1.5 ! root 1006: #define NB_DEPTHS 7
1.1.1.3 root 1007:
1008: static inline int get_depth_index(DisplayState *s)
1.1 root 1009: {
1.1.1.3 root 1010: switch(s->depth) {
1.1 root 1011: default:
1012: case 8:
1013: return 0;
1014: case 15:
1.1.1.5 ! root 1015: if (s->bgr)
! 1016: return 5;
! 1017: else
! 1018: return 1;
1.1 root 1019: case 16:
1.1.1.5 ! root 1020: if (s->bgr)
! 1021: return 6;
! 1022: else
! 1023: return 2;
1.1 root 1024: case 32:
1.1.1.3 root 1025: if (s->bgr)
1026: return 4;
1027: else
1028: return 3;
1.1 root 1029: }
1030: }
1031:
1.1.1.3 root 1032: static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1.1 root 1033: vga_draw_glyph8_8,
1034: vga_draw_glyph8_16,
1035: vga_draw_glyph8_16,
1036: vga_draw_glyph8_32,
1.1.1.3 root 1037: vga_draw_glyph8_32,
1.1.1.5 ! root 1038: vga_draw_glyph8_16,
! 1039: vga_draw_glyph8_16,
1.1 root 1040: };
1041:
1.1.1.3 root 1042: static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1.1 root 1043: vga_draw_glyph16_8,
1044: vga_draw_glyph16_16,
1045: vga_draw_glyph16_16,
1046: vga_draw_glyph16_32,
1.1.1.3 root 1047: vga_draw_glyph16_32,
1.1.1.5 ! root 1048: vga_draw_glyph16_16,
! 1049: vga_draw_glyph16_16,
1.1 root 1050: };
1051:
1.1.1.3 root 1052: static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1.1 root 1053: vga_draw_glyph9_8,
1054: vga_draw_glyph9_16,
1055: vga_draw_glyph9_16,
1056: vga_draw_glyph9_32,
1.1.1.3 root 1057: vga_draw_glyph9_32,
1.1.1.5 ! root 1058: vga_draw_glyph9_16,
! 1059: vga_draw_glyph9_16,
1.1 root 1060: };
1.1.1.5 ! root 1061:
1.1 root 1062: static const uint8_t cursor_glyph[32 * 4] = {
1063: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1064: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1065: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1066: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1067: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1068: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1070: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1071: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1072: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1073: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1075: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1076: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1077: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1078: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1.1.1.5 ! root 1079: };
1.1 root 1080:
1.1.1.5 ! root 1081: /*
! 1082: * Text mode update
1.1 root 1083: * Missing:
1084: * - double scan
1.1.1.5 ! root 1085: * - double width
1.1 root 1086: * - underline
1087: * - flashing
1088: */
1089: static void vga_draw_text(VGAState *s, int full_update)
1090: {
1091: int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1092: int cx_min, cx_max, linesize, x_incr;
1093: uint32_t offset, fgcol, bgcol, v, cursor_offset;
1094: uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1095: const uint8_t *font_ptr, *font_base[2];
1096: int dup9, line_offset, depth_index;
1097: uint32_t *palette;
1098: uint32_t *ch_attr_ptr;
1099: vga_draw_glyph8_func *vga_draw_glyph8;
1100: vga_draw_glyph9_func *vga_draw_glyph9;
1101:
1102: full_update |= update_palette16(s);
1103: palette = s->last_palette;
1.1.1.5 ! root 1104:
1.1 root 1105: /* compute font data address (in plane 2) */
1106: v = s->sr[3];
1107: offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1108: if (offset != s->font_offsets[0]) {
1109: s->font_offsets[0] = offset;
1110: full_update = 1;
1111: }
1112: font_base[0] = s->vram_ptr + offset;
1113:
1114: offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1115: font_base[1] = s->vram_ptr + offset;
1116: if (offset != s->font_offsets[1]) {
1117: s->font_offsets[1] = offset;
1118: full_update = 1;
1119: }
1120: if (s->plane_updated & (1 << 2)) {
1121: /* if the plane 2 was modified since the last display, it
1122: indicates the font may have been modified */
1123: s->plane_updated = 0;
1124: full_update = 1;
1125: }
1126: full_update |= update_basic_params(s);
1127:
1128: line_offset = s->line_offset;
1129: s1 = s->vram_ptr + (s->start_addr * 4);
1130:
1131: /* total width & height */
1132: cheight = (s->cr[9] & 0x1f) + 1;
1133: cw = 8;
1134: if (!(s->sr[1] & 0x01))
1135: cw = 9;
1136: if (s->sr[1] & 0x08)
1137: cw = 16; /* NOTE: no 18 pixel wide */
1138: x_incr = cw * ((s->ds->depth + 7) >> 3);
1139: width = (s->cr[0x01] + 1);
1140: if (s->cr[0x06] == 100) {
1141: /* ugly hack for CGA 160x100x16 - explain me the logic */
1142: height = 100;
1143: } else {
1.1.1.5 ! root 1144: height = s->cr[0x12] |
! 1145: ((s->cr[0x07] & 0x02) << 7) |
1.1 root 1146: ((s->cr[0x07] & 0x40) << 3);
1147: height = (height + 1) / cheight;
1148: }
1149: if ((height * width) > CH_ATTR_SIZE) {
1150: /* better than nothing: exit if transient size is too big */
1151: return;
1152: }
1153:
1154: if (width != s->last_width || height != s->last_height ||
1155: cw != s->last_cw || cheight != s->last_ch) {
1156: s->last_scr_width = width * cw;
1157: s->last_scr_height = height * cheight;
1158: dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1159: s->last_width = width;
1160: s->last_height = height;
1161: s->last_ch = cheight;
1162: s->last_cw = cw;
1163: full_update = 1;
1164: }
1165: cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1166: if (cursor_offset != s->cursor_offset ||
1167: s->cr[0xa] != s->cursor_start ||
1168: s->cr[0xb] != s->cursor_end) {
1169: /* if the cursor position changed, we update the old and new
1170: chars */
1171: if (s->cursor_offset < CH_ATTR_SIZE)
1172: s->last_ch_attr[s->cursor_offset] = -1;
1173: if (cursor_offset < CH_ATTR_SIZE)
1174: s->last_ch_attr[cursor_offset] = -1;
1175: s->cursor_offset = cursor_offset;
1176: s->cursor_start = s->cr[0xa];
1177: s->cursor_end = s->cr[0xb];
1178: }
1179: cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1.1.1.5 ! root 1180:
1.1.1.3 root 1181: depth_index = get_depth_index(s->ds);
1.1 root 1182: if (cw == 16)
1183: vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1184: else
1185: vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1186: vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1.1.1.5 ! root 1187:
1.1 root 1188: dest = s->ds->data;
1189: linesize = s->ds->linesize;
1190: ch_attr_ptr = s->last_ch_attr;
1191: for(cy = 0; cy < height; cy++) {
1192: d1 = dest;
1193: src = s1;
1194: cx_min = width;
1195: cx_max = -1;
1196: for(cx = 0; cx < width; cx++) {
1197: ch_attr = *(uint16_t *)src;
1198: if (full_update || ch_attr != *ch_attr_ptr) {
1199: if (cx < cx_min)
1200: cx_min = cx;
1201: if (cx > cx_max)
1202: cx_max = cx;
1203: *ch_attr_ptr = ch_attr;
1204: #ifdef WORDS_BIGENDIAN
1205: ch = ch_attr >> 8;
1206: cattr = ch_attr & 0xff;
1207: #else
1208: ch = ch_attr & 0xff;
1209: cattr = ch_attr >> 8;
1210: #endif
1211: font_ptr = font_base[(cattr >> 3) & 1];
1212: font_ptr += 32 * 4 * ch;
1213: bgcol = palette[cattr >> 4];
1214: fgcol = palette[cattr & 0x0f];
1215: if (cw != 9) {
1.1.1.5 ! root 1216: vga_draw_glyph8(d1, linesize,
1.1 root 1217: font_ptr, cheight, fgcol, bgcol);
1218: } else {
1219: dup9 = 0;
1220: if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1221: dup9 = 1;
1.1.1.5 ! root 1222: vga_draw_glyph9(d1, linesize,
1.1 root 1223: font_ptr, cheight, fgcol, bgcol, dup9);
1224: }
1225: if (src == cursor_ptr &&
1226: !(s->cr[0x0a] & 0x20)) {
1227: int line_start, line_last, h;
1228: /* draw the cursor */
1229: line_start = s->cr[0x0a] & 0x1f;
1230: line_last = s->cr[0x0b] & 0x1f;
1231: /* XXX: check that */
1232: if (line_last > cheight - 1)
1233: line_last = cheight - 1;
1234: if (line_last >= line_start && line_start < cheight) {
1235: h = line_last - line_start + 1;
1236: d = d1 + linesize * line_start;
1237: if (cw != 9) {
1.1.1.5 ! root 1238: vga_draw_glyph8(d, linesize,
1.1 root 1239: cursor_glyph, h, fgcol, bgcol);
1240: } else {
1.1.1.5 ! root 1241: vga_draw_glyph9(d, linesize,
1.1 root 1242: cursor_glyph, h, fgcol, bgcol, 1);
1243: }
1244: }
1245: }
1246: }
1247: d1 += x_incr;
1248: src += 4;
1249: ch_attr_ptr++;
1250: }
1251: if (cx_max != -1) {
1.1.1.5 ! root 1252: dpy_update(s->ds, cx_min * cw, cy * cheight,
1.1 root 1253: (cx_max - cx_min + 1) * cw, cheight);
1254: }
1255: dest += linesize * cheight;
1256: s1 += line_offset;
1257: }
1258: }
1259:
1260: enum {
1261: VGA_DRAW_LINE2,
1262: VGA_DRAW_LINE2D2,
1263: VGA_DRAW_LINE4,
1264: VGA_DRAW_LINE4D2,
1265: VGA_DRAW_LINE8D2,
1266: VGA_DRAW_LINE8,
1267: VGA_DRAW_LINE15,
1268: VGA_DRAW_LINE16,
1269: VGA_DRAW_LINE24,
1270: VGA_DRAW_LINE32,
1271: VGA_DRAW_LINE_NB,
1272: };
1273:
1.1.1.3 root 1274: static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1.1 root 1275: vga_draw_line2_8,
1276: vga_draw_line2_16,
1277: vga_draw_line2_16,
1278: vga_draw_line2_32,
1.1.1.3 root 1279: vga_draw_line2_32,
1.1.1.5 ! root 1280: vga_draw_line2_16,
! 1281: vga_draw_line2_16,
1.1 root 1282:
1283: vga_draw_line2d2_8,
1284: vga_draw_line2d2_16,
1285: vga_draw_line2d2_16,
1286: vga_draw_line2d2_32,
1.1.1.3 root 1287: vga_draw_line2d2_32,
1.1.1.5 ! root 1288: vga_draw_line2d2_16,
! 1289: vga_draw_line2d2_16,
1.1 root 1290:
1291: vga_draw_line4_8,
1292: vga_draw_line4_16,
1293: vga_draw_line4_16,
1294: vga_draw_line4_32,
1.1.1.3 root 1295: vga_draw_line4_32,
1.1.1.5 ! root 1296: vga_draw_line4_16,
! 1297: vga_draw_line4_16,
1.1 root 1298:
1299: vga_draw_line4d2_8,
1300: vga_draw_line4d2_16,
1301: vga_draw_line4d2_16,
1302: vga_draw_line4d2_32,
1.1.1.3 root 1303: vga_draw_line4d2_32,
1.1.1.5 ! root 1304: vga_draw_line4d2_16,
! 1305: vga_draw_line4d2_16,
1.1 root 1306:
1307: vga_draw_line8d2_8,
1308: vga_draw_line8d2_16,
1309: vga_draw_line8d2_16,
1310: vga_draw_line8d2_32,
1.1.1.3 root 1311: vga_draw_line8d2_32,
1.1.1.5 ! root 1312: vga_draw_line8d2_16,
! 1313: vga_draw_line8d2_16,
1.1 root 1314:
1315: vga_draw_line8_8,
1316: vga_draw_line8_16,
1317: vga_draw_line8_16,
1318: vga_draw_line8_32,
1.1.1.3 root 1319: vga_draw_line8_32,
1.1.1.5 ! root 1320: vga_draw_line8_16,
! 1321: vga_draw_line8_16,
1.1 root 1322:
1323: vga_draw_line15_8,
1324: vga_draw_line15_15,
1325: vga_draw_line15_16,
1326: vga_draw_line15_32,
1.1.1.3 root 1327: vga_draw_line15_32bgr,
1.1.1.5 ! root 1328: vga_draw_line15_15bgr,
! 1329: vga_draw_line15_16bgr,
1.1 root 1330:
1331: vga_draw_line16_8,
1332: vga_draw_line16_15,
1333: vga_draw_line16_16,
1334: vga_draw_line16_32,
1.1.1.3 root 1335: vga_draw_line16_32bgr,
1.1.1.5 ! root 1336: vga_draw_line16_15bgr,
! 1337: vga_draw_line16_16bgr,
1.1 root 1338:
1339: vga_draw_line24_8,
1340: vga_draw_line24_15,
1341: vga_draw_line24_16,
1342: vga_draw_line24_32,
1.1.1.3 root 1343: vga_draw_line24_32bgr,
1.1.1.5 ! root 1344: vga_draw_line24_15bgr,
! 1345: vga_draw_line24_16bgr,
1.1 root 1346:
1347: vga_draw_line32_8,
1348: vga_draw_line32_15,
1349: vga_draw_line32_16,
1350: vga_draw_line32_32,
1.1.1.3 root 1351: vga_draw_line32_32bgr,
1.1.1.5 ! root 1352: vga_draw_line32_15bgr,
! 1353: vga_draw_line32_16bgr,
1.1.1.3 root 1354: };
1355:
1356: typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1357:
1358: static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1359: rgb_to_pixel8_dup,
1360: rgb_to_pixel15_dup,
1361: rgb_to_pixel16_dup,
1362: rgb_to_pixel32_dup,
1363: rgb_to_pixel32bgr_dup,
1.1.1.5 ! root 1364: rgb_to_pixel15bgr_dup,
! 1365: rgb_to_pixel16bgr_dup,
1.1 root 1366: };
1367:
1368: static int vga_get_bpp(VGAState *s)
1369: {
1370: int ret;
1371: #ifdef CONFIG_BOCHS_VBE
1372: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1373: ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1.1.1.5 ! root 1374: } else
1.1 root 1375: #endif
1376: {
1377: ret = 0;
1378: }
1379: return ret;
1380: }
1381:
1382: static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1383: {
1384: int width, height;
1.1.1.5 ! root 1385:
1.1.1.3 root 1386: #ifdef CONFIG_BOCHS_VBE
1387: if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1388: width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1389: height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1.1.1.5 ! root 1390: } else
1.1.1.3 root 1391: #endif
1392: {
1393: width = (s->cr[0x01] + 1) * 8;
1.1.1.5 ! root 1394: height = s->cr[0x12] |
! 1395: ((s->cr[0x07] & 0x02) << 7) |
1.1.1.3 root 1396: ((s->cr[0x07] & 0x40) << 3);
1397: height = (height + 1);
1398: }
1.1 root 1399: *pwidth = width;
1400: *pheight = height;
1401: }
1402:
1403: void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1404: {
1405: int y;
1406: if (y1 >= VGA_MAX_HEIGHT)
1407: return;
1408: if (y2 >= VGA_MAX_HEIGHT)
1409: y2 = VGA_MAX_HEIGHT;
1410: for(y = y1; y < y2; y++) {
1411: s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1412: }
1413: }
1414:
1.1.1.5 ! root 1415: /*
1.1 root 1416: * graphic modes
1417: */
1418: static void vga_draw_graphic(VGAState *s, int full_update)
1419: {
1420: int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1421: int width, height, shift_control, line_offset, page0, page1, bwidth;
1422: int disp_width, multi_scan, multi_run;
1423: uint8_t *d;
1424: uint32_t v, addr1, addr;
1425: vga_draw_line_func *vga_draw_line;
1.1.1.5 ! root 1426:
1.1 root 1427: full_update |= update_basic_params(s);
1428:
1429: s->get_resolution(s, &width, &height);
1430: disp_width = width;
1431:
1432: shift_control = (s->gr[0x05] >> 5) & 3;
1433: double_scan = (s->cr[0x09] >> 7);
1434: if (shift_control != 1) {
1435: multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1436: } else {
1437: /* in CGA modes, multi_scan is ignored */
1438: /* XXX: is it correct ? */
1439: multi_scan = double_scan;
1440: }
1441: multi_run = multi_scan;
1442: if (shift_control != s->shift_control ||
1443: double_scan != s->double_scan) {
1444: full_update = 1;
1445: s->shift_control = shift_control;
1446: s->double_scan = double_scan;
1447: }
1.1.1.5 ! root 1448:
1.1 root 1449: if (shift_control == 0) {
1450: full_update |= update_palette16(s);
1451: if (s->sr[0x01] & 8) {
1452: v = VGA_DRAW_LINE4D2;
1453: disp_width <<= 1;
1454: } else {
1455: v = VGA_DRAW_LINE4;
1456: }
1457: } else if (shift_control == 1) {
1458: full_update |= update_palette16(s);
1459: if (s->sr[0x01] & 8) {
1460: v = VGA_DRAW_LINE2D2;
1461: disp_width <<= 1;
1462: } else {
1463: v = VGA_DRAW_LINE2;
1464: }
1465: } else {
1466: switch(s->get_bpp(s)) {
1467: default:
1468: case 0:
1469: full_update |= update_palette256(s);
1470: v = VGA_DRAW_LINE8D2;
1471: break;
1472: case 8:
1473: full_update |= update_palette256(s);
1474: v = VGA_DRAW_LINE8;
1475: break;
1476: case 15:
1477: v = VGA_DRAW_LINE15;
1478: break;
1479: case 16:
1480: v = VGA_DRAW_LINE16;
1481: break;
1482: case 24:
1483: v = VGA_DRAW_LINE24;
1484: break;
1485: case 32:
1486: v = VGA_DRAW_LINE32;
1487: break;
1488: }
1489: }
1.1.1.3 root 1490: vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1.1 root 1491:
1492: if (disp_width != s->last_width ||
1493: height != s->last_height) {
1494: dpy_resize(s->ds, disp_width, height);
1495: s->last_scr_width = disp_width;
1496: s->last_scr_height = height;
1497: s->last_width = disp_width;
1498: s->last_height = height;
1499: full_update = 1;
1500: }
1501: if (s->cursor_invalidate)
1502: s->cursor_invalidate(s);
1.1.1.5 ! root 1503:
1.1 root 1504: line_offset = s->line_offset;
1505: #if 0
1506: 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",
1507: width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1508: #endif
1509: addr1 = (s->start_addr * 4);
1510: bwidth = width * 4;
1511: y_start = -1;
1512: page_min = 0x7fffffff;
1513: page_max = -1;
1514: d = s->ds->data;
1515: linesize = s->ds->linesize;
1516: y1 = 0;
1517: for(y = 0; y < height; y++) {
1518: addr = addr1;
1519: if (!(s->cr[0x17] & 1)) {
1520: int shift;
1521: /* CGA compatibility handling */
1522: shift = 14 + ((s->cr[0x17] >> 6) & 1);
1523: addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1524: }
1525: if (!(s->cr[0x17] & 2)) {
1526: addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1527: }
1528: page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1529: page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1.1.1.5 ! root 1530: update = full_update |
1.1 root 1531: cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1532: cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1533: if ((page1 - page0) > TARGET_PAGE_SIZE) {
1534: /* if wide line, can use another page */
1.1.1.5 ! root 1535: update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1.1 root 1536: VGA_DIRTY_FLAG);
1537: }
1538: /* explicit invalidation for the hardware cursor */
1539: update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1540: if (update) {
1541: if (y_start < 0)
1542: y_start = y;
1543: if (page0 < page_min)
1544: page_min = page0;
1545: if (page1 > page_max)
1546: page_max = page1;
1547: vga_draw_line(s, d, s->vram_ptr + addr, width);
1548: if (s->cursor_draw_line)
1549: s->cursor_draw_line(s, d, y);
1550: } else {
1551: if (y_start >= 0) {
1552: /* flush to display */
1.1.1.5 ! root 1553: dpy_update(s->ds, 0, y_start,
1.1 root 1554: disp_width, y - y_start);
1555: y_start = -1;
1556: }
1557: }
1558: if (!multi_run) {
1559: mask = (s->cr[0x17] & 3) ^ 3;
1560: if ((y1 & mask) == mask)
1561: addr1 += line_offset;
1562: y1++;
1563: multi_run = multi_scan;
1564: } else {
1565: multi_run--;
1566: }
1567: /* line compare acts on the displayed lines */
1568: if (y == s->line_compare)
1569: addr1 = 0;
1570: d += linesize;
1571: }
1572: if (y_start >= 0) {
1573: /* flush to display */
1.1.1.5 ! root 1574: dpy_update(s->ds, 0, y_start,
1.1 root 1575: disp_width, y - y_start);
1576: }
1577: /* reset modified pages */
1578: if (page_max != -1) {
1579: cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1580: VGA_DIRTY_FLAG);
1581: }
1582: memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1583: }
1584:
1585: static void vga_draw_blank(VGAState *s, int full_update)
1586: {
1587: int i, w, val;
1588: uint8_t *d;
1589:
1590: if (!full_update)
1591: return;
1592: if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1593: return;
1.1.1.5 ! root 1594: if (s->ds->depth == 8)
1.1 root 1595: val = s->rgb_to_pixel(0, 0, 0);
1596: else
1597: val = 0;
1598: w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1599: d = s->ds->data;
1600: for(i = 0; i < s->last_scr_height; i++) {
1601: memset(d, val, w);
1602: d += s->ds->linesize;
1603: }
1.1.1.5 ! root 1604: dpy_update(s->ds, 0, 0,
1.1 root 1605: s->last_scr_width, s->last_scr_height);
1606: }
1607:
1608: #define GMODE_TEXT 0
1609: #define GMODE_GRAPH 1
1.1.1.5 ! root 1610: #define GMODE_BLANK 2
1.1 root 1611:
1.1.1.2 root 1612: static void vga_update_display(void *opaque)
1.1 root 1613: {
1.1.1.2 root 1614: VGAState *s = (VGAState *)opaque;
1.1 root 1615: int full_update, graphic_mode;
1616:
1617: if (s->ds->depth == 0) {
1618: /* nothing to do */
1619: } else {
1.1.1.5 ! root 1620: s->rgb_to_pixel =
1.1.1.3 root 1621: rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1.1.1.5 ! root 1622:
1.1 root 1623: full_update = 0;
1624: if (!(s->ar_index & 0x20)) {
1625: graphic_mode = GMODE_BLANK;
1626: } else {
1627: graphic_mode = s->gr[6] & 1;
1628: }
1629: if (graphic_mode != s->graphic_mode) {
1630: s->graphic_mode = graphic_mode;
1631: full_update = 1;
1632: }
1633: switch(graphic_mode) {
1634: case GMODE_TEXT:
1635: vga_draw_text(s, full_update);
1636: break;
1637: case GMODE_GRAPH:
1638: vga_draw_graphic(s, full_update);
1639: break;
1640: case GMODE_BLANK:
1641: default:
1642: vga_draw_blank(s, full_update);
1643: break;
1644: }
1645: }
1646: }
1647:
1648: /* force a full display refresh */
1.1.1.2 root 1649: static void vga_invalidate_display(void *opaque)
1.1 root 1650: {
1.1.1.2 root 1651: VGAState *s = (VGAState *)opaque;
1.1.1.5 ! root 1652:
1.1 root 1653: s->last_width = -1;
1654: s->last_height = -1;
1655: }
1656:
1657: static void vga_reset(VGAState *s)
1658: {
1659: memset(s, 0, sizeof(VGAState));
1660: s->graphic_mode = -1; /* force full update */
1661: }
1662:
1663: static CPUReadMemoryFunc *vga_mem_read[3] = {
1664: vga_mem_readb,
1665: vga_mem_readw,
1666: vga_mem_readl,
1667: };
1668:
1669: static CPUWriteMemoryFunc *vga_mem_write[3] = {
1670: vga_mem_writeb,
1671: vga_mem_writew,
1672: vga_mem_writel,
1673: };
1674:
1675: static void vga_save(QEMUFile *f, void *opaque)
1676: {
1677: VGAState *s = opaque;
1678: int i;
1679:
1.1.1.4 root 1680: if (s->pci_dev)
1681: pci_device_save(s->pci_dev, f);
1682:
1.1 root 1683: qemu_put_be32s(f, &s->latch);
1684: qemu_put_8s(f, &s->sr_index);
1685: qemu_put_buffer(f, s->sr, 8);
1686: qemu_put_8s(f, &s->gr_index);
1687: qemu_put_buffer(f, s->gr, 16);
1688: qemu_put_8s(f, &s->ar_index);
1689: qemu_put_buffer(f, s->ar, 21);
1.1.1.5 ! root 1690: qemu_put_be32(f, s->ar_flip_flop);
1.1 root 1691: qemu_put_8s(f, &s->cr_index);
1692: qemu_put_buffer(f, s->cr, 256);
1693: qemu_put_8s(f, &s->msr);
1694: qemu_put_8s(f, &s->fcr);
1.1.1.5 ! root 1695: qemu_put_byte(f, s->st00);
1.1 root 1696: qemu_put_8s(f, &s->st01);
1697:
1698: qemu_put_8s(f, &s->dac_state);
1699: qemu_put_8s(f, &s->dac_sub_index);
1700: qemu_put_8s(f, &s->dac_read_index);
1701: qemu_put_8s(f, &s->dac_write_index);
1702: qemu_put_buffer(f, s->dac_cache, 3);
1703: qemu_put_buffer(f, s->palette, 768);
1704:
1.1.1.5 ! root 1705: qemu_put_be32(f, s->bank_offset);
1.1 root 1706: #ifdef CONFIG_BOCHS_VBE
1707: qemu_put_byte(f, 1);
1708: qemu_put_be16s(f, &s->vbe_index);
1709: for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1710: qemu_put_be16s(f, &s->vbe_regs[i]);
1711: qemu_put_be32s(f, &s->vbe_start_addr);
1712: qemu_put_be32s(f, &s->vbe_line_offset);
1713: qemu_put_be32s(f, &s->vbe_bank_mask);
1714: #else
1715: qemu_put_byte(f, 0);
1716: #endif
1717: }
1718:
1719: static int vga_load(QEMUFile *f, void *opaque, int version_id)
1720: {
1721: VGAState *s = opaque;
1.1.1.4 root 1722: int is_vbe, i, ret;
1.1 root 1723:
1.1.1.4 root 1724: if (version_id > 2)
1.1 root 1725: return -EINVAL;
1726:
1.1.1.4 root 1727: if (s->pci_dev && version_id >= 2) {
1728: ret = pci_device_load(s->pci_dev, f);
1729: if (ret < 0)
1730: return ret;
1731: }
1732:
1.1 root 1733: qemu_get_be32s(f, &s->latch);
1734: qemu_get_8s(f, &s->sr_index);
1735: qemu_get_buffer(f, s->sr, 8);
1736: qemu_get_8s(f, &s->gr_index);
1737: qemu_get_buffer(f, s->gr, 16);
1738: qemu_get_8s(f, &s->ar_index);
1739: qemu_get_buffer(f, s->ar, 21);
1.1.1.5 ! root 1740: s->ar_flip_flop=qemu_get_be32(f);
1.1 root 1741: qemu_get_8s(f, &s->cr_index);
1742: qemu_get_buffer(f, s->cr, 256);
1743: qemu_get_8s(f, &s->msr);
1744: qemu_get_8s(f, &s->fcr);
1745: qemu_get_8s(f, &s->st00);
1746: qemu_get_8s(f, &s->st01);
1747:
1748: qemu_get_8s(f, &s->dac_state);
1749: qemu_get_8s(f, &s->dac_sub_index);
1750: qemu_get_8s(f, &s->dac_read_index);
1751: qemu_get_8s(f, &s->dac_write_index);
1752: qemu_get_buffer(f, s->dac_cache, 3);
1753: qemu_get_buffer(f, s->palette, 768);
1754:
1.1.1.5 ! root 1755: s->bank_offset=qemu_get_be32(f);
1.1 root 1756: is_vbe = qemu_get_byte(f);
1757: #ifdef CONFIG_BOCHS_VBE
1758: if (!is_vbe)
1759: return -EINVAL;
1760: qemu_get_be16s(f, &s->vbe_index);
1761: for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1762: qemu_get_be16s(f, &s->vbe_regs[i]);
1763: qemu_get_be32s(f, &s->vbe_start_addr);
1764: qemu_get_be32s(f, &s->vbe_line_offset);
1765: qemu_get_be32s(f, &s->vbe_bank_mask);
1766: #else
1767: if (is_vbe)
1768: return -EINVAL;
1769: #endif
1770:
1771: /* force refresh */
1772: s->graphic_mode = -1;
1773: return 0;
1774: }
1775:
1.1.1.4 root 1776: typedef struct PCIVGAState {
1777: PCIDevice dev;
1778: VGAState vga_state;
1779: } PCIVGAState;
1780:
1.1.1.5 ! root 1781: static void vga_map(PCIDevice *pci_dev, int region_num,
1.1 root 1782: uint32_t addr, uint32_t size, int type)
1783: {
1.1.1.4 root 1784: PCIVGAState *d = (PCIVGAState *)pci_dev;
1785: VGAState *s = &d->vga_state;
1.1 root 1786: if (region_num == PCI_ROM_SLOT) {
1787: cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1788: } else {
1789: cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1790: }
1791: }
1792:
1.1.1.5 ! root 1793: void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1.1 root 1794: unsigned long vga_ram_offset, int vga_ram_size)
1795: {
1796: int i, j, v, b;
1797:
1798: for(i = 0;i < 256; i++) {
1799: v = 0;
1800: for(j = 0; j < 8; j++) {
1801: v |= ((i >> j) & 1) << (j * 4);
1802: }
1803: expand4[i] = v;
1804:
1805: v = 0;
1806: for(j = 0; j < 4; j++) {
1807: v |= ((i >> (2 * j)) & 3) << (j * 4);
1808: }
1809: expand2[i] = v;
1810: }
1811: for(i = 0; i < 16; i++) {
1812: v = 0;
1813: for(j = 0; j < 4; j++) {
1814: b = ((i >> j) & 1);
1815: v |= b << (2 * j);
1816: v |= b << (2 * j + 1);
1817: }
1818: expand4to8[i] = v;
1819: }
1820:
1821: vga_reset(s);
1822:
1823: s->vram_ptr = vga_ram_base;
1824: s->vram_offset = vga_ram_offset;
1825: s->vram_size = vga_ram_size;
1826: s->ds = ds;
1827: s->get_bpp = vga_get_bpp;
1828: s->get_offsets = vga_get_offsets;
1829: s->get_resolution = vga_get_resolution;
1.1.1.5 ! root 1830: s->update = vga_update_display;
! 1831: s->invalidate = vga_invalidate_display;
! 1832: s->screen_dump = vga_screen_dump;
1.1 root 1833: }
1834:
1.1.1.4 root 1835: /* used by both ISA and PCI */
1.1.1.5 ! root 1836: void vga_init(VGAState *s)
1.1 root 1837: {
1.1.1.4 root 1838: int vga_io_memory;
1.1 root 1839:
1.1.1.4 root 1840: register_savevm("vga", 0, 2, vga_save, vga_load, s);
1.1 root 1841:
1842: register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1843:
1844: register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1845: register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1846: register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1847: register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1848:
1849: register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1850:
1851: register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1852: register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1853: register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1854: register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1855: s->bank_offset = 0;
1856:
1857: #ifdef CONFIG_BOCHS_VBE
1858: s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1859: s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1860: #if defined (TARGET_I386)
1861: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1862: register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1863:
1864: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1865: register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1866:
1867: /* old Bochs IO ports */
1868: register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1869: register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1870:
1871: register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1.1.1.5 ! root 1872: register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1.1 root 1873: #else
1874: register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1875: register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1876:
1877: register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1878: register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1879: #endif
1880: #endif /* CONFIG_BOCHS_VBE */
1881:
1882: vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1.1.1.5 ! root 1883: cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1.1 root 1884: vga_io_memory);
1.1.1.4 root 1885: }
1.1 root 1886:
1.1.1.5 ! root 1887: /* Memory mapped interface */
! 1888: static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
! 1889: {
! 1890: VGAState *s = opaque;
! 1891:
! 1892: return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
! 1893: }
! 1894:
! 1895: static void vga_mm_writeb (void *opaque,
! 1896: target_phys_addr_t addr, uint32_t value)
! 1897: {
! 1898: VGAState *s = opaque;
! 1899:
! 1900: vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
! 1901: }
! 1902:
! 1903: static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
! 1904: {
! 1905: VGAState *s = opaque;
! 1906:
! 1907: return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
! 1908: }
! 1909:
! 1910: static void vga_mm_writew (void *opaque,
! 1911: target_phys_addr_t addr, uint32_t value)
! 1912: {
! 1913: VGAState *s = opaque;
! 1914:
! 1915: vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
! 1916: }
! 1917:
! 1918: static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
! 1919: {
! 1920: VGAState *s = opaque;
! 1921:
! 1922: return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
! 1923: }
! 1924:
! 1925: static void vga_mm_writel (void *opaque,
! 1926: target_phys_addr_t addr, uint32_t value)
! 1927: {
! 1928: VGAState *s = opaque;
! 1929:
! 1930: vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
! 1931: }
! 1932:
! 1933: static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
! 1934: &vga_mm_readb,
! 1935: &vga_mm_readw,
! 1936: &vga_mm_readl,
! 1937: };
! 1938:
! 1939: static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
! 1940: &vga_mm_writeb,
! 1941: &vga_mm_writew,
! 1942: &vga_mm_writel,
! 1943: };
! 1944:
! 1945: static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
! 1946: target_phys_addr_t ctrl_base, int it_shift)
! 1947: {
! 1948: int s_ioport_ctrl, vga_io_memory;
! 1949:
! 1950: s->base_ctrl = ctrl_base;
! 1951: s->it_shift = it_shift;
! 1952: s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
! 1953: vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
! 1954:
! 1955: register_savevm("vga", 0, 2, vga_save, vga_load, s);
! 1956:
! 1957: cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
! 1958: s->bank_offset = 0;
! 1959: cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
! 1960: }
! 1961:
! 1962: int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1.1.1.4 root 1963: unsigned long vga_ram_offset, int vga_ram_size)
1964: {
1965: VGAState *s;
1966:
1967: s = qemu_mallocz(sizeof(VGAState));
1968: if (!s)
1969: return -1;
1970:
1971: vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1972: vga_init(s);
1.1 root 1973:
1.1.1.5 ! root 1974: graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
! 1975:
1.1 root 1976: #ifdef CONFIG_BOCHS_VBE
1.1.1.4 root 1977: /* XXX: use optimized standard vga accesses */
1.1.1.5 ! root 1978: cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1.1.1.4 root 1979: vga_ram_size, vga_ram_offset);
1.1 root 1980: #endif
1.1.1.4 root 1981: return 0;
1982: }
1983:
1.1.1.5 ! root 1984: int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
! 1985: unsigned long vga_ram_offset, int vga_ram_size,
! 1986: target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
! 1987: int it_shift)
! 1988: {
! 1989: VGAState *s;
! 1990:
! 1991: s = qemu_mallocz(sizeof(VGAState));
! 1992: if (!s)
! 1993: return -1;
! 1994:
! 1995: vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
! 1996: vga_mm_init(s, vram_base, ctrl_base, it_shift);
! 1997:
! 1998: graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
! 1999:
! 2000: #ifdef CONFIG_BOCHS_VBE
! 2001: /* XXX: use optimized standard vga accesses */
! 2002: cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
! 2003: vga_ram_size, vga_ram_offset);
! 2004: #endif
! 2005: return 0;
! 2006: }
! 2007:
! 2008: int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
1.1.1.4 root 2009: unsigned long vga_ram_offset, int vga_ram_size,
2010: unsigned long vga_bios_offset, int vga_bios_size)
2011: {
2012: PCIVGAState *d;
2013: VGAState *s;
2014: uint8_t *pci_conf;
1.1.1.5 ! root 2015:
! 2016: d = (PCIVGAState *)pci_register_device(bus, "VGA",
1.1.1.4 root 2017: sizeof(PCIVGAState),
2018: -1, NULL, NULL);
2019: if (!d)
2020: return -1;
2021: s = &d->vga_state;
1.1.1.5 ! root 2022:
1.1.1.4 root 2023: vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2024: vga_init(s);
1.1.1.5 ! root 2025:
! 2026: graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
! 2027:
1.1.1.4 root 2028: s->pci_dev = &d->dev;
1.1.1.5 ! root 2029:
1.1.1.4 root 2030: pci_conf = d->dev.config;
2031: pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2032: pci_conf[0x01] = 0x12;
2033: pci_conf[0x02] = 0x11;
2034: pci_conf[0x03] = 0x11;
1.1.1.5 ! root 2035: pci_conf[0x0a] = 0x00; // VGA controller
1.1.1.4 root 2036: pci_conf[0x0b] = 0x03;
2037: pci_conf[0x0e] = 0x00; // header_type
1.1.1.5 ! root 2038:
1.1.1.4 root 2039: /* XXX: vga_ram_size must be a power of two */
1.1.1.5 ! root 2040: pci_register_io_region(&d->dev, 0, vga_ram_size,
1.1.1.4 root 2041: PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2042: if (vga_bios_size != 0) {
2043: unsigned int bios_total_size;
2044: s->bios_offset = vga_bios_offset;
2045: s->bios_size = vga_bios_size;
2046: /* must be a power of two */
2047: bios_total_size = 1;
2048: while (bios_total_size < vga_bios_size)
2049: bios_total_size <<= 1;
1.1.1.5 ! root 2050: pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
1.1.1.4 root 2051: PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1.1 root 2052: }
2053: return 0;
2054: }
2055:
2056: /********************************************************/
2057: /* vga screen dump */
2058:
2059: static int vga_save_w, vga_save_h;
2060:
1.1.1.5 ! root 2061: static void vga_save_dpy_update(DisplayState *s,
1.1 root 2062: int x, int y, int w, int h)
2063: {
2064: }
2065:
2066: static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2067: {
2068: s->linesize = w * 4;
2069: s->data = qemu_malloc(h * s->linesize);
2070: vga_save_w = w;
2071: vga_save_h = h;
2072: }
2073:
2074: static void vga_save_dpy_refresh(DisplayState *s)
2075: {
2076: }
2077:
1.1.1.5 ! root 2078: int ppm_save(const char *filename, uint8_t *data,
! 2079: int w, int h, int linesize)
1.1 root 2080: {
2081: FILE *f;
2082: uint8_t *d, *d1;
2083: unsigned int v;
2084: int y, x;
2085:
2086: f = fopen(filename, "wb");
2087: if (!f)
2088: return -1;
2089: fprintf(f, "P6\n%d %d\n%d\n",
2090: w, h, 255);
2091: d1 = data;
2092: for(y = 0; y < h; y++) {
2093: d = d1;
2094: for(x = 0; x < w; x++) {
2095: v = *(uint32_t *)d;
2096: fputc((v >> 16) & 0xff, f);
2097: fputc((v >> 8) & 0xff, f);
2098: fputc((v) & 0xff, f);
2099: d += 4;
2100: }
2101: d1 += linesize;
2102: }
2103: fclose(f);
2104: return 0;
2105: }
2106:
2107: /* save the vga display in a PPM image even if no display is
2108: available */
1.1.1.2 root 2109: static void vga_screen_dump(void *opaque, const char *filename)
1.1 root 2110: {
1.1.1.2 root 2111: VGAState *s = (VGAState *)opaque;
1.1 root 2112: DisplayState *saved_ds, ds1, *ds = &ds1;
1.1.1.5 ! root 2113:
1.1 root 2114: /* XXX: this is a little hackish */
1.1.1.2 root 2115: vga_invalidate_display(s);
1.1 root 2116: saved_ds = s->ds;
2117:
2118: memset(ds, 0, sizeof(DisplayState));
2119: ds->dpy_update = vga_save_dpy_update;
2120: ds->dpy_resize = vga_save_dpy_resize;
2121: ds->dpy_refresh = vga_save_dpy_refresh;
2122: ds->depth = 32;
2123:
2124: s->ds = ds;
2125: s->graphic_mode = -1;
1.1.1.2 root 2126: vga_update_display(s);
1.1.1.5 ! root 2127:
1.1 root 2128: if (ds->data) {
1.1.1.5 ! root 2129: ppm_save(filename, ds->data, vga_save_w, vga_save_h,
1.1 root 2130: s->ds->linesize);
2131: qemu_free(ds->data);
2132: }
2133: s->ds = saved_ds;
2134: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.