Statistics
| Branch: | Revision:

root / hw / display / vga.c @ 42e038fe

History | View | Annotate | Download (70.6 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/hw.h"
25
#include "vga.h"
26
#include "ui/console.h"
27
#include "hw/i386/pc.h"
28
#include "hw/pci/pci.h"
29
#include "vga_int.h"
30
#include "ui/pixel_ops.h"
31
#include "qemu/timer.h"
32
#include "hw/xen/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_update_memory_access(VGACommonState *s)
170
{
171
    MemoryRegion *region, *old_region = s->chain4_alias;
172
    hwaddr base, offset, size;
173

    
174
    s->chain4_alias = NULL;
175

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

    
215
static void vga_dumb_update_retrace_info(VGACommonState *s)
216
{
217
    (void) s;
218
}
219

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

    
227
    int vtotal_lines;
228
    int vretr_start_line;
229
    int vretr_end_line;
230

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

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

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

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

    
258
    chars_per_sec = clk_hz[clock_sel] / dots;
259

    
260
    htotal_chars <<= clocking_mode;
261

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

    
269
    r->vstart = vretr_start_line;
270
    r->vend = r->vstart + vretr_end_line + 1;
271

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

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

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

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

    
321
        cur_tick = qemu_get_clock_ns(vm_clock);
322

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

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

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

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

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

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

    
362
    qemu_flush_coalesced_mmio_buffer();
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
    qemu_flush_coalesced_mmio_buffer();
457

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
785
/* called for accesses between 0xa0000 and 0xc0000 */
786
uint32_t vga_mem_readb(VGACommonState *s, hwaddr 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, hwaddr 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

    
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
        /* compute line_offset in bytes */
1135
        line_offset = s->cr[VGA_CRTC_OFFSET];
1136
        line_offset <<= 3;
1137

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

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

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

    
1158
    full_update = 0;
1159

    
1160
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1161

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

    
1173
#define NB_DEPTHS 7
1174

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

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

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

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

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

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

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

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

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

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

    
1286
/*
1287
 * Text mode update
1288
 * Missing:
1289
 * - double scan
1290
 * - double width
1291
 * - underline
1292
 * - flashing
1293
 */
1294
static void vga_draw_text(VGACommonState *s, int full_update)
1295
{
1296
    DisplaySurface *surface = qemu_console_surface(s->con);
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->con, s->last_scr_width, s->last_scr_height);
1349
        surface = qemu_console_surface(s->con);
1350
        dpy_text_resize(s->con, width, height);
1351
        s->last_depth = 0;
1352
        s->last_width = width;
1353
        s->last_height = height;
1354
        s->last_ch = cheight;
1355
        s->last_cw = cw;
1356
        full_update = 1;
1357
    }
1358
    s->rgb_to_pixel =
1359
        rgb_to_pixel_dup_table[get_depth_index(surface)];
1360
    full_update |= update_palette16(s);
1361
    palette = s->last_palette;
1362
    x_incr = cw * surface_bytes_per_pixel(surface);
1363

    
1364
    if (full_update) {
1365
        s->full_update_text = 1;
1366
    }
1367
    if (s->full_update_gfx) {
1368
        s->full_update_gfx = 0;
1369
        full_update |= 1;
1370
    }
1371

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

    
1393
    depth_index = get_depth_index(surface);
1394
    if (cw == 16)
1395
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1396
    else
1397
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1398
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1399

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

    
1482
enum {
1483
    VGA_DRAW_LINE2,
1484
    VGA_DRAW_LINE2D2,
1485
    VGA_DRAW_LINE4,
1486
    VGA_DRAW_LINE4D2,
1487
    VGA_DRAW_LINE8D2,
1488
    VGA_DRAW_LINE8,
1489
    VGA_DRAW_LINE15,
1490
    VGA_DRAW_LINE16,
1491
    VGA_DRAW_LINE24,
1492
    VGA_DRAW_LINE32,
1493
    VGA_DRAW_LINE_NB,
1494
};
1495

    
1496
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1497
    vga_draw_line2_8,
1498
    vga_draw_line2_16,
1499
    vga_draw_line2_16,
1500
    vga_draw_line2_32,
1501
    vga_draw_line2_32,
1502
    vga_draw_line2_16,
1503
    vga_draw_line2_16,
1504

    
1505
    vga_draw_line2d2_8,
1506
    vga_draw_line2d2_16,
1507
    vga_draw_line2d2_16,
1508
    vga_draw_line2d2_32,
1509
    vga_draw_line2d2_32,
1510
    vga_draw_line2d2_16,
1511
    vga_draw_line2d2_16,
1512

    
1513
    vga_draw_line4_8,
1514
    vga_draw_line4_16,
1515
    vga_draw_line4_16,
1516
    vga_draw_line4_32,
1517
    vga_draw_line4_32,
1518
    vga_draw_line4_16,
1519
    vga_draw_line4_16,
1520

    
1521
    vga_draw_line4d2_8,
1522
    vga_draw_line4d2_16,
1523
    vga_draw_line4d2_16,
1524
    vga_draw_line4d2_32,
1525
    vga_draw_line4d2_32,
1526
    vga_draw_line4d2_16,
1527
    vga_draw_line4d2_16,
1528

    
1529
    vga_draw_line8d2_8,
1530
    vga_draw_line8d2_16,
1531
    vga_draw_line8d2_16,
1532
    vga_draw_line8d2_32,
1533
    vga_draw_line8d2_32,
1534
    vga_draw_line8d2_16,
1535
    vga_draw_line8d2_16,
1536

    
1537
    vga_draw_line8_8,
1538
    vga_draw_line8_16,
1539
    vga_draw_line8_16,
1540
    vga_draw_line8_32,
1541
    vga_draw_line8_32,
1542
    vga_draw_line8_16,
1543
    vga_draw_line8_16,
1544

    
1545
    vga_draw_line15_8,
1546
    vga_draw_line15_15,
1547
    vga_draw_line15_16,
1548
    vga_draw_line15_32,
1549
    vga_draw_line15_32bgr,
1550
    vga_draw_line15_15bgr,
1551
    vga_draw_line15_16bgr,
1552

    
1553
    vga_draw_line16_8,
1554
    vga_draw_line16_15,
1555
    vga_draw_line16_16,
1556
    vga_draw_line16_32,
1557
    vga_draw_line16_32bgr,
1558
    vga_draw_line16_15bgr,
1559
    vga_draw_line16_16bgr,
1560

    
1561
    vga_draw_line24_8,
1562
    vga_draw_line24_15,
1563
    vga_draw_line24_16,
1564
    vga_draw_line24_32,
1565
    vga_draw_line24_32bgr,
1566
    vga_draw_line24_15bgr,
1567
    vga_draw_line24_16bgr,
1568

    
1569
    vga_draw_line32_8,
1570
    vga_draw_line32_15,
1571
    vga_draw_line32_16,
1572
    vga_draw_line32_32,
1573
    vga_draw_line32_32bgr,
1574
    vga_draw_line32_15bgr,
1575
    vga_draw_line32_16bgr,
1576
};
1577

    
1578
static int vga_get_bpp(VGACommonState *s)
1579
{
1580
    int ret;
1581

    
1582
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1583
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1584
    } else {
1585
        ret = 0;
1586
    }
1587
    return ret;
1588
}
1589

    
1590
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1591
{
1592
    int width, height;
1593

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

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

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

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

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

    
1635
/*
1636
 * graphic modes
1637
 */
1638
static void vga_draw_graphic(VGACommonState *s, int full_update)
1639
{
1640
    DisplaySurface *surface = qemu_console_surface(s->con);
1641
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1642
    int width, height, shift_control, line_offset, bwidth, bits;
1643
    ram_addr_t page0, page1, page_min, page_max;
1644
    int disp_width, multi_scan, multi_run;
1645
    uint8_t *d;
1646
    uint32_t v, addr1, addr;
1647
    vga_draw_line_func *vga_draw_line;
1648
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1649
    static const bool byteswap = false;
1650
#else
1651
    static const bool byteswap = true;
1652
#endif
1653

    
1654
    full_update |= update_basic_params(s);
1655

    
1656
    if (!full_update)
1657
        vga_sync_dirty_bitmap(s);
1658

    
1659
    s->get_resolution(s, &width, &height);
1660
    disp_width = width;
1661

    
1662
    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1663
    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1664
    if (shift_control != 1) {
1665
        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1666
            - 1;
1667
    } else {
1668
        /* in CGA modes, multi_scan is ignored */
1669
        /* XXX: is it correct ? */
1670
        multi_scan = double_scan;
1671
    }
1672
    multi_run = multi_scan;
1673
    if (shift_control != s->shift_control ||
1674
        double_scan != s->double_scan) {
1675
        full_update = 1;
1676
        s->shift_control = shift_control;
1677
        s->double_scan = double_scan;
1678
    }
1679

    
1680
    if (shift_control == 0) {
1681
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1682
            disp_width <<= 1;
1683
        }
1684
    } else if (shift_control == 1) {
1685
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1686
            disp_width <<= 1;
1687
        }
1688
    }
1689

    
1690
    depth = s->get_bpp(s);
1691
    if (s->line_offset != s->last_line_offset ||
1692
        disp_width != s->last_width ||
1693
        height != s->last_height ||
1694
        s->last_depth != depth) {
1695
        if (depth == 32 || (depth == 16 && !byteswap)) {
1696
            surface = qemu_create_displaysurface_from(disp_width,
1697
                    height, depth, s->line_offset,
1698
                    s->vram_ptr + (s->start_addr * 4), byteswap);
1699
            dpy_gfx_replace_surface(s->con, surface);
1700
        } else {
1701
            qemu_console_resize(s->con, disp_width, height);
1702
            surface = qemu_console_surface(s->con);
1703
        }
1704
        s->last_scr_width = disp_width;
1705
        s->last_scr_height = height;
1706
        s->last_width = disp_width;
1707
        s->last_height = height;
1708
        s->last_line_offset = s->line_offset;
1709
        s->last_depth = depth;
1710
        full_update = 1;
1711
    } else if (is_buffer_shared(surface) &&
1712
               (full_update || surface_data(surface) != s->vram_ptr
1713
                + (s->start_addr * 4))) {
1714
        DisplaySurface *surface;
1715
        surface = qemu_create_displaysurface_from(disp_width,
1716
                height, depth, s->line_offset,
1717
                s->vram_ptr + (s->start_addr * 4), byteswap);
1718
        dpy_gfx_replace_surface(s->con, surface);
1719
    }
1720

    
1721
    s->rgb_to_pixel =
1722
        rgb_to_pixel_dup_table[get_depth_index(surface)];
1723

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

    
1774
    if (!is_buffer_shared(surface) && s->cursor_invalidate) {
1775
        s->cursor_invalidate(s);
1776
    }
1777

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

    
1859
static void vga_draw_blank(VGACommonState *s, int full_update)
1860
{
1861
    DisplaySurface *surface = qemu_console_surface(s->con);
1862
    int i, w, val;
1863
    uint8_t *d;
1864

    
1865
    if (!full_update)
1866
        return;
1867
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1868
        return;
1869

    
1870
    s->rgb_to_pixel =
1871
        rgb_to_pixel_dup_table[get_depth_index(surface)];
1872
    if (surface_bits_per_pixel(surface) == 8) {
1873
        val = s->rgb_to_pixel(0, 0, 0);
1874
    } else {
1875
        val = 0;
1876
    }
1877
    w = s->last_scr_width * surface_bytes_per_pixel(surface);
1878
    d = surface_data(surface);
1879
    for(i = 0; i < s->last_scr_height; i++) {
1880
        memset(d, val, w);
1881
        d += surface_stride(surface);
1882
    }
1883
    dpy_gfx_update(s->con, 0, 0,
1884
                   s->last_scr_width, s->last_scr_height);
1885
}
1886

    
1887
#define GMODE_TEXT     0
1888
#define GMODE_GRAPH    1
1889
#define GMODE_BLANK 2
1890

    
1891
static void vga_update_display(void *opaque)
1892
{
1893
    VGACommonState *s = opaque;
1894
    DisplaySurface *surface = qemu_console_surface(s->con);
1895
    int full_update, graphic_mode;
1896

    
1897
    qemu_flush_coalesced_mmio_buffer();
1898

    
1899
    if (surface_bits_per_pixel(surface) == 0) {
1900
        /* nothing to do */
1901
    } else {
1902
        full_update = 0;
1903
        if (!(s->ar_index & 0x20)) {
1904
            graphic_mode = GMODE_BLANK;
1905
        } else {
1906
            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1907
        }
1908
        if (graphic_mode != s->graphic_mode) {
1909
            s->graphic_mode = graphic_mode;
1910
            s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
1911
            full_update = 1;
1912
        }
1913
        switch(graphic_mode) {
1914
        case GMODE_TEXT:
1915
            vga_draw_text(s, full_update);
1916
            break;
1917
        case GMODE_GRAPH:
1918
            vga_draw_graphic(s, full_update);
1919
            break;
1920
        case GMODE_BLANK:
1921
        default:
1922
            vga_draw_blank(s, full_update);
1923
            break;
1924
        }
1925
    }
1926
}
1927

    
1928
/* force a full display refresh */
1929
static void vga_invalidate_display(void *opaque)
1930
{
1931
    VGACommonState *s = opaque;
1932

    
1933
    s->last_width = -1;
1934
    s->last_height = -1;
1935
}
1936

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

    
1996
static void vga_reset(void *opaque)
1997
{
1998
    VGACommonState *s =  opaque;
1999
    vga_common_reset(s);
2000
}
2001

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

    
2018
    qemu_flush_coalesced_mmio_buffer();
2019

    
2020
    if (!(s->ar_index & 0x20)) {
2021
        graphic_mode = GMODE_BLANK;
2022
    } else {
2023
        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
2024
    }
2025
    if (graphic_mode != s->graphic_mode) {
2026
        s->graphic_mode = graphic_mode;
2027
        full_update = 1;
2028
    }
2029
    if (s->last_width == -1) {
2030
        s->last_width = 0;
2031
        full_update = 1;
2032
    }
2033

    
2034
    switch (graphic_mode) {
2035
    case GMODE_TEXT:
2036
        /* TODO: update palette */
2037
        full_update |= update_basic_params(s);
2038

    
2039
        /* total width & height */
2040
        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2041
        cw = 8;
2042
        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2043
            cw = 9;
2044
        }
2045
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2046
            cw = 16; /* NOTE: no 18 pixel wide */
2047
        }
2048
        width = (s->cr[VGA_CRTC_H_DISP] + 1);
2049
        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2050
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2051
            height = 100;
2052
        } else {
2053
            height = s->cr[VGA_CRTC_V_DISP_END] |
2054
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2055
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
2056
            height = (height + 1) / cheight;
2057
        }
2058

    
2059
        size = (height * width);
2060
        if (size > CH_ATTR_SIZE) {
2061
            if (!full_update)
2062
                return;
2063

    
2064
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2065
                     width, height);
2066
            break;
2067
        }
2068

    
2069
        if (width != s->last_width || height != s->last_height ||
2070
            cw != s->last_cw || cheight != s->last_ch) {
2071
            s->last_scr_width = width * cw;
2072
            s->last_scr_height = height * cheight;
2073
            qemu_console_resize(s->con, s->last_scr_width, s->last_scr_height);
2074
            dpy_text_resize(s->con, width, height);
2075
            s->last_depth = 0;
2076
            s->last_width = width;
2077
            s->last_height = height;
2078
            s->last_ch = cheight;
2079
            s->last_cw = cw;
2080
            full_update = 1;
2081
        }
2082

    
2083
        if (full_update) {
2084
            s->full_update_gfx = 1;
2085
        }
2086
        if (s->full_update_text) {
2087
            s->full_update_text = 0;
2088
            full_update |= 1;
2089
        }
2090

    
2091
        /* Update "hardware" cursor */
2092
        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
2093
                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2094
        if (cursor_offset != s->cursor_offset ||
2095
            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2096
            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2097
            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2098
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2099
                dpy_text_cursor(s->con,
2100
                                TEXTMODE_X(cursor_offset),
2101
                                TEXTMODE_Y(cursor_offset));
2102
            else
2103
                dpy_text_cursor(s->con, -1, -1);
2104
            s->cursor_offset = cursor_offset;
2105
            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2106
            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2107
        }
2108

    
2109
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2110
        dst = chardata;
2111

    
2112
        if (full_update) {
2113
            for (i = 0; i < size; src ++, dst ++, i ++)
2114
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2115

    
2116
            dpy_text_update(s->con, 0, 0, width, height);
2117
        } else {
2118
            c_max = 0;
2119

    
2120
            for (i = 0; i < size; src ++, dst ++, i ++) {
2121
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2122
                if (*dst != val) {
2123
                    *dst = val;
2124
                    c_max = i;
2125
                    break;
2126
                }
2127
            }
2128
            c_min = i;
2129
            for (; i < size; src ++, dst ++, i ++) {
2130
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2131
                if (*dst != val) {
2132
                    *dst = val;
2133
                    c_max = i;
2134
                }
2135
            }
2136

    
2137
            if (c_min <= c_max) {
2138
                i = TEXTMODE_Y(c_min);
2139
                dpy_text_update(s->con, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2140
            }
2141
        }
2142

    
2143
        return;
2144
    case GMODE_GRAPH:
2145
        if (!full_update)
2146
            return;
2147

    
2148
        s->get_resolution(s, &width, &height);
2149
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2150
                 width, height);
2151
        break;
2152
    case GMODE_BLANK:
2153
    default:
2154
        if (!full_update)
2155
            return;
2156

    
2157
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2158
        break;
2159
    }
2160

    
2161
    /* Display a message */
2162
    s->last_width = 60;
2163
    s->last_height = height = 3;
2164
    dpy_text_cursor(s->con, -1, -1);
2165
    dpy_text_resize(s->con, s->last_width, height);
2166

    
2167
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2168
        console_write_ch(dst ++, ' ');
2169

    
2170
    size = strlen(msg_buffer);
2171
    width = (s->last_width - size) / 2;
2172
    dst = chardata + s->last_width + width;
2173
    for (i = 0; i < size; i ++)
2174
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2175

    
2176
    dpy_text_update(s->con, 0, 0, s->last_width, height);
2177
}
2178

    
2179
static uint64_t vga_mem_read(void *opaque, hwaddr addr,
2180
                             unsigned size)
2181
{
2182
    VGACommonState *s = opaque;
2183

    
2184
    return vga_mem_readb(s, addr);
2185
}
2186

    
2187
static void vga_mem_write(void *opaque, hwaddr addr,
2188
                          uint64_t data, unsigned size)
2189
{
2190
    VGACommonState *s = opaque;
2191

    
2192
    return vga_mem_writeb(s, addr, data);
2193
}
2194

    
2195
const MemoryRegionOps vga_mem_ops = {
2196
    .read = vga_mem_read,
2197
    .write = vga_mem_write,
2198
    .endianness = DEVICE_LITTLE_ENDIAN,
2199
    .impl = {
2200
        .min_access_size = 1,
2201
        .max_access_size = 1,
2202
    },
2203
};
2204

    
2205
static int vga_common_post_load(void *opaque, int version_id)
2206
{
2207
    VGACommonState *s = opaque;
2208

    
2209
    /* force refresh */
2210
    s->graphic_mode = -1;
2211
    return 0;
2212
}
2213

    
2214
const VMStateDescription vmstate_vga_common = {
2215
    .name = "vga",
2216
    .version_id = 2,
2217
    .minimum_version_id = 2,
2218
    .minimum_version_id_old = 2,
2219
    .post_load = vga_common_post_load,
2220
    .fields      = (VMStateField []) {
2221
        VMSTATE_UINT32(latch, VGACommonState),
2222
        VMSTATE_UINT8(sr_index, VGACommonState),
2223
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2224
        VMSTATE_UINT8(gr_index, VGACommonState),
2225
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2226
        VMSTATE_UINT8(ar_index, VGACommonState),
2227
        VMSTATE_BUFFER(ar, VGACommonState),
2228
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2229
        VMSTATE_UINT8(cr_index, VGACommonState),
2230
        VMSTATE_BUFFER(cr, VGACommonState),
2231
        VMSTATE_UINT8(msr, VGACommonState),
2232
        VMSTATE_UINT8(fcr, VGACommonState),
2233
        VMSTATE_UINT8(st00, VGACommonState),
2234
        VMSTATE_UINT8(st01, VGACommonState),
2235

    
2236
        VMSTATE_UINT8(dac_state, VGACommonState),
2237
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2238
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2239
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2240
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2241
        VMSTATE_BUFFER(palette, VGACommonState),
2242

    
2243
        VMSTATE_INT32(bank_offset, VGACommonState),
2244
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2245
        VMSTATE_UINT16(vbe_index, VGACommonState),
2246
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2247
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2248
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2249
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2250
        VMSTATE_END_OF_LIST()
2251
    }
2252
};
2253

    
2254
static const GraphicHwOps vga_ops = {
2255
    .invalidate  = vga_invalidate_display,
2256
    .gfx_update  = vga_update_display,
2257
    .text_update = vga_update_text,
2258
};
2259

    
2260
void vga_common_init(VGACommonState *s, Object *obj)
2261
{
2262
    int i, j, v, b;
2263

    
2264
    for(i = 0;i < 256; i++) {
2265
        v = 0;
2266
        for(j = 0; j < 8; j++) {
2267
            v |= ((i >> j) & 1) << (j * 4);
2268
        }
2269
        expand4[i] = v;
2270

    
2271
        v = 0;
2272
        for(j = 0; j < 4; j++) {
2273
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2274
        }
2275
        expand2[i] = v;
2276
    }
2277
    for(i = 0; i < 16; i++) {
2278
        v = 0;
2279
        for(j = 0; j < 4; j++) {
2280
            b = ((i >> j) & 1);
2281
            v |= b << (2 * j);
2282
            v |= b << (2 * j + 1);
2283
        }
2284
        expand4to8[i] = v;
2285
    }
2286

    
2287
    /* valid range: 1 MB -> 256 MB */
2288
    s->vram_size = 1024 * 1024;
2289
    while (s->vram_size < (s->vram_size_mb << 20) &&
2290
           s->vram_size < (256 << 20)) {
2291
        s->vram_size <<= 1;
2292
    }
2293
    s->vram_size_mb = s->vram_size >> 20;
2294

    
2295
    s->is_vbe_vmstate = 1;
2296
    memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size);
2297
    vmstate_register_ram_global(&s->vram);
2298
    xen_register_framebuffer(&s->vram);
2299
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2300
    s->get_bpp = vga_get_bpp;
2301
    s->get_offsets = vga_get_offsets;
2302
    s->get_resolution = vga_get_resolution;
2303
    s->hw_ops = &vga_ops;
2304
    switch (vga_retrace_method) {
2305
    case VGA_RETRACE_DUMB:
2306
        s->retrace = vga_dumb_retrace;
2307
        s->update_retrace_info = vga_dumb_update_retrace_info;
2308
        break;
2309

    
2310
    case VGA_RETRACE_PRECISE:
2311
        s->retrace = vga_precise_retrace;
2312
        s->update_retrace_info = vga_precise_update_retrace_info;
2313
        break;
2314
    }
2315
    vga_dirty_log_start(s);
2316
}
2317

    
2318
static const MemoryRegionPortio vga_portio_list[] = {
2319
    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2320
    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2321
    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2322
    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2323
    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2324
    PORTIO_END_OF_LIST(),
2325
};
2326

    
2327
static const MemoryRegionPortio vbe_portio_list[] = {
2328
    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2329
# ifdef TARGET_I386
2330
    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2331
# endif
2332
    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2333
    PORTIO_END_OF_LIST(),
2334
};
2335

    
2336
/* Used by both ISA and PCI */
2337
MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
2338
                          const MemoryRegionPortio **vga_ports,
2339
                          const MemoryRegionPortio **vbe_ports)
2340
{
2341
    MemoryRegion *vga_mem;
2342

    
2343
    *vga_ports = vga_portio_list;
2344
    *vbe_ports = vbe_portio_list;
2345

    
2346
    vga_mem = g_malloc(sizeof(*vga_mem));
2347
    memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
2348
                          "vga-lowmem", 0x20000);
2349
    memory_region_set_flush_coalesced(vga_mem);
2350

    
2351
    return vga_mem;
2352
}
2353

    
2354
void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space,
2355
              MemoryRegion *address_space_io, bool init_vga_ports)
2356
{
2357
    MemoryRegion *vga_io_memory;
2358
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2359
    PortioList *vga_port_list = g_new(PortioList, 1);
2360
    PortioList *vbe_port_list = g_new(PortioList, 1);
2361

    
2362
    qemu_register_reset(vga_reset, s);
2363

    
2364
    s->bank_offset = 0;
2365

    
2366
    s->legacy_address_space = address_space;
2367

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

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