Statistics
| Branch: | Revision:

root / hw / vga.c @ 7bc3018b

History | View | Annotate | Download (70.9 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
/*
42
 * Video Graphics Array (VGA)
43
 *
44
 * Chipset docs for original IBM VGA:
45
 * http://www.mcamafia.de/pdf/ibm_vgaxga_trm2.pdf
46
 *
47
 * FreeVGA site:
48
 * http://www.osdever.net/FreeVGA/home.htm
49
 *
50
 * Standard VGA features and Bochs VBE extensions are implemented.
51
 */
52

    
53
/* force some bits to zero */
54
const uint8_t sr_mask[8] = {
55
    0x03,
56
    0x3d,
57
    0x0f,
58
    0x3f,
59
    0x0e,
60
    0x00,
61
    0x00,
62
    0xff,
63
};
64

    
65
const uint8_t gr_mask[16] = {
66
    0x0f, /* 0x00 */
67
    0x0f, /* 0x01 */
68
    0x0f, /* 0x02 */
69
    0x1f, /* 0x03 */
70
    0x03, /* 0x04 */
71
    0x7b, /* 0x05 */
72
    0x0f, /* 0x06 */
73
    0x0f, /* 0x07 */
74
    0xff, /* 0x08 */
75
    0x00, /* 0x09 */
76
    0x00, /* 0x0a */
77
    0x00, /* 0x0b */
78
    0x00, /* 0x0c */
79
    0x00, /* 0x0d */
80
    0x00, /* 0x0e */
81
    0x00, /* 0x0f */
82
};
83

    
84
#define cbswap_32(__x) \
85
((uint32_t)( \
86
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
87
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
88
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
89
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
90

    
91
#ifdef HOST_WORDS_BIGENDIAN
92
#define PAT(x) cbswap_32(x)
93
#else
94
#define PAT(x) (x)
95
#endif
96

    
97
#ifdef HOST_WORDS_BIGENDIAN
98
#define BIG 1
99
#else
100
#define BIG 0
101
#endif
102

    
103
#ifdef HOST_WORDS_BIGENDIAN
104
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
105
#else
106
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
107
#endif
108

    
109
static const uint32_t mask16[16] = {
110
    PAT(0x00000000),
111
    PAT(0x000000ff),
112
    PAT(0x0000ff00),
113
    PAT(0x0000ffff),
114
    PAT(0x00ff0000),
115
    PAT(0x00ff00ff),
116
    PAT(0x00ffff00),
117
    PAT(0x00ffffff),
118
    PAT(0xff000000),
119
    PAT(0xff0000ff),
120
    PAT(0xff00ff00),
121
    PAT(0xff00ffff),
122
    PAT(0xffff0000),
123
    PAT(0xffff00ff),
124
    PAT(0xffffff00),
125
    PAT(0xffffffff),
126
};
127

    
128
#undef PAT
129

    
130
#ifdef HOST_WORDS_BIGENDIAN
131
#define PAT(x) (x)
132
#else
133
#define PAT(x) cbswap_32(x)
134
#endif
135

    
136
static const uint32_t dmask16[16] = {
137
    PAT(0x00000000),
138
    PAT(0x000000ff),
139
    PAT(0x0000ff00),
140
    PAT(0x0000ffff),
141
    PAT(0x00ff0000),
142
    PAT(0x00ff00ff),
143
    PAT(0x00ffff00),
144
    PAT(0x00ffffff),
145
    PAT(0xff000000),
146
    PAT(0xff0000ff),
147
    PAT(0xff00ff00),
148
    PAT(0xff00ffff),
149
    PAT(0xffff0000),
150
    PAT(0xffff00ff),
151
    PAT(0xffffff00),
152
    PAT(0xffffffff),
153
};
154

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

    
162
static uint32_t expand4[256];
163
static uint16_t expand2[256];
164
static uint8_t expand4to8[16];
165

    
166
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch);
167

    
168
static void vga_update_memory_access(VGACommonState *s)
169
{
170
    MemoryRegion *region, *old_region = s->chain4_alias;
171
    target_phys_addr_t base, offset, size;
172

    
173
    s->chain4_alias = NULL;
174

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

    
213
static void vga_dumb_update_retrace_info(VGACommonState *s)
214
{
215
    (void) s;
216
}
217

    
218
static void vga_precise_update_retrace_info(VGACommonState *s)
219
{
220
    int htotal_chars;
221
    int hretr_start_char;
222
    int hretr_skew_chars;
223
    int hretr_end_char;
224

    
225
    int vtotal_lines;
226
    int vretr_start_line;
227
    int vretr_end_line;
228

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

    
239
    htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
240
    hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
241
    hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
242
    hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
243

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

    
252
    clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
253
    clock_sel = (s->msr >> 2) & 3;
254
    dots = (s->msr & 1) ? 8 : 9;
255

    
256
    chars_per_sec = clk_hz[clock_sel] / dots;
257

    
258
    htotal_chars <<= clocking_mode;
259

    
260
    r->total_chars = vtotal_lines * htotal_chars;
261
    if (r->freq) {
262
        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
263
    } else {
264
        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
265
    }
266

    
267
    r->vstart = vretr_start_line;
268
    r->vend = r->vstart + vretr_end_line + 1;
269

    
270
    r->hstart = hretr_start_char + hretr_skew_chars;
271
    r->hend = r->hstart + hretr_end_char + 1;
272
    r->htotal = htotal_chars;
273

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

    
310
static uint8_t vga_precise_retrace(VGACommonState *s)
311
{
312
    struct vga_precise_retrace *r = &s->retrace_info.precise;
313
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
314

    
315
    if (r->total_chars) {
316
        int cur_line, cur_line_char, cur_char;
317
        int64_t cur_tick;
318

    
319
        cur_tick = qemu_get_clock_ns(vm_clock);
320

    
321
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
322
        cur_line = cur_char / r->htotal;
323

    
324
        if (cur_line >= r->vstart && cur_line <= r->vend) {
325
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
326
        } else {
327
            cur_line_char = cur_char % r->htotal;
328
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
329
                val |= ST01_DISP_ENABLE;
330
            }
331
        }
332

    
333
        return val;
334
    } else {
335
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
336
    }
337
}
338

    
339
static uint8_t vga_dumb_retrace(VGACommonState *s)
340
{
341
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
342
}
343

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

    
355
uint32_t vga_ioport_read(void *opaque, uint32_t addr)
356
{
357
    VGACommonState *s = opaque;
358
    int val, index;
359

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

    
447
void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
448
{
449
    VGACommonState *s = opaque;
450
    int index;
451

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

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

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

    
577
#ifdef CONFIG_BOCHS_VBE
578
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
579
{
580
    VGACommonState *s = opaque;
581
    uint32_t val;
582
    val = s->vbe_index;
583
    return val;
584
}
585

    
586
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
587
{
588
    VGACommonState *s = opaque;
589
    uint32_t val;
590

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

    
622
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
623
{
624
    VGACommonState *s = opaque;
625
    s->vbe_index = val;
626
}
627

    
628
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
629
{
630
    VGACommonState *s = opaque;
631

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

    
679
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
680
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
681
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
682
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
683
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
684
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
685

    
686
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
687
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
688
                else
689
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
690
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
691
                s->vbe_start_addr = 0;
692

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

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

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

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

    
781
/* called for accesses between 0xa0000 and 0xc0000 */
782
uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
783
{
784
    int memory_map_mode, plane;
785
    uint32_t ret;
786

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

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

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

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

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

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

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

    
926
            bit_mask = s->gr[VGA_GFX_BIT_MASK] & val;
927
            val = mask16[s->gr[VGA_GFX_SR_VALUE]];
928
            break;
929
        }
930

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

    
952
        /* apply bit mask */
953
        bit_mask |= bit_mask << 8;
954
        bit_mask |= bit_mask << 16;
955
        val = (val & bit_mask) | (s->latch & ~bit_mask);
956

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

    
973
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
974
                             const uint8_t *font_ptr, int h,
975
                             uint32_t fgcol, uint32_t bgcol);
976
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
977
                                  const uint8_t *font_ptr, int h,
978
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
979
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
980
                                const uint8_t *s, int width);
981

    
982
#define DEPTH 8
983
#include "vga_template.h"
984

    
985
#define DEPTH 15
986
#include "vga_template.h"
987

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

    
992
#define DEPTH 16
993
#include "vga_template.h"
994

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

    
999
#define DEPTH 32
1000
#include "vga_template.h"
1001

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

    
1006
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1007
{
1008
    unsigned int col;
1009
    col = rgb_to_pixel8(r, g, b);
1010
    col |= col << 8;
1011
    col |= col << 16;
1012
    return col;
1013
}
1014

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

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

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

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

    
1049
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1050
{
1051
    unsigned int col;
1052
    col = rgb_to_pixel32(r, g, b);
1053
    return col;
1054
}
1055

    
1056
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1057
{
1058
    unsigned int col;
1059
    col = rgb_to_pixel32bgr(r, g, b);
1060
    return col;
1061
}
1062

    
1063
/* return true if the palette was modified */
1064
static int update_palette16(VGACommonState *s)
1065
{
1066
    int full_update, i;
1067
    uint32_t v, col, *palette;
1068

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

    
1090
/* return true if the palette was modified */
1091
static int update_palette256(VGACommonState *s)
1092
{
1093
    int full_update, i;
1094
    uint32_t v, col, *palette;
1095

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

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

    
1136
        /* starting address */
1137
        start_addr = s->cr[VGA_CRTC_START_LO] |
1138
            (s->cr[VGA_CRTC_START_HI] << 8);
1139

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

    
1150
/* update start_addr and line_offset. Return TRUE if modified */
1151
static int update_basic_params(VGACommonState *s)
1152
{
1153
    int full_update;
1154
    uint32_t start_addr, line_offset, line_compare;
1155

    
1156
    full_update = 0;
1157

    
1158
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1159

    
1160
    if (line_offset != s->line_offset ||
1161
        start_addr != s->start_addr ||
1162
        line_compare != s->line_compare) {
1163
        s->line_offset = line_offset;
1164
        s->start_addr = start_addr;
1165
        s->line_compare = line_compare;
1166
        full_update = 1;
1167
    }
1168
    return full_update;
1169
}
1170

    
1171
#define NB_DEPTHS 7
1172

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

    
1191
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1192
    vga_draw_glyph8_8,
1193
    vga_draw_glyph8_16,
1194
    vga_draw_glyph8_16,
1195
    vga_draw_glyph8_32,
1196
    vga_draw_glyph8_32,
1197
    vga_draw_glyph8_16,
1198
    vga_draw_glyph8_16,
1199
};
1200

    
1201
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1202
    vga_draw_glyph16_8,
1203
    vga_draw_glyph16_16,
1204
    vga_draw_glyph16_16,
1205
    vga_draw_glyph16_32,
1206
    vga_draw_glyph16_32,
1207
    vga_draw_glyph16_16,
1208
    vga_draw_glyph16_16,
1209
};
1210

    
1211
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1212
    vga_draw_glyph9_8,
1213
    vga_draw_glyph9_16,
1214
    vga_draw_glyph9_16,
1215
    vga_draw_glyph9_32,
1216
    vga_draw_glyph9_32,
1217
    vga_draw_glyph9_16,
1218
    vga_draw_glyph9_16,
1219
};
1220

    
1221
static const uint8_t cursor_glyph[32 * 4] = {
1222
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1225
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1227
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1228
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1229
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1230
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1231
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1232
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1233
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1234
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1235
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1236
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1237
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1238
};
1239

    
1240
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1241
                                    int *pcwidth, int *pcheight)
1242
{
1243
    int width, cwidth, height, cheight;
1244

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

    
1265
    *pwidth = width;
1266
    *pheight = height;
1267
    *pcwidth = cwidth;
1268
    *pcheight = cheight;
1269
}
1270

    
1271
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1272

    
1273
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1274
    rgb_to_pixel8_dup,
1275
    rgb_to_pixel15_dup,
1276
    rgb_to_pixel16_dup,
1277
    rgb_to_pixel32_dup,
1278
    rgb_to_pixel32bgr_dup,
1279
    rgb_to_pixel15bgr_dup,
1280
    rgb_to_pixel16bgr_dup,
1281
};
1282

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

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

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

    
1327
    line_offset = s->line_offset;
1328

    
1329
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1330
    if ((height * width) <= 1) {
1331
        /* better than nothing: exit if transient size is too small */
1332
        return;
1333
    }
1334
    if ((height * width) > CH_ATTR_SIZE) {
1335
        /* better than nothing: exit if transient size is too big */
1336
        return;
1337
    }
1338

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

    
1357
    cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1358
                     s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1359
    if (cursor_offset != s->cursor_offset ||
1360
        s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1361
        s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1362
      /* if the cursor position changed, we update the old and new
1363
         chars */
1364
        if (s->cursor_offset < CH_ATTR_SIZE)
1365
            s->last_ch_attr[s->cursor_offset] = -1;
1366
        if (cursor_offset < CH_ATTR_SIZE)
1367
            s->last_ch_attr[cursor_offset] = -1;
1368
        s->cursor_offset = cursor_offset;
1369
        s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1370
        s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1371
    }
1372
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1373

    
1374
    depth_index = get_depth_index(s->ds);
1375
    if (cw == 16)
1376
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1377
    else
1378
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1379
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1380

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

    
1462
enum {
1463
    VGA_DRAW_LINE2,
1464
    VGA_DRAW_LINE2D2,
1465
    VGA_DRAW_LINE4,
1466
    VGA_DRAW_LINE4D2,
1467
    VGA_DRAW_LINE8D2,
1468
    VGA_DRAW_LINE8,
1469
    VGA_DRAW_LINE15,
1470
    VGA_DRAW_LINE16,
1471
    VGA_DRAW_LINE24,
1472
    VGA_DRAW_LINE32,
1473
    VGA_DRAW_LINE_NB,
1474
};
1475

    
1476
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1477
    vga_draw_line2_8,
1478
    vga_draw_line2_16,
1479
    vga_draw_line2_16,
1480
    vga_draw_line2_32,
1481
    vga_draw_line2_32,
1482
    vga_draw_line2_16,
1483
    vga_draw_line2_16,
1484

    
1485
    vga_draw_line2d2_8,
1486
    vga_draw_line2d2_16,
1487
    vga_draw_line2d2_16,
1488
    vga_draw_line2d2_32,
1489
    vga_draw_line2d2_32,
1490
    vga_draw_line2d2_16,
1491
    vga_draw_line2d2_16,
1492

    
1493
    vga_draw_line4_8,
1494
    vga_draw_line4_16,
1495
    vga_draw_line4_16,
1496
    vga_draw_line4_32,
1497
    vga_draw_line4_32,
1498
    vga_draw_line4_16,
1499
    vga_draw_line4_16,
1500

    
1501
    vga_draw_line4d2_8,
1502
    vga_draw_line4d2_16,
1503
    vga_draw_line4d2_16,
1504
    vga_draw_line4d2_32,
1505
    vga_draw_line4d2_32,
1506
    vga_draw_line4d2_16,
1507
    vga_draw_line4d2_16,
1508

    
1509
    vga_draw_line8d2_8,
1510
    vga_draw_line8d2_16,
1511
    vga_draw_line8d2_16,
1512
    vga_draw_line8d2_32,
1513
    vga_draw_line8d2_32,
1514
    vga_draw_line8d2_16,
1515
    vga_draw_line8d2_16,
1516

    
1517
    vga_draw_line8_8,
1518
    vga_draw_line8_16,
1519
    vga_draw_line8_16,
1520
    vga_draw_line8_32,
1521
    vga_draw_line8_32,
1522
    vga_draw_line8_16,
1523
    vga_draw_line8_16,
1524

    
1525
    vga_draw_line15_8,
1526
    vga_draw_line15_15,
1527
    vga_draw_line15_16,
1528
    vga_draw_line15_32,
1529
    vga_draw_line15_32bgr,
1530
    vga_draw_line15_15bgr,
1531
    vga_draw_line15_16bgr,
1532

    
1533
    vga_draw_line16_8,
1534
    vga_draw_line16_15,
1535
    vga_draw_line16_16,
1536
    vga_draw_line16_32,
1537
    vga_draw_line16_32bgr,
1538
    vga_draw_line16_15bgr,
1539
    vga_draw_line16_16bgr,
1540

    
1541
    vga_draw_line24_8,
1542
    vga_draw_line24_15,
1543
    vga_draw_line24_16,
1544
    vga_draw_line24_32,
1545
    vga_draw_line24_32bgr,
1546
    vga_draw_line24_15bgr,
1547
    vga_draw_line24_16bgr,
1548

    
1549
    vga_draw_line32_8,
1550
    vga_draw_line32_15,
1551
    vga_draw_line32_16,
1552
    vga_draw_line32_32,
1553
    vga_draw_line32_32bgr,
1554
    vga_draw_line32_15bgr,
1555
    vga_draw_line32_16bgr,
1556
};
1557

    
1558
static int vga_get_bpp(VGACommonState *s)
1559
{
1560
    int ret;
1561
#ifdef CONFIG_BOCHS_VBE
1562
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1563
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1564
    } else
1565
#endif
1566
    {
1567
        ret = 0;
1568
    }
1569
    return ret;
1570
}
1571

    
1572
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1573
{
1574
    int width, height;
1575

    
1576
#ifdef CONFIG_BOCHS_VBE
1577
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1578
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1579
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1580
    } else
1581
#endif
1582
    {
1583
        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1584
        height = s->cr[VGA_CRTC_V_DISP_END] |
1585
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1586
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1587
        height = (height + 1);
1588
    }
1589
    *pwidth = width;
1590
    *pheight = height;
1591
}
1592

    
1593
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1594
{
1595
    int y;
1596
    if (y1 >= VGA_MAX_HEIGHT)
1597
        return;
1598
    if (y2 >= VGA_MAX_HEIGHT)
1599
        y2 = VGA_MAX_HEIGHT;
1600
    for(y = y1; y < y2; y++) {
1601
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1602
    }
1603
}
1604

    
1605
static void vga_sync_dirty_bitmap(VGACommonState *s)
1606
{
1607
    memory_region_sync_dirty_bitmap(&s->vram);
1608
}
1609

    
1610
void vga_dirty_log_start(VGACommonState *s)
1611
{
1612
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1613
}
1614

    
1615
void vga_dirty_log_stop(VGACommonState *s)
1616
{
1617
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1618
}
1619

    
1620
/*
1621
 * graphic modes
1622
 */
1623
static void vga_draw_graphic(VGACommonState *s, int full_update)
1624
{
1625
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1626
    int width, height, shift_control, line_offset, bwidth, bits;
1627
    ram_addr_t page0, page1, page_min, page_max;
1628
    int disp_width, multi_scan, multi_run;
1629
    uint8_t *d;
1630
    uint32_t v, addr1, addr;
1631
    vga_draw_line_func *vga_draw_line;
1632

    
1633
    full_update |= update_basic_params(s);
1634

    
1635
    if (!full_update)
1636
        vga_sync_dirty_bitmap(s);
1637

    
1638
    s->get_resolution(s, &width, &height);
1639
    disp_width = width;
1640

    
1641
    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1642
    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1643
    if (shift_control != 1) {
1644
        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1645
            - 1;
1646
    } else {
1647
        /* in CGA modes, multi_scan is ignored */
1648
        /* XXX: is it correct ? */
1649
        multi_scan = double_scan;
1650
    }
1651
    multi_run = multi_scan;
1652
    if (shift_control != s->shift_control ||
1653
        double_scan != s->double_scan) {
1654
        full_update = 1;
1655
        s->shift_control = shift_control;
1656
        s->double_scan = double_scan;
1657
    }
1658

    
1659
    if (shift_control == 0) {
1660
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1661
            disp_width <<= 1;
1662
        }
1663
    } else if (shift_control == 1) {
1664
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1665
            disp_width <<= 1;
1666
        }
1667
    }
1668

    
1669
    depth = s->get_bpp(s);
1670
    if (s->line_offset != s->last_line_offset ||
1671
        disp_width != s->last_width ||
1672
        height != s->last_height ||
1673
        s->last_depth != depth) {
1674
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1675
        if (depth == 16 || depth == 32) {
1676
#else
1677
        if (depth == 32) {
1678
#endif
1679
            qemu_free_displaysurface(s->ds);
1680
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1681
                    s->line_offset,
1682
                    s->vram_ptr + (s->start_addr * 4));
1683
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1684
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1685
#endif
1686
            dpy_resize(s->ds);
1687
        } else {
1688
            qemu_console_resize(s->ds, disp_width, height);
1689
        }
1690
        s->last_scr_width = disp_width;
1691
        s->last_scr_height = height;
1692
        s->last_width = disp_width;
1693
        s->last_height = height;
1694
        s->last_line_offset = s->line_offset;
1695
        s->last_depth = depth;
1696
        full_update = 1;
1697
    } else if (is_buffer_shared(s->ds->surface) &&
1698
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1699
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1700
        dpy_setdata(s->ds);
1701
    }
1702

    
1703
    s->rgb_to_pixel =
1704
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1705

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

    
1755
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1756
        s->cursor_invalidate(s);
1757

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

    
1839
static void vga_draw_blank(VGACommonState *s, int full_update)
1840
{
1841
    int i, w, val;
1842
    uint8_t *d;
1843

    
1844
    if (!full_update)
1845
        return;
1846
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1847
        return;
1848

    
1849
    s->rgb_to_pixel =
1850
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1851
    if (ds_get_bits_per_pixel(s->ds) == 8)
1852
        val = s->rgb_to_pixel(0, 0, 0);
1853
    else
1854
        val = 0;
1855
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1856
    d = ds_get_data(s->ds);
1857
    for(i = 0; i < s->last_scr_height; i++) {
1858
        memset(d, val, w);
1859
        d += ds_get_linesize(s->ds);
1860
    }
1861
    dpy_update(s->ds, 0, 0,
1862
               s->last_scr_width, s->last_scr_height);
1863
}
1864

    
1865
#define GMODE_TEXT     0
1866
#define GMODE_GRAPH    1
1867
#define GMODE_BLANK 2
1868

    
1869
static void vga_update_display(void *opaque)
1870
{
1871
    VGACommonState *s = opaque;
1872
    int full_update, graphic_mode;
1873

    
1874
    qemu_flush_coalesced_mmio_buffer();
1875

    
1876
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1877
        /* nothing to do */
1878
    } else {
1879
        full_update = 0;
1880
        if (!(s->ar_index & 0x20)) {
1881
            graphic_mode = GMODE_BLANK;
1882
        } else {
1883
            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1884
        }
1885
        if (graphic_mode != s->graphic_mode) {
1886
            s->graphic_mode = graphic_mode;
1887
            full_update = 1;
1888
        }
1889
        switch(graphic_mode) {
1890
        case GMODE_TEXT:
1891
            vga_draw_text(s, full_update);
1892
            break;
1893
        case GMODE_GRAPH:
1894
            vga_draw_graphic(s, full_update);
1895
            break;
1896
        case GMODE_BLANK:
1897
        default:
1898
            vga_draw_blank(s, full_update);
1899
            break;
1900
        }
1901
    }
1902
}
1903

    
1904
/* force a full display refresh */
1905
static void vga_invalidate_display(void *opaque)
1906
{
1907
    VGACommonState *s = opaque;
1908

    
1909
    s->last_width = -1;
1910
    s->last_height = -1;
1911
}
1912

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

    
1974
static void vga_reset(void *opaque)
1975
{
1976
    VGACommonState *s =  opaque;
1977
    vga_common_reset(s);
1978
}
1979

    
1980
#define TEXTMODE_X(x)        ((x) % width)
1981
#define TEXTMODE_Y(x)        ((x) / width)
1982
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1983
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1984
/* relay text rendering to the display driver
1985
 * instead of doing a full vga_update_display() */
1986
static void vga_update_text(void *opaque, console_ch_t *chardata)
1987
{
1988
    VGACommonState *s =  opaque;
1989
    int graphic_mode, i, cursor_offset, cursor_visible;
1990
    int cw, cheight, width, height, size, c_min, c_max;
1991
    uint32_t *src;
1992
    console_ch_t *dst, val;
1993
    char msg_buffer[80];
1994
    int full_update = 0;
1995

    
1996
    qemu_flush_coalesced_mmio_buffer();
1997

    
1998
    if (!(s->ar_index & 0x20)) {
1999
        graphic_mode = GMODE_BLANK;
2000
    } else {
2001
        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
2002
    }
2003
    if (graphic_mode != s->graphic_mode) {
2004
        s->graphic_mode = graphic_mode;
2005
        full_update = 1;
2006
    }
2007
    if (s->last_width == -1) {
2008
        s->last_width = 0;
2009
        full_update = 1;
2010
    }
2011

    
2012
    switch (graphic_mode) {
2013
    case GMODE_TEXT:
2014
        /* TODO: update palette */
2015
        full_update |= update_basic_params(s);
2016

    
2017
        /* total width & height */
2018
        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2019
        cw = 8;
2020
        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2021
            cw = 9;
2022
        }
2023
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2024
            cw = 16; /* NOTE: no 18 pixel wide */
2025
        }
2026
        width = (s->cr[VGA_CRTC_H_DISP] + 1);
2027
        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2028
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2029
            height = 100;
2030
        } else {
2031
            height = s->cr[VGA_CRTC_V_DISP_END] |
2032
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2033
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
2034
            height = (height + 1) / cheight;
2035
        }
2036

    
2037
        size = (height * width);
2038
        if (size > CH_ATTR_SIZE) {
2039
            if (!full_update)
2040
                return;
2041

    
2042
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2043
                     width, height);
2044
            break;
2045
        }
2046

    
2047
        if (width != s->last_width || height != s->last_height ||
2048
            cw != s->last_cw || cheight != s->last_ch) {
2049
            s->last_scr_width = width * cw;
2050
            s->last_scr_height = height * cheight;
2051
            s->ds->surface->width = width;
2052
            s->ds->surface->height = height;
2053
            dpy_resize(s->ds);
2054
            s->last_width = width;
2055
            s->last_height = height;
2056
            s->last_ch = cheight;
2057
            s->last_cw = cw;
2058
            full_update = 1;
2059
        }
2060

    
2061
        /* Update "hardware" cursor */
2062
        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
2063
                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2064
        if (cursor_offset != s->cursor_offset ||
2065
            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2066
            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2067
            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2068
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2069
                dpy_cursor(s->ds,
2070
                           TEXTMODE_X(cursor_offset),
2071
                           TEXTMODE_Y(cursor_offset));
2072
            else
2073
                dpy_cursor(s->ds, -1, -1);
2074
            s->cursor_offset = cursor_offset;
2075
            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2076
            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2077
        }
2078

    
2079
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2080
        dst = chardata;
2081

    
2082
        if (full_update) {
2083
            for (i = 0; i < size; src ++, dst ++, i ++)
2084
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2085

    
2086
            dpy_update(s->ds, 0, 0, width, height);
2087
        } else {
2088
            c_max = 0;
2089

    
2090
            for (i = 0; i < size; src ++, dst ++, i ++) {
2091
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2092
                if (*dst != val) {
2093
                    *dst = val;
2094
                    c_max = i;
2095
                    break;
2096
                }
2097
            }
2098
            c_min = i;
2099
            for (; i < size; src ++, dst ++, i ++) {
2100
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2101
                if (*dst != val) {
2102
                    *dst = val;
2103
                    c_max = i;
2104
                }
2105
            }
2106

    
2107
            if (c_min <= c_max) {
2108
                i = TEXTMODE_Y(c_min);
2109
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2110
            }
2111
        }
2112

    
2113
        return;
2114
    case GMODE_GRAPH:
2115
        if (!full_update)
2116
            return;
2117

    
2118
        s->get_resolution(s, &width, &height);
2119
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2120
                 width, height);
2121
        break;
2122
    case GMODE_BLANK:
2123
    default:
2124
        if (!full_update)
2125
            return;
2126

    
2127
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2128
        break;
2129
    }
2130

    
2131
    /* Display a message */
2132
    s->last_width = 60;
2133
    s->last_height = height = 3;
2134
    dpy_cursor(s->ds, -1, -1);
2135
    s->ds->surface->width = s->last_width;
2136
    s->ds->surface->height = height;
2137
    dpy_resize(s->ds);
2138

    
2139
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2140
        console_write_ch(dst ++, ' ');
2141

    
2142
    size = strlen(msg_buffer);
2143
    width = (s->last_width - size) / 2;
2144
    dst = chardata + s->last_width + width;
2145
    for (i = 0; i < size; i ++)
2146
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2147

    
2148
    dpy_update(s->ds, 0, 0, s->last_width, height);
2149
}
2150

    
2151
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2152
                             unsigned size)
2153
{
2154
    VGACommonState *s = opaque;
2155

    
2156
    return vga_mem_readb(s, addr);
2157
}
2158

    
2159
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2160
                          uint64_t data, unsigned size)
2161
{
2162
    VGACommonState *s = opaque;
2163

    
2164
    return vga_mem_writeb(s, addr, data);
2165
}
2166

    
2167
const MemoryRegionOps vga_mem_ops = {
2168
    .read = vga_mem_read,
2169
    .write = vga_mem_write,
2170
    .endianness = DEVICE_LITTLE_ENDIAN,
2171
    .impl = {
2172
        .min_access_size = 1,
2173
        .max_access_size = 1,
2174
    },
2175
};
2176

    
2177
static int vga_common_post_load(void *opaque, int version_id)
2178
{
2179
    VGACommonState *s = opaque;
2180

    
2181
    /* force refresh */
2182
    s->graphic_mode = -1;
2183
    return 0;
2184
}
2185

    
2186
const VMStateDescription vmstate_vga_common = {
2187
    .name = "vga",
2188
    .version_id = 2,
2189
    .minimum_version_id = 2,
2190
    .minimum_version_id_old = 2,
2191
    .post_load = vga_common_post_load,
2192
    .fields      = (VMStateField []) {
2193
        VMSTATE_UINT32(latch, VGACommonState),
2194
        VMSTATE_UINT8(sr_index, VGACommonState),
2195
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2196
        VMSTATE_UINT8(gr_index, VGACommonState),
2197
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2198
        VMSTATE_UINT8(ar_index, VGACommonState),
2199
        VMSTATE_BUFFER(ar, VGACommonState),
2200
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2201
        VMSTATE_UINT8(cr_index, VGACommonState),
2202
        VMSTATE_BUFFER(cr, VGACommonState),
2203
        VMSTATE_UINT8(msr, VGACommonState),
2204
        VMSTATE_UINT8(fcr, VGACommonState),
2205
        VMSTATE_UINT8(st00, VGACommonState),
2206
        VMSTATE_UINT8(st01, VGACommonState),
2207

    
2208
        VMSTATE_UINT8(dac_state, VGACommonState),
2209
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2210
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2211
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2212
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2213
        VMSTATE_BUFFER(palette, VGACommonState),
2214

    
2215
        VMSTATE_INT32(bank_offset, VGACommonState),
2216
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2217
#ifdef CONFIG_BOCHS_VBE
2218
        VMSTATE_UINT16(vbe_index, VGACommonState),
2219
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2220
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2221
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2222
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2223
#endif
2224
        VMSTATE_END_OF_LIST()
2225
    }
2226
};
2227

    
2228
void vga_common_init(VGACommonState *s, int vga_ram_size)
2229
{
2230
    int i, j, v, b;
2231

    
2232
    for(i = 0;i < 256; i++) {
2233
        v = 0;
2234
        for(j = 0; j < 8; j++) {
2235
            v |= ((i >> j) & 1) << (j * 4);
2236
        }
2237
        expand4[i] = v;
2238

    
2239
        v = 0;
2240
        for(j = 0; j < 4; j++) {
2241
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2242
        }
2243
        expand2[i] = v;
2244
    }
2245
    for(i = 0; i < 16; i++) {
2246
        v = 0;
2247
        for(j = 0; j < 4; j++) {
2248
            b = ((i >> j) & 1);
2249
            v |= b << (2 * j);
2250
            v |= b << (2 * j + 1);
2251
        }
2252
        expand4to8[i] = v;
2253
    }
2254

    
2255
#ifdef CONFIG_BOCHS_VBE
2256
    s->is_vbe_vmstate = 1;
2257
#else
2258
    s->is_vbe_vmstate = 0;
2259
#endif
2260
    memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size);
2261
    vmstate_register_ram_global(&s->vram);
2262
    xen_register_framebuffer(&s->vram);
2263
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2264
    s->vram_size = vga_ram_size;
2265
    s->get_bpp = vga_get_bpp;
2266
    s->get_offsets = vga_get_offsets;
2267
    s->get_resolution = vga_get_resolution;
2268
    s->update = vga_update_display;
2269
    s->invalidate = vga_invalidate_display;
2270
    s->screen_dump = vga_screen_dump;
2271
    s->text_update = vga_update_text;
2272
    switch (vga_retrace_method) {
2273
    case VGA_RETRACE_DUMB:
2274
        s->retrace = vga_dumb_retrace;
2275
        s->update_retrace_info = vga_dumb_update_retrace_info;
2276
        break;
2277

    
2278
    case VGA_RETRACE_PRECISE:
2279
        s->retrace = vga_precise_retrace;
2280
        s->update_retrace_info = vga_precise_update_retrace_info;
2281
        break;
2282
    }
2283
    vga_dirty_log_start(s);
2284
}
2285

    
2286
static const MemoryRegionPortio vga_portio_list[] = {
2287
    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2288
    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2289
    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2290
    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2291
    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2292
    PORTIO_END_OF_LIST(),
2293
};
2294

    
2295
#ifdef CONFIG_BOCHS_VBE
2296
static const MemoryRegionPortio vbe_portio_list[] = {
2297
    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2298
# ifdef TARGET_I386
2299
    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2300
# else
2301
    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2302
# endif
2303
    PORTIO_END_OF_LIST(),
2304
};
2305
#endif /* CONFIG_BOCHS_VBE */
2306

    
2307
/* Used by both ISA and PCI */
2308
MemoryRegion *vga_init_io(VGACommonState *s,
2309
                          const MemoryRegionPortio **vga_ports,
2310
                          const MemoryRegionPortio **vbe_ports)
2311
{
2312
    MemoryRegion *vga_mem;
2313

    
2314
    *vga_ports = vga_portio_list;
2315
    *vbe_ports = NULL;
2316
#ifdef CONFIG_BOCHS_VBE
2317
    *vbe_ports = vbe_portio_list;
2318
#endif
2319

    
2320
    vga_mem = g_malloc(sizeof(*vga_mem));
2321
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2322
                          "vga-lowmem", 0x20000);
2323

    
2324
    return vga_mem;
2325
}
2326

    
2327
void vga_init(VGACommonState *s, MemoryRegion *address_space,
2328
              MemoryRegion *address_space_io, bool init_vga_ports)
2329
{
2330
    MemoryRegion *vga_io_memory;
2331
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2332
    PortioList *vga_port_list = g_new(PortioList, 1);
2333
    PortioList *vbe_port_list = g_new(PortioList, 1);
2334

    
2335
    qemu_register_reset(vga_reset, s);
2336

    
2337
    s->bank_offset = 0;
2338

    
2339
    s->legacy_address_space = address_space;
2340

    
2341
    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
2342
    memory_region_add_subregion_overlap(address_space,
2343
                                        isa_mem_base + 0x000a0000,
2344
                                        vga_io_memory,
2345
                                        1);
2346
    memory_region_set_coalescing(vga_io_memory);
2347
    if (init_vga_ports) {
2348
        portio_list_init(vga_port_list, vga_ports, s, "vga");
2349
        portio_list_add(vga_port_list, address_space_io, 0x3b0);
2350
    }
2351
    if (vbe_ports) {
2352
        portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
2353
        portio_list_add(vbe_port_list, address_space_io, 0x1ce);
2354
    }
2355
}
2356

    
2357
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
2358
{
2359
#ifdef CONFIG_BOCHS_VBE
2360
    /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region,
2361
     * so use an alias to avoid double-mapping the same region.
2362
     */
2363
    memory_region_init_alias(&s->vram_vbe, "vram.vbe",
2364
                             &s->vram, 0, memory_region_size(&s->vram));
2365
    /* XXX: use optimized standard vga accesses */
2366
    memory_region_add_subregion(system_memory,
2367
                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2368
                                &s->vram_vbe);
2369
    s->vbe_mapped = 1;
2370
#endif 
2371
}
2372
/********************************************************/
2373
/* vga screen dump */
2374

    
2375
int ppm_save(const char *filename, struct DisplaySurface *ds)
2376
{
2377
    FILE *f;
2378
    uint8_t *d, *d1;
2379
    uint32_t v;
2380
    int y, x;
2381
    uint8_t r, g, b;
2382
    int ret;
2383
    char *linebuf, *pbuf;
2384

    
2385
    trace_ppm_save(filename, ds);
2386
    f = fopen(filename, "wb");
2387
    if (!f)
2388
        return -1;
2389
    fprintf(f, "P6\n%d %d\n%d\n",
2390
            ds->width, ds->height, 255);
2391
    linebuf = g_malloc(ds->width * 3);
2392
    d1 = ds->data;
2393
    for(y = 0; y < ds->height; y++) {
2394
        d = d1;
2395
        pbuf = linebuf;
2396
        for(x = 0; x < ds->width; x++) {
2397
            if (ds->pf.bits_per_pixel == 32)
2398
                v = *(uint32_t *)d;
2399
            else
2400
                v = (uint32_t) (*(uint16_t *)d);
2401
            /* Limited to 8 or fewer bits per channel: */
2402
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
2403
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
2404
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
2405
            *pbuf++ = r;
2406
            *pbuf++ = g;
2407
            *pbuf++ = b;
2408
            d += ds->pf.bytes_per_pixel;
2409
        }
2410
        d1 += ds->linesize;
2411
        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2412
        (void)ret;
2413
    }
2414
    g_free(linebuf);
2415
    fclose(f);
2416
    return 0;
2417
}
2418

    
2419
/* save the vga display in a PPM image even if no display is
2420
   available */
2421
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
2422
{
2423
    VGACommonState *s = opaque;
2424

    
2425
    if (cswitch) {
2426
        vga_invalidate_display(s);
2427
    }
2428
    vga_hw_update();
2429
    ppm_save(filename, s->ds->surface);
2430
}