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