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