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