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