Statistics
| Branch: | Revision:

root / hw / vga.c @ ed9873bf

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

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

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

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

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

    
581
#ifdef CONFIG_BOCHS_VBE
582
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
583
{
584
    VGACommonState *s = opaque;
585
    uint32_t val;
586
    val = s->vbe_index;
587
    return val;
588
}
589

    
590
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
591
{
592
    VGACommonState *s = opaque;
593
    uint32_t val;
594

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

    
626
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
627
{
628
    VGACommonState *s = opaque;
629
    s->vbe_index = val;
630
}
631

    
632
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
633
{
634
    VGACommonState *s = opaque;
635

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

    
683
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
684
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
685
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
686
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
687
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
688
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
689

    
690
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
691
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
692
                else
693
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
694
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
695
                s->vbe_start_addr = 0;
696

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

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

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

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

    
785
/* called for accesses between 0xa0000 and 0xc0000 */
786
uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
787
{
788
    int memory_map_mode, plane;
789
    uint32_t ret;
790

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

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

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

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

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

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

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

    
930
            bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
931
            val = mask16[s->gr[VGA_GFX_SR_VALUE]];
932
            break;
933
        }
934

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

    
956
        /* apply bit mask */
957
        bit_mask |= bit_mask << 8;
958
        bit_mask |= bit_mask << 16;
959
        val = (val & bit_mask) | (s->latch & ~bit_mask);
960

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

    
977
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
978
                             const uint8_t *font_ptr, int h,
979
                             uint32_t fgcol, uint32_t bgcol);
980
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
981
                                  const uint8_t *font_ptr, int h,
982
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
983
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
984
                                const uint8_t *s, int width);
985

    
986
#define DEPTH 8
987
#include "vga_template.h"
988

    
989
#define DEPTH 15
990
#include "vga_template.h"
991

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

    
996
#define DEPTH 16
997
#include "vga_template.h"
998

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

    
1003
#define DEPTH 32
1004
#include "vga_template.h"
1005

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

    
1010
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1011
{
1012
    unsigned int col;
1013
    col = rgb_to_pixel8(r, g, b);
1014
    col |= col << 8;
1015
    col |= col << 16;
1016
    return col;
1017
}
1018

    
1019
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1020
{
1021
    unsigned int col;
1022
    col = rgb_to_pixel15(r, g, b);
1023
    col |= col << 16;
1024
    return col;
1025
}
1026

    
1027
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1028
                                          unsigned int b)
1029
{
1030
    unsigned int col;
1031
    col = rgb_to_pixel15bgr(r, g, b);
1032
    col |= col << 16;
1033
    return col;
1034
}
1035

    
1036
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1037
{
1038
    unsigned int col;
1039
    col = rgb_to_pixel16(r, g, b);
1040
    col |= col << 16;
1041
    return col;
1042
}
1043

    
1044
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1045
                                          unsigned int b)
1046
{
1047
    unsigned int col;
1048
    col = rgb_to_pixel16bgr(r, g, b);
1049
    col |= col << 16;
1050
    return col;
1051
}
1052

    
1053
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1054
{
1055
    unsigned int col;
1056
    col = rgb_to_pixel32(r, g, b);
1057
    return col;
1058
}
1059

    
1060
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1061
{
1062
    unsigned int col;
1063
    col = rgb_to_pixel32bgr(r, g, b);
1064
    return col;
1065
}
1066

    
1067
/* return true if the palette was modified */
1068
static int update_palette16(VGACommonState *s)
1069
{
1070
    int full_update, i;
1071
    uint32_t v, col, *palette;
1072

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

    
1094
/* return true if the palette was modified */
1095
static int update_palette256(VGACommonState *s)
1096
{
1097
    int full_update, i;
1098
    uint32_t v, col, *palette;
1099

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

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

    
1140
        /* starting address */
1141
        start_addr = s->cr[VGA_CRTC_START_LO] |
1142
            (s->cr[VGA_CRTC_START_HI] << 8);
1143

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

    
1154
/* update start_addr and line_offset. Return TRUE if modified */
1155
static int update_basic_params(VGACommonState *s)
1156
{
1157
    int full_update;
1158
    uint32_t start_addr, line_offset, line_compare;
1159

    
1160
    full_update = 0;
1161

    
1162
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1163

    
1164
    if (line_offset != s->line_offset ||
1165
        start_addr != s->start_addr ||
1166
        line_compare != s->line_compare) {
1167
        s->line_offset = line_offset;
1168
        s->start_addr = start_addr;
1169
        s->line_compare = line_compare;
1170
        full_update = 1;
1171
    }
1172
    return full_update;
1173
}
1174

    
1175
#define NB_DEPTHS 7
1176

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

    
1195
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1196
    vga_draw_glyph8_8,
1197
    vga_draw_glyph8_16,
1198
    vga_draw_glyph8_16,
1199
    vga_draw_glyph8_32,
1200
    vga_draw_glyph8_32,
1201
    vga_draw_glyph8_16,
1202
    vga_draw_glyph8_16,
1203
};
1204

    
1205
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1206
    vga_draw_glyph16_8,
1207
    vga_draw_glyph16_16,
1208
    vga_draw_glyph16_16,
1209
    vga_draw_glyph16_32,
1210
    vga_draw_glyph16_32,
1211
    vga_draw_glyph16_16,
1212
    vga_draw_glyph16_16,
1213
};
1214

    
1215
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1216
    vga_draw_glyph9_8,
1217
    vga_draw_glyph9_16,
1218
    vga_draw_glyph9_16,
1219
    vga_draw_glyph9_32,
1220
    vga_draw_glyph9_32,
1221
    vga_draw_glyph9_16,
1222
    vga_draw_glyph9_16,
1223
};
1224

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

    
1244
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1245
                                    int *pcwidth, int *pcheight)
1246
{
1247
    int width, cwidth, height, cheight;
1248

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

    
1269
    *pwidth = width;
1270
    *pheight = height;
1271
    *pcwidth = cwidth;
1272
    *pcheight = cheight;
1273
}
1274

    
1275
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1276

    
1277
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1278
    rgb_to_pixel8_dup,
1279
    rgb_to_pixel15_dup,
1280
    rgb_to_pixel16_dup,
1281
    rgb_to_pixel32_dup,
1282
    rgb_to_pixel32bgr_dup,
1283
    rgb_to_pixel15bgr_dup,
1284
    rgb_to_pixel16bgr_dup,
1285
};
1286

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

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

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

    
1332
    line_offset = s->line_offset;
1333

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

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

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

    
1383
    depth_index = get_depth_index(s->ds);
1384
    if (cw == 16)
1385
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1386
    else
1387
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1388
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1389

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

    
1472
enum {
1473
    VGA_DRAW_LINE2,
1474
    VGA_DRAW_LINE2D2,
1475
    VGA_DRAW_LINE4,
1476
    VGA_DRAW_LINE4D2,
1477
    VGA_DRAW_LINE8D2,
1478
    VGA_DRAW_LINE8,
1479
    VGA_DRAW_LINE15,
1480
    VGA_DRAW_LINE16,
1481
    VGA_DRAW_LINE24,
1482
    VGA_DRAW_LINE32,
1483
    VGA_DRAW_LINE_NB,
1484
};
1485

    
1486
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1487
    vga_draw_line2_8,
1488
    vga_draw_line2_16,
1489
    vga_draw_line2_16,
1490
    vga_draw_line2_32,
1491
    vga_draw_line2_32,
1492
    vga_draw_line2_16,
1493
    vga_draw_line2_16,
1494

    
1495
    vga_draw_line2d2_8,
1496
    vga_draw_line2d2_16,
1497
    vga_draw_line2d2_16,
1498
    vga_draw_line2d2_32,
1499
    vga_draw_line2d2_32,
1500
    vga_draw_line2d2_16,
1501
    vga_draw_line2d2_16,
1502

    
1503
    vga_draw_line4_8,
1504
    vga_draw_line4_16,
1505
    vga_draw_line4_16,
1506
    vga_draw_line4_32,
1507
    vga_draw_line4_32,
1508
    vga_draw_line4_16,
1509
    vga_draw_line4_16,
1510

    
1511
    vga_draw_line4d2_8,
1512
    vga_draw_line4d2_16,
1513
    vga_draw_line4d2_16,
1514
    vga_draw_line4d2_32,
1515
    vga_draw_line4d2_32,
1516
    vga_draw_line4d2_16,
1517
    vga_draw_line4d2_16,
1518

    
1519
    vga_draw_line8d2_8,
1520
    vga_draw_line8d2_16,
1521
    vga_draw_line8d2_16,
1522
    vga_draw_line8d2_32,
1523
    vga_draw_line8d2_32,
1524
    vga_draw_line8d2_16,
1525
    vga_draw_line8d2_16,
1526

    
1527
    vga_draw_line8_8,
1528
    vga_draw_line8_16,
1529
    vga_draw_line8_16,
1530
    vga_draw_line8_32,
1531
    vga_draw_line8_32,
1532
    vga_draw_line8_16,
1533
    vga_draw_line8_16,
1534

    
1535
    vga_draw_line15_8,
1536
    vga_draw_line15_15,
1537
    vga_draw_line15_16,
1538
    vga_draw_line15_32,
1539
    vga_draw_line15_32bgr,
1540
    vga_draw_line15_15bgr,
1541
    vga_draw_line15_16bgr,
1542

    
1543
    vga_draw_line16_8,
1544
    vga_draw_line16_15,
1545
    vga_draw_line16_16,
1546
    vga_draw_line16_32,
1547
    vga_draw_line16_32bgr,
1548
    vga_draw_line16_15bgr,
1549
    vga_draw_line16_16bgr,
1550

    
1551
    vga_draw_line24_8,
1552
    vga_draw_line24_15,
1553
    vga_draw_line24_16,
1554
    vga_draw_line24_32,
1555
    vga_draw_line24_32bgr,
1556
    vga_draw_line24_15bgr,
1557
    vga_draw_line24_16bgr,
1558

    
1559
    vga_draw_line32_8,
1560
    vga_draw_line32_15,
1561
    vga_draw_line32_16,
1562
    vga_draw_line32_32,
1563
    vga_draw_line32_32bgr,
1564
    vga_draw_line32_15bgr,
1565
    vga_draw_line32_16bgr,
1566
};
1567

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

    
1582
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1583
{
1584
    int width, height;
1585

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

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

    
1615
static void vga_sync_dirty_bitmap(VGACommonState *s)
1616
{
1617
    memory_region_sync_dirty_bitmap(&s->vram);
1618
}
1619

    
1620
void vga_dirty_log_start(VGACommonState *s)
1621
{
1622
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1623
}
1624

    
1625
void vga_dirty_log_stop(VGACommonState *s)
1626
{
1627
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1628
}
1629

    
1630
/*
1631
 * graphic modes
1632
 */
1633
static void vga_draw_graphic(VGACommonState *s, int full_update)
1634
{
1635
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1636
    int width, height, shift_control, line_offset, bwidth, bits;
1637
    ram_addr_t page0, page1, page_min, page_max;
1638
    int disp_width, multi_scan, multi_run;
1639
    uint8_t *d;
1640
    uint32_t v, addr1, addr;
1641
    vga_draw_line_func *vga_draw_line;
1642

    
1643
    full_update |= update_basic_params(s);
1644

    
1645
    if (!full_update)
1646
        vga_sync_dirty_bitmap(s);
1647

    
1648
    s->get_resolution(s, &width, &height);
1649
    disp_width = width;
1650

    
1651
    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1652
    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1653
    if (shift_control != 1) {
1654
        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1655
            - 1;
1656
    } else {
1657
        /* in CGA modes, multi_scan is ignored */
1658
        /* XXX: is it correct ? */
1659
        multi_scan = double_scan;
1660
    }
1661
    multi_run = multi_scan;
1662
    if (shift_control != s->shift_control ||
1663
        double_scan != s->double_scan) {
1664
        full_update = 1;
1665
        s->shift_control = shift_control;
1666
        s->double_scan = double_scan;
1667
    }
1668

    
1669
    if (shift_control == 0) {
1670
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1671
            disp_width <<= 1;
1672
        }
1673
    } else if (shift_control == 1) {
1674
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1675
            disp_width <<= 1;
1676
        }
1677
    }
1678

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

    
1713
    s->rgb_to_pixel =
1714
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1715

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

    
1765
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1766
        s->cursor_invalidate(s);
1767

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

    
1849
static void vga_draw_blank(VGACommonState *s, int full_update)
1850
{
1851
    int i, w, val;
1852
    uint8_t *d;
1853

    
1854
    if (!full_update)
1855
        return;
1856
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1857
        return;
1858

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

    
1875
#define GMODE_TEXT     0
1876
#define GMODE_GRAPH    1
1877
#define GMODE_BLANK 2
1878

    
1879
static void vga_update_display(void *opaque)
1880
{
1881
    VGACommonState *s = opaque;
1882
    int full_update, graphic_mode;
1883

    
1884
    qemu_flush_coalesced_mmio_buffer();
1885

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

    
1915
/* force a full display refresh */
1916
static void vga_invalidate_display(void *opaque)
1917
{
1918
    VGACommonState *s = opaque;
1919

    
1920
    s->last_width = -1;
1921
    s->last_height = -1;
1922
}
1923

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

    
1985
static void vga_reset(void *opaque)
1986
{
1987
    VGACommonState *s =  opaque;
1988
    vga_common_reset(s);
1989
}
1990

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

    
2007
    qemu_flush_coalesced_mmio_buffer();
2008

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

    
2023
    switch (graphic_mode) {
2024
    case GMODE_TEXT:
2025
        /* TODO: update palette */
2026
        full_update |= update_basic_params(s);
2027

    
2028
        /* total width & height */
2029
        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2030
        cw = 8;
2031
        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2032
            cw = 9;
2033
        }
2034
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2035
            cw = 16; /* NOTE: no 18 pixel wide */
2036
        }
2037
        width = (s->cr[VGA_CRTC_H_DISP] + 1);
2038
        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2039
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2040
            height = 100;
2041
        } else {
2042
            height = s->cr[VGA_CRTC_V_DISP_END] |
2043
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2044
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
2045
            height = (height + 1) / cheight;
2046
        }
2047

    
2048
        size = (height * width);
2049
        if (size > CH_ATTR_SIZE) {
2050
            if (!full_update)
2051
                return;
2052

    
2053
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2054
                     width, height);
2055
            break;
2056
        }
2057

    
2058
        if (width != s->last_width || height != s->last_height ||
2059
            cw != s->last_cw || cheight != s->last_ch) {
2060
            s->last_scr_width = width * cw;
2061
            s->last_scr_height = height * cheight;
2062
            s->ds->surface->width = width;
2063
            s->ds->surface->height = height;
2064
            dpy_resize(s->ds);
2065
            s->last_width = width;
2066
            s->last_height = height;
2067
            s->last_ch = cheight;
2068
            s->last_cw = cw;
2069
            full_update = 1;
2070
        }
2071

    
2072
        /* Update "hardware" cursor */
2073
        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
2074
                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2075
        if (cursor_offset != s->cursor_offset ||
2076
            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2077
            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2078
            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2079
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2080
                dpy_cursor(s->ds,
2081
                           TEXTMODE_X(cursor_offset),
2082
                           TEXTMODE_Y(cursor_offset));
2083
            else
2084
                dpy_cursor(s->ds, -1, -1);
2085
            s->cursor_offset = cursor_offset;
2086
            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2087
            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2088
        }
2089

    
2090
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2091
        dst = chardata;
2092

    
2093
        if (full_update) {
2094
            for (i = 0; i < size; src ++, dst ++, i ++)
2095
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2096

    
2097
            dpy_update(s->ds, 0, 0, width, height);
2098
        } else {
2099
            c_max = 0;
2100

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

    
2118
            if (c_min <= c_max) {
2119
                i = TEXTMODE_Y(c_min);
2120
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2121
            }
2122
        }
2123

    
2124
        return;
2125
    case GMODE_GRAPH:
2126
        if (!full_update)
2127
            return;
2128

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

    
2138
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2139
        break;
2140
    }
2141

    
2142
    /* Display a message */
2143
    s->last_width = 60;
2144
    s->last_height = height = 3;
2145
    dpy_cursor(s->ds, -1, -1);
2146
    s->ds->surface->width = s->last_width;
2147
    s->ds->surface->height = height;
2148
    dpy_resize(s->ds);
2149

    
2150
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2151
        console_write_ch(dst ++, ' ');
2152

    
2153
    size = strlen(msg_buffer);
2154
    width = (s->last_width - size) / 2;
2155
    dst = chardata + s->last_width + width;
2156
    for (i = 0; i < size; i ++)
2157
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2158

    
2159
    dpy_update(s->ds, 0, 0, s->last_width, height);
2160
}
2161

    
2162
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2163
                             unsigned size)
2164
{
2165
    VGACommonState *s = opaque;
2166

    
2167
    return vga_mem_readb(s, addr);
2168
}
2169

    
2170
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2171
                          uint64_t data, unsigned size)
2172
{
2173
    VGACommonState *s = opaque;
2174

    
2175
    return vga_mem_writeb(s, addr, data);
2176
}
2177

    
2178
const MemoryRegionOps vga_mem_ops = {
2179
    .read = vga_mem_read,
2180
    .write = vga_mem_write,
2181
    .endianness = DEVICE_LITTLE_ENDIAN,
2182
    .impl = {
2183
        .min_access_size = 1,
2184
        .max_access_size = 1,
2185
    },
2186
};
2187

    
2188
static int vga_common_post_load(void *opaque, int version_id)
2189
{
2190
    VGACommonState *s = opaque;
2191

    
2192
    /* force refresh */
2193
    s->graphic_mode = -1;
2194
    return 0;
2195
}
2196

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

    
2219
        VMSTATE_UINT8(dac_state, VGACommonState),
2220
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2221
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2222
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2223
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2224
        VMSTATE_BUFFER(palette, VGACommonState),
2225

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

    
2239
void vga_common_init(VGACommonState *s)
2240
{
2241
    int i, j, v, b;
2242

    
2243
    for(i = 0;i < 256; i++) {
2244
        v = 0;
2245
        for(j = 0; j < 8; j++) {
2246
            v |= ((i >> j) & 1) << (j * 4);
2247
        }
2248
        expand4[i] = v;
2249

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

    
2266
    /* valid range: 1 MB -> 256 MB */
2267
    s->vram_size = 1024 * 1024;
2268
    while (s->vram_size < (s->vram_size_mb << 20) &&
2269
           s->vram_size < (256 << 20)) {
2270
        s->vram_size <<= 1;
2271
    }
2272
    s->vram_size_mb = s->vram_size >> 20;
2273

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

    
2296
    case VGA_RETRACE_PRECISE:
2297
        s->retrace = vga_precise_retrace;
2298
        s->update_retrace_info = vga_precise_update_retrace_info;
2299
        break;
2300
    }
2301
    vga_dirty_log_start(s);
2302
}
2303

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

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

    
2325
/* Used by both ISA and PCI */
2326
MemoryRegion *vga_init_io(VGACommonState *s,
2327
                          const MemoryRegionPortio **vga_ports,
2328
                          const MemoryRegionPortio **vbe_ports)
2329
{
2330
    MemoryRegion *vga_mem;
2331

    
2332
    *vga_ports = vga_portio_list;
2333
    *vbe_ports = NULL;
2334
#ifdef CONFIG_BOCHS_VBE
2335
    *vbe_ports = vbe_portio_list;
2336
#endif
2337

    
2338
    vga_mem = g_malloc(sizeof(*vga_mem));
2339
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2340
                          "vga-lowmem", 0x20000);
2341

    
2342
    return vga_mem;
2343
}
2344

    
2345
void vga_init(VGACommonState *s, MemoryRegion *address_space,
2346
              MemoryRegion *address_space_io, bool init_vga_ports)
2347
{
2348
    MemoryRegion *vga_io_memory;
2349
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2350
    PortioList *vga_port_list = g_new(PortioList, 1);
2351
    PortioList *vbe_port_list = g_new(PortioList, 1);
2352

    
2353
    qemu_register_reset(vga_reset, s);
2354

    
2355
    s->bank_offset = 0;
2356

    
2357
    s->legacy_address_space = address_space;
2358

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

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

    
2393
void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
2394
{
2395
    FILE *f;
2396
    uint8_t *d, *d1;
2397
    uint32_t v;
2398
    int y, x;
2399
    uint8_t r, g, b;
2400
    int ret;
2401
    char *linebuf, *pbuf;
2402

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

    
2443
out:
2444
    g_free(linebuf);
2445
    fclose(f);
2446
    return;
2447

    
2448
write_err:
2449
    error_setg(errp, "failed to write to file '%s': %s", filename,
2450
               strerror(errno));
2451
    unlink(filename);
2452
    goto out;
2453
}
2454

    
2455
/* save the vga display in a PPM image even if no display is
2456
   available */
2457
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch,
2458
                            Error **errp)
2459
{
2460
    VGACommonState *s = opaque;
2461

    
2462
    if (cswitch) {
2463
        vga_invalidate_display(s);
2464
    }
2465
    vga_hw_update();
2466
    ppm_save(filename, s->ds->surface, errp);
2467
}