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