Statistics
| Branch: | Revision:

root / hw / vga.c @ a0f42610

History | View | Annotate | Download (68.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.h"
25
#include "console.h"
26
#include "pc.h"
27
#include "pci.h"
28
#include "vga_int.h"
29
#include "pixel_ops.h"
30
#include "qemu-timer.h"
31
#include "xen.h"
32

    
33
//#define DEBUG_VGA
34
//#define DEBUG_VGA_MEM
35
//#define DEBUG_VGA_REG
36

    
37
//#define DEBUG_BOCHS_VBE
38

    
39
/* force some bits to zero */
40
const uint8_t sr_mask[8] = {
41
    0x03,
42
    0x3d,
43
    0x0f,
44
    0x3f,
45
    0x0e,
46
    0x00,
47
    0x00,
48
    0xff,
49
};
50

    
51
const uint8_t gr_mask[16] = {
52
    0x0f, /* 0x00 */
53
    0x0f, /* 0x01 */
54
    0x0f, /* 0x02 */
55
    0x1f, /* 0x03 */
56
    0x03, /* 0x04 */
57
    0x7b, /* 0x05 */
58
    0x0f, /* 0x06 */
59
    0x0f, /* 0x07 */
60
    0xff, /* 0x08 */
61
    0x00, /* 0x09 */
62
    0x00, /* 0x0a */
63
    0x00, /* 0x0b */
64
    0x00, /* 0x0c */
65
    0x00, /* 0x0d */
66
    0x00, /* 0x0e */
67
    0x00, /* 0x0f */
68
};
69

    
70
#define cbswap_32(__x) \
71
((uint32_t)( \
72
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
74
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
75
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
76

    
77
#ifdef HOST_WORDS_BIGENDIAN
78
#define PAT(x) cbswap_32(x)
79
#else
80
#define PAT(x) (x)
81
#endif
82

    
83
#ifdef HOST_WORDS_BIGENDIAN
84
#define BIG 1
85
#else
86
#define BIG 0
87
#endif
88

    
89
#ifdef HOST_WORDS_BIGENDIAN
90
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
91
#else
92
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93
#endif
94

    
95
static const uint32_t mask16[16] = {
96
    PAT(0x00000000),
97
    PAT(0x000000ff),
98
    PAT(0x0000ff00),
99
    PAT(0x0000ffff),
100
    PAT(0x00ff0000),
101
    PAT(0x00ff00ff),
102
    PAT(0x00ffff00),
103
    PAT(0x00ffffff),
104
    PAT(0xff000000),
105
    PAT(0xff0000ff),
106
    PAT(0xff00ff00),
107
    PAT(0xff00ffff),
108
    PAT(0xffff0000),
109
    PAT(0xffff00ff),
110
    PAT(0xffffff00),
111
    PAT(0xffffffff),
112
};
113

    
114
#undef PAT
115

    
116
#ifdef HOST_WORDS_BIGENDIAN
117
#define PAT(x) (x)
118
#else
119
#define PAT(x) cbswap_32(x)
120
#endif
121

    
122
static const uint32_t dmask16[16] = {
123
    PAT(0x00000000),
124
    PAT(0x000000ff),
125
    PAT(0x0000ff00),
126
    PAT(0x0000ffff),
127
    PAT(0x00ff0000),
128
    PAT(0x00ff00ff),
129
    PAT(0x00ffff00),
130
    PAT(0x00ffffff),
131
    PAT(0xff000000),
132
    PAT(0xff0000ff),
133
    PAT(0xff00ff00),
134
    PAT(0xff00ffff),
135
    PAT(0xffff0000),
136
    PAT(0xffff00ff),
137
    PAT(0xffffff00),
138
    PAT(0xffffffff),
139
};
140

    
141
static const uint32_t dmask4[4] = {
142
    PAT(0x00000000),
143
    PAT(0x0000ffff),
144
    PAT(0xffff0000),
145
    PAT(0xffffffff),
146
};
147

    
148
static uint32_t expand4[256];
149
static uint16_t expand2[256];
150
static uint8_t expand4to8[16];
151

    
152
static void vga_screen_dump(void *opaque, const char *filename);
153
static const char *screen_dump_filename;
154
static DisplayChangeListener *screen_dump_dcl;
155

    
156
static void vga_update_memory_access(VGACommonState *s)
157
{
158
    MemoryRegion *region, *old_region = s->chain4_alias;
159
    target_phys_addr_t base, offset, size;
160

    
161
    s->chain4_alias = NULL;
162

    
163
    if ((s->sr[0x02] & 0xf) == 0xf && s->sr[0x04] & 0x08) {
164
        offset = 0;
165
        switch ((s->gr[6] >> 2) & 3) {
166
        case 0:
167
            base = 0xa0000;
168
            size = 0x20000;
169
            break;
170
        case 1:
171
            base = 0xa0000;
172
            size = 0x10000;
173
            offset = s->bank_offset;
174
            break;
175
        case 2:
176
            base = 0xb0000;
177
            size = 0x8000;
178
            break;
179
        case 3:
180
        default:
181
            base = 0xb8000;
182
            size = 0x8000;
183
            break;
184
        }
185
        base += isa_mem_base;
186
        region = g_malloc(sizeof(*region));
187
        memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
188
        memory_region_add_subregion_overlap(s->legacy_address_space, base,
189
                                            region, 2);
190
        s->chain4_alias = region;
191
    }
192
    if (old_region) {
193
        memory_region_del_subregion(s->legacy_address_space, old_region);
194
        memory_region_destroy(old_region);
195
        g_free(old_region);
196
        s->plane_updated = 0xf;
197
    }
198
}
199

    
200
static void vga_dumb_update_retrace_info(VGACommonState *s)
201
{
202
    (void) s;
203
}
204

    
205
static void vga_precise_update_retrace_info(VGACommonState *s)
206
{
207
    int htotal_chars;
208
    int hretr_start_char;
209
    int hretr_skew_chars;
210
    int hretr_end_char;
211

    
212
    int vtotal_lines;
213
    int vretr_start_line;
214
    int vretr_end_line;
215

    
216
    int dots;
217
#if 0
218
    int div2, sldiv2;
219
#endif
220
    int clocking_mode;
221
    int clock_sel;
222
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
223
    int64_t chars_per_sec;
224
    struct vga_precise_retrace *r = &s->retrace_info.precise;
225

    
226
    htotal_chars = s->cr[0x00] + 5;
227
    hretr_start_char = s->cr[0x04];
228
    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
229
    hretr_end_char = s->cr[0x05] & 0x1f;
230

    
231
    vtotal_lines = (s->cr[0x06]
232
                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
233
        ;
234
    vretr_start_line = s->cr[0x10]
235
        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
236
        ;
237
    vretr_end_line = s->cr[0x11] & 0xf;
238

    
239

    
240

    
241
    clocking_mode = (s->sr[0x01] >> 3) & 1;
242
    clock_sel = (s->msr >> 2) & 3;
243
    dots = (s->msr & 1) ? 8 : 9;
244

    
245
    chars_per_sec = clk_hz[clock_sel] / dots;
246

    
247
    htotal_chars <<= clocking_mode;
248

    
249
    r->total_chars = vtotal_lines * htotal_chars;
250
    if (r->freq) {
251
        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
252
    } else {
253
        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
254
    }
255

    
256
    r->vstart = vretr_start_line;
257
    r->vend = r->vstart + vretr_end_line + 1;
258

    
259
    r->hstart = hretr_start_char + hretr_skew_chars;
260
    r->hend = r->hstart + hretr_end_char + 1;
261
    r->htotal = htotal_chars;
262

    
263
#if 0
264
    div2 = (s->cr[0x17] >> 2) & 1;
265
    sldiv2 = (s->cr[0x17] >> 3) & 1;
266
    printf (
267
        "hz=%f\n"
268
        "htotal = %d\n"
269
        "hretr_start = %d\n"
270
        "hretr_skew = %d\n"
271
        "hretr_end = %d\n"
272
        "vtotal = %d\n"
273
        "vretr_start = %d\n"
274
        "vretr_end = %d\n"
275
        "div2 = %d sldiv2 = %d\n"
276
        "clocking_mode = %d\n"
277
        "clock_sel = %d %d\n"
278
        "dots = %d\n"
279
        "ticks/char = %" PRId64 "\n"
280
        "\n",
281
        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
282
        htotal_chars,
283
        hretr_start_char,
284
        hretr_skew_chars,
285
        hretr_end_char,
286
        vtotal_lines,
287
        vretr_start_line,
288
        vretr_end_line,
289
        div2, sldiv2,
290
        clocking_mode,
291
        clock_sel,
292
        clk_hz[clock_sel],
293
        dots,
294
        r->ticks_per_char
295
        );
296
#endif
297
}
298

    
299
static uint8_t vga_precise_retrace(VGACommonState *s)
300
{
301
    struct vga_precise_retrace *r = &s->retrace_info.precise;
302
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
303

    
304
    if (r->total_chars) {
305
        int cur_line, cur_line_char, cur_char;
306
        int64_t cur_tick;
307

    
308
        cur_tick = qemu_get_clock_ns(vm_clock);
309

    
310
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
311
        cur_line = cur_char / r->htotal;
312

    
313
        if (cur_line >= r->vstart && cur_line <= r->vend) {
314
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
315
        } else {
316
            cur_line_char = cur_char % r->htotal;
317
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
318
                val |= ST01_DISP_ENABLE;
319
            }
320
        }
321

    
322
        return val;
323
    } else {
324
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
325
    }
326
}
327

    
328
static uint8_t vga_dumb_retrace(VGACommonState *s)
329
{
330
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
331
}
332

    
333
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
334
{
335
    if (s->msr & MSR_COLOR_EMULATION) {
336
        /* Color */
337
        return (addr >= 0x3b0 && addr <= 0x3bf);
338
    } else {
339
        /* Monochrome */
340
        return (addr >= 0x3d0 && addr <= 0x3df);
341
    }
342
}
343

    
344
uint32_t vga_ioport_read(void *opaque, uint32_t addr)
345
{
346
    VGACommonState *s = opaque;
347
    int val, index;
348

    
349
    if (vga_ioport_invalid(s, addr)) {
350
        val = 0xff;
351
    } else {
352
        switch(addr) {
353
        case 0x3c0:
354
            if (s->ar_flip_flop == 0) {
355
                val = s->ar_index;
356
            } else {
357
                val = 0;
358
            }
359
            break;
360
        case 0x3c1:
361
            index = s->ar_index & 0x1f;
362
            if (index < 21)
363
                val = s->ar[index];
364
            else
365
                val = 0;
366
            break;
367
        case 0x3c2:
368
            val = s->st00;
369
            break;
370
        case 0x3c4:
371
            val = s->sr_index;
372
            break;
373
        case 0x3c5:
374
            val = s->sr[s->sr_index];
375
#ifdef DEBUG_VGA_REG
376
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
377
#endif
378
            break;
379
        case 0x3c7:
380
            val = s->dac_state;
381
            break;
382
        case 0x3c8:
383
            val = s->dac_write_index;
384
            break;
385
        case 0x3c9:
386
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
387
            if (++s->dac_sub_index == 3) {
388
                s->dac_sub_index = 0;
389
                s->dac_read_index++;
390
            }
391
            break;
392
        case 0x3ca:
393
            val = s->fcr;
394
            break;
395
        case 0x3cc:
396
            val = s->msr;
397
            break;
398
        case 0x3ce:
399
            val = s->gr_index;
400
            break;
401
        case 0x3cf:
402
            val = s->gr[s->gr_index];
403
#ifdef DEBUG_VGA_REG
404
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
405
#endif
406
            break;
407
        case 0x3b4:
408
        case 0x3d4:
409
            val = s->cr_index;
410
            break;
411
        case 0x3b5:
412
        case 0x3d5:
413
            val = s->cr[s->cr_index];
414
#ifdef DEBUG_VGA_REG
415
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
416
#endif
417
            break;
418
        case 0x3ba:
419
        case 0x3da:
420
            /* just toggle to fool polling */
421
            val = s->st01 = s->retrace(s);
422
            s->ar_flip_flop = 0;
423
            break;
424
        default:
425
            val = 0x00;
426
            break;
427
        }
428
    }
429
#if defined(DEBUG_VGA)
430
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
431
#endif
432
    return val;
433
}
434

    
435
void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
436
{
437
    VGACommonState *s = opaque;
438
    int index;
439

    
440
    /* check port range access depending on color/monochrome mode */
441
    if (vga_ioport_invalid(s, addr)) {
442
        return;
443
    }
444
#ifdef DEBUG_VGA
445
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
446
#endif
447

    
448
    switch(addr) {
449
    case 0x3c0:
450
        if (s->ar_flip_flop == 0) {
451
            val &= 0x3f;
452
            s->ar_index = val;
453
        } else {
454
            index = s->ar_index & 0x1f;
455
            switch(index) {
456
            case 0x00 ... 0x0f:
457
                s->ar[index] = val & 0x3f;
458
                break;
459
            case 0x10:
460
                s->ar[index] = val & ~0x10;
461
                break;
462
            case 0x11:
463
                s->ar[index] = val;
464
                break;
465
            case 0x12:
466
                s->ar[index] = val & ~0xc0;
467
                break;
468
            case 0x13:
469
                s->ar[index] = val & ~0xf0;
470
                break;
471
            case 0x14:
472
                s->ar[index] = val & ~0xf0;
473
                break;
474
            default:
475
                break;
476
            }
477
        }
478
        s->ar_flip_flop ^= 1;
479
        break;
480
    case 0x3c2:
481
        s->msr = val & ~0x10;
482
        s->update_retrace_info(s);
483
        break;
484
    case 0x3c4:
485
        s->sr_index = val & 7;
486
        break;
487
    case 0x3c5:
488
#ifdef DEBUG_VGA_REG
489
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
490
#endif
491
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
492
        if (s->sr_index == 1) s->update_retrace_info(s);
493
        vga_update_memory_access(s);
494
        break;
495
    case 0x3c7:
496
        s->dac_read_index = val;
497
        s->dac_sub_index = 0;
498
        s->dac_state = 3;
499
        break;
500
    case 0x3c8:
501
        s->dac_write_index = val;
502
        s->dac_sub_index = 0;
503
        s->dac_state = 0;
504
        break;
505
    case 0x3c9:
506
        s->dac_cache[s->dac_sub_index] = val;
507
        if (++s->dac_sub_index == 3) {
508
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
509
            s->dac_sub_index = 0;
510
            s->dac_write_index++;
511
        }
512
        break;
513
    case 0x3ce:
514
        s->gr_index = val & 0x0f;
515
        break;
516
    case 0x3cf:
517
#ifdef DEBUG_VGA_REG
518
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
519
#endif
520
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
521
        vga_update_memory_access(s);
522
        break;
523
    case 0x3b4:
524
    case 0x3d4:
525
        s->cr_index = val;
526
        break;
527
    case 0x3b5:
528
    case 0x3d5:
529
#ifdef DEBUG_VGA_REG
530
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
531
#endif
532
        /* handle CR0-7 protection */
533
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
534
            /* can always write bit 4 of CR7 */
535
            if (s->cr_index == 7)
536
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
537
            return;
538
        }
539
        s->cr[s->cr_index] = val;
540

    
541
        switch(s->cr_index) {
542
        case 0x00:
543
        case 0x04:
544
        case 0x05:
545
        case 0x06:
546
        case 0x07:
547
        case 0x11:
548
        case 0x17:
549
            s->update_retrace_info(s);
550
            break;
551
        }
552
        break;
553
    case 0x3ba:
554
    case 0x3da:
555
        s->fcr = val & 0x10;
556
        break;
557
    }
558
}
559

    
560
#ifdef CONFIG_BOCHS_VBE
561
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
562
{
563
    VGACommonState *s = opaque;
564
    uint32_t val;
565
    val = s->vbe_index;
566
    return val;
567
}
568

    
569
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
570
{
571
    VGACommonState *s = opaque;
572
    uint32_t val;
573

    
574
    if (s->vbe_index < VBE_DISPI_INDEX_NB) {
575
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
576
            switch(s->vbe_index) {
577
                /* XXX: do not hardcode ? */
578
            case VBE_DISPI_INDEX_XRES:
579
                val = VBE_DISPI_MAX_XRES;
580
                break;
581
            case VBE_DISPI_INDEX_YRES:
582
                val = VBE_DISPI_MAX_YRES;
583
                break;
584
            case VBE_DISPI_INDEX_BPP:
585
                val = VBE_DISPI_MAX_BPP;
586
                break;
587
            default:
588
                val = s->vbe_regs[s->vbe_index];
589
                break;
590
            }
591
        } else {
592
            val = s->vbe_regs[s->vbe_index];
593
        }
594
    } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
595
        val = s->vram_size / (64 * 1024);
596
    } else {
597
        val = 0;
598
    }
599
#ifdef DEBUG_BOCHS_VBE
600
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
601
#endif
602
    return val;
603
}
604

    
605
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
606
{
607
    VGACommonState *s = opaque;
608
    s->vbe_index = val;
609
}
610

    
611
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
612
{
613
    VGACommonState *s = opaque;
614

    
615
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
616
#ifdef DEBUG_BOCHS_VBE
617
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
618
#endif
619
        switch(s->vbe_index) {
620
        case VBE_DISPI_INDEX_ID:
621
            if (val == VBE_DISPI_ID0 ||
622
                val == VBE_DISPI_ID1 ||
623
                val == VBE_DISPI_ID2 ||
624
                val == VBE_DISPI_ID3 ||
625
                val == VBE_DISPI_ID4) {
626
                s->vbe_regs[s->vbe_index] = val;
627
            }
628
            break;
629
        case VBE_DISPI_INDEX_XRES:
630
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
631
                s->vbe_regs[s->vbe_index] = val;
632
            }
633
            break;
634
        case VBE_DISPI_INDEX_YRES:
635
            if (val <= VBE_DISPI_MAX_YRES) {
636
                s->vbe_regs[s->vbe_index] = val;
637
            }
638
            break;
639
        case VBE_DISPI_INDEX_BPP:
640
            if (val == 0)
641
                val = 8;
642
            if (val == 4 || val == 8 || val == 15 ||
643
                val == 16 || val == 24 || val == 32) {
644
                s->vbe_regs[s->vbe_index] = val;
645
            }
646
            break;
647
        case VBE_DISPI_INDEX_BANK:
648
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
649
              val &= (s->vbe_bank_mask >> 2);
650
            } else {
651
              val &= s->vbe_bank_mask;
652
            }
653
            s->vbe_regs[s->vbe_index] = val;
654
            s->bank_offset = (val << 16);
655
            vga_update_memory_access(s);
656
            break;
657
        case VBE_DISPI_INDEX_ENABLE:
658
            if ((val & VBE_DISPI_ENABLED) &&
659
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
660
                int h, shift_control;
661

    
662
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
663
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
664
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
665
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
666
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
667
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
668

    
669
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
670
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
671
                else
672
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
673
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
674
                s->vbe_start_addr = 0;
675

    
676
                /* clear the screen (should be done in BIOS) */
677
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
678
                    memset(s->vram_ptr, 0,
679
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
680
                }
681

    
682
                /* we initialize the VGA graphic mode (should be done
683
                   in BIOS) */
684
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
685
                s->cr[0x17] |= 3; /* no CGA modes */
686
                s->cr[0x13] = s->vbe_line_offset >> 3;
687
                /* width */
688
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
689
                /* height (only meaningful if < 1024) */
690
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
691
                s->cr[0x12] = h;
692
                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
693
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
694
                /* line compare to 1023 */
695
                s->cr[0x18] = 0xff;
696
                s->cr[0x07] |= 0x10;
697
                s->cr[0x09] |= 0x40;
698

    
699
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
700
                    shift_control = 0;
701
                    s->sr[0x01] &= ~8; /* no double line */
702
                } else {
703
                    shift_control = 2;
704
                    s->sr[4] |= 0x08; /* set chain 4 mode */
705
                    s->sr[2] |= 0x0f; /* activate all planes */
706
                }
707
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
708
                s->cr[0x09] &= ~0x9f; /* no double scan */
709
            } else {
710
                /* XXX: the bios should do that */
711
                s->bank_offset = 0;
712
            }
713
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
714
            s->vbe_regs[s->vbe_index] = val;
715
            vga_update_memory_access(s);
716
            break;
717
        case VBE_DISPI_INDEX_VIRT_WIDTH:
718
            {
719
                int w, h, line_offset;
720

    
721
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
722
                    return;
723
                w = val;
724
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
725
                    line_offset = w >> 1;
726
                else
727
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
728
                h = s->vram_size / line_offset;
729
                /* XXX: support weird bochs semantics ? */
730
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
731
                    return;
732
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
733
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
734
                s->vbe_line_offset = line_offset;
735
            }
736
            break;
737
        case VBE_DISPI_INDEX_X_OFFSET:
738
        case VBE_DISPI_INDEX_Y_OFFSET:
739
            {
740
                int x;
741
                s->vbe_regs[s->vbe_index] = val;
742
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
743
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
744
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
745
                    s->vbe_start_addr += x >> 1;
746
                else
747
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
748
                s->vbe_start_addr >>= 2;
749
            }
750
            break;
751
        default:
752
            break;
753
        }
754
    }
755
}
756
#endif
757

    
758
/* called for accesses between 0xa0000 and 0xc0000 */
759
uint32_t vga_mem_readb(VGACommonState *s, target_phys_addr_t addr)
760
{
761
    int memory_map_mode, plane;
762
    uint32_t ret;
763

    
764
    /* convert to VGA memory offset */
765
    memory_map_mode = (s->gr[6] >> 2) & 3;
766
    addr &= 0x1ffff;
767
    switch(memory_map_mode) {
768
    case 0:
769
        break;
770
    case 1:
771
        if (addr >= 0x10000)
772
            return 0xff;
773
        addr += s->bank_offset;
774
        break;
775
    case 2:
776
        addr -= 0x10000;
777
        if (addr >= 0x8000)
778
            return 0xff;
779
        break;
780
    default:
781
    case 3:
782
        addr -= 0x18000;
783
        if (addr >= 0x8000)
784
            return 0xff;
785
        break;
786
    }
787

    
788
    if (s->sr[4] & 0x08) {
789
        /* chain 4 mode : simplest access */
790
        ret = s->vram_ptr[addr];
791
    } else if (s->gr[5] & 0x10) {
792
        /* odd/even mode (aka text mode mapping) */
793
        plane = (s->gr[4] & 2) | (addr & 1);
794
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
795
    } else {
796
        /* standard VGA latched access */
797
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
798

    
799
        if (!(s->gr[5] & 0x08)) {
800
            /* read mode 0 */
801
            plane = s->gr[4];
802
            ret = GET_PLANE(s->latch, plane);
803
        } else {
804
            /* read mode 1 */
805
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
806
            ret |= ret >> 16;
807
            ret |= ret >> 8;
808
            ret = (~ret) & 0xff;
809
        }
810
    }
811
    return ret;
812
}
813

    
814
/* called for accesses between 0xa0000 and 0xc0000 */
815
void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
816
{
817
    int memory_map_mode, plane, write_mode, b, func_select, mask;
818
    uint32_t write_mask, bit_mask, set_mask;
819

    
820
#ifdef DEBUG_VGA_MEM
821
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
822
#endif
823
    /* convert to VGA memory offset */
824
    memory_map_mode = (s->gr[6] >> 2) & 3;
825
    addr &= 0x1ffff;
826
    switch(memory_map_mode) {
827
    case 0:
828
        break;
829
    case 1:
830
        if (addr >= 0x10000)
831
            return;
832
        addr += s->bank_offset;
833
        break;
834
    case 2:
835
        addr -= 0x10000;
836
        if (addr >= 0x8000)
837
            return;
838
        break;
839
    default:
840
    case 3:
841
        addr -= 0x18000;
842
        if (addr >= 0x8000)
843
            return;
844
        break;
845
    }
846

    
847
    if (s->sr[4] & 0x08) {
848
        /* chain 4 mode : simplest access */
849
        plane = addr & 3;
850
        mask = (1 << plane);
851
        if (s->sr[2] & mask) {
852
            s->vram_ptr[addr] = val;
853
#ifdef DEBUG_VGA_MEM
854
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
855
#endif
856
            s->plane_updated |= mask; /* only used to detect font change */
857
            memory_region_set_dirty(&s->vram, addr);
858
        }
859
    } else if (s->gr[5] & 0x10) {
860
        /* odd/even mode (aka text mode mapping) */
861
        plane = (s->gr[4] & 2) | (addr & 1);
862
        mask = (1 << plane);
863
        if (s->sr[2] & mask) {
864
            addr = ((addr & ~1) << 1) | plane;
865
            s->vram_ptr[addr] = val;
866
#ifdef DEBUG_VGA_MEM
867
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
868
#endif
869
            s->plane_updated |= mask; /* only used to detect font change */
870
            memory_region_set_dirty(&s->vram, addr);
871
        }
872
    } else {
873
        /* standard VGA latched access */
874
        write_mode = s->gr[5] & 3;
875
        switch(write_mode) {
876
        default:
877
        case 0:
878
            /* rotate */
879
            b = s->gr[3] & 7;
880
            val = ((val >> b) | (val << (8 - b))) & 0xff;
881
            val |= val << 8;
882
            val |= val << 16;
883

    
884
            /* apply set/reset mask */
885
            set_mask = mask16[s->gr[1]];
886
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
887
            bit_mask = s->gr[8];
888
            break;
889
        case 1:
890
            val = s->latch;
891
            goto do_write;
892
        case 2:
893
            val = mask16[val & 0x0f];
894
            bit_mask = s->gr[8];
895
            break;
896
        case 3:
897
            /* rotate */
898
            b = s->gr[3] & 7;
899
            val = (val >> b) | (val << (8 - b));
900

    
901
            bit_mask = s->gr[8] & val;
902
            val = mask16[s->gr[0]];
903
            break;
904
        }
905

    
906
        /* apply logical operation */
907
        func_select = s->gr[3] >> 3;
908
        switch(func_select) {
909
        case 0:
910
        default:
911
            /* nothing to do */
912
            break;
913
        case 1:
914
            /* and */
915
            val &= s->latch;
916
            break;
917
        case 2:
918
            /* or */
919
            val |= s->latch;
920
            break;
921
        case 3:
922
            /* xor */
923
            val ^= s->latch;
924
            break;
925
        }
926

    
927
        /* apply bit mask */
928
        bit_mask |= bit_mask << 8;
929
        bit_mask |= bit_mask << 16;
930
        val = (val & bit_mask) | (s->latch & ~bit_mask);
931

    
932
    do_write:
933
        /* mask data according to sr[2] */
934
        mask = s->sr[2];
935
        s->plane_updated |= mask; /* only used to detect font change */
936
        write_mask = mask16[mask];
937
        ((uint32_t *)s->vram_ptr)[addr] =
938
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
939
            (val & write_mask);
940
#ifdef DEBUG_VGA_MEM
941
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
942
               addr * 4, write_mask, val);
943
#endif
944
        memory_region_set_dirty(&s->vram, addr << 2);
945
    }
946
}
947

    
948
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
949
                             const uint8_t *font_ptr, int h,
950
                             uint32_t fgcol, uint32_t bgcol);
951
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
952
                                  const uint8_t *font_ptr, int h,
953
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
954
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
955
                                const uint8_t *s, int width);
956

    
957
#define DEPTH 8
958
#include "vga_template.h"
959

    
960
#define DEPTH 15
961
#include "vga_template.h"
962

    
963
#define BGR_FORMAT
964
#define DEPTH 15
965
#include "vga_template.h"
966

    
967
#define DEPTH 16
968
#include "vga_template.h"
969

    
970
#define BGR_FORMAT
971
#define DEPTH 16
972
#include "vga_template.h"
973

    
974
#define DEPTH 32
975
#include "vga_template.h"
976

    
977
#define BGR_FORMAT
978
#define DEPTH 32
979
#include "vga_template.h"
980

    
981
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
982
{
983
    unsigned int col;
984
    col = rgb_to_pixel8(r, g, b);
985
    col |= col << 8;
986
    col |= col << 16;
987
    return col;
988
}
989

    
990
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
991
{
992
    unsigned int col;
993
    col = rgb_to_pixel15(r, g, b);
994
    col |= col << 16;
995
    return col;
996
}
997

    
998
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
999
                                          unsigned int b)
1000
{
1001
    unsigned int col;
1002
    col = rgb_to_pixel15bgr(r, g, b);
1003
    col |= col << 16;
1004
    return col;
1005
}
1006

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

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

    
1024
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1025
{
1026
    unsigned int col;
1027
    col = rgb_to_pixel32(r, g, b);
1028
    return col;
1029
}
1030

    
1031
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1032
{
1033
    unsigned int col;
1034
    col = rgb_to_pixel32bgr(r, g, b);
1035
    return col;
1036
}
1037

    
1038
/* return true if the palette was modified */
1039
static int update_palette16(VGACommonState *s)
1040
{
1041
    int full_update, i;
1042
    uint32_t v, col, *palette;
1043

    
1044
    full_update = 0;
1045
    palette = s->last_palette;
1046
    for(i = 0; i < 16; i++) {
1047
        v = s->ar[i];
1048
        if (s->ar[0x10] & 0x80)
1049
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1050
        else
1051
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1052
        v = v * 3;
1053
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1054
                              c6_to_8(s->palette[v + 1]),
1055
                              c6_to_8(s->palette[v + 2]));
1056
        if (col != palette[i]) {
1057
            full_update = 1;
1058
            palette[i] = col;
1059
        }
1060
    }
1061
    return full_update;
1062
}
1063

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

    
1070
    full_update = 0;
1071
    palette = s->last_palette;
1072
    v = 0;
1073
    for(i = 0; i < 256; i++) {
1074
        if (s->dac_8bit) {
1075
          col = s->rgb_to_pixel(s->palette[v],
1076
                                s->palette[v + 1],
1077
                                s->palette[v + 2]);
1078
        } else {
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
        }
1083
        if (col != palette[i]) {
1084
            full_update = 1;
1085
            palette[i] = col;
1086
        }
1087
        v += 3;
1088
    }
1089
    return full_update;
1090
}
1091

    
1092
static void vga_get_offsets(VGACommonState *s,
1093
                            uint32_t *pline_offset,
1094
                            uint32_t *pstart_addr,
1095
                            uint32_t *pline_compare)
1096
{
1097
    uint32_t start_addr, line_offset, line_compare;
1098
#ifdef CONFIG_BOCHS_VBE
1099
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1100
        line_offset = s->vbe_line_offset;
1101
        start_addr = s->vbe_start_addr;
1102
        line_compare = 65535;
1103
    } else
1104
#endif
1105
    {
1106
        /* compute line_offset in bytes */
1107
        line_offset = s->cr[0x13];
1108
        line_offset <<= 3;
1109

    
1110
        /* starting address */
1111
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1112

    
1113
        /* line compare */
1114
        line_compare = s->cr[0x18] |
1115
            ((s->cr[0x07] & 0x10) << 4) |
1116
            ((s->cr[0x09] & 0x40) << 3);
1117
    }
1118
    *pline_offset = line_offset;
1119
    *pstart_addr = start_addr;
1120
    *pline_compare = line_compare;
1121
}
1122

    
1123
/* update start_addr and line_offset. Return TRUE if modified */
1124
static int update_basic_params(VGACommonState *s)
1125
{
1126
    int full_update;
1127
    uint32_t start_addr, line_offset, line_compare;
1128

    
1129
    full_update = 0;
1130

    
1131
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1132

    
1133
    if (line_offset != s->line_offset ||
1134
        start_addr != s->start_addr ||
1135
        line_compare != s->line_compare) {
1136
        s->line_offset = line_offset;
1137
        s->start_addr = start_addr;
1138
        s->line_compare = line_compare;
1139
        full_update = 1;
1140
    }
1141
    return full_update;
1142
}
1143

    
1144
#define NB_DEPTHS 7
1145

    
1146
static inline int get_depth_index(DisplayState *s)
1147
{
1148
    switch(ds_get_bits_per_pixel(s)) {
1149
    default:
1150
    case 8:
1151
        return 0;
1152
    case 15:
1153
        return 1;
1154
    case 16:
1155
        return 2;
1156
    case 32:
1157
        if (is_surface_bgr(s->surface))
1158
            return 4;
1159
        else
1160
            return 3;
1161
    }
1162
}
1163

    
1164
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1165
    vga_draw_glyph8_8,
1166
    vga_draw_glyph8_16,
1167
    vga_draw_glyph8_16,
1168
    vga_draw_glyph8_32,
1169
    vga_draw_glyph8_32,
1170
    vga_draw_glyph8_16,
1171
    vga_draw_glyph8_16,
1172
};
1173

    
1174
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1175
    vga_draw_glyph16_8,
1176
    vga_draw_glyph16_16,
1177
    vga_draw_glyph16_16,
1178
    vga_draw_glyph16_32,
1179
    vga_draw_glyph16_32,
1180
    vga_draw_glyph16_16,
1181
    vga_draw_glyph16_16,
1182
};
1183

    
1184
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1185
    vga_draw_glyph9_8,
1186
    vga_draw_glyph9_16,
1187
    vga_draw_glyph9_16,
1188
    vga_draw_glyph9_32,
1189
    vga_draw_glyph9_32,
1190
    vga_draw_glyph9_16,
1191
    vga_draw_glyph9_16,
1192
};
1193

    
1194
static const uint8_t cursor_glyph[32 * 4] = {
1195
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1196
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1197
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1198
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1199
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1200
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1201
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1202
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1203
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1204
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1205
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211
};
1212

    
1213
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1214
                                    int *pcwidth, int *pcheight)
1215
{
1216
    int width, cwidth, height, cheight;
1217

    
1218
    /* total width & height */
1219
    cheight = (s->cr[9] & 0x1f) + 1;
1220
    cwidth = 8;
1221
    if (!(s->sr[1] & 0x01))
1222
        cwidth = 9;
1223
    if (s->sr[1] & 0x08)
1224
        cwidth = 16; /* NOTE: no 18 pixel wide */
1225
    width = (s->cr[0x01] + 1);
1226
    if (s->cr[0x06] == 100) {
1227
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1228
        height = 100;
1229
    } else {
1230
        height = s->cr[0x12] |
1231
            ((s->cr[0x07] & 0x02) << 7) |
1232
            ((s->cr[0x07] & 0x40) << 3);
1233
        height = (height + 1) / cheight;
1234
    }
1235

    
1236
    *pwidth = width;
1237
    *pheight = height;
1238
    *pcwidth = cwidth;
1239
    *pcheight = cheight;
1240
}
1241

    
1242
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1243

    
1244
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1245
    rgb_to_pixel8_dup,
1246
    rgb_to_pixel15_dup,
1247
    rgb_to_pixel16_dup,
1248
    rgb_to_pixel32_dup,
1249
    rgb_to_pixel32bgr_dup,
1250
    rgb_to_pixel15bgr_dup,
1251
    rgb_to_pixel16bgr_dup,
1252
};
1253

    
1254
/*
1255
 * Text mode update
1256
 * Missing:
1257
 * - double scan
1258
 * - double width
1259
 * - underline
1260
 * - flashing
1261
 */
1262
static void vga_draw_text(VGACommonState *s, int full_update)
1263
{
1264
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1265
    int cx_min, cx_max, linesize, x_incr, line, line1;
1266
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1267
    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1268
    const uint8_t *font_ptr, *font_base[2];
1269
    int dup9, line_offset, depth_index;
1270
    uint32_t *palette;
1271
    uint32_t *ch_attr_ptr;
1272
    vga_draw_glyph8_func *vga_draw_glyph8;
1273
    vga_draw_glyph9_func *vga_draw_glyph9;
1274

    
1275
    /* compute font data address (in plane 2) */
1276
    v = s->sr[3];
1277
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1278
    if (offset != s->font_offsets[0]) {
1279
        s->font_offsets[0] = offset;
1280
        full_update = 1;
1281
    }
1282
    font_base[0] = s->vram_ptr + offset;
1283

    
1284
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1285
    font_base[1] = s->vram_ptr + offset;
1286
    if (offset != s->font_offsets[1]) {
1287
        s->font_offsets[1] = offset;
1288
        full_update = 1;
1289
    }
1290
    if (s->plane_updated & (1 << 2) || s->chain4_alias) {
1291
        /* if the plane 2 was modified since the last display, it
1292
           indicates the font may have been modified */
1293
        s->plane_updated = 0;
1294
        full_update = 1;
1295
    }
1296
    full_update |= update_basic_params(s);
1297

    
1298
    line_offset = s->line_offset;
1299

    
1300
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1301
    if ((height * width) > CH_ATTR_SIZE) {
1302
        /* better than nothing: exit if transient size is too big */
1303
        return;
1304
    }
1305

    
1306
    if (width != s->last_width || height != s->last_height ||
1307
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1308
        s->last_scr_width = width * cw;
1309
        s->last_scr_height = height * cheight;
1310
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1311
        s->last_depth = 0;
1312
        s->last_width = width;
1313
        s->last_height = height;
1314
        s->last_ch = cheight;
1315
        s->last_cw = cw;
1316
        full_update = 1;
1317
    }
1318
    s->rgb_to_pixel =
1319
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1320
    full_update |= update_palette16(s);
1321
    palette = s->last_palette;
1322
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1323

    
1324
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1325
    if (cursor_offset != s->cursor_offset ||
1326
        s->cr[0xa] != s->cursor_start ||
1327
        s->cr[0xb] != s->cursor_end) {
1328
      /* if the cursor position changed, we update the old and new
1329
         chars */
1330
        if (s->cursor_offset < CH_ATTR_SIZE)
1331
            s->last_ch_attr[s->cursor_offset] = -1;
1332
        if (cursor_offset < CH_ATTR_SIZE)
1333
            s->last_ch_attr[cursor_offset] = -1;
1334
        s->cursor_offset = cursor_offset;
1335
        s->cursor_start = s->cr[0xa];
1336
        s->cursor_end = s->cr[0xb];
1337
    }
1338
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1339

    
1340
    depth_index = get_depth_index(s->ds);
1341
    if (cw == 16)
1342
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1343
    else
1344
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1345
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1346

    
1347
    dest = ds_get_data(s->ds);
1348
    linesize = ds_get_linesize(s->ds);
1349
    ch_attr_ptr = s->last_ch_attr;
1350
    line = 0;
1351
    offset = s->start_addr * 4;
1352
    for(cy = 0; cy < height; cy++) {
1353
        d1 = dest;
1354
        src = s->vram_ptr + offset;
1355
        cx_min = width;
1356
        cx_max = -1;
1357
        for(cx = 0; cx < width; cx++) {
1358
            ch_attr = *(uint16_t *)src;
1359
            if (full_update || ch_attr != *ch_attr_ptr) {
1360
                if (cx < cx_min)
1361
                    cx_min = cx;
1362
                if (cx > cx_max)
1363
                    cx_max = cx;
1364
                *ch_attr_ptr = ch_attr;
1365
#ifdef HOST_WORDS_BIGENDIAN
1366
                ch = ch_attr >> 8;
1367
                cattr = ch_attr & 0xff;
1368
#else
1369
                ch = ch_attr & 0xff;
1370
                cattr = ch_attr >> 8;
1371
#endif
1372
                font_ptr = font_base[(cattr >> 3) & 1];
1373
                font_ptr += 32 * 4 * ch;
1374
                bgcol = palette[cattr >> 4];
1375
                fgcol = palette[cattr & 0x0f];
1376
                if (cw != 9) {
1377
                    vga_draw_glyph8(d1, linesize,
1378
                                    font_ptr, cheight, fgcol, bgcol);
1379
                } else {
1380
                    dup9 = 0;
1381
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1382
                        dup9 = 1;
1383
                    vga_draw_glyph9(d1, linesize,
1384
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1385
                }
1386
                if (src == cursor_ptr &&
1387
                    !(s->cr[0x0a] & 0x20)) {
1388
                    int line_start, line_last, h;
1389
                    /* draw the cursor */
1390
                    line_start = s->cr[0x0a] & 0x1f;
1391
                    line_last = s->cr[0x0b] & 0x1f;
1392
                    /* XXX: check that */
1393
                    if (line_last > cheight - 1)
1394
                        line_last = cheight - 1;
1395
                    if (line_last >= line_start && line_start < cheight) {
1396
                        h = line_last - line_start + 1;
1397
                        d = d1 + linesize * line_start;
1398
                        if (cw != 9) {
1399
                            vga_draw_glyph8(d, linesize,
1400
                                            cursor_glyph, h, fgcol, bgcol);
1401
                        } else {
1402
                            vga_draw_glyph9(d, linesize,
1403
                                            cursor_glyph, h, fgcol, bgcol, 1);
1404
                        }
1405
                    }
1406
                }
1407
            }
1408
            d1 += x_incr;
1409
            src += 4;
1410
            ch_attr_ptr++;
1411
        }
1412
        if (cx_max != -1) {
1413
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1414
                       (cx_max - cx_min + 1) * cw, cheight);
1415
        }
1416
        dest += linesize * cheight;
1417
        line1 = line + cheight;
1418
        offset += line_offset;
1419
        if (line < s->line_compare && line1 >= s->line_compare) {
1420
            offset = 0;
1421
        }
1422
        line = line1;
1423
    }
1424
}
1425

    
1426
enum {
1427
    VGA_DRAW_LINE2,
1428
    VGA_DRAW_LINE2D2,
1429
    VGA_DRAW_LINE4,
1430
    VGA_DRAW_LINE4D2,
1431
    VGA_DRAW_LINE8D2,
1432
    VGA_DRAW_LINE8,
1433
    VGA_DRAW_LINE15,
1434
    VGA_DRAW_LINE16,
1435
    VGA_DRAW_LINE24,
1436
    VGA_DRAW_LINE32,
1437
    VGA_DRAW_LINE_NB,
1438
};
1439

    
1440
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1441
    vga_draw_line2_8,
1442
    vga_draw_line2_16,
1443
    vga_draw_line2_16,
1444
    vga_draw_line2_32,
1445
    vga_draw_line2_32,
1446
    vga_draw_line2_16,
1447
    vga_draw_line2_16,
1448

    
1449
    vga_draw_line2d2_8,
1450
    vga_draw_line2d2_16,
1451
    vga_draw_line2d2_16,
1452
    vga_draw_line2d2_32,
1453
    vga_draw_line2d2_32,
1454
    vga_draw_line2d2_16,
1455
    vga_draw_line2d2_16,
1456

    
1457
    vga_draw_line4_8,
1458
    vga_draw_line4_16,
1459
    vga_draw_line4_16,
1460
    vga_draw_line4_32,
1461
    vga_draw_line4_32,
1462
    vga_draw_line4_16,
1463
    vga_draw_line4_16,
1464

    
1465
    vga_draw_line4d2_8,
1466
    vga_draw_line4d2_16,
1467
    vga_draw_line4d2_16,
1468
    vga_draw_line4d2_32,
1469
    vga_draw_line4d2_32,
1470
    vga_draw_line4d2_16,
1471
    vga_draw_line4d2_16,
1472

    
1473
    vga_draw_line8d2_8,
1474
    vga_draw_line8d2_16,
1475
    vga_draw_line8d2_16,
1476
    vga_draw_line8d2_32,
1477
    vga_draw_line8d2_32,
1478
    vga_draw_line8d2_16,
1479
    vga_draw_line8d2_16,
1480

    
1481
    vga_draw_line8_8,
1482
    vga_draw_line8_16,
1483
    vga_draw_line8_16,
1484
    vga_draw_line8_32,
1485
    vga_draw_line8_32,
1486
    vga_draw_line8_16,
1487
    vga_draw_line8_16,
1488

    
1489
    vga_draw_line15_8,
1490
    vga_draw_line15_15,
1491
    vga_draw_line15_16,
1492
    vga_draw_line15_32,
1493
    vga_draw_line15_32bgr,
1494
    vga_draw_line15_15bgr,
1495
    vga_draw_line15_16bgr,
1496

    
1497
    vga_draw_line16_8,
1498
    vga_draw_line16_15,
1499
    vga_draw_line16_16,
1500
    vga_draw_line16_32,
1501
    vga_draw_line16_32bgr,
1502
    vga_draw_line16_15bgr,
1503
    vga_draw_line16_16bgr,
1504

    
1505
    vga_draw_line24_8,
1506
    vga_draw_line24_15,
1507
    vga_draw_line24_16,
1508
    vga_draw_line24_32,
1509
    vga_draw_line24_32bgr,
1510
    vga_draw_line24_15bgr,
1511
    vga_draw_line24_16bgr,
1512

    
1513
    vga_draw_line32_8,
1514
    vga_draw_line32_15,
1515
    vga_draw_line32_16,
1516
    vga_draw_line32_32,
1517
    vga_draw_line32_32bgr,
1518
    vga_draw_line32_15bgr,
1519
    vga_draw_line32_16bgr,
1520
};
1521

    
1522
static int vga_get_bpp(VGACommonState *s)
1523
{
1524
    int ret;
1525
#ifdef CONFIG_BOCHS_VBE
1526
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1527
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1528
    } else
1529
#endif
1530
    {
1531
        ret = 0;
1532
    }
1533
    return ret;
1534
}
1535

    
1536
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1537
{
1538
    int width, height;
1539

    
1540
#ifdef CONFIG_BOCHS_VBE
1541
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1542
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1543
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1544
    } else
1545
#endif
1546
    {
1547
        width = (s->cr[0x01] + 1) * 8;
1548
        height = s->cr[0x12] |
1549
            ((s->cr[0x07] & 0x02) << 7) |
1550
            ((s->cr[0x07] & 0x40) << 3);
1551
        height = (height + 1);
1552
    }
1553
    *pwidth = width;
1554
    *pheight = height;
1555
}
1556

    
1557
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1558
{
1559
    int y;
1560
    if (y1 >= VGA_MAX_HEIGHT)
1561
        return;
1562
    if (y2 >= VGA_MAX_HEIGHT)
1563
        y2 = VGA_MAX_HEIGHT;
1564
    for(y = y1; y < y2; y++) {
1565
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1566
    }
1567
}
1568

    
1569
static void vga_sync_dirty_bitmap(VGACommonState *s)
1570
{
1571
    memory_region_sync_dirty_bitmap(&s->vram);
1572
}
1573

    
1574
void vga_dirty_log_start(VGACommonState *s)
1575
{
1576
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1577
}
1578

    
1579
void vga_dirty_log_stop(VGACommonState *s)
1580
{
1581
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1582
}
1583

    
1584
/*
1585
 * graphic modes
1586
 */
1587
static void vga_draw_graphic(VGACommonState *s, int full_update)
1588
{
1589
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1590
    int width, height, shift_control, line_offset, bwidth, bits;
1591
    ram_addr_t page0, page1, page_min, page_max;
1592
    int disp_width, multi_scan, multi_run;
1593
    uint8_t *d;
1594
    uint32_t v, addr1, addr;
1595
    vga_draw_line_func *vga_draw_line;
1596

    
1597
    full_update |= update_basic_params(s);
1598

    
1599
    if (!full_update)
1600
        vga_sync_dirty_bitmap(s);
1601

    
1602
    s->get_resolution(s, &width, &height);
1603
    disp_width = width;
1604

    
1605
    shift_control = (s->gr[0x05] >> 5) & 3;
1606
    double_scan = (s->cr[0x09] >> 7);
1607
    if (shift_control != 1) {
1608
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1609
    } else {
1610
        /* in CGA modes, multi_scan is ignored */
1611
        /* XXX: is it correct ? */
1612
        multi_scan = double_scan;
1613
    }
1614
    multi_run = multi_scan;
1615
    if (shift_control != s->shift_control ||
1616
        double_scan != s->double_scan) {
1617
        full_update = 1;
1618
        s->shift_control = shift_control;
1619
        s->double_scan = double_scan;
1620
    }
1621

    
1622
    if (shift_control == 0) {
1623
        if (s->sr[0x01] & 8) {
1624
            disp_width <<= 1;
1625
        }
1626
    } else if (shift_control == 1) {
1627
        if (s->sr[0x01] & 8) {
1628
            disp_width <<= 1;
1629
        }
1630
    }
1631

    
1632
    depth = s->get_bpp(s);
1633
    if (s->line_offset != s->last_line_offset ||
1634
        disp_width != s->last_width ||
1635
        height != s->last_height ||
1636
        s->last_depth != depth) {
1637
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1638
        if (depth == 16 || depth == 32) {
1639
#else
1640
        if (depth == 32) {
1641
#endif
1642
            qemu_free_displaysurface(s->ds);
1643
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1644
                    s->line_offset,
1645
                    s->vram_ptr + (s->start_addr * 4));
1646
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1647
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1648
#endif
1649
            dpy_resize(s->ds);
1650
        } else {
1651
            qemu_console_resize(s->ds, disp_width, height);
1652
        }
1653
        s->last_scr_width = disp_width;
1654
        s->last_scr_height = height;
1655
        s->last_width = disp_width;
1656
        s->last_height = height;
1657
        s->last_line_offset = s->line_offset;
1658
        s->last_depth = depth;
1659
        full_update = 1;
1660
    } else if (is_buffer_shared(s->ds->surface) &&
1661
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1662
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1663
        dpy_setdata(s->ds);
1664
    }
1665

    
1666
    s->rgb_to_pixel =
1667
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1668

    
1669
    if (shift_control == 0) {
1670
        full_update |= update_palette16(s);
1671
        if (s->sr[0x01] & 8) {
1672
            v = VGA_DRAW_LINE4D2;
1673
        } else {
1674
            v = VGA_DRAW_LINE4;
1675
        }
1676
        bits = 4;
1677
    } else if (shift_control == 1) {
1678
        full_update |= update_palette16(s);
1679
        if (s->sr[0x01] & 8) {
1680
            v = VGA_DRAW_LINE2D2;
1681
        } else {
1682
            v = VGA_DRAW_LINE2;
1683
        }
1684
        bits = 4;
1685
    } else {
1686
        switch(s->get_bpp(s)) {
1687
        default:
1688
        case 0:
1689
            full_update |= update_palette256(s);
1690
            v = VGA_DRAW_LINE8D2;
1691
            bits = 4;
1692
            break;
1693
        case 8:
1694
            full_update |= update_palette256(s);
1695
            v = VGA_DRAW_LINE8;
1696
            bits = 8;
1697
            break;
1698
        case 15:
1699
            v = VGA_DRAW_LINE15;
1700
            bits = 16;
1701
            break;
1702
        case 16:
1703
            v = VGA_DRAW_LINE16;
1704
            bits = 16;
1705
            break;
1706
        case 24:
1707
            v = VGA_DRAW_LINE24;
1708
            bits = 24;
1709
            break;
1710
        case 32:
1711
            v = VGA_DRAW_LINE32;
1712
            bits = 32;
1713
            break;
1714
        }
1715
    }
1716
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1717

    
1718
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1719
        s->cursor_invalidate(s);
1720

    
1721
    line_offset = s->line_offset;
1722
#if 0
1723
    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",
1724
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1725
#endif
1726
    addr1 = (s->start_addr * 4);
1727
    bwidth = (width * bits + 7) / 8;
1728
    y_start = -1;
1729
    page_min = -1;
1730
    page_max = 0;
1731
    d = ds_get_data(s->ds);
1732
    linesize = ds_get_linesize(s->ds);
1733
    y1 = 0;
1734
    for(y = 0; y < height; y++) {
1735
        addr = addr1;
1736
        if (!(s->cr[0x17] & 1)) {
1737
            int shift;
1738
            /* CGA compatibility handling */
1739
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1740
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1741
        }
1742
        if (!(s->cr[0x17] & 2)) {
1743
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1744
        }
1745
        page0 = addr & TARGET_PAGE_MASK;
1746
        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
1747
        update = full_update |
1748
            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
1749
            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
1750
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1751
            /* if wide line, can use another page */
1752
            update |= memory_region_get_dirty(&s->vram,
1753
                                              page0 + TARGET_PAGE_SIZE,
1754
                                              DIRTY_MEMORY_VGA);
1755
        }
1756
        /* explicit invalidation for the hardware cursor */
1757
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1758
        if (update) {
1759
            if (y_start < 0)
1760
                y_start = y;
1761
            if (page0 < page_min)
1762
                page_min = page0;
1763
            if (page1 > page_max)
1764
                page_max = page1;
1765
            if (!(is_buffer_shared(s->ds->surface))) {
1766
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1767
                if (s->cursor_draw_line)
1768
                    s->cursor_draw_line(s, d, y);
1769
            }
1770
        } else {
1771
            if (y_start >= 0) {
1772
                /* flush to display */
1773
                dpy_update(s->ds, 0, y_start,
1774
                           disp_width, y - y_start);
1775
                y_start = -1;
1776
            }
1777
        }
1778
        if (!multi_run) {
1779
            mask = (s->cr[0x17] & 3) ^ 3;
1780
            if ((y1 & mask) == mask)
1781
                addr1 += line_offset;
1782
            y1++;
1783
            multi_run = multi_scan;
1784
        } else {
1785
            multi_run--;
1786
        }
1787
        /* line compare acts on the displayed lines */
1788
        if (y == s->line_compare)
1789
            addr1 = 0;
1790
        d += linesize;
1791
    }
1792
    if (y_start >= 0) {
1793
        /* flush to display */
1794
        dpy_update(s->ds, 0, y_start,
1795
                   disp_width, y - y_start);
1796
    }
1797
    /* reset modified pages */
1798
    if (page_max >= page_min) {
1799
        memory_region_reset_dirty(&s->vram,
1800
                                  page_min,
1801
                                  page_max + TARGET_PAGE_SIZE - page_min,
1802
                                  DIRTY_MEMORY_VGA);
1803
    }
1804
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1805
}
1806

    
1807
static void vga_draw_blank(VGACommonState *s, int full_update)
1808
{
1809
    int i, w, val;
1810
    uint8_t *d;
1811

    
1812
    if (!full_update)
1813
        return;
1814
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1815
        return;
1816

    
1817
    s->rgb_to_pixel =
1818
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1819
    if (ds_get_bits_per_pixel(s->ds) == 8)
1820
        val = s->rgb_to_pixel(0, 0, 0);
1821
    else
1822
        val = 0;
1823
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1824
    d = ds_get_data(s->ds);
1825
    for(i = 0; i < s->last_scr_height; i++) {
1826
        memset(d, val, w);
1827
        d += ds_get_linesize(s->ds);
1828
    }
1829
    dpy_update(s->ds, 0, 0,
1830
               s->last_scr_width, s->last_scr_height);
1831
}
1832

    
1833
#define GMODE_TEXT     0
1834
#define GMODE_GRAPH    1
1835
#define GMODE_BLANK 2
1836

    
1837
static void vga_update_display(void *opaque)
1838
{
1839
    VGACommonState *s = opaque;
1840
    int full_update, graphic_mode;
1841

    
1842
    qemu_flush_coalesced_mmio_buffer();
1843

    
1844
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1845
        /* nothing to do */
1846
    } else {
1847
        full_update = 0;
1848
        if (!(s->ar_index & 0x20)) {
1849
            graphic_mode = GMODE_BLANK;
1850
        } else {
1851
            graphic_mode = s->gr[6] & 1;
1852
        }
1853
        if (graphic_mode != s->graphic_mode) {
1854
            s->graphic_mode = graphic_mode;
1855
            full_update = 1;
1856
        }
1857
        switch(graphic_mode) {
1858
        case GMODE_TEXT:
1859
            vga_draw_text(s, full_update);
1860
            break;
1861
        case GMODE_GRAPH:
1862
            vga_draw_graphic(s, full_update);
1863
            break;
1864
        case GMODE_BLANK:
1865
        default:
1866
            vga_draw_blank(s, full_update);
1867
            break;
1868
        }
1869
    }
1870
}
1871

    
1872
/* force a full display refresh */
1873
static void vga_invalidate_display(void *opaque)
1874
{
1875
    VGACommonState *s = opaque;
1876

    
1877
    s->last_width = -1;
1878
    s->last_height = -1;
1879
}
1880

    
1881
void vga_common_reset(VGACommonState *s)
1882
{
1883
    s->sr_index = 0;
1884
    memset(s->sr, '\0', sizeof(s->sr));
1885
    s->gr_index = 0;
1886
    memset(s->gr, '\0', sizeof(s->gr));
1887
    s->ar_index = 0;
1888
    memset(s->ar, '\0', sizeof(s->ar));
1889
    s->ar_flip_flop = 0;
1890
    s->cr_index = 0;
1891
    memset(s->cr, '\0', sizeof(s->cr));
1892
    s->msr = 0;
1893
    s->fcr = 0;
1894
    s->st00 = 0;
1895
    s->st01 = 0;
1896
    s->dac_state = 0;
1897
    s->dac_sub_index = 0;
1898
    s->dac_read_index = 0;
1899
    s->dac_write_index = 0;
1900
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1901
    s->dac_8bit = 0;
1902
    memset(s->palette, '\0', sizeof(s->palette));
1903
    s->bank_offset = 0;
1904
#ifdef CONFIG_BOCHS_VBE
1905
    s->vbe_index = 0;
1906
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1907
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1908
    s->vbe_start_addr = 0;
1909
    s->vbe_line_offset = 0;
1910
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1911
#endif
1912
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1913
    s->graphic_mode = -1; /* force full update */
1914
    s->shift_control = 0;
1915
    s->double_scan = 0;
1916
    s->line_offset = 0;
1917
    s->line_compare = 0;
1918
    s->start_addr = 0;
1919
    s->plane_updated = 0;
1920
    s->last_cw = 0;
1921
    s->last_ch = 0;
1922
    s->last_width = 0;
1923
    s->last_height = 0;
1924
    s->last_scr_width = 0;
1925
    s->last_scr_height = 0;
1926
    s->cursor_start = 0;
1927
    s->cursor_end = 0;
1928
    s->cursor_offset = 0;
1929
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1930
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1931
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1932
    switch (vga_retrace_method) {
1933
    case VGA_RETRACE_DUMB:
1934
        break;
1935
    case VGA_RETRACE_PRECISE:
1936
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1937
        break;
1938
    }
1939
    vga_update_memory_access(s);
1940
}
1941

    
1942
static void vga_reset(void *opaque)
1943
{
1944
    VGACommonState *s =  opaque;
1945
    vga_common_reset(s);
1946
}
1947

    
1948
#define TEXTMODE_X(x)        ((x) % width)
1949
#define TEXTMODE_Y(x)        ((x) / width)
1950
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1951
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1952
/* relay text rendering to the display driver
1953
 * instead of doing a full vga_update_display() */
1954
static void vga_update_text(void *opaque, console_ch_t *chardata)
1955
{
1956
    VGACommonState *s =  opaque;
1957
    int graphic_mode, i, cursor_offset, cursor_visible;
1958
    int cw, cheight, width, height, size, c_min, c_max;
1959
    uint32_t *src;
1960
    console_ch_t *dst, val;
1961
    char msg_buffer[80];
1962
    int full_update = 0;
1963

    
1964
    qemu_flush_coalesced_mmio_buffer();
1965

    
1966
    if (!(s->ar_index & 0x20)) {
1967
        graphic_mode = GMODE_BLANK;
1968
    } else {
1969
        graphic_mode = s->gr[6] & 1;
1970
    }
1971
    if (graphic_mode != s->graphic_mode) {
1972
        s->graphic_mode = graphic_mode;
1973
        full_update = 1;
1974
    }
1975
    if (s->last_width == -1) {
1976
        s->last_width = 0;
1977
        full_update = 1;
1978
    }
1979

    
1980
    switch (graphic_mode) {
1981
    case GMODE_TEXT:
1982
        /* TODO: update palette */
1983
        full_update |= update_basic_params(s);
1984

    
1985
        /* total width & height */
1986
        cheight = (s->cr[9] & 0x1f) + 1;
1987
        cw = 8;
1988
        if (!(s->sr[1] & 0x01))
1989
            cw = 9;
1990
        if (s->sr[1] & 0x08)
1991
            cw = 16; /* NOTE: no 18 pixel wide */
1992
        width = (s->cr[0x01] + 1);
1993
        if (s->cr[0x06] == 100) {
1994
            /* ugly hack for CGA 160x100x16 - explain me the logic */
1995
            height = 100;
1996
        } else {
1997
            height = s->cr[0x12] | 
1998
                ((s->cr[0x07] & 0x02) << 7) | 
1999
                ((s->cr[0x07] & 0x40) << 3);
2000
            height = (height + 1) / cheight;
2001
        }
2002

    
2003
        size = (height * width);
2004
        if (size > CH_ATTR_SIZE) {
2005
            if (!full_update)
2006
                return;
2007

    
2008
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2009
                     width, height);
2010
            break;
2011
        }
2012

    
2013
        if (width != s->last_width || height != s->last_height ||
2014
            cw != s->last_cw || cheight != s->last_ch) {
2015
            s->last_scr_width = width * cw;
2016
            s->last_scr_height = height * cheight;
2017
            s->ds->surface->width = width;
2018
            s->ds->surface->height = height;
2019
            dpy_resize(s->ds);
2020
            s->last_width = width;
2021
            s->last_height = height;
2022
            s->last_ch = cheight;
2023
            s->last_cw = cw;
2024
            full_update = 1;
2025
        }
2026

    
2027
        /* Update "hardware" cursor */
2028
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2029
        if (cursor_offset != s->cursor_offset ||
2030
            s->cr[0xa] != s->cursor_start ||
2031
            s->cr[0xb] != s->cursor_end || full_update) {
2032
            cursor_visible = !(s->cr[0xa] & 0x20);
2033
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2034
                dpy_cursor(s->ds,
2035
                           TEXTMODE_X(cursor_offset),
2036
                           TEXTMODE_Y(cursor_offset));
2037
            else
2038
                dpy_cursor(s->ds, -1, -1);
2039
            s->cursor_offset = cursor_offset;
2040
            s->cursor_start = s->cr[0xa];
2041
            s->cursor_end = s->cr[0xb];
2042
        }
2043

    
2044
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2045
        dst = chardata;
2046

    
2047
        if (full_update) {
2048
            for (i = 0; i < size; src ++, dst ++, i ++)
2049
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2050

    
2051
            dpy_update(s->ds, 0, 0, width, height);
2052
        } else {
2053
            c_max = 0;
2054

    
2055
            for (i = 0; i < size; src ++, dst ++, i ++) {
2056
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2057
                if (*dst != val) {
2058
                    *dst = val;
2059
                    c_max = i;
2060
                    break;
2061
                }
2062
            }
2063
            c_min = i;
2064
            for (; i < size; src ++, dst ++, i ++) {
2065
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2066
                if (*dst != val) {
2067
                    *dst = val;
2068
                    c_max = i;
2069
                }
2070
            }
2071

    
2072
            if (c_min <= c_max) {
2073
                i = TEXTMODE_Y(c_min);
2074
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2075
            }
2076
        }
2077

    
2078
        return;
2079
    case GMODE_GRAPH:
2080
        if (!full_update)
2081
            return;
2082

    
2083
        s->get_resolution(s, &width, &height);
2084
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2085
                 width, height);
2086
        break;
2087
    case GMODE_BLANK:
2088
    default:
2089
        if (!full_update)
2090
            return;
2091

    
2092
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2093
        break;
2094
    }
2095

    
2096
    /* Display a message */
2097
    s->last_width = 60;
2098
    s->last_height = height = 3;
2099
    dpy_cursor(s->ds, -1, -1);
2100
    s->ds->surface->width = s->last_width;
2101
    s->ds->surface->height = height;
2102
    dpy_resize(s->ds);
2103

    
2104
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2105
        console_write_ch(dst ++, ' ');
2106

    
2107
    size = strlen(msg_buffer);
2108
    width = (s->last_width - size) / 2;
2109
    dst = chardata + s->last_width + width;
2110
    for (i = 0; i < size; i ++)
2111
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2112

    
2113
    dpy_update(s->ds, 0, 0, s->last_width, height);
2114
}
2115

    
2116
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2117
                             unsigned size)
2118
{
2119
    VGACommonState *s = opaque;
2120

    
2121
    return vga_mem_readb(s, addr);
2122
}
2123

    
2124
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2125
                          uint64_t data, unsigned size)
2126
{
2127
    VGACommonState *s = opaque;
2128

    
2129
    return vga_mem_writeb(s, addr, data);
2130
}
2131

    
2132
const MemoryRegionOps vga_mem_ops = {
2133
    .read = vga_mem_read,
2134
    .write = vga_mem_write,
2135
    .endianness = DEVICE_LITTLE_ENDIAN,
2136
    .impl = {
2137
        .min_access_size = 1,
2138
        .max_access_size = 1,
2139
    },
2140
};
2141

    
2142
static int vga_common_post_load(void *opaque, int version_id)
2143
{
2144
    VGACommonState *s = opaque;
2145

    
2146
    /* force refresh */
2147
    s->graphic_mode = -1;
2148
    return 0;
2149
}
2150

    
2151
const VMStateDescription vmstate_vga_common = {
2152
    .name = "vga",
2153
    .version_id = 2,
2154
    .minimum_version_id = 2,
2155
    .minimum_version_id_old = 2,
2156
    .post_load = vga_common_post_load,
2157
    .fields      = (VMStateField []) {
2158
        VMSTATE_UINT32(latch, VGACommonState),
2159
        VMSTATE_UINT8(sr_index, VGACommonState),
2160
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2161
        VMSTATE_UINT8(gr_index, VGACommonState),
2162
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2163
        VMSTATE_UINT8(ar_index, VGACommonState),
2164
        VMSTATE_BUFFER(ar, VGACommonState),
2165
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2166
        VMSTATE_UINT8(cr_index, VGACommonState),
2167
        VMSTATE_BUFFER(cr, VGACommonState),
2168
        VMSTATE_UINT8(msr, VGACommonState),
2169
        VMSTATE_UINT8(fcr, VGACommonState),
2170
        VMSTATE_UINT8(st00, VGACommonState),
2171
        VMSTATE_UINT8(st01, VGACommonState),
2172

    
2173
        VMSTATE_UINT8(dac_state, VGACommonState),
2174
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2175
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2176
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2177
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2178
        VMSTATE_BUFFER(palette, VGACommonState),
2179

    
2180
        VMSTATE_INT32(bank_offset, VGACommonState),
2181
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2182
#ifdef CONFIG_BOCHS_VBE
2183
        VMSTATE_UINT16(vbe_index, VGACommonState),
2184
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2185
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2186
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2187
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2188
#endif
2189
        VMSTATE_END_OF_LIST()
2190
    }
2191
};
2192

    
2193
void vga_common_init(VGACommonState *s, int vga_ram_size)
2194
{
2195
    int i, j, v, b;
2196

    
2197
    for(i = 0;i < 256; i++) {
2198
        v = 0;
2199
        for(j = 0; j < 8; j++) {
2200
            v |= ((i >> j) & 1) << (j * 4);
2201
        }
2202
        expand4[i] = v;
2203

    
2204
        v = 0;
2205
        for(j = 0; j < 4; j++) {
2206
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2207
        }
2208
        expand2[i] = v;
2209
    }
2210
    for(i = 0; i < 16; i++) {
2211
        v = 0;
2212
        for(j = 0; j < 4; j++) {
2213
            b = ((i >> j) & 1);
2214
            v |= b << (2 * j);
2215
            v |= b << (2 * j + 1);
2216
        }
2217
        expand4to8[i] = v;
2218
    }
2219

    
2220
#ifdef CONFIG_BOCHS_VBE
2221
    s->is_vbe_vmstate = 1;
2222
#else
2223
    s->is_vbe_vmstate = 0;
2224
#endif
2225
    memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size);
2226
    vmstate_register_ram_global(&s->vram);
2227
    xen_register_framebuffer(&s->vram);
2228
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2229
    s->vram_size = vga_ram_size;
2230
    s->get_bpp = vga_get_bpp;
2231
    s->get_offsets = vga_get_offsets;
2232
    s->get_resolution = vga_get_resolution;
2233
    s->update = vga_update_display;
2234
    s->invalidate = vga_invalidate_display;
2235
    s->screen_dump = vga_screen_dump;
2236
    s->text_update = vga_update_text;
2237
    switch (vga_retrace_method) {
2238
    case VGA_RETRACE_DUMB:
2239
        s->retrace = vga_dumb_retrace;
2240
        s->update_retrace_info = vga_dumb_update_retrace_info;
2241
        break;
2242

    
2243
    case VGA_RETRACE_PRECISE:
2244
        s->retrace = vga_precise_retrace;
2245
        s->update_retrace_info = vga_precise_update_retrace_info;
2246
        break;
2247
    }
2248
    vga_dirty_log_start(s);
2249
}
2250

    
2251
static const MemoryRegionPortio vga_portio_list[] = {
2252
    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2253
    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2254
    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2255
    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2256
    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2257
    PORTIO_END_OF_LIST(),
2258
};
2259

    
2260
#ifdef CONFIG_BOCHS_VBE
2261
static const MemoryRegionPortio vbe_portio_list[] = {
2262
    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2263
# ifdef TARGET_I386
2264
    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2265
# else
2266
    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2267
# endif
2268
    PORTIO_END_OF_LIST(),
2269
};
2270
#endif /* CONFIG_BOCHS_VBE */
2271

    
2272
/* Used by both ISA and PCI */
2273
MemoryRegion *vga_init_io(VGACommonState *s,
2274
                          const MemoryRegionPortio **vga_ports,
2275
                          const MemoryRegionPortio **vbe_ports)
2276
{
2277
    MemoryRegion *vga_mem;
2278

    
2279
    *vga_ports = vga_portio_list;
2280
    *vbe_ports = NULL;
2281
#ifdef CONFIG_BOCHS_VBE
2282
    *vbe_ports = vbe_portio_list;
2283
#endif
2284

    
2285
    vga_mem = g_malloc(sizeof(*vga_mem));
2286
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2287
                          "vga-lowmem", 0x20000);
2288

    
2289
    return vga_mem;
2290
}
2291

    
2292
void vga_init(VGACommonState *s, MemoryRegion *address_space,
2293
              MemoryRegion *address_space_io, bool init_vga_ports)
2294
{
2295
    MemoryRegion *vga_io_memory;
2296
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2297
    PortioList *vga_port_list = g_new(PortioList, 1);
2298
    PortioList *vbe_port_list = g_new(PortioList, 1);
2299

    
2300
    qemu_register_reset(vga_reset, s);
2301

    
2302
    s->bank_offset = 0;
2303

    
2304
    s->legacy_address_space = address_space;
2305

    
2306
    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
2307
    memory_region_add_subregion_overlap(address_space,
2308
                                        isa_mem_base + 0x000a0000,
2309
                                        vga_io_memory,
2310
                                        1);
2311
    memory_region_set_coalescing(vga_io_memory);
2312
    if (init_vga_ports) {
2313
        portio_list_init(vga_port_list, vga_ports, s, "vga");
2314
        portio_list_add(vga_port_list, address_space_io, 0x3b0);
2315
    }
2316
    if (vbe_ports) {
2317
        portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
2318
        portio_list_add(vbe_port_list, address_space_io, 0x1ce);
2319
    }
2320
}
2321

    
2322
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
2323
{
2324
#ifdef CONFIG_BOCHS_VBE
2325
    /* XXX: use optimized standard vga accesses */
2326
    memory_region_add_subregion(system_memory,
2327
                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2328
                                &s->vram);
2329
    s->vbe_mapped = 1;
2330
#endif 
2331
}
2332
/********************************************************/
2333
/* vga screen dump */
2334

    
2335
static void vga_save_dpy_update(DisplayState *ds,
2336
                                int x, int y, int w, int h)
2337
{
2338
    if (screen_dump_filename) {
2339
        ppm_save(screen_dump_filename, ds->surface);
2340
    }
2341
}
2342

    
2343
static void vga_save_dpy_resize(DisplayState *s)
2344
{
2345
}
2346

    
2347
static void vga_save_dpy_refresh(DisplayState *s)
2348
{
2349
}
2350

    
2351
int ppm_save(const char *filename, struct DisplaySurface *ds)
2352
{
2353
    FILE *f;
2354
    uint8_t *d, *d1;
2355
    uint32_t v;
2356
    int y, x;
2357
    uint8_t r, g, b;
2358
    int ret;
2359
    char *linebuf, *pbuf;
2360

    
2361
    f = fopen(filename, "wb");
2362
    if (!f)
2363
        return -1;
2364
    fprintf(f, "P6\n%d %d\n%d\n",
2365
            ds->width, ds->height, 255);
2366
    linebuf = g_malloc(ds->width * 3);
2367
    d1 = ds->data;
2368
    for(y = 0; y < ds->height; y++) {
2369
        d = d1;
2370
        pbuf = linebuf;
2371
        for(x = 0; x < ds->width; x++) {
2372
            if (ds->pf.bits_per_pixel == 32)
2373
                v = *(uint32_t *)d;
2374
            else
2375
                v = (uint32_t) (*(uint16_t *)d);
2376
            /* Limited to 8 or fewer bits per channel: */
2377
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
2378
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
2379
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
2380
            *pbuf++ = r;
2381
            *pbuf++ = g;
2382
            *pbuf++ = b;
2383
            d += ds->pf.bytes_per_pixel;
2384
        }
2385
        d1 += ds->linesize;
2386
        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2387
        (void)ret;
2388
    }
2389
    g_free(linebuf);
2390
    fclose(f);
2391
    return 0;
2392
}
2393

    
2394
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2395
{
2396
    DisplayChangeListener *dcl;
2397

    
2398
    dcl = g_malloc0(sizeof(DisplayChangeListener));
2399
    dcl->dpy_update = vga_save_dpy_update;
2400
    dcl->dpy_resize = vga_save_dpy_resize;
2401
    dcl->dpy_refresh = vga_save_dpy_refresh;
2402
    register_displaychangelistener(ds, dcl);
2403
    return dcl;
2404
}
2405

    
2406
/* save the vga display in a PPM image even if no display is
2407
   available */
2408
static void vga_screen_dump(void *opaque, const char *filename)
2409
{
2410
    VGACommonState *s = opaque;
2411

    
2412
    if (!screen_dump_dcl)
2413
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2414

    
2415
    screen_dump_filename = filename;
2416
    vga_invalidate_display(s);
2417
    vga_hw_update();
2418
    screen_dump_filename = NULL;
2419
}