Statistics
| Branch: | Revision:

root / hw / vga.c @ bd8f2f5d

History | View | Annotate | Download (72.1 kB)

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 */
57
const uint8_t sr_mask[8] = {
58
    0x03,
59
    0x3d,
60
    0x0f,
61
    0x3f,
62
    0x0e,
63
    0x00,
64
    0x00,
65
    0xff,
66
};
67

    
68
const 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

    
112
static 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

    
139
static 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

    
158
static const uint32_t dmask4[4] = {
159
    PAT(0x00000000),
160
    PAT(0x0000ffff),
161
    PAT(0xffff0000),
162
    PAT(0xffffffff),
163
};
164

    
165
static uint32_t expand4[256];
166
static uint16_t expand2[256];
167
static uint8_t expand4to8[16];
168

    
169
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
170
                            Error **errp);
171

    
172
static void vga_update_memory_access(VGACommonState *s)
173
{
174
    MemoryRegion *region, *old_region = s->chain4_alias;
175
    target_phys_addr_t base, offset, size;
176

    
177
    s->chain4_alias = NULL;
178

    
179
    if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
180
        VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
181
        offset = 0;
182
        switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
183
        case 0:
184
            base = 0xa0000;
185
            size = 0x20000;
186
            break;
187
        case 1:
188
            base = 0xa0000;
189
            size = 0x10000;
190
            offset = s->bank_offset;
191
            break;
192
        case 2:
193
            base = 0xb0000;
194
            size = 0x8000;
195
            break;
196
        case 3:
197
        default:
198
            base = 0xb8000;
199
            size = 0x8000;
200
            break;
201
        }
202
        base += isa_mem_base;
203
        region = g_malloc(sizeof(*region));
204
        memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
205
        memory_region_add_subregion_overlap(s->legacy_address_space, base,
206
                                            region, 2);
207
        s->chain4_alias = region;
208
    }
209
    if (old_region) {
210
        memory_region_del_subregion(s->legacy_address_space, old_region);
211
        memory_region_destroy(old_region);
212
        g_free(old_region);
213
        s->plane_updated = 0xf;
214
    }
215
}
216

    
217
static void vga_dumb_update_retrace_info(VGACommonState *s)
218
{
219
    (void) s;
220
}
221

    
222
static void vga_precise_update_retrace_info(VGACommonState *s)
223
{
224
    int htotal_chars;
225
    int hretr_start_char;
226
    int hretr_skew_chars;
227
    int hretr_end_char;
228

    
229
    int vtotal_lines;
230
    int vretr_start_line;
231
    int vretr_end_line;
232

    
233
    int dots;
234
#if 0
235
    int div2, sldiv2;
236
#endif
237
    int clocking_mode;
238
    int clock_sel;
239
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
240
    int64_t chars_per_sec;
241
    struct vga_precise_retrace *r = &s->retrace_info.precise;
242

    
243
    htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
244
    hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
245
    hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
246
    hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
247

    
248
    vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
249
                    (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
250
                      ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
251
    vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
252
        ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
253
          ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
254
    vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
255

    
256
    clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
257
    clock_sel = (s->msr >> 2) & 3;
258
    dots = (s->msr & 1) ? 8 : 9;
259

    
260
    chars_per_sec = clk_hz[clock_sel] / dots;
261

    
262
    htotal_chars <<= clocking_mode;
263

    
264
    r->total_chars = vtotal_lines * htotal_chars;
265
    if (r->freq) {
266
        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
267
    } else {
268
        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
269
    }
270

    
271
    r->vstart = vretr_start_line;
272
    r->vend = r->vstart + vretr_end_line + 1;
273

    
274
    r->hstart = hretr_start_char + hretr_skew_chars;
275
    r->hend = r->hstart + hretr_end_char + 1;
276
    r->htotal = htotal_chars;
277

    
278
#if 0
279
    div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
280
    sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
281
    printf (
282
        "hz=%f\n"
283
        "htotal = %d\n"
284
        "hretr_start = %d\n"
285
        "hretr_skew = %d\n"
286
        "hretr_end = %d\n"
287
        "vtotal = %d\n"
288
        "vretr_start = %d\n"
289
        "vretr_end = %d\n"
290
        "div2 = %d sldiv2 = %d\n"
291
        "clocking_mode = %d\n"
292
        "clock_sel = %d %d\n"
293
        "dots = %d\n"
294
        "ticks/char = %" PRId64 "\n"
295
        "\n",
296
        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
297
        htotal_chars,
298
        hretr_start_char,
299
        hretr_skew_chars,
300
        hretr_end_char,
301
        vtotal_lines,
302
        vretr_start_line,
303
        vretr_end_line,
304
        div2, sldiv2,
305
        clocking_mode,
306
        clock_sel,
307
        clk_hz[clock_sel],
308
        dots,
309
        r->ticks_per_char
310
        );
311
#endif
312
}
313

    
314
static uint8_t vga_precise_retrace(VGACommonState *s)
315
{
316
    struct vga_precise_retrace *r = &s->retrace_info.precise;
317
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
318

    
319
    if (r->total_chars) {
320
        int cur_line, cur_line_char, cur_char;
321
        int64_t cur_tick;
322

    
323
        cur_tick = qemu_get_clock_ns(vm_clock);
324

    
325
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
326
        cur_line = cur_char / r->htotal;
327

    
328
        if (cur_line >= r->vstart && cur_line <= r->vend) {
329
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
330
        } else {
331
            cur_line_char = cur_char % r->htotal;
332
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
333
                val |= ST01_DISP_ENABLE;
334
            }
335
        }
336

    
337
        return val;
338
    } else {
339
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
340
    }
341
}
342

    
343
static uint8_t vga_dumb_retrace(VGACommonState *s)
344
{
345
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
346
}
347

    
348
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
349
{
350
    if (s->msr & VGA_MIS_COLOR) {
351
        /* Color */
352
        return (addr >= 0x3b0 && addr <= 0x3bf);
353
    } else {
354
        /* Monochrome */
355
        return (addr >= 0x3d0 && addr <= 0x3df);
356
    }
357
}
358

    
359
uint32_t vga_ioport_read(void *opaque, uint32_t addr)
360
{
361
    VGACommonState *s = opaque;
362
    int val, index;
363

    
364
    qemu_flush_coalesced_mmio_buffer();
365

    
366
    if (vga_ioport_invalid(s, addr)) {
367
        val = 0xff;
368
    } else {
369
        switch(addr) {
370
        case VGA_ATT_W:
371
            if (s->ar_flip_flop == 0) {
372
                val = s->ar_index;
373
            } else {
374
                val = 0;
375
            }
376
            break;
377
        case VGA_ATT_R:
378
            index = s->ar_index & 0x1f;
379
            if (index < VGA_ATT_C) {
380
                val = s->ar[index];
381
            } else {
382
                val = 0;
383
            }
384
            break;
385
        case VGA_MIS_W:
386
            val = s->st00;
387
            break;
388
        case VGA_SEQ_I:
389
            val = s->sr_index;
390
            break;
391
        case VGA_SEQ_D:
392
            val = s->sr[s->sr_index];
393
#ifdef DEBUG_VGA_REG
394
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
395
#endif
396
            break;
397
        case VGA_PEL_IR:
398
            val = s->dac_state;
399
            break;
400
        case VGA_PEL_IW:
401
            val = s->dac_write_index;
402
            break;
403
        case VGA_PEL_D:
404
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
405
            if (++s->dac_sub_index == 3) {
406
                s->dac_sub_index = 0;
407
                s->dac_read_index++;
408
            }
409
            break;
410
        case VGA_FTC_R:
411
            val = s->fcr;
412
            break;
413
        case VGA_MIS_R:
414
            val = s->msr;
415
            break;
416
        case VGA_GFX_I:
417
            val = s->gr_index;
418
            break;
419
        case VGA_GFX_D:
420
            val = s->gr[s->gr_index];
421
#ifdef DEBUG_VGA_REG
422
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
423
#endif
424
            break;
425
        case VGA_CRT_IM:
426
        case VGA_CRT_IC:
427
            val = s->cr_index;
428
            break;
429
        case VGA_CRT_DM:
430
        case VGA_CRT_DC:
431
            val = s->cr[s->cr_index];
432
#ifdef DEBUG_VGA_REG
433
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
434
#endif
435
            break;
436
        case VGA_IS1_RM:
437
        case VGA_IS1_RC:
438
            /* just toggle to fool polling */
439
            val = s->st01 = s->retrace(s);
440
            s->ar_flip_flop = 0;
441
            break;
442
        default:
443
            val = 0x00;
444
            break;
445
        }
446
    }
447
#if defined(DEBUG_VGA)
448
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
449
#endif
450
    return val;
451
}
452

    
453
void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
454
{
455
    VGACommonState *s = opaque;
456
    int index;
457

    
458
    qemu_flush_coalesced_mmio_buffer();
459

    
460
    /* check port range access depending on color/monochrome mode */
461
    if (vga_ioport_invalid(s, addr)) {
462
        return;
463
    }
464
#ifdef DEBUG_VGA
465
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
466
#endif
467

    
468
    switch(addr) {
469
    case VGA_ATT_W:
470
        if (s->ar_flip_flop == 0) {
471
            val &= 0x3f;
472
            s->ar_index = val;
473
        } else {
474
            index = s->ar_index & 0x1f;
475
            switch(index) {
476
            case VGA_ATC_PALETTE0 ... VGA_ATC_PALETTEF:
477
                s->ar[index] = val & 0x3f;
478
                break;
479
            case VGA_ATC_MODE:
480
                s->ar[index] = val & ~0x10;
481
                break;
482
            case VGA_ATC_OVERSCAN:
483
                s->ar[index] = val;
484
                break;
485
            case VGA_ATC_PLANE_ENABLE:
486
                s->ar[index] = val & ~0xc0;
487
                break;
488
            case VGA_ATC_PEL:
489
                s->ar[index] = val & ~0xf0;
490
                break;
491
            case VGA_ATC_COLOR_PAGE:
492
                s->ar[index] = val & ~0xf0;
493
                break;
494
            default:
495
                break;
496
            }
497
        }
498
        s->ar_flip_flop ^= 1;
499
        break;
500
    case VGA_MIS_W:
501
        s->msr = val & ~0x10;
502
        s->update_retrace_info(s);
503
        break;
504
    case VGA_SEQ_I:
505
        s->sr_index = val & 7;
506
        break;
507
    case VGA_SEQ_D:
508
#ifdef DEBUG_VGA_REG
509
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
510
#endif
511
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
512
        if (s->sr_index == VGA_SEQ_CLOCK_MODE) {
513
            s->update_retrace_info(s);
514
        }
515
        vga_update_memory_access(s);
516
        break;
517
    case VGA_PEL_IR:
518
        s->dac_read_index = val;
519
        s->dac_sub_index = 0;
520
        s->dac_state = 3;
521
        break;
522
    case VGA_PEL_IW:
523
        s->dac_write_index = val;
524
        s->dac_sub_index = 0;
525
        s->dac_state = 0;
526
        break;
527
    case VGA_PEL_D:
528
        s->dac_cache[s->dac_sub_index] = val;
529
        if (++s->dac_sub_index == 3) {
530
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
531
            s->dac_sub_index = 0;
532
            s->dac_write_index++;
533
        }
534
        break;
535
    case VGA_GFX_I:
536
        s->gr_index = val & 0x0f;
537
        break;
538
    case VGA_GFX_D:
539
#ifdef DEBUG_VGA_REG
540
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
541
#endif
542
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
543
        vga_update_memory_access(s);
544
        break;
545
    case VGA_CRT_IM:
546
    case VGA_CRT_IC:
547
        s->cr_index = val;
548
        break;
549
    case VGA_CRT_DM:
550
    case VGA_CRT_DC:
551
#ifdef DEBUG_VGA_REG
552
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
553
#endif
554
        /* handle CR0-7 protection */
555
        if ((s->cr[VGA_CRTC_V_SYNC_END] & VGA_CR11_LOCK_CR0_CR7) &&
556
            s->cr_index <= VGA_CRTC_OVERFLOW) {
557
            /* can always write bit 4 of CR7 */
558
            if (s->cr_index == VGA_CRTC_OVERFLOW) {
559
                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x10) |
560
                    (val & 0x10);
561
            }
562
            return;
563
        }
564
        s->cr[s->cr_index] = val;
565

    
566
        switch(s->cr_index) {
567
        case VGA_CRTC_H_TOTAL:
568
        case VGA_CRTC_H_SYNC_START:
569
        case VGA_CRTC_H_SYNC_END:
570
        case VGA_CRTC_V_TOTAL:
571
        case VGA_CRTC_OVERFLOW:
572
        case VGA_CRTC_V_SYNC_END:
573
        case VGA_CRTC_MODE:
574
            s->update_retrace_info(s);
575
            break;
576
        }
577
        break;
578
    case VGA_IS1_RM:
579
    case VGA_IS1_RC:
580
        s->fcr = val & 0x10;
581
        break;
582
    }
583
}
584

    
585
#ifdef CONFIG_BOCHS_VBE
586
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
587
{
588
    VGACommonState *s = opaque;
589
    uint32_t val;
590
    val = s->vbe_index;
591
    return val;
592
}
593

    
594
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
595
{
596
    VGACommonState *s = opaque;
597
    uint32_t val;
598

    
599
    if (s->vbe_index < VBE_DISPI_INDEX_NB) {
600
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
601
            switch(s->vbe_index) {
602
                /* XXX: do not hardcode ? */
603
            case VBE_DISPI_INDEX_XRES:
604
                val = VBE_DISPI_MAX_XRES;
605
                break;
606
            case VBE_DISPI_INDEX_YRES:
607
                val = VBE_DISPI_MAX_YRES;
608
                break;
609
            case VBE_DISPI_INDEX_BPP:
610
                val = VBE_DISPI_MAX_BPP;
611
                break;
612
            default:
613
                val = s->vbe_regs[s->vbe_index];
614
                break;
615
            }
616
        } else {
617
            val = s->vbe_regs[s->vbe_index];
618
        }
619
    } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
620
        val = s->vram_size / (64 * 1024);
621
    } else {
622
        val = 0;
623
    }
624
#ifdef DEBUG_BOCHS_VBE
625
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
626
#endif
627
    return val;
628
}
629

    
630
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
631
{
632
    VGACommonState *s = opaque;
633
    s->vbe_index = val;
634
}
635

    
636
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
637
{
638
    VGACommonState *s = opaque;
639

    
640
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
641
#ifdef DEBUG_BOCHS_VBE
642
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
643
#endif
644
        switch(s->vbe_index) {
645
        case VBE_DISPI_INDEX_ID:
646
            if (val == VBE_DISPI_ID0 ||
647
                val == VBE_DISPI_ID1 ||
648
                val == VBE_DISPI_ID2 ||
649
                val == VBE_DISPI_ID3 ||
650
                val == VBE_DISPI_ID4) {
651
                s->vbe_regs[s->vbe_index] = val;
652
            }
653
            break;
654
        case VBE_DISPI_INDEX_XRES:
655
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
656
                s->vbe_regs[s->vbe_index] = val;
657
            }
658
            break;
659
        case VBE_DISPI_INDEX_YRES:
660
            if (val <= VBE_DISPI_MAX_YRES) {
661
                s->vbe_regs[s->vbe_index] = val;
662
            }
663
            break;
664
        case VBE_DISPI_INDEX_BPP:
665
            if (val == 0)
666
                val = 8;
667
            if (val == 4 || val == 8 || val == 15 ||
668
                val == 16 || val == 24 || val == 32) {
669
                s->vbe_regs[s->vbe_index] = val;
670
            }
671
            break;
672
        case VBE_DISPI_INDEX_BANK:
673
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
674
              val &= (s->vbe_bank_mask >> 2);
675
            } else {
676
              val &= s->vbe_bank_mask;
677
            }
678
            s->vbe_regs[s->vbe_index] = val;
679
            s->bank_offset = (val << 16);
680
            vga_update_memory_access(s);
681
            break;
682
        case VBE_DISPI_INDEX_ENABLE:
683
            if ((val & VBE_DISPI_ENABLED) &&
684
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
685
                int h, shift_control;
686

    
687
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
688
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
689
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
690
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
691
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
692
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
693

    
694
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
695
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
696
                else
697
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
698
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
699
                s->vbe_start_addr = 0;
700

    
701
                /* clear the screen (should be done in BIOS) */
702
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
703
                    memset(s->vram_ptr, 0,
704
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
705
                }
706

    
707
                /* we initialize the VGA graphic mode (should be done
708
                   in BIOS) */
709
                /* graphic mode + memory map 1 */
710
                s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
711
                    VGA_GR06_GRAPHICS_MODE;
712
                s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
713
                s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
714
                /* width */
715
                s->cr[VGA_CRTC_H_DISP] =
716
                    (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
717
                /* height (only meaningful if < 1024) */
718
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
719
                s->cr[VGA_CRTC_V_DISP_END] = h;
720
                s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
721
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
722
                /* line compare to 1023 */
723
                s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
724
                s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
725
                s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
726

    
727
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
728
                    shift_control = 0;
729
                    s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
730
                } else {
731
                    shift_control = 2;
732
                    /* set chain 4 mode */
733
                    s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
734
                    /* activate all planes */
735
                    s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
736
                }
737
                s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
738
                    (shift_control << 5);
739
                s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
740
            } else {
741
                /* XXX: the bios should do that */
742
                s->bank_offset = 0;
743
            }
744
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
745
            s->vbe_regs[s->vbe_index] = val;
746
            vga_update_memory_access(s);
747
            break;
748
        case VBE_DISPI_INDEX_VIRT_WIDTH:
749
            {
750
                int w, h, line_offset;
751

    
752
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
753
                    return;
754
                w = val;
755
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
756
                    line_offset = w >> 1;
757
                else
758
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
759
                h = s->vram_size / line_offset;
760
                /* XXX: support weird bochs semantics ? */
761
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
762
                    return;
763
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
764
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
765
                s->vbe_line_offset = line_offset;
766
            }
767
            break;
768
        case VBE_DISPI_INDEX_X_OFFSET:
769
        case VBE_DISPI_INDEX_Y_OFFSET:
770
            {
771
                int x;
772
                s->vbe_regs[s->vbe_index] = val;
773
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
774
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
775
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
776
                    s->vbe_start_addr += x >> 1;
777
                else
778
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
779
                s->vbe_start_addr >>= 2;
780
            }
781
            break;
782
        default:
783
            break;
784
        }
785
    }
786
}
787
#endif
788

    
789
/* called for accesses between 0xa0000 and 0xc0000 */
790
uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
791
{
792
    int memory_map_mode, plane;
793
    uint32_t ret;
794

    
795
    /* convert to VGA memory offset */
796
    memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
797
    addr &= 0x1ffff;
798
    switch(memory_map_mode) {
799
    case 0:
800
        break;
801
    case 1:
802
        if (addr >= 0x10000)
803
            return 0xff;
804
        addr += s->bank_offset;
805
        break;
806
    case 2:
807
        addr -= 0x10000;
808
        if (addr >= 0x8000)
809
            return 0xff;
810
        break;
811
    default:
812
    case 3:
813
        addr -= 0x18000;
814
        if (addr >= 0x8000)
815
            return 0xff;
816
        break;
817
    }
818

    
819
    if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
820
        /* chain 4 mode : simplest access */
821
        ret = s->vram_ptr[addr];
822
    } else if (s->gr[VGA_GFX_MODE] & 0x10) {
823
        /* odd/even mode (aka text mode mapping) */
824
        plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
825
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
826
    } else {
827
        /* standard VGA latched access */
828
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
829

    
830
        if (!(s->gr[VGA_GFX_MODE] & 0x08)) {
831
            /* read mode 0 */
832
            plane = s->gr[VGA_GFX_PLANE_READ];
833
            ret = GET_PLANE(s->latch, plane);
834
        } else {
835
            /* read mode 1 */
836
            ret = (s->latch ^ mask16[s->gr[VGA_GFX_COMPARE_VALUE]]) &
837
                mask16[s->gr[VGA_GFX_COMPARE_MASK]];
838
            ret |= ret >> 16;
839
            ret |= ret >> 8;
840
            ret = (~ret) & 0xff;
841
        }
842
    }
843
    return ret;
844
}
845

    
846
/* called for accesses between 0xa0000 and 0xc0000 */
847
void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
848
{
849
    int memory_map_mode, plane, write_mode, b, func_select, mask;
850
    uint32_t write_mask, bit_mask, set_mask;
851

    
852
#ifdef DEBUG_VGA_MEM
853
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
854
#endif
855
    /* convert to VGA memory offset */
856
    memory_map_mode = (s->gr[VGA_GFX_MISC] >> 2) & 3;
857
    addr &= 0x1ffff;
858
    switch(memory_map_mode) {
859
    case 0:
860
        break;
861
    case 1:
862
        if (addr >= 0x10000)
863
            return;
864
        addr += s->bank_offset;
865
        break;
866
    case 2:
867
        addr -= 0x10000;
868
        if (addr >= 0x8000)
869
            return;
870
        break;
871
    default:
872
    case 3:
873
        addr -= 0x18000;
874
        if (addr >= 0x8000)
875
            return;
876
        break;
877
    }
878

    
879
    if (s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
880
        /* chain 4 mode : simplest access */
881
        plane = addr & 3;
882
        mask = (1 << plane);
883
        if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
884
            s->vram_ptr[addr] = val;
885
#ifdef DEBUG_VGA_MEM
886
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
887
#endif
888
            s->plane_updated |= mask; /* only used to detect font change */
889
            memory_region_set_dirty(&s->vram, addr, 1);
890
        }
891
    } else if (s->gr[VGA_GFX_MODE] & 0x10) {
892
        /* odd/even mode (aka text mode mapping) */
893
        plane = (s->gr[VGA_GFX_PLANE_READ] & 2) | (addr & 1);
894
        mask = (1 << plane);
895
        if (s->sr[VGA_SEQ_PLANE_WRITE] & mask) {
896
            addr = ((addr & ~1) << 1) | plane;
897
            s->vram_ptr[addr] = val;
898
#ifdef DEBUG_VGA_MEM
899
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
900
#endif
901
            s->plane_updated |= mask; /* only used to detect font change */
902
            memory_region_set_dirty(&s->vram, addr, 1);
903
        }
904
    } else {
905
        /* standard VGA latched access */
906
        write_mode = s->gr[VGA_GFX_MODE] & 3;
907
        switch(write_mode) {
908
        default:
909
        case 0:
910
            /* rotate */
911
            b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
912
            val = ((val >> b) | (val << (8 - b))) & 0xff;
913
            val |= val << 8;
914
            val |= val << 16;
915

    
916
            /* apply set/reset mask */
917
            set_mask = mask16[s->gr[VGA_GFX_SR_ENABLE]];
918
            val = (val & ~set_mask) |
919
                (mask16[s->gr[VGA_GFX_SR_VALUE]] & set_mask);
920
            bit_mask = s->gr[VGA_GFX_BIT_MASK];
921
            break;
922
        case 1:
923
            val = s->latch;
924
            goto do_write;
925
        case 2:
926
            val = mask16[val & 0x0f];
927
            bit_mask = s->gr[VGA_GFX_BIT_MASK];
928
            break;
929
        case 3:
930
            /* rotate */
931
            b = s->gr[VGA_GFX_DATA_ROTATE] & 7;
932
            val = (val >> b) | (val << (8 - b));
933

    
934
            bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
935
            val = mask16[s->gr[VGA_GFX_SR_VALUE]];
936
            break;
937
        }
938

    
939
        /* apply logical operation */
940
        func_select = s->gr[VGA_GFX_DATA_ROTATE] >> 3;
941
        switch(func_select) {
942
        case 0:
943
        default:
944
            /* nothing to do */
945
            break;
946
        case 1:
947
            /* and */
948
            val &= s->latch;
949
            break;
950
        case 2:
951
            /* or */
952
            val |= s->latch;
953
            break;
954
        case 3:
955
            /* xor */
956
            val ^= s->latch;
957
            break;
958
        }
959

    
960
        /* apply bit mask */
961
        bit_mask |= bit_mask << 8;
962
        bit_mask |= bit_mask << 16;
963
        val = (val & bit_mask) | (s->latch & ~bit_mask);
964

    
965
    do_write:
966
        /* mask data according to sr[2] */
967
        mask = s->sr[VGA_SEQ_PLANE_WRITE];
968
        s->plane_updated |= mask; /* only used to detect font change */
969
        write_mask = mask16[mask];
970
        ((uint32_t *)s->vram_ptr)[addr] =
971
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
972
            (val & write_mask);
973
#ifdef DEBUG_VGA_MEM
974
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
975
               addr * 4, write_mask, val);
976
#endif
977
        memory_region_set_dirty(&s->vram, addr << 2, sizeof(uint32_t));
978
    }
979
}
980

    
981
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
982
                             const uint8_t *font_ptr, int h,
983
                             uint32_t fgcol, uint32_t bgcol);
984
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
985
                                  const uint8_t *font_ptr, int h,
986
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
987
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
988
                                const uint8_t *s, int width);
989

    
990
#define DEPTH 8
991
#include "vga_template.h"
992

    
993
#define DEPTH 15
994
#include "vga_template.h"
995

    
996
#define BGR_FORMAT
997
#define DEPTH 15
998
#include "vga_template.h"
999

    
1000
#define DEPTH 16
1001
#include "vga_template.h"
1002

    
1003
#define BGR_FORMAT
1004
#define DEPTH 16
1005
#include "vga_template.h"
1006

    
1007
#define DEPTH 32
1008
#include "vga_template.h"
1009

    
1010
#define BGR_FORMAT
1011
#define DEPTH 32
1012
#include "vga_template.h"
1013

    
1014
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1015
{
1016
    unsigned int col;
1017
    col = rgb_to_pixel8(r, g, b);
1018
    col |= col << 8;
1019
    col |= col << 16;
1020
    return col;
1021
}
1022

    
1023
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1024
{
1025
    unsigned int col;
1026
    col = rgb_to_pixel15(r, g, b);
1027
    col |= col << 16;
1028
    return col;
1029
}
1030

    
1031
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1032
                                          unsigned int b)
1033
{
1034
    unsigned int col;
1035
    col = rgb_to_pixel15bgr(r, g, b);
1036
    col |= col << 16;
1037
    return col;
1038
}
1039

    
1040
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1041
{
1042
    unsigned int col;
1043
    col = rgb_to_pixel16(r, g, b);
1044
    col |= col << 16;
1045
    return col;
1046
}
1047

    
1048
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1049
                                          unsigned int b)
1050
{
1051
    unsigned int col;
1052
    col = rgb_to_pixel16bgr(r, g, b);
1053
    col |= col << 16;
1054
    return col;
1055
}
1056

    
1057
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1058
{
1059
    unsigned int col;
1060
    col = rgb_to_pixel32(r, g, b);
1061
    return col;
1062
}
1063

    
1064
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1065
{
1066
    unsigned int col;
1067
    col = rgb_to_pixel32bgr(r, g, b);
1068
    return col;
1069
}
1070

    
1071
/* return true if the palette was modified */
1072
static int update_palette16(VGACommonState *s)
1073
{
1074
    int full_update, i;
1075
    uint32_t v, col, *palette;
1076

    
1077
    full_update = 0;
1078
    palette = s->last_palette;
1079
    for(i = 0; i < 16; i++) {
1080
        v = s->ar[i];
1081
        if (s->ar[VGA_ATC_MODE] & 0x80) {
1082
            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
1083
        } else {
1084
            v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
1085
        }
1086
        v = v * 3;
1087
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1088
                              c6_to_8(s->palette[v + 1]),
1089
                              c6_to_8(s->palette[v + 2]));
1090
        if (col != palette[i]) {
1091
            full_update = 1;
1092
            palette[i] = col;
1093
        }
1094
    }
1095
    return full_update;
1096
}
1097

    
1098
/* return true if the palette was modified */
1099
static int update_palette256(VGACommonState *s)
1100
{
1101
    int full_update, i;
1102
    uint32_t v, col, *palette;
1103

    
1104
    full_update = 0;
1105
    palette = s->last_palette;
1106
    v = 0;
1107
    for(i = 0; i < 256; i++) {
1108
        if (s->dac_8bit) {
1109
          col = s->rgb_to_pixel(s->palette[v],
1110
                                s->palette[v + 1],
1111
                                s->palette[v + 2]);
1112
        } else {
1113
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1114
                                c6_to_8(s->palette[v + 1]),
1115
                                c6_to_8(s->palette[v + 2]));
1116
        }
1117
        if (col != palette[i]) {
1118
            full_update = 1;
1119
            palette[i] = col;
1120
        }
1121
        v += 3;
1122
    }
1123
    return full_update;
1124
}
1125

    
1126
static void vga_get_offsets(VGACommonState *s,
1127
                            uint32_t *pline_offset,
1128
                            uint32_t *pstart_addr,
1129
                            uint32_t *pline_compare)
1130
{
1131
    uint32_t start_addr, line_offset, line_compare;
1132
#ifdef CONFIG_BOCHS_VBE
1133
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1134
        line_offset = s->vbe_line_offset;
1135
        start_addr = s->vbe_start_addr;
1136
        line_compare = 65535;
1137
    } else
1138
#endif
1139
    {
1140
        /* compute line_offset in bytes */
1141
        line_offset = s->cr[VGA_CRTC_OFFSET];
1142
        line_offset <<= 3;
1143

    
1144
        /* starting address */
1145
        start_addr = s->cr[VGA_CRTC_START_LO] |
1146
            (s->cr[VGA_CRTC_START_HI] << 8);
1147

    
1148
        /* line compare */
1149
        line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
1150
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
1151
            ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
1152
    }
1153
    *pline_offset = line_offset;
1154
    *pstart_addr = start_addr;
1155
    *pline_compare = line_compare;
1156
}
1157

    
1158
/* update start_addr and line_offset. Return TRUE if modified */
1159
static int update_basic_params(VGACommonState *s)
1160
{
1161
    int full_update;
1162
    uint32_t start_addr, line_offset, line_compare;
1163

    
1164
    full_update = 0;
1165

    
1166
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1167

    
1168
    if (line_offset != s->line_offset ||
1169
        start_addr != s->start_addr ||
1170
        line_compare != s->line_compare) {
1171
        s->line_offset = line_offset;
1172
        s->start_addr = start_addr;
1173
        s->line_compare = line_compare;
1174
        full_update = 1;
1175
    }
1176
    return full_update;
1177
}
1178

    
1179
#define NB_DEPTHS 7
1180

    
1181
static inline int get_depth_index(DisplayState *s)
1182
{
1183
    switch(ds_get_bits_per_pixel(s)) {
1184
    default:
1185
    case 8:
1186
        return 0;
1187
    case 15:
1188
        return 1;
1189
    case 16:
1190
        return 2;
1191
    case 32:
1192
        if (is_surface_bgr(s->surface))
1193
            return 4;
1194
        else
1195
            return 3;
1196
    }
1197
}
1198

    
1199
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1200
    vga_draw_glyph8_8,
1201
    vga_draw_glyph8_16,
1202
    vga_draw_glyph8_16,
1203
    vga_draw_glyph8_32,
1204
    vga_draw_glyph8_32,
1205
    vga_draw_glyph8_16,
1206
    vga_draw_glyph8_16,
1207
};
1208

    
1209
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1210
    vga_draw_glyph16_8,
1211
    vga_draw_glyph16_16,
1212
    vga_draw_glyph16_16,
1213
    vga_draw_glyph16_32,
1214
    vga_draw_glyph16_32,
1215
    vga_draw_glyph16_16,
1216
    vga_draw_glyph16_16,
1217
};
1218

    
1219
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1220
    vga_draw_glyph9_8,
1221
    vga_draw_glyph9_16,
1222
    vga_draw_glyph9_16,
1223
    vga_draw_glyph9_32,
1224
    vga_draw_glyph9_32,
1225
    vga_draw_glyph9_16,
1226
    vga_draw_glyph9_16,
1227
};
1228

    
1229
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1242
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1243
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1244
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1245
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1246
};
1247

    
1248
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1249
                                    int *pcwidth, int *pcheight)
1250
{
1251
    int width, cwidth, height, cheight;
1252

    
1253
    /* total width & height */
1254
    cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1255
    cwidth = 8;
1256
    if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
1257
        cwidth = 9;
1258
    }
1259
    if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
1260
        cwidth = 16; /* NOTE: no 18 pixel wide */
1261
    }
1262
    width = (s->cr[VGA_CRTC_H_DISP] + 1);
1263
    if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1264
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1265
        height = 100;
1266
    } else {
1267
        height = s->cr[VGA_CRTC_V_DISP_END] |
1268
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1269
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1270
        height = (height + 1) / cheight;
1271
    }
1272

    
1273
    *pwidth = width;
1274
    *pheight = height;
1275
    *pcwidth = cwidth;
1276
    *pcheight = cheight;
1277
}
1278

    
1279
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1280

    
1281
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1282
    rgb_to_pixel8_dup,
1283
    rgb_to_pixel15_dup,
1284
    rgb_to_pixel16_dup,
1285
    rgb_to_pixel32_dup,
1286
    rgb_to_pixel32bgr_dup,
1287
    rgb_to_pixel15bgr_dup,
1288
    rgb_to_pixel16bgr_dup,
1289
};
1290

    
1291
/*
1292
 * Text mode update
1293
 * Missing:
1294
 * - double scan
1295
 * - double width
1296
 * - underline
1297
 * - flashing
1298
 */
1299
static void vga_draw_text(VGACommonState *s, int full_update)
1300
{
1301
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1302
    int cx_min, cx_max, linesize, x_incr, line, line1;
1303
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1304
    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1305
    const uint8_t *font_ptr, *font_base[2];
1306
    int dup9, line_offset, depth_index;
1307
    uint32_t *palette;
1308
    uint32_t *ch_attr_ptr;
1309
    vga_draw_glyph8_func *vga_draw_glyph8;
1310
    vga_draw_glyph9_func *vga_draw_glyph9;
1311
    int64_t now = qemu_get_clock_ms(vm_clock);
1312

    
1313
    /* compute font data address (in plane 2) */
1314
    v = s->sr[VGA_SEQ_CHARACTER_MAP];
1315
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1316
    if (offset != s->font_offsets[0]) {
1317
        s->font_offsets[0] = offset;
1318
        full_update = 1;
1319
    }
1320
    font_base[0] = s->vram_ptr + offset;
1321

    
1322
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1323
    font_base[1] = s->vram_ptr + offset;
1324
    if (offset != s->font_offsets[1]) {
1325
        s->font_offsets[1] = offset;
1326
        full_update = 1;
1327
    }
1328
    if (s->plane_updated & (1 << 2) || s->chain4_alias) {
1329
        /* if the plane 2 was modified since the last display, it
1330
           indicates the font may have been modified */
1331
        s->plane_updated = 0;
1332
        full_update = 1;
1333
    }
1334
    full_update |= update_basic_params(s);
1335

    
1336
    line_offset = s->line_offset;
1337

    
1338
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1339
    if ((height * width) <= 1) {
1340
        /* better than nothing: exit if transient size is too small */
1341
        return;
1342
    }
1343
    if ((height * width) > CH_ATTR_SIZE) {
1344
        /* better than nothing: exit if transient size is too big */
1345
        return;
1346
    }
1347

    
1348
    if (width != s->last_width || height != s->last_height ||
1349
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1350
        s->last_scr_width = width * cw;
1351
        s->last_scr_height = height * cheight;
1352
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1353
        s->last_depth = 0;
1354
        s->last_width = width;
1355
        s->last_height = height;
1356
        s->last_ch = cheight;
1357
        s->last_cw = cw;
1358
        full_update = 1;
1359
    }
1360
    s->rgb_to_pixel =
1361
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1362
    full_update |= update_palette16(s);
1363
    palette = s->last_palette;
1364
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1365

    
1366
    cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1367
                     s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1368
    if (cursor_offset != s->cursor_offset ||
1369
        s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1370
        s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1371
      /* if the cursor position changed, we update the old and new
1372
         chars */
1373
        if (s->cursor_offset < CH_ATTR_SIZE)
1374
            s->last_ch_attr[s->cursor_offset] = -1;
1375
        if (cursor_offset < CH_ATTR_SIZE)
1376
            s->last_ch_attr[cursor_offset] = -1;
1377
        s->cursor_offset = cursor_offset;
1378
        s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1379
        s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1380
    }
1381
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1382
    if (now >= s->cursor_blink_time) {
1383
        s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
1384
        s->cursor_visible_phase = !s->cursor_visible_phase;
1385
    }
1386

    
1387
    depth_index = get_depth_index(s->ds);
1388
    if (cw == 16)
1389
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1390
    else
1391
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1392
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1393

    
1394
    dest = ds_get_data(s->ds);
1395
    linesize = ds_get_linesize(s->ds);
1396
    ch_attr_ptr = s->last_ch_attr;
1397
    line = 0;
1398
    offset = s->start_addr * 4;
1399
    for(cy = 0; cy < height; cy++) {
1400
        d1 = dest;
1401
        src = s->vram_ptr + offset;
1402
        cx_min = width;
1403
        cx_max = -1;
1404
        for(cx = 0; cx < width; cx++) {
1405
            ch_attr = *(uint16_t *)src;
1406
            if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
1407
                if (cx < cx_min)
1408
                    cx_min = cx;
1409
                if (cx > cx_max)
1410
                    cx_max = cx;
1411
                *ch_attr_ptr = ch_attr;
1412
#ifdef HOST_WORDS_BIGENDIAN
1413
                ch = ch_attr >> 8;
1414
                cattr = ch_attr & 0xff;
1415
#else
1416
                ch = ch_attr & 0xff;
1417
                cattr = ch_attr >> 8;
1418
#endif
1419
                font_ptr = font_base[(cattr >> 3) & 1];
1420
                font_ptr += 32 * 4 * ch;
1421
                bgcol = palette[cattr >> 4];
1422
                fgcol = palette[cattr & 0x0f];
1423
                if (cw != 9) {
1424
                    vga_draw_glyph8(d1, linesize,
1425
                                    font_ptr, cheight, fgcol, bgcol);
1426
                } else {
1427
                    dup9 = 0;
1428
                    if (ch >= 0xb0 && ch <= 0xdf &&
1429
                        (s->ar[VGA_ATC_MODE] & 0x04)) {
1430
                        dup9 = 1;
1431
                    }
1432
                    vga_draw_glyph9(d1, linesize,
1433
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1434
                }
1435
                if (src == cursor_ptr &&
1436
                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1437
                    s->cursor_visible_phase) {
1438
                    int line_start, line_last, h;
1439
                    /* draw the cursor */
1440
                    line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1441
                    line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1442
                    /* XXX: check that */
1443
                    if (line_last > cheight - 1)
1444
                        line_last = cheight - 1;
1445
                    if (line_last >= line_start && line_start < cheight) {
1446
                        h = line_last - line_start + 1;
1447
                        d = d1 + linesize * line_start;
1448
                        if (cw != 9) {
1449
                            vga_draw_glyph8(d, linesize,
1450
                                            cursor_glyph, h, fgcol, bgcol);
1451
                        } else {
1452
                            vga_draw_glyph9(d, linesize,
1453
                                            cursor_glyph, h, fgcol, bgcol, 1);
1454
                        }
1455
                    }
1456
                }
1457
            }
1458
            d1 += x_incr;
1459
            src += 4;
1460
            ch_attr_ptr++;
1461
        }
1462
        if (cx_max != -1) {
1463
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1464
                       (cx_max - cx_min + 1) * cw, cheight);
1465
        }
1466
        dest += linesize * cheight;
1467
        line1 = line + cheight;
1468
        offset += line_offset;
1469
        if (line < s->line_compare && line1 >= s->line_compare) {
1470
            offset = 0;
1471
        }
1472
        line = line1;
1473
    }
1474
}
1475

    
1476
enum {
1477
    VGA_DRAW_LINE2,
1478
    VGA_DRAW_LINE2D2,
1479
    VGA_DRAW_LINE4,
1480
    VGA_DRAW_LINE4D2,
1481
    VGA_DRAW_LINE8D2,
1482
    VGA_DRAW_LINE8,
1483
    VGA_DRAW_LINE15,
1484
    VGA_DRAW_LINE16,
1485
    VGA_DRAW_LINE24,
1486
    VGA_DRAW_LINE32,
1487
    VGA_DRAW_LINE_NB,
1488
};
1489

    
1490
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1491
    vga_draw_line2_8,
1492
    vga_draw_line2_16,
1493
    vga_draw_line2_16,
1494
    vga_draw_line2_32,
1495
    vga_draw_line2_32,
1496
    vga_draw_line2_16,
1497
    vga_draw_line2_16,
1498

    
1499
    vga_draw_line2d2_8,
1500
    vga_draw_line2d2_16,
1501
    vga_draw_line2d2_16,
1502
    vga_draw_line2d2_32,
1503
    vga_draw_line2d2_32,
1504
    vga_draw_line2d2_16,
1505
    vga_draw_line2d2_16,
1506

    
1507
    vga_draw_line4_8,
1508
    vga_draw_line4_16,
1509
    vga_draw_line4_16,
1510
    vga_draw_line4_32,
1511
    vga_draw_line4_32,
1512
    vga_draw_line4_16,
1513
    vga_draw_line4_16,
1514

    
1515
    vga_draw_line4d2_8,
1516
    vga_draw_line4d2_16,
1517
    vga_draw_line4d2_16,
1518
    vga_draw_line4d2_32,
1519
    vga_draw_line4d2_32,
1520
    vga_draw_line4d2_16,
1521
    vga_draw_line4d2_16,
1522

    
1523
    vga_draw_line8d2_8,
1524
    vga_draw_line8d2_16,
1525
    vga_draw_line8d2_16,
1526
    vga_draw_line8d2_32,
1527
    vga_draw_line8d2_32,
1528
    vga_draw_line8d2_16,
1529
    vga_draw_line8d2_16,
1530

    
1531
    vga_draw_line8_8,
1532
    vga_draw_line8_16,
1533
    vga_draw_line8_16,
1534
    vga_draw_line8_32,
1535
    vga_draw_line8_32,
1536
    vga_draw_line8_16,
1537
    vga_draw_line8_16,
1538

    
1539
    vga_draw_line15_8,
1540
    vga_draw_line15_15,
1541
    vga_draw_line15_16,
1542
    vga_draw_line15_32,
1543
    vga_draw_line15_32bgr,
1544
    vga_draw_line15_15bgr,
1545
    vga_draw_line15_16bgr,
1546

    
1547
    vga_draw_line16_8,
1548
    vga_draw_line16_15,
1549
    vga_draw_line16_16,
1550
    vga_draw_line16_32,
1551
    vga_draw_line16_32bgr,
1552
    vga_draw_line16_15bgr,
1553
    vga_draw_line16_16bgr,
1554

    
1555
    vga_draw_line24_8,
1556
    vga_draw_line24_15,
1557
    vga_draw_line24_16,
1558
    vga_draw_line24_32,
1559
    vga_draw_line24_32bgr,
1560
    vga_draw_line24_15bgr,
1561
    vga_draw_line24_16bgr,
1562

    
1563
    vga_draw_line32_8,
1564
    vga_draw_line32_15,
1565
    vga_draw_line32_16,
1566
    vga_draw_line32_32,
1567
    vga_draw_line32_32bgr,
1568
    vga_draw_line32_15bgr,
1569
    vga_draw_line32_16bgr,
1570
};
1571

    
1572
static int vga_get_bpp(VGACommonState *s)
1573
{
1574
    int ret;
1575
#ifdef CONFIG_BOCHS_VBE
1576
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1577
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1578
    } else
1579
#endif
1580
    {
1581
        ret = 0;
1582
    }
1583
    return ret;
1584
}
1585

    
1586
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1587
{
1588
    int width, height;
1589

    
1590
#ifdef CONFIG_BOCHS_VBE
1591
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1592
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1593
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1594
    } else
1595
#endif
1596
    {
1597
        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1598
        height = s->cr[VGA_CRTC_V_DISP_END] |
1599
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1600
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1601
        height = (height + 1);
1602
    }
1603
    *pwidth = width;
1604
    *pheight = height;
1605
}
1606

    
1607
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1608
{
1609
    int y;
1610
    if (y1 >= VGA_MAX_HEIGHT)
1611
        return;
1612
    if (y2 >= VGA_MAX_HEIGHT)
1613
        y2 = VGA_MAX_HEIGHT;
1614
    for(y = y1; y < y2; y++) {
1615
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1616
    }
1617
}
1618

    
1619
static void vga_sync_dirty_bitmap(VGACommonState *s)
1620
{
1621
    memory_region_sync_dirty_bitmap(&s->vram);
1622
}
1623

    
1624
void vga_dirty_log_start(VGACommonState *s)
1625
{
1626
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1627
}
1628

    
1629
void vga_dirty_log_stop(VGACommonState *s)
1630
{
1631
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1632
}
1633

    
1634
/*
1635
 * graphic modes
1636
 */
1637
static 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[VGA_GFX_MODE] >> 5) & 3;
1656
    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1657
    if (shift_control != 1) {
1658
        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1659
            - 1;
1660
    } else {
1661
        /* in CGA modes, multi_scan is ignored */
1662
        /* XXX: is it correct ? */
1663
        multi_scan = double_scan;
1664
    }
1665
    multi_run = multi_scan;
1666
    if (shift_control != s->shift_control ||
1667
        double_scan != s->double_scan) {
1668
        full_update = 1;
1669
        s->shift_control = shift_control;
1670
        s->double_scan = double_scan;
1671
    }
1672

    
1673
    if (shift_control == 0) {
1674
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1675
            disp_width <<= 1;
1676
        }
1677
    } else if (shift_control == 1) {
1678
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1679
            disp_width <<= 1;
1680
        }
1681
    }
1682

    
1683
    depth = s->get_bpp(s);
1684
    if (s->line_offset != s->last_line_offset ||
1685
        disp_width != s->last_width ||
1686
        height != s->last_height ||
1687
        s->last_depth != depth) {
1688
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1689
        if (depth == 16 || depth == 32) {
1690
#else
1691
        if (depth == 32) {
1692
#endif
1693
            qemu_free_displaysurface(s->ds);
1694
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1695
                    s->line_offset,
1696
                    s->vram_ptr + (s->start_addr * 4));
1697
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1698
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1699
#endif
1700
            dpy_resize(s->ds);
1701
        } else {
1702
            qemu_console_resize(s->ds, disp_width, height);
1703
        }
1704
        s->last_scr_width = disp_width;
1705
        s->last_scr_height = height;
1706
        s->last_width = disp_width;
1707
        s->last_height = height;
1708
        s->last_line_offset = s->line_offset;
1709
        s->last_depth = depth;
1710
        full_update = 1;
1711
    } else if (is_buffer_shared(s->ds->surface) &&
1712
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1713
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1714
        dpy_setdata(s->ds);
1715
    }
1716

    
1717
    s->rgb_to_pixel =
1718
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1719

    
1720
    if (shift_control == 0) {
1721
        full_update |= update_palette16(s);
1722
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1723
            v = VGA_DRAW_LINE4D2;
1724
        } else {
1725
            v = VGA_DRAW_LINE4;
1726
        }
1727
        bits = 4;
1728
    } else if (shift_control == 1) {
1729
        full_update |= update_palette16(s);
1730
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1731
            v = VGA_DRAW_LINE2D2;
1732
        } else {
1733
            v = VGA_DRAW_LINE2;
1734
        }
1735
        bits = 4;
1736
    } else {
1737
        switch(s->get_bpp(s)) {
1738
        default:
1739
        case 0:
1740
            full_update |= update_palette256(s);
1741
            v = VGA_DRAW_LINE8D2;
1742
            bits = 4;
1743
            break;
1744
        case 8:
1745
            full_update |= update_palette256(s);
1746
            v = VGA_DRAW_LINE8;
1747
            bits = 8;
1748
            break;
1749
        case 15:
1750
            v = VGA_DRAW_LINE15;
1751
            bits = 16;
1752
            break;
1753
        case 16:
1754
            v = VGA_DRAW_LINE16;
1755
            bits = 16;
1756
            break;
1757
        case 24:
1758
            v = VGA_DRAW_LINE24;
1759
            bits = 24;
1760
            break;
1761
        case 32:
1762
            v = VGA_DRAW_LINE32;
1763
            bits = 32;
1764
            break;
1765
        }
1766
    }
1767
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1768

    
1769
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1770
        s->cursor_invalidate(s);
1771

    
1772
    line_offset = s->line_offset;
1773
#if 0
1774
    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",
1775
           width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1776
           s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
1777
#endif
1778
    addr1 = (s->start_addr * 4);
1779
    bwidth = (width * bits + 7) / 8;
1780
    y_start = -1;
1781
    page_min = -1;
1782
    page_max = 0;
1783
    d = ds_get_data(s->ds);
1784
    linesize = ds_get_linesize(s->ds);
1785
    y1 = 0;
1786
    for(y = 0; y < height; y++) {
1787
        addr = addr1;
1788
        if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1789
            int shift;
1790
            /* CGA compatibility handling */
1791
            shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1792
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1793
        }
1794
        if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1795
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1796
        }
1797
        update = full_update;
1798
        page0 = addr;
1799
        page1 = addr + bwidth - 1;
1800
        update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
1801
                                          DIRTY_MEMORY_VGA);
1802
        /* explicit invalidation for the hardware cursor */
1803
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1804
        if (update) {
1805
            if (y_start < 0)
1806
                y_start = y;
1807
            if (page0 < page_min)
1808
                page_min = page0;
1809
            if (page1 > page_max)
1810
                page_max = page1;
1811
            if (!(is_buffer_shared(s->ds->surface))) {
1812
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1813
                if (s->cursor_draw_line)
1814
                    s->cursor_draw_line(s, d, y);
1815
            }
1816
        } else {
1817
            if (y_start >= 0) {
1818
                /* flush to display */
1819
                dpy_update(s->ds, 0, y_start,
1820
                           disp_width, y - y_start);
1821
                y_start = -1;
1822
            }
1823
        }
1824
        if (!multi_run) {
1825
            mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1826
            if ((y1 & mask) == mask)
1827
                addr1 += line_offset;
1828
            y1++;
1829
            multi_run = multi_scan;
1830
        } else {
1831
            multi_run--;
1832
        }
1833
        /* line compare acts on the displayed lines */
1834
        if (y == s->line_compare)
1835
            addr1 = 0;
1836
        d += linesize;
1837
    }
1838
    if (y_start >= 0) {
1839
        /* flush to display */
1840
        dpy_update(s->ds, 0, y_start,
1841
                   disp_width, y - y_start);
1842
    }
1843
    /* reset modified pages */
1844
    if (page_max >= page_min) {
1845
        memory_region_reset_dirty(&s->vram,
1846
                                  page_min,
1847
                                  page_max - page_min,
1848
                                  DIRTY_MEMORY_VGA);
1849
    }
1850
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1851
}
1852

    
1853
static void vga_draw_blank(VGACommonState *s, int full_update)
1854
{
1855
    int i, w, val;
1856
    uint8_t *d;
1857

    
1858
    if (!full_update)
1859
        return;
1860
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1861
        return;
1862

    
1863
    s->rgb_to_pixel =
1864
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1865
    if (ds_get_bits_per_pixel(s->ds) == 8)
1866
        val = s->rgb_to_pixel(0, 0, 0);
1867
    else
1868
        val = 0;
1869
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1870
    d = ds_get_data(s->ds);
1871
    for(i = 0; i < s->last_scr_height; i++) {
1872
        memset(d, val, w);
1873
        d += ds_get_linesize(s->ds);
1874
    }
1875
    dpy_update(s->ds, 0, 0,
1876
               s->last_scr_width, s->last_scr_height);
1877
}
1878

    
1879
#define GMODE_TEXT     0
1880
#define GMODE_GRAPH    1
1881
#define GMODE_BLANK 2
1882

    
1883
static void vga_update_display(void *opaque)
1884
{
1885
    VGACommonState *s = opaque;
1886
    int full_update, graphic_mode;
1887

    
1888
    qemu_flush_coalesced_mmio_buffer();
1889

    
1890
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1891
        /* nothing to do */
1892
    } else {
1893
        full_update = 0;
1894
        if (!(s->ar_index & 0x20)) {
1895
            graphic_mode = GMODE_BLANK;
1896
        } else {
1897
            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1898
        }
1899
        if (graphic_mode != s->graphic_mode) {
1900
            s->graphic_mode = graphic_mode;
1901
            s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
1902
            full_update = 1;
1903
        }
1904
        switch(graphic_mode) {
1905
        case GMODE_TEXT:
1906
            vga_draw_text(s, full_update);
1907
            break;
1908
        case GMODE_GRAPH:
1909
            vga_draw_graphic(s, full_update);
1910
            break;
1911
        case GMODE_BLANK:
1912
        default:
1913
            vga_draw_blank(s, full_update);
1914
            break;
1915
        }
1916
    }
1917
}
1918

    
1919
/* force a full display refresh */
1920
static void vga_invalidate_display(void *opaque)
1921
{
1922
    VGACommonState *s = opaque;
1923

    
1924
    s->last_width = -1;
1925
    s->last_height = -1;
1926
}
1927

    
1928
void vga_common_reset(VGACommonState *s)
1929
{
1930
    s->sr_index = 0;
1931
    memset(s->sr, '\0', sizeof(s->sr));
1932
    s->gr_index = 0;
1933
    memset(s->gr, '\0', sizeof(s->gr));
1934
    s->ar_index = 0;
1935
    memset(s->ar, '\0', sizeof(s->ar));
1936
    s->ar_flip_flop = 0;
1937
    s->cr_index = 0;
1938
    memset(s->cr, '\0', sizeof(s->cr));
1939
    s->msr = 0;
1940
    s->fcr = 0;
1941
    s->st00 = 0;
1942
    s->st01 = 0;
1943
    s->dac_state = 0;
1944
    s->dac_sub_index = 0;
1945
    s->dac_read_index = 0;
1946
    s->dac_write_index = 0;
1947
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1948
    s->dac_8bit = 0;
1949
    memset(s->palette, '\0', sizeof(s->palette));
1950
    s->bank_offset = 0;
1951
#ifdef CONFIG_BOCHS_VBE
1952
    s->vbe_index = 0;
1953
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1954
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1955
    s->vbe_start_addr = 0;
1956
    s->vbe_line_offset = 0;
1957
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1958
#endif
1959
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1960
    s->graphic_mode = -1; /* force full update */
1961
    s->shift_control = 0;
1962
    s->double_scan = 0;
1963
    s->line_offset = 0;
1964
    s->line_compare = 0;
1965
    s->start_addr = 0;
1966
    s->plane_updated = 0;
1967
    s->last_cw = 0;
1968
    s->last_ch = 0;
1969
    s->last_width = 0;
1970
    s->last_height = 0;
1971
    s->last_scr_width = 0;
1972
    s->last_scr_height = 0;
1973
    s->cursor_start = 0;
1974
    s->cursor_end = 0;
1975
    s->cursor_offset = 0;
1976
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1977
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1978
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1979
    switch (vga_retrace_method) {
1980
    case VGA_RETRACE_DUMB:
1981
        break;
1982
    case VGA_RETRACE_PRECISE:
1983
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1984
        break;
1985
    }
1986
    vga_update_memory_access(s);
1987
}
1988

    
1989
static void vga_reset(void *opaque)
1990
{
1991
    VGACommonState *s =  opaque;
1992
    vga_common_reset(s);
1993
}
1994

    
1995
#define TEXTMODE_X(x)        ((x) % width)
1996
#define TEXTMODE_Y(x)        ((x) / width)
1997
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1998
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1999
/* relay text rendering to the display driver
2000
 * instead of doing a full vga_update_display() */
2001
static void vga_update_text(void *opaque, console_ch_t *chardata)
2002
{
2003
    VGACommonState *s =  opaque;
2004
    int graphic_mode, i, cursor_offset, cursor_visible;
2005
    int cw, cheight, width, height, size, c_min, c_max;
2006
    uint32_t *src;
2007
    console_ch_t *dst, val;
2008
    char msg_buffer[80];
2009
    int full_update = 0;
2010

    
2011
    qemu_flush_coalesced_mmio_buffer();
2012

    
2013
    if (!(s->ar_index & 0x20)) {
2014
        graphic_mode = GMODE_BLANK;
2015
    } else {
2016
        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
2017
    }
2018
    if (graphic_mode != s->graphic_mode) {
2019
        s->graphic_mode = graphic_mode;
2020
        full_update = 1;
2021
    }
2022
    if (s->last_width == -1) {
2023
        s->last_width = 0;
2024
        full_update = 1;
2025
    }
2026

    
2027
    switch (graphic_mode) {
2028
    case GMODE_TEXT:
2029
        /* TODO: update palette */
2030
        full_update |= update_basic_params(s);
2031

    
2032
        /* total width & height */
2033
        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2034
        cw = 8;
2035
        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2036
            cw = 9;
2037
        }
2038
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2039
            cw = 16; /* NOTE: no 18 pixel wide */
2040
        }
2041
        width = (s->cr[VGA_CRTC_H_DISP] + 1);
2042
        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2043
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2044
            height = 100;
2045
        } else {
2046
            height = s->cr[VGA_CRTC_V_DISP_END] |
2047
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2048
                ((s->cr[VGA_CRTC_OVERFLOW] & 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[VGA_CRTC_CURSOR_HI] << 8) |
2078
                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2079
        if (cursor_offset != s->cursor_offset ||
2080
            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2081
            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2082
            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2083
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2084
                dpy_cursor(s->ds,
2085
                           TEXTMODE_X(cursor_offset),
2086
                           TEXTMODE_Y(cursor_offset));
2087
            else
2088
                dpy_cursor(s->ds, -1, -1);
2089
            s->cursor_offset = cursor_offset;
2090
            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2091
            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2092
        }
2093

    
2094
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2095
        dst = chardata;
2096

    
2097
        if (full_update) {
2098
            for (i = 0; i < size; src ++, dst ++, i ++)
2099
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2100

    
2101
            dpy_update(s->ds, 0, 0, width, height);
2102
        } else {
2103
            c_max = 0;
2104

    
2105
            for (i = 0; i < size; src ++, dst ++, i ++) {
2106
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2107
                if (*dst != val) {
2108
                    *dst = val;
2109
                    c_max = i;
2110
                    break;
2111
                }
2112
            }
2113
            c_min = i;
2114
            for (; i < size; src ++, dst ++, i ++) {
2115
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2116
                if (*dst != val) {
2117
                    *dst = val;
2118
                    c_max = i;
2119
                }
2120
            }
2121

    
2122
            if (c_min <= c_max) {
2123
                i = TEXTMODE_Y(c_min);
2124
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2125
            }
2126
        }
2127

    
2128
        return;
2129
    case GMODE_GRAPH:
2130
        if (!full_update)
2131
            return;
2132

    
2133
        s->get_resolution(s, &width, &height);
2134
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2135
                 width, height);
2136
        break;
2137
    case GMODE_BLANK:
2138
    default:
2139
        if (!full_update)
2140
            return;
2141

    
2142
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2143
        break;
2144
    }
2145

    
2146
    /* Display a message */
2147
    s->last_width = 60;
2148
    s->last_height = height = 3;
2149
    dpy_cursor(s->ds, -1, -1);
2150
    s->ds->surface->width = s->last_width;
2151
    s->ds->surface->height = height;
2152
    dpy_resize(s->ds);
2153

    
2154
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2155
        console_write_ch(dst ++, ' ');
2156

    
2157
    size = strlen(msg_buffer);
2158
    width = (s->last_width - size) / 2;
2159
    dst = chardata + s->last_width + width;
2160
    for (i = 0; i < size; i ++)
2161
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2162

    
2163
    dpy_update(s->ds, 0, 0, s->last_width, height);
2164
}
2165

    
2166
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2167
                             unsigned size)
2168
{
2169
    VGACommonState *s = opaque;
2170

    
2171
    return vga_mem_readb(s, addr);
2172
}
2173

    
2174
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2175
                          uint64_t data, unsigned size)
2176
{
2177
    VGACommonState *s = opaque;
2178

    
2179
    return vga_mem_writeb(s, addr, data);
2180
}
2181

    
2182
const MemoryRegionOps vga_mem_ops = {
2183
    .read = vga_mem_read,
2184
    .write = vga_mem_write,
2185
    .endianness = DEVICE_LITTLE_ENDIAN,
2186
    .impl = {
2187
        .min_access_size = 1,
2188
        .max_access_size = 1,
2189
    },
2190
};
2191

    
2192
static int vga_common_post_load(void *opaque, int version_id)
2193
{
2194
    VGACommonState *s = opaque;
2195

    
2196
    /* force refresh */
2197
    s->graphic_mode = -1;
2198
    return 0;
2199
}
2200

    
2201
const VMStateDescription vmstate_vga_common = {
2202
    .name = "vga",
2203
    .version_id = 2,
2204
    .minimum_version_id = 2,
2205
    .minimum_version_id_old = 2,
2206
    .post_load = vga_common_post_load,
2207
    .fields      = (VMStateField []) {
2208
        VMSTATE_UINT32(latch, VGACommonState),
2209
        VMSTATE_UINT8(sr_index, VGACommonState),
2210
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2211
        VMSTATE_UINT8(gr_index, VGACommonState),
2212
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2213
        VMSTATE_UINT8(ar_index, VGACommonState),
2214
        VMSTATE_BUFFER(ar, VGACommonState),
2215
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2216
        VMSTATE_UINT8(cr_index, VGACommonState),
2217
        VMSTATE_BUFFER(cr, VGACommonState),
2218
        VMSTATE_UINT8(msr, VGACommonState),
2219
        VMSTATE_UINT8(fcr, VGACommonState),
2220
        VMSTATE_UINT8(st00, VGACommonState),
2221
        VMSTATE_UINT8(st01, VGACommonState),
2222

    
2223
        VMSTATE_UINT8(dac_state, VGACommonState),
2224
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2225
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2226
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2227
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2228
        VMSTATE_BUFFER(palette, VGACommonState),
2229

    
2230
        VMSTATE_INT32(bank_offset, VGACommonState),
2231
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2232
#ifdef CONFIG_BOCHS_VBE
2233
        VMSTATE_UINT16(vbe_index, VGACommonState),
2234
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2235
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2236
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2237
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2238
#endif
2239
        VMSTATE_END_OF_LIST()
2240
    }
2241
};
2242

    
2243
void vga_common_init(VGACommonState *s)
2244
{
2245
    int i, j, v, b;
2246

    
2247
    for(i = 0;i < 256; i++) {
2248
        v = 0;
2249
        for(j = 0; j < 8; j++) {
2250
            v |= ((i >> j) & 1) << (j * 4);
2251
        }
2252
        expand4[i] = v;
2253

    
2254
        v = 0;
2255
        for(j = 0; j < 4; j++) {
2256
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2257
        }
2258
        expand2[i] = v;
2259
    }
2260
    for(i = 0; i < 16; i++) {
2261
        v = 0;
2262
        for(j = 0; j < 4; j++) {
2263
            b = ((i >> j) & 1);
2264
            v |= b << (2 * j);
2265
            v |= b << (2 * j + 1);
2266
        }
2267
        expand4to8[i] = v;
2268
    }
2269

    
2270
    /* valid range: 1 MB -> 256 MB */
2271
    s->vram_size = 1024 * 1024;
2272
    while (s->vram_size < (s->vram_size_mb << 20) &&
2273
           s->vram_size < (256 << 20)) {
2274
        s->vram_size <<= 1;
2275
    }
2276
    s->vram_size_mb = s->vram_size >> 20;
2277

    
2278
#ifdef CONFIG_BOCHS_VBE
2279
    s->is_vbe_vmstate = 1;
2280
#else
2281
    s->is_vbe_vmstate = 0;
2282
#endif
2283
    memory_region_init_ram(&s->vram, "vga.vram", s->vram_size);
2284
    vmstate_register_ram_global(&s->vram);
2285
    xen_register_framebuffer(&s->vram);
2286
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2287
    s->get_bpp = vga_get_bpp;
2288
    s->get_offsets = vga_get_offsets;
2289
    s->get_resolution = vga_get_resolution;
2290
    s->update = vga_update_display;
2291
    s->invalidate = vga_invalidate_display;
2292
    s->screen_dump = vga_screen_dump;
2293
    s->text_update = vga_update_text;
2294
    switch (vga_retrace_method) {
2295
    case VGA_RETRACE_DUMB:
2296
        s->retrace = vga_dumb_retrace;
2297
        s->update_retrace_info = vga_dumb_update_retrace_info;
2298
        break;
2299

    
2300
    case VGA_RETRACE_PRECISE:
2301
        s->retrace = vga_precise_retrace;
2302
        s->update_retrace_info = vga_precise_update_retrace_info;
2303
        break;
2304
    }
2305
    vga_dirty_log_start(s);
2306
}
2307

    
2308
static const MemoryRegionPortio vga_portio_list[] = {
2309
    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2310
    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2311
    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2312
    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2313
    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2314
    PORTIO_END_OF_LIST(),
2315
};
2316

    
2317
#ifdef CONFIG_BOCHS_VBE
2318
static const MemoryRegionPortio vbe_portio_list[] = {
2319
    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2320
# ifdef TARGET_I386
2321
    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2322
# else
2323
    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2324
# endif
2325
    PORTIO_END_OF_LIST(),
2326
};
2327
#endif /* CONFIG_BOCHS_VBE */
2328

    
2329
/* Used by both ISA and PCI */
2330
MemoryRegion *vga_init_io(VGACommonState *s,
2331
                          const MemoryRegionPortio **vga_ports,
2332
                          const MemoryRegionPortio **vbe_ports)
2333
{
2334
    MemoryRegion *vga_mem;
2335

    
2336
    *vga_ports = vga_portio_list;
2337
    *vbe_ports = NULL;
2338
#ifdef CONFIG_BOCHS_VBE
2339
    *vbe_ports = vbe_portio_list;
2340
#endif
2341

    
2342
    vga_mem = g_malloc(sizeof(*vga_mem));
2343
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2344
                          "vga-lowmem", 0x20000);
2345
    memory_region_set_flush_coalesced(vga_mem);
2346

    
2347
    return vga_mem;
2348
}
2349

    
2350
void vga_init(VGACommonState *s, MemoryRegion *address_space,
2351
              MemoryRegion *address_space_io, bool init_vga_ports)
2352
{
2353
    MemoryRegion *vga_io_memory;
2354
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2355
    PortioList *vga_port_list = g_new(PortioList, 1);
2356
    PortioList *vbe_port_list = g_new(PortioList, 1);
2357

    
2358
    qemu_register_reset(vga_reset, s);
2359

    
2360
    s->bank_offset = 0;
2361

    
2362
    s->legacy_address_space = address_space;
2363

    
2364
    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
2365
    memory_region_add_subregion_overlap(address_space,
2366
                                        isa_mem_base + 0x000a0000,
2367
                                        vga_io_memory,
2368
                                        1);
2369
    memory_region_set_coalescing(vga_io_memory);
2370
    if (init_vga_ports) {
2371
        portio_list_init(vga_port_list, vga_ports, s, "vga");
2372
        portio_list_add(vga_port_list, address_space_io, 0x3b0);
2373
    }
2374
    if (vbe_ports) {
2375
        portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
2376
        portio_list_add(vbe_port_list, address_space_io, 0x1ce);
2377
    }
2378
}
2379

    
2380
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
2381
{
2382
#ifdef CONFIG_BOCHS_VBE
2383
    /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
2384
     * so use an alias to avoid double-mapping the same region.
2385
     */
2386
    memory_region_init_alias(&s->vram_vbe, "vram.vbe",
2387
                             &s->vram, 0, memory_region_size(&s->vram));
2388
    /* XXX: use optimized standard vga accesses */
2389
    memory_region_add_subregion(system_memory,
2390
                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2391
                                &s->vram_vbe);
2392
    s->vbe_mapped = 1;
2393
#endif 
2394
}
2395
/********************************************************/
2396
/* vga screen dump */
2397

    
2398
void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
2399
{
2400
    FILE *f;
2401
    uint8_t *d, *d1;
2402
    uint32_t v;
2403
    int y, x;
2404
    uint8_t r, g, b;
2405
    int ret;
2406
    char *linebuf, *pbuf;
2407

    
2408
    trace_ppm_save(filename, ds);
2409
    f = fopen(filename, "wb");
2410
    if (!f) {
2411
        error_setg(errp, "failed to open file '%s': %s", filename,
2412
                   strerror(errno));
2413
        return;
2414
    }
2415
    ret = fprintf(f, "P6\n%d %d\n%d\n", ds->width, ds->height, 255);
2416
    if (ret < 0) {
2417
        linebuf = NULL;
2418
        goto write_err;
2419
    }
2420
    linebuf = g_malloc(ds->width * 3);
2421
    d1 = ds->data;
2422
    for(y = 0; y < ds->height; y++) {
2423
        d = d1;
2424
        pbuf = linebuf;
2425
        for(x = 0; x < ds->width; x++) {
2426
            if (ds->pf.bits_per_pixel == 32)
2427
                v = *(uint32_t *)d;
2428
            else
2429
                v = (uint32_t) (*(uint16_t *)d);
2430
            /* Limited to 8 or fewer bits per channel: */
2431
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
2432
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
2433
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
2434
            *pbuf++ = r;
2435
            *pbuf++ = g;
2436
            *pbuf++ = b;
2437
            d += ds->pf.bytes_per_pixel;
2438
        }
2439
        d1 += ds->linesize;
2440
        clearerr(f);
2441
        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2442
        (void)ret;
2443
        if (ferror(f)) {
2444
            goto write_err;
2445
        }
2446
    }
2447

    
2448
out:
2449
    g_free(linebuf);
2450
    fclose(f);
2451
    return;
2452

    
2453
write_err:
2454
    error_setg(errp, "failed to write to file '%s': %s", filename,
2455
               strerror(errno));
2456
    unlink(filename);
2457
    goto out;
2458
}
2459

    
2460
/* save the vga display in a PPM image even if no display is
2461
   available */
2462
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
2463
                            Error **errp)
2464
{
2465
    VGACommonState *s = opaque;
2466

    
2467
    if (cswitch) {
2468
        vga_invalidate_display(s);
2469
    }
2470
    vga_hw_update();
2471
    ppm_save(filename, s->ds->surface, errp);
2472
}