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