Statistics
| Branch: | Revision:

root / hw / vga.c @ 0200db65

History | View | Annotate | Download (68.5 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

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

    
36
//#define DEBUG_BOCHS_VBE
37

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

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

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

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

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

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

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

    
113
#undef PAT
114

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

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

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

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

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

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

    
160
    s->chain4_alias = NULL;
161

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

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

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

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

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

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

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

    
238

    
239

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

    
244
    chars_per_sec = clk_hz[clock_sel] / dots;
245

    
246
    htotal_chars <<= clocking_mode;
247

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

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

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

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

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

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

    
307
        cur_tick = qemu_get_clock_ns(vm_clock);
308

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1128
    full_update = 0;
1129

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

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

    
1143
#define NB_DEPTHS 7
1144

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1297
    line_offset = s->line_offset;
1298

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1596
    full_update |= update_basic_params(s);
1597

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1841
    qemu_flush_coalesced_mmio_buffer();
1842

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

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

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

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

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

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

    
1963
    qemu_flush_coalesced_mmio_buffer();
1964

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2240
    case VGA_RETRACE_PRECISE:
2241
        s->retrace = vga_precise_retrace;
2242
        s->update_retrace_info = vga_precise_update_retrace_info;
2243
        break;
2244
    }
2245
    vga_dirty_log_start(s);
2246
}
2247

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

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

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

    
2276
    *vga_ports = vga_portio_list;
2277
    *vbe_ports = NULL;
2278
#ifdef CONFIG_BOCHS_VBE
2279
    *vbe_ports = vbe_portio_list;
2280
#endif
2281

    
2282
    vga_mem = g_malloc(sizeof(*vga_mem));
2283
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2284
                          "vga-lowmem", 0x20000);
2285

    
2286
    return vga_mem;
2287
}
2288

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

    
2297
    qemu_register_reset(vga_reset, s);
2298

    
2299
    s->bank_offset = 0;
2300

    
2301
    s->legacy_address_space = address_space;
2302

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

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

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

    
2340
static void vga_save_dpy_resize(DisplayState *s)
2341
{
2342
}
2343

    
2344
static void vga_save_dpy_refresh(DisplayState *s)
2345
{
2346
}
2347

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

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

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

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

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

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

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