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