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