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 "qapi/error.h"
  26#include "hw/hw.h"
  27#include "vga.h"
  28#include "ui/console.h"
  29#include "hw/i386/pc.h"
  30#include "hw/pci/pci.h"
  31#include "vga_int.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 * 1024);
 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            ch_attr = *(uint16_t *)src;
1284            if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
1285                if (cx < cx_min)
1286                    cx_min = cx;
1287                if (cx > cx_max)
1288                    cx_max = cx;
1289                *ch_attr_ptr = ch_attr;
1290#ifdef HOST_WORDS_BIGENDIAN
1291                ch = ch_attr >> 8;
1292                cattr = ch_attr & 0xff;
1293#else
1294                ch = ch_attr & 0xff;
1295                cattr = ch_attr >> 8;
1296#endif
1297                font_ptr = font_base[(cattr >> 3) & 1];
1298                font_ptr += 32 * 4 * ch;
1299                bgcol = palette[cattr >> 4];
1300                fgcol = palette[cattr & 0x0f];
1301                if (cw == 16) {
1302                    vga_draw_glyph16(d1, linesize,
1303                                     font_ptr, cheight, fgcol, bgcol);
1304                } else if (cw != 9) {
1305                    vga_draw_glyph8(d1, linesize,
1306                                    font_ptr, cheight, fgcol, bgcol);
1307                } else {
1308                    dup9 = 0;
1309                    if (ch >= 0xb0 && ch <= 0xdf &&
1310                        (s->ar[VGA_ATC_MODE] & 0x04)) {
1311                        dup9 = 1;
1312                    }
1313                    vga_draw_glyph9(d1, linesize,
1314                                    font_ptr, cheight, fgcol, bgcol, dup9);
1315                }
1316                if (src == cursor_ptr &&
1317                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1318                    s->cursor_visible_phase) {
1319                    int line_start, line_last, h;
1320                    /* draw the cursor */
1321                    line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1322                    line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1323                    /* XXX: check that */
1324                    if (line_last > cheight - 1)
1325                        line_last = cheight - 1;
1326                    if (line_last >= line_start && line_start < cheight) {
1327                        h = line_last - line_start + 1;
1328                        d = d1 + linesize * line_start;
1329                        if (cw == 16) {
1330                            vga_draw_glyph16(d, linesize,
1331                                             cursor_glyph, h, fgcol, bgcol);
1332                        } else if (cw != 9) {
1333                            vga_draw_glyph8(d, linesize,
1334                                            cursor_glyph, h, fgcol, bgcol);
1335                        } else {
1336                            vga_draw_glyph9(d, linesize,
1337                                            cursor_glyph, h, fgcol, bgcol, 1);
1338                        }
1339                    }
1340                }
1341            }
1342            d1 += x_incr;
1343            src += 4;
1344            ch_attr_ptr++;
1345        }
1346        if (cx_max != -1) {
1347            dpy_gfx_update(s->con, cx_min * cw, cy * cheight,
1348                           (cx_max - cx_min + 1) * cw, cheight);
1349        }
1350        dest += linesize * cheight;
1351        line1 = line + cheight;
1352        offset += line_offset;
1353        if (line < s->line_compare && line1 >= s->line_compare) {
1354            offset = 0;
1355        }
1356        line = line1;
1357    }
1358}
1359
1360enum {
1361    VGA_DRAW_LINE2,
1362    VGA_DRAW_LINE2D2,
1363    VGA_DRAW_LINE4,
1364    VGA_DRAW_LINE4D2,
1365    VGA_DRAW_LINE8D2,
1366    VGA_DRAW_LINE8,
1367    VGA_DRAW_LINE15_LE,
1368    VGA_DRAW_LINE16_LE,
1369    VGA_DRAW_LINE24_LE,
1370    VGA_DRAW_LINE32_LE,
1371    VGA_DRAW_LINE15_BE,
1372    VGA_DRAW_LINE16_BE,
1373    VGA_DRAW_LINE24_BE,
1374    VGA_DRAW_LINE32_BE,
1375    VGA_DRAW_LINE_NB,
1376};
1377
1378static vga_draw_line_func * const vga_draw_line_table[VGA_DRAW_LINE_NB] = {
1379    vga_draw_line2,
1380    vga_draw_line2d2,
1381    vga_draw_line4,
1382    vga_draw_line4d2,
1383    vga_draw_line8d2,
1384    vga_draw_line8,
1385    vga_draw_line15_le,
1386    vga_draw_line16_le,
1387    vga_draw_line24_le,
1388    vga_draw_line32_le,
1389    vga_draw_line15_be,
1390    vga_draw_line16_be,
1391    vga_draw_line24_be,
1392    vga_draw_line32_be,
1393};
1394
1395static int vga_get_bpp(VGACommonState *s)
1396{
1397    int ret;
1398
1399    if (vbe_enabled(s)) {
1400        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1401    } else {
1402        ret = 0;
1403    }
1404    return ret;
1405}
1406
1407static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1408{
1409    int width, height;
1410
1411    if (vbe_enabled(s)) {
1412        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1413        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1414    } else {
1415        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1416        height = s->cr[VGA_CRTC_V_DISP_END] |
1417            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1418            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1419        height = (height + 1);
1420    }
1421    *pwidth = width;
1422    *pheight = height;
1423}
1424
1425void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1426{
1427    int y;
1428    if (y1 >= VGA_MAX_HEIGHT)
1429        return;
1430    if (y2 >= VGA_MAX_HEIGHT)
1431        y2 = VGA_MAX_HEIGHT;
1432    for(y = y1; y < y2; y++) {
1433        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1434    }
1435}
1436
1437static bool vga_scanline_invalidated(VGACommonState *s, int y)
1438{
1439    if (y >= VGA_MAX_HEIGHT) {
1440        return false;
1441    }
1442    return s->invalidated_y_table[y >> 5] & (1 << (y & 0x1f));
1443}
1444
1445void vga_sync_dirty_bitmap(VGACommonState *s)
1446{
1447    memory_region_sync_dirty_bitmap(&s->vram);
1448}
1449
1450void vga_dirty_log_start(VGACommonState *s)
1451{
1452    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1453}
1454
1455void vga_dirty_log_stop(VGACommonState *s)
1456{
1457    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1458}
1459
1460/*
1461 * graphic modes
1462 */
1463static void vga_draw_graphic(VGACommonState *s, int full_update)
1464{
1465    DisplaySurface *surface = qemu_console_surface(s->con);
1466    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1467    int width, height, shift_control, bwidth, bits;
1468    ram_addr_t page0, page1, region_start, region_end;
1469    DirtyBitmapSnapshot *snap = NULL;
1470    int disp_width, multi_scan, multi_run;
1471    uint8_t *d;
1472    uint32_t v, addr1, addr;
1473    vga_draw_line_func *vga_draw_line = NULL;
1474    bool share_surface, force_shadow = false;
1475    pixman_format_code_t format;
1476#ifdef HOST_WORDS_BIGENDIAN
1477    bool byteswap = !s->big_endian_fb;
1478#else
1479    bool byteswap = s->big_endian_fb;
1480#endif
1481
1482    full_update |= update_basic_params(s);
1483
1484    s->get_resolution(s, &width, &height);
1485    disp_width = width;
1486
1487    region_start = (s->start_addr * 4);
1488    region_end = region_start + s->line_offset * height;
1489    if (region_end > s->vbe_size) {
1490        /* wraps around (can happen with cirrus vbe modes) */
1491        region_start = 0;
1492        region_end = s->vbe_size;
1493        force_shadow = true;
1494    }
1495
1496    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1497    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1498    if (shift_control != 1) {
1499        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1500            - 1;
1501    } else {
1502        /* in CGA modes, multi_scan is ignored */
1503        /* XXX: is it correct ? */
1504        multi_scan = double_scan;
1505    }
1506    multi_run = multi_scan;
1507    if (shift_control != s->shift_control ||
1508        double_scan != s->double_scan) {
1509        full_update = 1;
1510        s->shift_control = shift_control;
1511        s->double_scan = double_scan;
1512    }
1513
1514    if (shift_control == 0) {
1515        if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1516            disp_width <<= 1;
1517        }
1518    } else if (shift_control == 1) {
1519        if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1520            disp_width <<= 1;
1521        }
1522    }
1523
1524    depth = s->get_bpp(s);
1525
1526    /*
1527     * Check whether we can share the surface with the backend
1528     * or whether we need a shadow surface. We share native
1529     * endian surfaces for 15bpp and above and byteswapped
1530     * surfaces for 24bpp and above.
1531     */
1532    format = qemu_default_pixman_format(depth, !byteswap);
1533    if (format) {
1534        share_surface = dpy_gfx_check_format(s->con, format)
1535            && !s->force_shadow && !force_shadow;
1536    } else {
1537        share_surface = false;
1538    }
1539    if (s->line_offset != s->last_line_offset ||
1540        disp_width != s->last_width ||
1541        height != s->last_height ||
1542        s->last_depth != depth ||
1543        s->last_byteswap != byteswap ||
1544        share_surface != is_buffer_shared(surface)) {
1545        if (share_surface) {
1546            surface = qemu_create_displaysurface_from(disp_width,
1547                    height, format, s->line_offset,
1548                    s->vram_ptr + (s->start_addr * 4));
1549            dpy_gfx_replace_surface(s->con, surface);
1550        } else {
1551            qemu_console_resize(s->con, disp_width, height);
1552            surface = qemu_console_surface(s->con);
1553        }
1554        s->last_scr_width = disp_width;
1555        s->last_scr_height = height;
1556        s->last_width = disp_width;
1557        s->last_height = height;
1558        s->last_line_offset = s->line_offset;
1559        s->last_depth = depth;
1560        s->last_byteswap = byteswap;
1561        full_update = 1;
1562    } else if (is_buffer_shared(surface) &&
1563               (full_update || surface_data(surface) != s->vram_ptr
1564                + (s->start_addr * 4))) {
1565        pixman_format_code_t format =
1566            qemu_default_pixman_format(depth, !byteswap);
1567        surface = qemu_create_displaysurface_from(disp_width,
1568                height, format, s->line_offset,
1569                s->vram_ptr + (s->start_addr * 4));
1570        dpy_gfx_replace_surface(s->con, surface);
1571    }
1572
1573    if (shift_control == 0) {
1574        full_update |= update_palette16(s);
1575        if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1576            v = VGA_DRAW_LINE4D2;
1577        } else {
1578            v = VGA_DRAW_LINE4;
1579        }
1580        bits = 4;
1581    } else if (shift_control == 1) {
1582        full_update |= update_palette16(s);
1583        if (sr(s, VGA_SEQ_CLOCK_MODE) & 8) {
1584            v = VGA_DRAW_LINE2D2;
1585        } else {
1586            v = VGA_DRAW_LINE2;
1587        }
1588        bits = 4;
1589    } else {
1590        switch(s->get_bpp(s)) {
1591        default:
1592        case 0:
1593            full_update |= update_palette256(s);
1594            v = VGA_DRAW_LINE8D2;
1595            bits = 4;
1596            break;
1597        case 8:
1598            full_update |= update_palette256(s);
1599            v = VGA_DRAW_LINE8;
1600            bits = 8;
1601            break;
1602        case 15:
1603            v = s->big_endian_fb ? VGA_DRAW_LINE15_BE : VGA_DRAW_LINE15_LE;
1604            bits = 16;
1605            break;
1606        case 16:
1607            v = s->big_endian_fb ? VGA_DRAW_LINE16_BE : VGA_DRAW_LINE16_LE;
1608            bits = 16;
1609            break;
1610        case 24:
1611            v = s->big_endian_fb ? VGA_DRAW_LINE24_BE : VGA_DRAW_LINE24_LE;
1612            bits = 24;
1613            break;
1614        case 32:
1615            v = s->big_endian_fb ? VGA_DRAW_LINE32_BE : VGA_DRAW_LINE32_LE;
1616            bits = 32;
1617            break;
1618        }
1619    }
1620    vga_draw_line = vga_draw_line_table[v];
1621
1622    if (!is_buffer_shared(surface) && s->cursor_invalidate) {
1623        s->cursor_invalidate(s);
1624    }
1625
1626#if 0
1627    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",
1628           width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1629           s->line_compare, sr(s, VGA_SEQ_CLOCK_MODE));
1630#endif
1631    addr1 = (s->start_addr * 4);
1632    bwidth = (width * bits + 7) / 8;
1633    y_start = -1;
1634    d = surface_data(surface);
1635    linesize = surface_stride(surface);
1636    y1 = 0;
1637
1638    if (!full_update) {
1639        vga_sync_dirty_bitmap(s);
1640        if (s->line_compare < height) {
1641            /* split screen mode */
1642            region_start = 0;
1643        }
1644        snap = memory_region_snapshot_and_clear_dirty(&s->vram, region_start,
1645                                                      region_end - region_start,
1646                                                      DIRTY_MEMORY_VGA);
1647    }
1648
1649    for(y = 0; y < height; y++) {
1650        addr = addr1;
1651        if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1652            int shift;
1653            /* CGA compatibility handling */
1654            shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1655            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1656        }
1657        if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1658            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1659        }
1660        update = full_update;
1661        page0 = addr & s->vbe_size_mask;
1662        page1 = (addr + bwidth - 1) & s->vbe_size_mask;
1663        if (full_update) {
1664            update = 1;
1665        } else if (page1 < page0) {
1666            /* scanline wraps from end of video memory to the start */
1667            assert(force_shadow);
1668            update = memory_region_snapshot_get_dirty(&s->vram, snap,
1669                                                      page0, 0);
1670            update |= memory_region_snapshot_get_dirty(&s->vram, snap,
1671                                                       page1, 0);
1672        } else {
1673            update = memory_region_snapshot_get_dirty(&s->vram, snap,
1674                                                      page0, page1 - page0);
1675        }
1676        /* explicit invalidation for the hardware cursor (cirrus only) */
1677        update |= vga_scanline_invalidated(s, y);
1678        if (update) {
1679            if (y_start < 0)
1680                y_start = y;
1681            if (!(is_buffer_shared(surface))) {
1682                vga_draw_line(s, d, addr, width);
1683                if (s->cursor_draw_line)
1684                    s->cursor_draw_line(s, d, y);
1685            }
1686        } else {
1687            if (y_start >= 0) {
1688                /* flush to display */
1689                dpy_gfx_update(s->con, 0, y_start,
1690                               disp_width, y - y_start);
1691                y_start = -1;
1692            }
1693        }
1694        if (!multi_run) {
1695            mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1696            if ((y1 & mask) == mask)
1697                addr1 += s->line_offset;
1698            y1++;
1699            multi_run = multi_scan;
1700        } else {
1701            multi_run--;
1702        }
1703        /* line compare acts on the displayed lines */
1704        if (y == s->line_compare)
1705            addr1 = 0;
1706        d += linesize;
1707    }
1708    if (y_start >= 0) {
1709        /* flush to display */
1710        dpy_gfx_update(s->con, 0, y_start,
1711                       disp_width, y - y_start);
1712    }
1713    g_free(snap);
1714    memset(s->invalidated_y_table, 0, sizeof(s->invalidated_y_table));
1715}
1716
1717static void vga_draw_blank(VGACommonState *s, int full_update)
1718{
1719    DisplaySurface *surface = qemu_console_surface(s->con);
1720    int i, w;
1721    uint8_t *d;
1722
1723    if (!full_update)
1724        return;
1725    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1726        return;
1727
1728    w = s->last_scr_width * surface_bytes_per_pixel(surface);
1729    d = surface_data(surface);
1730    for(i = 0; i < s->last_scr_height; i++) {
1731        memset(d, 0, w);
1732        d += surface_stride(surface);
1733    }
1734    dpy_gfx_update(s->con, 0, 0,
1735                   s->last_scr_width, s->last_scr_height);
1736}
1737
1738#define GMODE_TEXT     0
1739#define GMODE_GRAPH    1
1740#define GMODE_BLANK 2
1741
1742static void vga_update_display(void *opaque)
1743{
1744    VGACommonState *s = opaque;
1745    DisplaySurface *surface = qemu_console_surface(s->con);
1746    int full_update, graphic_mode;
1747
1748    qemu_flush_coalesced_mmio_buffer();
1749
1750    if (surface_bits_per_pixel(surface) == 0) {
1751        /* nothing to do */
1752    } else {
1753        full_update = 0;
1754        if (!(s->ar_index & 0x20)) {
1755            graphic_mode = GMODE_BLANK;
1756        } else {
1757            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1758        }
1759        if (graphic_mode != s->graphic_mode) {
1760            s->graphic_mode = graphic_mode;
1761            s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL);
1762            full_update = 1;
1763        }
1764        switch(graphic_mode) {
1765        case GMODE_TEXT:
1766            vga_draw_text(s, full_update);
1767            break;
1768        case GMODE_GRAPH:
1769            vga_draw_graphic(s, full_update);
1770            break;
1771        case GMODE_BLANK:
1772        default:
1773            vga_draw_blank(s, full_update);
1774            break;
1775        }
1776    }
1777}
1778
1779/* force a full display refresh */
1780static void vga_invalidate_display(void *opaque)
1781{
1782    VGACommonState *s = opaque;
1783
1784    s->last_width = -1;
1785    s->last_height = -1;
1786}
1787
1788void vga_common_reset(VGACommonState *s)
1789{
1790    s->sr_index = 0;
1791    memset(s->sr, '\0', sizeof(s->sr));
1792    memset(s->sr_vbe, '\0', sizeof(s->sr_vbe));
1793    s->gr_index = 0;
1794    memset(s->gr, '\0', sizeof(s->gr));
1795    s->ar_index = 0;
1796    memset(s->ar, '\0', sizeof(s->ar));
1797    s->ar_flip_flop = 0;
1798    s->cr_index = 0;
1799    memset(s->cr, '\0', sizeof(s->cr));
1800    s->msr = 0;
1801    s->fcr = 0;
1802    s->st00 = 0;
1803    s->st01 = 0;
1804    s->dac_state = 0;
1805    s->dac_sub_index = 0;
1806    s->dac_read_index = 0;
1807    s->dac_write_index = 0;
1808    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1809    s->dac_8bit = 0;
1810    memset(s->palette, '\0', sizeof(s->palette));
1811    s->bank_offset = 0;
1812    s->vbe_index = 0;
1813    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1814    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1815    s->vbe_start_addr = 0;
1816    s->vbe_line_offset = 0;
1817    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1818    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1819    s->graphic_mode = -1; /* force full update */
1820    s->shift_control = 0;
1821    s->double_scan = 0;
1822    s->line_offset = 0;
1823    s->line_compare = 0;
1824    s->start_addr = 0;
1825    s->plane_updated = 0;
1826    s->last_cw = 0;
1827    s->last_ch = 0;
1828    s->last_width = 0;
1829    s->last_height = 0;
1830    s->last_scr_width = 0;
1831    s->last_scr_height = 0;
1832    s->cursor_start = 0;
1833    s->cursor_end = 0;
1834    s->cursor_offset = 0;
1835    s->big_endian_fb = s->default_endian_fb;
1836    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1837    memset(s->last_palette, '\0', sizeof(s->last_palette));
1838    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1839    switch (vga_retrace_method) {
1840    case VGA_RETRACE_DUMB:
1841        break;
1842    case VGA_RETRACE_PRECISE:
1843        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1844        break;
1845    }
1846    vga_update_memory_access(s);
1847}
1848
1849static void vga_reset(void *opaque)
1850{
1851    VGACommonState *s =  opaque;
1852    vga_common_reset(s);
1853}
1854
1855#define TEXTMODE_X(x)   ((x) % width)
1856#define TEXTMODE_Y(x)   ((x) / width)
1857#define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1858        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1859/* relay text rendering to the display driver
1860 * instead of doing a full vga_update_display() */
1861static void vga_update_text(void *opaque, console_ch_t *chardata)
1862{
1863    VGACommonState *s =  opaque;
1864    int graphic_mode, i, cursor_offset, cursor_visible;
1865    int cw, cheight, width, height, size, c_min, c_max;
1866    uint32_t *src;
1867    console_ch_t *dst, val;
1868    char msg_buffer[80];
1869    int full_update = 0;
1870
1871    qemu_flush_coalesced_mmio_buffer();
1872
1873    if (!(s->ar_index & 0x20)) {
1874        graphic_mode = GMODE_BLANK;
1875    } else {
1876        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1877    }
1878    if (graphic_mode != s->graphic_mode) {
1879        s->graphic_mode = graphic_mode;
1880        full_update = 1;
1881    }
1882    if (s->last_width == -1) {
1883        s->last_width = 0;
1884        full_update = 1;
1885    }
1886
1887    switch (graphic_mode) {
1888    case GMODE_TEXT:
1889        /* TODO: update palette */
1890        full_update |= update_basic_params(s);
1891
1892        /* total width & height */
1893        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1894        cw = 8;
1895        if (!(sr(s, VGA_SEQ_CLOCK_MODE) & VGA_SR01_CHAR_CLK_8DOTS)) {
1896            cw = 9;
1897        }
1898        if (sr(s, VGA_SEQ_CLOCK_MODE) & 0x08) {
1899            cw = 16; /* NOTE: no 18 pixel wide */
1900        }
1901        width = (s->cr[VGA_CRTC_H_DISP] + 1);
1902        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1903            /* ugly hack for CGA 160x100x16 - explain me the logic */
1904            height = 100;
1905        } else {
1906            height = s->cr[VGA_CRTC_V_DISP_END] |
1907                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1908                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1909            height = (height + 1) / cheight;
1910        }
1911
1912        size = (height * width);
1913        if (size > CH_ATTR_SIZE) {
1914            if (!full_update)
1915                return;
1916
1917            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1918                     width, height);
1919            break;
1920        }
1921
1922        if (width != s->last_width || height != s->last_height ||
1923            cw != s->last_cw || cheight != s->last_ch) {
1924            s->last_scr_width = width * cw;
1925            s->last_scr_height = height * cheight;
1926            qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
1927            dpy_text_resize(s->con, width, height);
1928            s->last_depth = 0;
1929            s->last_width = width;
1930            s->last_height = height;
1931            s->last_ch = cheight;
1932            s->last_cw = cw;
1933            full_update = 1;
1934        }
1935
1936        if (full_update) {
1937            s->full_update_gfx = 1;
1938        }
1939        if (s->full_update_text) {
1940            s->full_update_text = 0;
1941            full_update |= 1;
1942        }
1943
1944        /* Update "hardware" cursor */
1945        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1946                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1947        if (cursor_offset != s->cursor_offset ||
1948            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1949            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1950            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
1951            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1952                dpy_text_cursor(s->con,
1953                                TEXTMODE_X(cursor_offset),
1954                                TEXTMODE_Y(cursor_offset));
1955            else
1956                dpy_text_cursor(s->con, -1, -1);
1957            s->cursor_offset = cursor_offset;
1958            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1959            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1960        }
1961
1962        src = (uint32_t *) s->vram_ptr + s->start_addr;
1963        dst = chardata;
1964
1965        if (full_update) {
1966            for (i = 0; i < size; src ++, dst ++, i ++)
1967                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
1968
1969            dpy_text_update(s->con, 0, 0, width, height);
1970        } else {
1971            c_max = 0;
1972
1973            for (i = 0; i < size; src ++, dst ++, i ++) {
1974                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1975                if (*dst != val) {
1976                    *dst = val;
1977                    c_max = i;
1978                    break;
1979                }
1980            }
1981            c_min = i;
1982            for (; i < size; src ++, dst ++, i ++) {
1983                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1984                if (*dst != val) {
1985                    *dst = val;
1986                    c_max = i;
1987                }
1988            }
1989
1990            if (c_min <= c_max) {
1991                i = TEXTMODE_Y(c_min);
1992                dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1993            }
1994        }
1995
1996        return;
1997    case GMODE_GRAPH:
1998        if (!full_update)
1999            return;
2000
2001        s->get_resolution(s, &width, &height);
2002        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2003                 width, height);
2004        break;
2005    case GMODE_BLANK:
2006    default:
2007        if (!full_update)
2008            return;
2009
2010        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2011        break;
2012    }
2013
2014    /* Display a message */
2015    s->last_width = 60;
2016    s->last_height = height = 3;
2017    dpy_text_cursor(s->con, -1, -1);
2018    dpy_text_resize(s->con, s->last_width, height);
2019
2020    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2021        console_write_ch(dst ++, ' ');
2022
2023    size = strlen(msg_buffer);
2024    width = (s->last_width - size) / 2;
2025    dst = chardata + s->last_width + width;
2026    for (i = 0; i < size; i ++)
2027        console_write_ch(dst ++, ATTR2CHTYPE(msg_buffer[i], QEMU_COLOR_BLUE,
2028                                             QEMU_COLOR_BLACK, 1));
2029
2030    dpy_text_update(s->con, 0, 0, s->last_width, height);
2031}
2032
2033static uint64_t vga_mem_read(void *opaque, hwaddr addr,
2034                             unsigned size)
2035{
2036    VGACommonState *s = opaque;
2037
2038    return vga_mem_readb(s, addr);
2039}
2040
2041static void vga_mem_write(void *opaque, hwaddr addr,
2042                          uint64_t data, unsigned size)
2043{
2044    VGACommonState *s = opaque;
2045
2046    vga_mem_writeb(s, addr, data);
2047}
2048
2049const MemoryRegionOps vga_mem_ops = {
2050    .read = vga_mem_read,
2051    .write = vga_mem_write,
2052    .endianness = DEVICE_LITTLE_ENDIAN,
2053    .impl = {
2054        .min_access_size = 1,
2055        .max_access_size = 1,
2056    },
2057};
2058
2059static int vga_common_post_load(void *opaque, int version_id)
2060{
2061    VGACommonState *s = opaque;
2062
2063    /* force refresh */
2064    s->graphic_mode = -1;
2065    vbe_update_vgaregs(s);
2066    return 0;
2067}
2068
2069static bool vga_endian_state_needed(void *opaque)
2070{
2071    VGACommonState *s = opaque;
2072
2073    /*
2074     * Only send the endian state if it's different from the
2075     * default one, thus ensuring backward compatibility for
2076     * migration of the common case
2077     */
2078    return s->default_endian_fb != s->big_endian_fb;
2079}
2080
2081static const VMStateDescription vmstate_vga_endian = {
2082    .name = "vga.endian",
2083    .version_id = 1,
2084    .minimum_version_id = 1,
2085    .needed = vga_endian_state_needed,
2086    .fields = (VMStateField[]) {
2087        VMSTATE_BOOL(big_endian_fb, VGACommonState),
2088        VMSTATE_END_OF_LIST()
2089    }
2090};
2091
2092const VMStateDescription vmstate_vga_common = {
2093    .name = "vga",
2094    .version_id = 2,
2095    .minimum_version_id = 2,
2096    .post_load = vga_common_post_load,
2097    .fields = (VMStateField[]) {
2098        VMSTATE_UINT32(latch, VGACommonState),
2099        VMSTATE_UINT8(sr_index, VGACommonState),
2100        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2101        VMSTATE_UINT8(gr_index, VGACommonState),
2102        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2103        VMSTATE_UINT8(ar_index, VGACommonState),
2104        VMSTATE_BUFFER(ar, VGACommonState),
2105        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2106        VMSTATE_UINT8(cr_index, VGACommonState),
2107        VMSTATE_BUFFER(cr, VGACommonState),
2108        VMSTATE_UINT8(msr, VGACommonState),
2109        VMSTATE_UINT8(fcr, VGACommonState),
2110        VMSTATE_UINT8(st00, VGACommonState),
2111        VMSTATE_UINT8(st01, VGACommonState),
2112
2113        VMSTATE_UINT8(dac_state, VGACommonState),
2114        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2115        VMSTATE_UINT8(dac_read_index, VGACommonState),
2116        VMSTATE_UINT8(dac_write_index, VGACommonState),
2117        VMSTATE_BUFFER(dac_cache, VGACommonState),
2118        VMSTATE_BUFFER(palette, VGACommonState),
2119
2120        VMSTATE_INT32(bank_offset, VGACommonState),
2121        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState, NULL),
2122        VMSTATE_UINT16(vbe_index, VGACommonState),
2123        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2124        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2125        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2126        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2127        VMSTATE_END_OF_LIST()
2128    },
2129    .subsections = (const VMStateDescription*[]) {
2130        &vmstate_vga_endian,
2131        NULL
2132    }
2133};
2134
2135static const GraphicHwOps vga_ops = {
2136    .invalidate  = vga_invalidate_display,
2137    .gfx_update  = vga_update_display,
2138    .text_update = vga_update_text,
2139};
2140
2141static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax)
2142{
2143    if (val < vmin) {
2144        return vmin;
2145    }
2146    if (val > vmax) {
2147        return vmax;
2148    }
2149    return val;
2150}
2151
2152void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate)
2153{
2154    int i, j, v, b;
2155
2156    for(i = 0;i < 256; i++) {
2157        v = 0;
2158        for(j = 0; j < 8; j++) {
2159            v |= ((i >> j) & 1) << (j * 4);
2160        }
2161        expand4[i] = v;
2162
2163        v = 0;
2164        for(j = 0; j < 4; j++) {
2165            v |= ((i >> (2 * j)) & 3) << (j * 4);
2166        }
2167        expand2[i] = v;
2168    }
2169    for(i = 0; i < 16; i++) {
2170        v = 0;
2171        for(j = 0; j < 4; j++) {
2172            b = ((i >> j) & 1);
2173            v |= b << (2 * j);
2174            v |= b << (2 * j + 1);
2175        }
2176        expand4to8[i] = v;
2177    }
2178
2179    s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512);
2180    s->vram_size_mb = pow2ceil(s->vram_size_mb);
2181    s->vram_size = s->vram_size_mb << 20;
2182
2183    if (!s->vbe_size) {
2184        s->vbe_size = s->vram_size;
2185    }
2186    s->vbe_size_mask = s->vbe_size - 1;
2187
2188    s->is_vbe_vmstate = 1;
2189    memory_region_init_ram_nomigrate(&s->vram, obj, "vga.vram", s->vram_size,
2190                           &error_fatal);
2191    vmstate_register_ram(&s->vram, global_vmstate ? NULL : DEVICE(obj));
2192    xen_register_framebuffer(&s->vram);
2193    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2194    s->get_bpp = vga_get_bpp;
2195    s->get_offsets = vga_get_offsets;
2196    s->get_resolution = vga_get_resolution;
2197    s->hw_ops = &vga_ops;
2198    switch (vga_retrace_method) {
2199    case VGA_RETRACE_DUMB:
2200        s->retrace = vga_dumb_retrace;
2201        s->update_retrace_info = vga_dumb_update_retrace_info;
2202        break;
2203
2204    case VGA_RETRACE_PRECISE:
2205        s->retrace = vga_precise_retrace;
2206        s->update_retrace_info = vga_precise_update_retrace_info;
2207        break;
2208    }
2209
2210    /*
2211     * Set default fb endian based on target, could probably be turned
2212     * into a device attribute set by the machine/platform to remove
2213     * all target endian dependencies from this file.
2214     */
2215#ifdef TARGET_WORDS_BIGENDIAN
2216    s->default_endian_fb = true;
2217#else
2218    s->default_endian_fb = false;
2219#endif
2220    vga_dirty_log_start(s);
2221}
2222
2223static const MemoryRegionPortio vga_portio_list[] = {
2224    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2225    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2226    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2227    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2228    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2229    PORTIO_END_OF_LIST(),
2230};
2231
2232static const MemoryRegionPortio vbe_portio_list[] = {
2233    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2234# ifdef TARGET_I386
2235    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2236# endif
2237    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2238    PORTIO_END_OF_LIST(),
2239};
2240
2241/* Used by both ISA and PCI */
2242MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
2243                          const MemoryRegionPortio **vga_ports,
2244                          const MemoryRegionPortio **vbe_ports)
2245{
2246    MemoryRegion *vga_mem;
2247
2248    *vga_ports = vga_portio_list;
2249    *vbe_ports = vbe_portio_list;
2250
2251    vga_mem = g_malloc(sizeof(*vga_mem));
2252    memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
2253                          "vga-lowmem", 0x20000);
2254    memory_region_set_flush_coalesced(vga_mem);
2255
2256    return vga_mem;
2257}
2258
2259void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
2260              MemoryRegion *address_space_io, bool init_vga_ports)
2261{
2262    MemoryRegion *vga_io_memory;
2263    const MemoryRegionPortio *vga_ports, *vbe_ports;
2264
2265    qemu_register_reset(vga_reset, s);
2266
2267    s->bank_offset = 0;
2268
2269    s->legacy_address_space = address_space;
2270
2271    vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports);
2272    memory_region_add_subregion_overlap(address_space,
2273                                        0x000a0000,
2274                                        vga_io_memory,
2275                                        1);
2276    memory_region_set_coalescing(vga_io_memory);
2277    if (init_vga_ports) {
2278        portio_list_init(&s->vga_port_list, obj, vga_ports, s, "vga");
2279        portio_list_set_flush_coalesced(&s->vga_port_list);
2280        portio_list_add(&s->vga_port_list, address_space_io, 0x3b0);
2281    }
2282    if (vbe_ports) {
2283        portio_list_init(&s->vbe_port_list, obj, vbe_ports, s, "vbe");
2284        portio_list_add(&s->vbe_port_list, address_space_io, 0x1ce);
2285    }
2286}
2287
2288void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory)
2289{
2290    /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
2291     * so use an alias to avoid double-mapping the same region.
2292     */
2293    memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe",
2294                             &s->vram, 0, memory_region_size(&s->vram));
2295    /* XXX: use optimized standard vga accesses */
2296    memory_region_add_subregion(system_memory,
2297                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2298                                &s->vram_vbe);
2299    s->vbe_mapped = 1;
2300}
2301