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