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