Statistics
| Branch: | Revision:

root / hw / vga.c @ d60efc6b

History | View | Annotate | Download (74.3 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 "kvm.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 char *screen_dump_filename;
154
static DisplayChangeListener *screen_dump_dcl;
155

    
156
static void vga_dumb_update_retrace_info(VGAState *s)
157
{
158
    (void) s;
159
}
160

    
161
static void vga_precise_update_retrace_info(VGAState *s)
162
{
163
    int htotal_chars;
164
    int hretr_start_char;
165
    int hretr_skew_chars;
166
    int hretr_end_char;
167

    
168
    int vtotal_lines;
169
    int vretr_start_line;
170
    int vretr_end_line;
171

    
172
    int div2, sldiv2, dots;
173
    int clocking_mode;
174
    int clock_sel;
175
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
176
    int64_t chars_per_sec;
177
    struct vga_precise_retrace *r = &s->retrace_info.precise;
178

    
179
    htotal_chars = s->cr[0x00] + 5;
180
    hretr_start_char = s->cr[0x04];
181
    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
182
    hretr_end_char = s->cr[0x05] & 0x1f;
183

    
184
    vtotal_lines = (s->cr[0x06]
185
                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
186
        ;
187
    vretr_start_line = s->cr[0x10]
188
        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
189
        ;
190
    vretr_end_line = s->cr[0x11] & 0xf;
191

    
192

    
193
    div2 = (s->cr[0x17] >> 2) & 1;
194
    sldiv2 = (s->cr[0x17] >> 3) & 1;
195

    
196
    clocking_mode = (s->sr[0x01] >> 3) & 1;
197
    clock_sel = (s->msr >> 2) & 3;
198
    dots = (s->msr & 1) ? 8 : 9;
199

    
200
    chars_per_sec = clk_hz[clock_sel] / dots;
201

    
202
    htotal_chars <<= clocking_mode;
203

    
204
    r->total_chars = vtotal_lines * htotal_chars;
205
    if (r->freq) {
206
        r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
207
    } else {
208
        r->ticks_per_char = ticks_per_sec / chars_per_sec;
209
    }
210

    
211
    r->vstart = vretr_start_line;
212
    r->vend = r->vstart + vretr_end_line + 1;
213

    
214
    r->hstart = hretr_start_char + hretr_skew_chars;
215
    r->hend = r->hstart + hretr_end_char + 1;
216
    r->htotal = htotal_chars;
217

    
218
#if 0
219
    printf (
220
        "hz=%f\n"
221
        "htotal = %d\n"
222
        "hretr_start = %d\n"
223
        "hretr_skew = %d\n"
224
        "hretr_end = %d\n"
225
        "vtotal = %d\n"
226
        "vretr_start = %d\n"
227
        "vretr_end = %d\n"
228
        "div2 = %d sldiv2 = %d\n"
229
        "clocking_mode = %d\n"
230
        "clock_sel = %d %d\n"
231
        "dots = %d\n"
232
        "ticks/char = %lld\n"
233
        "\n",
234
        (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
235
        htotal_chars,
236
        hretr_start_char,
237
        hretr_skew_chars,
238
        hretr_end_char,
239
        vtotal_lines,
240
        vretr_start_line,
241
        vretr_end_line,
242
        div2, sldiv2,
243
        clocking_mode,
244
        clock_sel,
245
        clk_hz[clock_sel],
246
        dots,
247
        r->ticks_per_char
248
        );
249
#endif
250
}
251

    
252
static uint8_t vga_precise_retrace(VGAState *s)
253
{
254
    struct vga_precise_retrace *r = &s->retrace_info.precise;
255
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
256

    
257
    if (r->total_chars) {
258
        int cur_line, cur_line_char, cur_char;
259
        int64_t cur_tick;
260

    
261
        cur_tick = qemu_get_clock(vm_clock);
262

    
263
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
264
        cur_line = cur_char / r->htotal;
265

    
266
        if (cur_line >= r->vstart && cur_line <= r->vend) {
267
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
268
        } else {
269
            cur_line_char = cur_char % r->htotal;
270
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
271
                val |= ST01_DISP_ENABLE;
272
            }
273
        }
274

    
275
        return val;
276
    } else {
277
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
278
    }
279
}
280

    
281
static uint8_t vga_dumb_retrace(VGAState *s)
282
{
283
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
284
}
285

    
286
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
287
{
288
    VGAState *s = opaque;
289
    int val, index;
290

    
291
    /* check port range access depending on color/monochrome mode */
292
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
293
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
294
        val = 0xff;
295
    } else {
296
        switch(addr) {
297
        case 0x3c0:
298
            if (s->ar_flip_flop == 0) {
299
                val = s->ar_index;
300
            } else {
301
                val = 0;
302
            }
303
            break;
304
        case 0x3c1:
305
            index = s->ar_index & 0x1f;
306
            if (index < 21)
307
                val = s->ar[index];
308
            else
309
                val = 0;
310
            break;
311
        case 0x3c2:
312
            val = s->st00;
313
            break;
314
        case 0x3c4:
315
            val = s->sr_index;
316
            break;
317
        case 0x3c5:
318
            val = s->sr[s->sr_index];
319
#ifdef DEBUG_VGA_REG
320
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
321
#endif
322
            break;
323
        case 0x3c7:
324
            val = s->dac_state;
325
            break;
326
        case 0x3c8:
327
            val = s->dac_write_index;
328
            break;
329
        case 0x3c9:
330
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
331
            if (++s->dac_sub_index == 3) {
332
                s->dac_sub_index = 0;
333
                s->dac_read_index++;
334
            }
335
            break;
336
        case 0x3ca:
337
            val = s->fcr;
338
            break;
339
        case 0x3cc:
340
            val = s->msr;
341
            break;
342
        case 0x3ce:
343
            val = s->gr_index;
344
            break;
345
        case 0x3cf:
346
            val = s->gr[s->gr_index];
347
#ifdef DEBUG_VGA_REG
348
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
349
#endif
350
            break;
351
        case 0x3b4:
352
        case 0x3d4:
353
            val = s->cr_index;
354
            break;
355
        case 0x3b5:
356
        case 0x3d5:
357
            val = s->cr[s->cr_index];
358
#ifdef DEBUG_VGA_REG
359
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
360
#endif
361
            break;
362
        case 0x3ba:
363
        case 0x3da:
364
            /* just toggle to fool polling */
365
            val = s->st01 = s->retrace(s);
366
            s->ar_flip_flop = 0;
367
            break;
368
        default:
369
            val = 0x00;
370
            break;
371
        }
372
    }
373
#if defined(DEBUG_VGA)
374
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
375
#endif
376
    return val;
377
}
378

    
379
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
380
{
381
    VGAState *s = opaque;
382
    int index;
383

    
384
    /* check port range access depending on color/monochrome mode */
385
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
386
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
387
        return;
388

    
389
#ifdef DEBUG_VGA
390
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
391
#endif
392

    
393
    switch(addr) {
394
    case 0x3c0:
395
        if (s->ar_flip_flop == 0) {
396
            val &= 0x3f;
397
            s->ar_index = val;
398
        } else {
399
            index = s->ar_index & 0x1f;
400
            switch(index) {
401
            case 0x00 ... 0x0f:
402
                s->ar[index] = val & 0x3f;
403
                break;
404
            case 0x10:
405
                s->ar[index] = val & ~0x10;
406
                break;
407
            case 0x11:
408
                s->ar[index] = val;
409
                break;
410
            case 0x12:
411
                s->ar[index] = val & ~0xc0;
412
                break;
413
            case 0x13:
414
                s->ar[index] = val & ~0xf0;
415
                break;
416
            case 0x14:
417
                s->ar[index] = val & ~0xf0;
418
                break;
419
            default:
420
                break;
421
            }
422
        }
423
        s->ar_flip_flop ^= 1;
424
        break;
425
    case 0x3c2:
426
        s->msr = val & ~0x10;
427
        s->update_retrace_info(s);
428
        break;
429
    case 0x3c4:
430
        s->sr_index = val & 7;
431
        break;
432
    case 0x3c5:
433
#ifdef DEBUG_VGA_REG
434
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
435
#endif
436
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
437
        if (s->sr_index == 1) s->update_retrace_info(s);
438
        break;
439
    case 0x3c7:
440
        s->dac_read_index = val;
441
        s->dac_sub_index = 0;
442
        s->dac_state = 3;
443
        break;
444
    case 0x3c8:
445
        s->dac_write_index = val;
446
        s->dac_sub_index = 0;
447
        s->dac_state = 0;
448
        break;
449
    case 0x3c9:
450
        s->dac_cache[s->dac_sub_index] = val;
451
        if (++s->dac_sub_index == 3) {
452
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
453
            s->dac_sub_index = 0;
454
            s->dac_write_index++;
455
        }
456
        break;
457
    case 0x3ce:
458
        s->gr_index = val & 0x0f;
459
        break;
460
    case 0x3cf:
461
#ifdef DEBUG_VGA_REG
462
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
463
#endif
464
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
465
        break;
466
    case 0x3b4:
467
    case 0x3d4:
468
        s->cr_index = val;
469
        break;
470
    case 0x3b5:
471
    case 0x3d5:
472
#ifdef DEBUG_VGA_REG
473
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
474
#endif
475
        /* handle CR0-7 protection */
476
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
477
            /* can always write bit 4 of CR7 */
478
            if (s->cr_index == 7)
479
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
480
            return;
481
        }
482
        switch(s->cr_index) {
483
        case 0x01: /* horizontal display end */
484
        case 0x07:
485
        case 0x09:
486
        case 0x0c:
487
        case 0x0d:
488
        case 0x12: /* vertical display end */
489
            s->cr[s->cr_index] = val;
490
            break;
491
        default:
492
            s->cr[s->cr_index] = val;
493
            break;
494
        }
495

    
496
        switch(s->cr_index) {
497
        case 0x00:
498
        case 0x04:
499
        case 0x05:
500
        case 0x06:
501
        case 0x07:
502
        case 0x11:
503
        case 0x17:
504
            s->update_retrace_info(s);
505
            break;
506
        }
507
        break;
508
    case 0x3ba:
509
    case 0x3da:
510
        s->fcr = val & 0x10;
511
        break;
512
    }
513
}
514

    
515
#ifdef CONFIG_BOCHS_VBE
516
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
517
{
518
    VGAState *s = opaque;
519
    uint32_t val;
520
    val = s->vbe_index;
521
    return val;
522
}
523

    
524
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
525
{
526
    VGAState *s = opaque;
527
    uint32_t val;
528

    
529
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
530
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
531
            switch(s->vbe_index) {
532
                /* XXX: do not hardcode ? */
533
            case VBE_DISPI_INDEX_XRES:
534
                val = VBE_DISPI_MAX_XRES;
535
                break;
536
            case VBE_DISPI_INDEX_YRES:
537
                val = VBE_DISPI_MAX_YRES;
538
                break;
539
            case VBE_DISPI_INDEX_BPP:
540
                val = VBE_DISPI_MAX_BPP;
541
                break;
542
            default:
543
                val = s->vbe_regs[s->vbe_index];
544
                break;
545
            }
546
        } else {
547
            val = s->vbe_regs[s->vbe_index];
548
        }
549
    } else {
550
        val = 0;
551
    }
552
#ifdef DEBUG_BOCHS_VBE
553
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
554
#endif
555
    return val;
556
}
557

    
558
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
559
{
560
    VGAState *s = opaque;
561
    s->vbe_index = val;
562
}
563

    
564
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
565
{
566
    VGAState *s = opaque;
567

    
568
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
569
#ifdef DEBUG_BOCHS_VBE
570
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
571
#endif
572
        switch(s->vbe_index) {
573
        case VBE_DISPI_INDEX_ID:
574
            if (val == VBE_DISPI_ID0 ||
575
                val == VBE_DISPI_ID1 ||
576
                val == VBE_DISPI_ID2 ||
577
                val == VBE_DISPI_ID3 ||
578
                val == VBE_DISPI_ID4) {
579
                s->vbe_regs[s->vbe_index] = val;
580
            }
581
            break;
582
        case VBE_DISPI_INDEX_XRES:
583
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
584
                s->vbe_regs[s->vbe_index] = val;
585
            }
586
            break;
587
        case VBE_DISPI_INDEX_YRES:
588
            if (val <= VBE_DISPI_MAX_YRES) {
589
                s->vbe_regs[s->vbe_index] = val;
590
            }
591
            break;
592
        case VBE_DISPI_INDEX_BPP:
593
            if (val == 0)
594
                val = 8;
595
            if (val == 4 || val == 8 || val == 15 ||
596
                val == 16 || val == 24 || val == 32) {
597
                s->vbe_regs[s->vbe_index] = val;
598
            }
599
            break;
600
        case VBE_DISPI_INDEX_BANK:
601
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
602
              val &= (s->vbe_bank_mask >> 2);
603
            } else {
604
              val &= s->vbe_bank_mask;
605
            }
606
            s->vbe_regs[s->vbe_index] = val;
607
            s->bank_offset = (val << 16);
608
            break;
609
        case VBE_DISPI_INDEX_ENABLE:
610
            if ((val & VBE_DISPI_ENABLED) &&
611
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
612
                int h, shift_control;
613

    
614
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
615
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
616
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
617
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
618
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
619
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
620

    
621
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
622
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
623
                else
624
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
625
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
626
                s->vbe_start_addr = 0;
627

    
628
                /* clear the screen (should be done in BIOS) */
629
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
630
                    memset(s->vram_ptr, 0,
631
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
632
                }
633

    
634
                /* we initialize the VGA graphic mode (should be done
635
                   in BIOS) */
636
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
637
                s->cr[0x17] |= 3; /* no CGA modes */
638
                s->cr[0x13] = s->vbe_line_offset >> 3;
639
                /* width */
640
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
641
                /* height (only meaningful if < 1024) */
642
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
643
                s->cr[0x12] = h;
644
                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
645
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
646
                /* line compare to 1023 */
647
                s->cr[0x18] = 0xff;
648
                s->cr[0x07] |= 0x10;
649
                s->cr[0x09] |= 0x40;
650

    
651
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
652
                    shift_control = 0;
653
                    s->sr[0x01] &= ~8; /* no double line */
654
                } else {
655
                    shift_control = 2;
656
                    s->sr[4] |= 0x08; /* set chain 4 mode */
657
                    s->sr[2] |= 0x0f; /* activate all planes */
658
                }
659
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
660
                s->cr[0x09] &= ~0x9f; /* no double scan */
661
            } else {
662
                /* XXX: the bios should do that */
663
                s->bank_offset = 0;
664
            }
665
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
666
            s->vbe_regs[s->vbe_index] = val;
667
            break;
668
        case VBE_DISPI_INDEX_VIRT_WIDTH:
669
            {
670
                int w, h, line_offset;
671

    
672
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
673
                    return;
674
                w = val;
675
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
676
                    line_offset = w >> 1;
677
                else
678
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
679
                h = s->vram_size / line_offset;
680
                /* XXX: support weird bochs semantics ? */
681
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
682
                    return;
683
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
684
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
685
                s->vbe_line_offset = line_offset;
686
            }
687
            break;
688
        case VBE_DISPI_INDEX_X_OFFSET:
689
        case VBE_DISPI_INDEX_Y_OFFSET:
690
            {
691
                int x;
692
                s->vbe_regs[s->vbe_index] = val;
693
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
694
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
695
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
696
                    s->vbe_start_addr += x >> 1;
697
                else
698
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
699
                s->vbe_start_addr >>= 2;
700
            }
701
            break;
702
        default:
703
            break;
704
        }
705
    }
706
}
707
#endif
708

    
709
/* called for accesses between 0xa0000 and 0xc0000 */
710
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
711
{
712
    VGAState *s = opaque;
713
    int memory_map_mode, plane;
714
    uint32_t ret;
715

    
716
    /* convert to VGA memory offset */
717
    memory_map_mode = (s->gr[6] >> 2) & 3;
718
    addr &= 0x1ffff;
719
    switch(memory_map_mode) {
720
    case 0:
721
        break;
722
    case 1:
723
        if (addr >= 0x10000)
724
            return 0xff;
725
        addr += s->bank_offset;
726
        break;
727
    case 2:
728
        addr -= 0x10000;
729
        if (addr >= 0x8000)
730
            return 0xff;
731
        break;
732
    default:
733
    case 3:
734
        addr -= 0x18000;
735
        if (addr >= 0x8000)
736
            return 0xff;
737
        break;
738
    }
739

    
740
    if (s->sr[4] & 0x08) {
741
        /* chain 4 mode : simplest access */
742
        ret = s->vram_ptr[addr];
743
    } else if (s->gr[5] & 0x10) {
744
        /* odd/even mode (aka text mode mapping) */
745
        plane = (s->gr[4] & 2) | (addr & 1);
746
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
747
    } else {
748
        /* standard VGA latched access */
749
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
750

    
751
        if (!(s->gr[5] & 0x08)) {
752
            /* read mode 0 */
753
            plane = s->gr[4];
754
            ret = GET_PLANE(s->latch, plane);
755
        } else {
756
            /* read mode 1 */
757
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
758
            ret |= ret >> 16;
759
            ret |= ret >> 8;
760
            ret = (~ret) & 0xff;
761
        }
762
    }
763
    return ret;
764
}
765

    
766
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
767
{
768
    uint32_t v;
769
#ifdef TARGET_WORDS_BIGENDIAN
770
    v = vga_mem_readb(opaque, addr) << 8;
771
    v |= vga_mem_readb(opaque, addr + 1);
772
#else
773
    v = vga_mem_readb(opaque, addr);
774
    v |= vga_mem_readb(opaque, addr + 1) << 8;
775
#endif
776
    return v;
777
}
778

    
779
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
780
{
781
    uint32_t v;
782
#ifdef TARGET_WORDS_BIGENDIAN
783
    v = vga_mem_readb(opaque, addr) << 24;
784
    v |= vga_mem_readb(opaque, addr + 1) << 16;
785
    v |= vga_mem_readb(opaque, addr + 2) << 8;
786
    v |= vga_mem_readb(opaque, addr + 3);
787
#else
788
    v = vga_mem_readb(opaque, addr);
789
    v |= vga_mem_readb(opaque, addr + 1) << 8;
790
    v |= vga_mem_readb(opaque, addr + 2) << 16;
791
    v |= vga_mem_readb(opaque, addr + 3) << 24;
792
#endif
793
    return v;
794
}
795

    
796
/* called for accesses between 0xa0000 and 0xc0000 */
797
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
798
{
799
    VGAState *s = opaque;
800
    int memory_map_mode, plane, write_mode, b, func_select, mask;
801
    uint32_t write_mask, bit_mask, set_mask;
802

    
803
#ifdef DEBUG_VGA_MEM
804
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
805
#endif
806
    /* convert to VGA memory offset */
807
    memory_map_mode = (s->gr[6] >> 2) & 3;
808
    addr &= 0x1ffff;
809
    switch(memory_map_mode) {
810
    case 0:
811
        break;
812
    case 1:
813
        if (addr >= 0x10000)
814
            return;
815
        addr += s->bank_offset;
816
        break;
817
    case 2:
818
        addr -= 0x10000;
819
        if (addr >= 0x8000)
820
            return;
821
        break;
822
    default:
823
    case 3:
824
        addr -= 0x18000;
825
        if (addr >= 0x8000)
826
            return;
827
        break;
828
    }
829

    
830
    if (s->sr[4] & 0x08) {
831
        /* chain 4 mode : simplest access */
832
        plane = addr & 3;
833
        mask = (1 << plane);
834
        if (s->sr[2] & mask) {
835
            s->vram_ptr[addr] = val;
836
#ifdef DEBUG_VGA_MEM
837
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
838
#endif
839
            s->plane_updated |= mask; /* only used to detect font change */
840
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
841
        }
842
    } else if (s->gr[5] & 0x10) {
843
        /* odd/even mode (aka text mode mapping) */
844
        plane = (s->gr[4] & 2) | (addr & 1);
845
        mask = (1 << plane);
846
        if (s->sr[2] & mask) {
847
            addr = ((addr & ~1) << 1) | plane;
848
            s->vram_ptr[addr] = val;
849
#ifdef DEBUG_VGA_MEM
850
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
851
#endif
852
            s->plane_updated |= mask; /* only used to detect font change */
853
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
854
        }
855
    } else {
856
        /* standard VGA latched access */
857
        write_mode = s->gr[5] & 3;
858
        switch(write_mode) {
859
        default:
860
        case 0:
861
            /* rotate */
862
            b = s->gr[3] & 7;
863
            val = ((val >> b) | (val << (8 - b))) & 0xff;
864
            val |= val << 8;
865
            val |= val << 16;
866

    
867
            /* apply set/reset mask */
868
            set_mask = mask16[s->gr[1]];
869
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
870
            bit_mask = s->gr[8];
871
            break;
872
        case 1:
873
            val = s->latch;
874
            goto do_write;
875
        case 2:
876
            val = mask16[val & 0x0f];
877
            bit_mask = s->gr[8];
878
            break;
879
        case 3:
880
            /* rotate */
881
            b = s->gr[3] & 7;
882
            val = (val >> b) | (val << (8 - b));
883

    
884
            bit_mask = s->gr[8] & val;
885
            val = mask16[s->gr[0]];
886
            break;
887
        }
888

    
889
        /* apply logical operation */
890
        func_select = s->gr[3] >> 3;
891
        switch(func_select) {
892
        case 0:
893
        default:
894
            /* nothing to do */
895
            break;
896
        case 1:
897
            /* and */
898
            val &= s->latch;
899
            break;
900
        case 2:
901
            /* or */
902
            val |= s->latch;
903
            break;
904
        case 3:
905
            /* xor */
906
            val ^= s->latch;
907
            break;
908
        }
909

    
910
        /* apply bit mask */
911
        bit_mask |= bit_mask << 8;
912
        bit_mask |= bit_mask << 16;
913
        val = (val & bit_mask) | (s->latch & ~bit_mask);
914

    
915
    do_write:
916
        /* mask data according to sr[2] */
917
        mask = s->sr[2];
918
        s->plane_updated |= mask; /* only used to detect font change */
919
        write_mask = mask16[mask];
920
        ((uint32_t *)s->vram_ptr)[addr] =
921
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
922
            (val & write_mask);
923
#ifdef DEBUG_VGA_MEM
924
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
925
               addr * 4, write_mask, val);
926
#endif
927
        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
928
    }
929
}
930

    
931
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
932
{
933
#ifdef TARGET_WORDS_BIGENDIAN
934
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
935
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
936
#else
937
    vga_mem_writeb(opaque, addr, val & 0xff);
938
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
939
#endif
940
}
941

    
942
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
943
{
944
#ifdef TARGET_WORDS_BIGENDIAN
945
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
946
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
947
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
948
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
949
#else
950
    vga_mem_writeb(opaque, addr, val & 0xff);
951
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
952
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
953
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
954
#endif
955
}
956

    
957
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
958
                             const uint8_t *font_ptr, int h,
959
                             uint32_t fgcol, uint32_t bgcol);
960
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
961
                                  const uint8_t *font_ptr, int h,
962
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
963
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
964
                                const uint8_t *s, int width);
965

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

    
969
#define DEPTH 15
970
#include "vga_template.h"
971

    
972
#define BGR_FORMAT
973
#define DEPTH 15
974
#include "vga_template.h"
975

    
976
#define DEPTH 16
977
#include "vga_template.h"
978

    
979
#define BGR_FORMAT
980
#define DEPTH 16
981
#include "vga_template.h"
982

    
983
#define DEPTH 32
984
#include "vga_template.h"
985

    
986
#define BGR_FORMAT
987
#define DEPTH 32
988
#include "vga_template.h"
989

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

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

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

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

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

    
1033
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1034
{
1035
    unsigned int col;
1036
    col = rgb_to_pixel32(r, g, b);
1037
    return col;
1038
}
1039

    
1040
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1041
{
1042
    unsigned int col;
1043
    col = rgb_to_pixel32bgr(r, g, b);
1044
    return col;
1045
}
1046

    
1047
/* return true if the palette was modified */
1048
static int update_palette16(VGAState *s)
1049
{
1050
    int full_update, i;
1051
    uint32_t v, col, *palette;
1052

    
1053
    full_update = 0;
1054
    palette = s->last_palette;
1055
    for(i = 0; i < 16; i++) {
1056
        v = s->ar[i];
1057
        if (s->ar[0x10] & 0x80)
1058
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1059
        else
1060
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1061
        v = v * 3;
1062
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1063
                              c6_to_8(s->palette[v + 1]),
1064
                              c6_to_8(s->palette[v + 2]));
1065
        if (col != palette[i]) {
1066
            full_update = 1;
1067
            palette[i] = col;
1068
        }
1069
    }
1070
    return full_update;
1071
}
1072

    
1073
/* return true if the palette was modified */
1074
static int update_palette256(VGAState *s)
1075
{
1076
    int full_update, i;
1077
    uint32_t v, col, *palette;
1078

    
1079
    full_update = 0;
1080
    palette = s->last_palette;
1081
    v = 0;
1082
    for(i = 0; i < 256; i++) {
1083
        if (s->dac_8bit) {
1084
          col = s->rgb_to_pixel(s->palette[v],
1085
                                s->palette[v + 1],
1086
                                s->palette[v + 2]);
1087
        } else {
1088
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1089
                                c6_to_8(s->palette[v + 1]),
1090
                                c6_to_8(s->palette[v + 2]));
1091
        }
1092
        if (col != palette[i]) {
1093
            full_update = 1;
1094
            palette[i] = col;
1095
        }
1096
        v += 3;
1097
    }
1098
    return full_update;
1099
}
1100

    
1101
static void vga_get_offsets(VGAState *s,
1102
                            uint32_t *pline_offset,
1103
                            uint32_t *pstart_addr,
1104
                            uint32_t *pline_compare)
1105
{
1106
    uint32_t start_addr, line_offset, line_compare;
1107
#ifdef CONFIG_BOCHS_VBE
1108
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1109
        line_offset = s->vbe_line_offset;
1110
        start_addr = s->vbe_start_addr;
1111
        line_compare = 65535;
1112
    } else
1113
#endif
1114
    {
1115
        /* compute line_offset in bytes */
1116
        line_offset = s->cr[0x13];
1117
        line_offset <<= 3;
1118

    
1119
        /* starting address */
1120
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1121

    
1122
        /* line compare */
1123
        line_compare = s->cr[0x18] |
1124
            ((s->cr[0x07] & 0x10) << 4) |
1125
            ((s->cr[0x09] & 0x40) << 3);
1126
    }
1127
    *pline_offset = line_offset;
1128
    *pstart_addr = start_addr;
1129
    *pline_compare = line_compare;
1130
}
1131

    
1132
/* update start_addr and line_offset. Return TRUE if modified */
1133
static int update_basic_params(VGAState *s)
1134
{
1135
    int full_update;
1136
    uint32_t start_addr, line_offset, line_compare;
1137

    
1138
    full_update = 0;
1139

    
1140
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1141

    
1142
    if (line_offset != s->line_offset ||
1143
        start_addr != s->start_addr ||
1144
        line_compare != s->line_compare) {
1145
        s->line_offset = line_offset;
1146
        s->start_addr = start_addr;
1147
        s->line_compare = line_compare;
1148
        full_update = 1;
1149
    }
1150
    return full_update;
1151
}
1152

    
1153
#define NB_DEPTHS 7
1154

    
1155
static inline int get_depth_index(DisplayState *s)
1156
{
1157
    switch(ds_get_bits_per_pixel(s)) {
1158
    default:
1159
    case 8:
1160
        return 0;
1161
    case 15:
1162
        return 1;
1163
    case 16:
1164
        return 2;
1165
    case 32:
1166
        if (is_surface_bgr(s->surface))
1167
            return 4;
1168
        else
1169
            return 3;
1170
    }
1171
}
1172

    
1173
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1174
    vga_draw_glyph8_8,
1175
    vga_draw_glyph8_16,
1176
    vga_draw_glyph8_16,
1177
    vga_draw_glyph8_32,
1178
    vga_draw_glyph8_32,
1179
    vga_draw_glyph8_16,
1180
    vga_draw_glyph8_16,
1181
};
1182

    
1183
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1184
    vga_draw_glyph16_8,
1185
    vga_draw_glyph16_16,
1186
    vga_draw_glyph16_16,
1187
    vga_draw_glyph16_32,
1188
    vga_draw_glyph16_32,
1189
    vga_draw_glyph16_16,
1190
    vga_draw_glyph16_16,
1191
};
1192

    
1193
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1194
    vga_draw_glyph9_8,
1195
    vga_draw_glyph9_16,
1196
    vga_draw_glyph9_16,
1197
    vga_draw_glyph9_32,
1198
    vga_draw_glyph9_32,
1199
    vga_draw_glyph9_16,
1200
    vga_draw_glyph9_16,
1201
};
1202

    
1203
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220
};
1221

    
1222
static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1223
                                    int *pcwidth, int *pcheight)
1224
{
1225
    int width, cwidth, height, cheight;
1226

    
1227
    /* total width & height */
1228
    cheight = (s->cr[9] & 0x1f) + 1;
1229
    cwidth = 8;
1230
    if (!(s->sr[1] & 0x01))
1231
        cwidth = 9;
1232
    if (s->sr[1] & 0x08)
1233
        cwidth = 16; /* NOTE: no 18 pixel wide */
1234
    width = (s->cr[0x01] + 1);
1235
    if (s->cr[0x06] == 100) {
1236
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1237
        height = 100;
1238
    } else {
1239
        height = s->cr[0x12] |
1240
            ((s->cr[0x07] & 0x02) << 7) |
1241
            ((s->cr[0x07] & 0x40) << 3);
1242
        height = (height + 1) / cheight;
1243
    }
1244

    
1245
    *pwidth = width;
1246
    *pheight = height;
1247
    *pcwidth = cwidth;
1248
    *pcheight = cheight;
1249
}
1250

    
1251
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1252

    
1253
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1254
    rgb_to_pixel8_dup,
1255
    rgb_to_pixel15_dup,
1256
    rgb_to_pixel16_dup,
1257
    rgb_to_pixel32_dup,
1258
    rgb_to_pixel32bgr_dup,
1259
    rgb_to_pixel15bgr_dup,
1260
    rgb_to_pixel16bgr_dup,
1261
};
1262

    
1263
/*
1264
 * Text mode update
1265
 * Missing:
1266
 * - double scan
1267
 * - double width
1268
 * - underline
1269
 * - flashing
1270
 */
1271
static void vga_draw_text(VGAState *s, int full_update)
1272
{
1273
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1274
    int cx_min, cx_max, linesize, x_incr;
1275
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1276
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1277
    const uint8_t *font_ptr, *font_base[2];
1278
    int dup9, line_offset, depth_index;
1279
    uint32_t *palette;
1280
    uint32_t *ch_attr_ptr;
1281
    vga_draw_glyph8_func *vga_draw_glyph8;
1282
    vga_draw_glyph9_func *vga_draw_glyph9;
1283

    
1284
    /* compute font data address (in plane 2) */
1285
    v = s->sr[3];
1286
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1287
    if (offset != s->font_offsets[0]) {
1288
        s->font_offsets[0] = offset;
1289
        full_update = 1;
1290
    }
1291
    font_base[0] = s->vram_ptr + offset;
1292

    
1293
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1294
    font_base[1] = s->vram_ptr + offset;
1295
    if (offset != s->font_offsets[1]) {
1296
        s->font_offsets[1] = offset;
1297
        full_update = 1;
1298
    }
1299
    if (s->plane_updated & (1 << 2)) {
1300
        /* if the plane 2 was modified since the last display, it
1301
           indicates the font may have been modified */
1302
        s->plane_updated = 0;
1303
        full_update = 1;
1304
    }
1305
    full_update |= update_basic_params(s);
1306

    
1307
    line_offset = s->line_offset;
1308
    s1 = s->vram_ptr + (s->start_addr * 4);
1309

    
1310
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1311
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1312
    if ((height * width) > CH_ATTR_SIZE) {
1313
        /* better than nothing: exit if transient size is too big */
1314
        return;
1315
    }
1316

    
1317
    if (width != s->last_width || height != s->last_height ||
1318
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1319
        s->last_scr_width = width * cw;
1320
        s->last_scr_height = height * cheight;
1321
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1322
        s->last_depth = 0;
1323
        s->last_width = width;
1324
        s->last_height = height;
1325
        s->last_ch = cheight;
1326
        s->last_cw = cw;
1327
        full_update = 1;
1328
    }
1329
    s->rgb_to_pixel =
1330
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1331
    full_update |= update_palette16(s);
1332
    palette = s->last_palette;
1333
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1334

    
1335
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1336
    if (cursor_offset != s->cursor_offset ||
1337
        s->cr[0xa] != s->cursor_start ||
1338
        s->cr[0xb] != s->cursor_end) {
1339
      /* if the cursor position changed, we update the old and new
1340
         chars */
1341
        if (s->cursor_offset < CH_ATTR_SIZE)
1342
            s->last_ch_attr[s->cursor_offset] = -1;
1343
        if (cursor_offset < CH_ATTR_SIZE)
1344
            s->last_ch_attr[cursor_offset] = -1;
1345
        s->cursor_offset = cursor_offset;
1346
        s->cursor_start = s->cr[0xa];
1347
        s->cursor_end = s->cr[0xb];
1348
    }
1349
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1350

    
1351
    depth_index = get_depth_index(s->ds);
1352
    if (cw == 16)
1353
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1354
    else
1355
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1356
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1357

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

    
1430
enum {
1431
    VGA_DRAW_LINE2,
1432
    VGA_DRAW_LINE2D2,
1433
    VGA_DRAW_LINE4,
1434
    VGA_DRAW_LINE4D2,
1435
    VGA_DRAW_LINE8D2,
1436
    VGA_DRAW_LINE8,
1437
    VGA_DRAW_LINE15,
1438
    VGA_DRAW_LINE16,
1439
    VGA_DRAW_LINE24,
1440
    VGA_DRAW_LINE32,
1441
    VGA_DRAW_LINE_NB,
1442
};
1443

    
1444
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1445
    vga_draw_line2_8,
1446
    vga_draw_line2_16,
1447
    vga_draw_line2_16,
1448
    vga_draw_line2_32,
1449
    vga_draw_line2_32,
1450
    vga_draw_line2_16,
1451
    vga_draw_line2_16,
1452

    
1453
    vga_draw_line2d2_8,
1454
    vga_draw_line2d2_16,
1455
    vga_draw_line2d2_16,
1456
    vga_draw_line2d2_32,
1457
    vga_draw_line2d2_32,
1458
    vga_draw_line2d2_16,
1459
    vga_draw_line2d2_16,
1460

    
1461
    vga_draw_line4_8,
1462
    vga_draw_line4_16,
1463
    vga_draw_line4_16,
1464
    vga_draw_line4_32,
1465
    vga_draw_line4_32,
1466
    vga_draw_line4_16,
1467
    vga_draw_line4_16,
1468

    
1469
    vga_draw_line4d2_8,
1470
    vga_draw_line4d2_16,
1471
    vga_draw_line4d2_16,
1472
    vga_draw_line4d2_32,
1473
    vga_draw_line4d2_32,
1474
    vga_draw_line4d2_16,
1475
    vga_draw_line4d2_16,
1476

    
1477
    vga_draw_line8d2_8,
1478
    vga_draw_line8d2_16,
1479
    vga_draw_line8d2_16,
1480
    vga_draw_line8d2_32,
1481
    vga_draw_line8d2_32,
1482
    vga_draw_line8d2_16,
1483
    vga_draw_line8d2_16,
1484

    
1485
    vga_draw_line8_8,
1486
    vga_draw_line8_16,
1487
    vga_draw_line8_16,
1488
    vga_draw_line8_32,
1489
    vga_draw_line8_32,
1490
    vga_draw_line8_16,
1491
    vga_draw_line8_16,
1492

    
1493
    vga_draw_line15_8,
1494
    vga_draw_line15_15,
1495
    vga_draw_line15_16,
1496
    vga_draw_line15_32,
1497
    vga_draw_line15_32bgr,
1498
    vga_draw_line15_15bgr,
1499
    vga_draw_line15_16bgr,
1500

    
1501
    vga_draw_line16_8,
1502
    vga_draw_line16_15,
1503
    vga_draw_line16_16,
1504
    vga_draw_line16_32,
1505
    vga_draw_line16_32bgr,
1506
    vga_draw_line16_15bgr,
1507
    vga_draw_line16_16bgr,
1508

    
1509
    vga_draw_line24_8,
1510
    vga_draw_line24_15,
1511
    vga_draw_line24_16,
1512
    vga_draw_line24_32,
1513
    vga_draw_line24_32bgr,
1514
    vga_draw_line24_15bgr,
1515
    vga_draw_line24_16bgr,
1516

    
1517
    vga_draw_line32_8,
1518
    vga_draw_line32_15,
1519
    vga_draw_line32_16,
1520
    vga_draw_line32_32,
1521
    vga_draw_line32_32bgr,
1522
    vga_draw_line32_15bgr,
1523
    vga_draw_line32_16bgr,
1524
};
1525

    
1526
static int vga_get_bpp(VGAState *s)
1527
{
1528
    int ret;
1529
#ifdef CONFIG_BOCHS_VBE
1530
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1531
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1532
    } else
1533
#endif
1534
    {
1535
        ret = 0;
1536
    }
1537
    return ret;
1538
}
1539

    
1540
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1541
{
1542
    int width, height;
1543

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

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

    
1573
static void vga_sync_dirty_bitmap(VGAState *s)
1574
{
1575
    if (s->map_addr)
1576
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1577

    
1578
    if (s->lfb_vram_mapped) {
1579
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1580
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1581
    }
1582
}
1583

    
1584
/*
1585
 * graphic modes
1586
 */
1587
static void vga_draw_graphic(VGAState *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 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1746
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1747
        update = full_update |
1748
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1749
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1750
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1751
            /* if wide line, can use another page */
1752
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1753
                                                    VGA_DIRTY_FLAG);
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
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1799
                                        VGA_DIRTY_FLAG);
1800
    }
1801
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1802
}
1803

    
1804
static void vga_draw_blank(VGAState *s, int full_update)
1805
{
1806
    int i, w, val;
1807
    uint8_t *d;
1808

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

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

    
1830
#define GMODE_TEXT     0
1831
#define GMODE_GRAPH    1
1832
#define GMODE_BLANK 2
1833

    
1834
static void vga_update_display(void *opaque)
1835
{
1836
    VGAState *s = (VGAState *)opaque;
1837
    int full_update, graphic_mode;
1838

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

    
1868
/* force a full display refresh */
1869
static void vga_invalidate_display(void *opaque)
1870
{
1871
    VGAState *s = (VGAState *)opaque;
1872

    
1873
    s->full_update = 1;
1874
}
1875

    
1876
void vga_reset(void *opaque)
1877
{
1878
    VGAState *s = (VGAState *) opaque;
1879

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

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

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

    
1975
    switch (graphic_mode) {
1976
    case GMODE_TEXT:
1977
        /* TODO: update palette */
1978
        full_update |= update_basic_params(s);
1979

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

    
1998
        size = (height * width);
1999
        if (size > CH_ATTR_SIZE) {
2000
            if (!full_update)
2001
                return;
2002

    
2003
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2004
                     width, height);
2005
            break;
2006
        }
2007

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

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

    
2039
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2040
        dst = chardata;
2041

    
2042
        if (full_update) {
2043
            for (i = 0; i < size; src ++, dst ++, i ++)
2044
                console_write_ch(dst, VMEM2CHTYPE(*src));
2045

    
2046
            dpy_update(s->ds, 0, 0, width, height);
2047
        } else {
2048
            c_max = 0;
2049

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

    
2067
            if (c_min <= c_max) {
2068
                i = TEXTMODE_Y(c_min);
2069
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2070
            }
2071
        }
2072

    
2073
        return;
2074
    case GMODE_GRAPH:
2075
        if (!full_update)
2076
            return;
2077

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

    
2087
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2088
        break;
2089
    }
2090

    
2091
    /* Display a message */
2092
    s->last_width = 60;
2093
    s->last_height = height = 3;
2094
    dpy_cursor(s->ds, -1, -1);
2095
    s->ds->surface->width = s->last_width;
2096
    s->ds->surface->height = height;
2097
    dpy_resize(s->ds);
2098

    
2099
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2100
        console_write_ch(dst ++, ' ');
2101

    
2102
    size = strlen(msg_buffer);
2103
    width = (s->last_width - size) / 2;
2104
    dst = chardata + s->last_width + width;
2105
    for (i = 0; i < size; i ++)
2106
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2107

    
2108
    dpy_update(s->ds, 0, 0, s->last_width, height);
2109
}
2110

    
2111
static CPUReadMemoryFunc * const vga_mem_read[3] = {
2112
    vga_mem_readb,
2113
    vga_mem_readw,
2114
    vga_mem_readl,
2115
};
2116

    
2117
static CPUWriteMemoryFunc * const vga_mem_write[3] = {
2118
    vga_mem_writeb,
2119
    vga_mem_writew,
2120
    vga_mem_writel,
2121
};
2122

    
2123
static void vga_save(QEMUFile *f, void *opaque)
2124
{
2125
    VGAState *s = opaque;
2126
    int i;
2127

    
2128
    if (s->pci_dev)
2129
        pci_device_save(s->pci_dev, f);
2130

    
2131
    qemu_put_be32s(f, &s->latch);
2132
    qemu_put_8s(f, &s->sr_index);
2133
    qemu_put_buffer(f, s->sr, 8);
2134
    qemu_put_8s(f, &s->gr_index);
2135
    qemu_put_buffer(f, s->gr, 16);
2136
    qemu_put_8s(f, &s->ar_index);
2137
    qemu_put_buffer(f, s->ar, 21);
2138
    qemu_put_be32(f, s->ar_flip_flop);
2139
    qemu_put_8s(f, &s->cr_index);
2140
    qemu_put_buffer(f, s->cr, 256);
2141
    qemu_put_8s(f, &s->msr);
2142
    qemu_put_8s(f, &s->fcr);
2143
    qemu_put_byte(f, s->st00);
2144
    qemu_put_8s(f, &s->st01);
2145

    
2146
    qemu_put_8s(f, &s->dac_state);
2147
    qemu_put_8s(f, &s->dac_sub_index);
2148
    qemu_put_8s(f, &s->dac_read_index);
2149
    qemu_put_8s(f, &s->dac_write_index);
2150
    qemu_put_buffer(f, s->dac_cache, 3);
2151
    qemu_put_buffer(f, s->palette, 768);
2152

    
2153
    qemu_put_be32(f, s->bank_offset);
2154
#ifdef CONFIG_BOCHS_VBE
2155
    qemu_put_byte(f, 1);
2156
    qemu_put_be16s(f, &s->vbe_index);
2157
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2158
        qemu_put_be16s(f, &s->vbe_regs[i]);
2159
    qemu_put_be32s(f, &s->vbe_start_addr);
2160
    qemu_put_be32s(f, &s->vbe_line_offset);
2161
    qemu_put_be32s(f, &s->vbe_bank_mask);
2162
#else
2163
    qemu_put_byte(f, 0);
2164
#endif
2165
}
2166

    
2167
static int vga_load(QEMUFile *f, void *opaque, int version_id)
2168
{
2169
    VGAState *s = opaque;
2170
    int is_vbe, i, ret;
2171

    
2172
    if (version_id > 2)
2173
        return -EINVAL;
2174

    
2175
    if (s->pci_dev && version_id >= 2) {
2176
        ret = pci_device_load(s->pci_dev, f);
2177
        if (ret < 0)
2178
            return ret;
2179
    }
2180

    
2181
    qemu_get_be32s(f, &s->latch);
2182
    qemu_get_8s(f, &s->sr_index);
2183
    qemu_get_buffer(f, s->sr, 8);
2184
    qemu_get_8s(f, &s->gr_index);
2185
    qemu_get_buffer(f, s->gr, 16);
2186
    qemu_get_8s(f, &s->ar_index);
2187
    qemu_get_buffer(f, s->ar, 21);
2188
    s->ar_flip_flop=qemu_get_be32(f);
2189
    qemu_get_8s(f, &s->cr_index);
2190
    qemu_get_buffer(f, s->cr, 256);
2191
    qemu_get_8s(f, &s->msr);
2192
    qemu_get_8s(f, &s->fcr);
2193
    qemu_get_8s(f, &s->st00);
2194
    qemu_get_8s(f, &s->st01);
2195

    
2196
    qemu_get_8s(f, &s->dac_state);
2197
    qemu_get_8s(f, &s->dac_sub_index);
2198
    qemu_get_8s(f, &s->dac_read_index);
2199
    qemu_get_8s(f, &s->dac_write_index);
2200
    qemu_get_buffer(f, s->dac_cache, 3);
2201
    qemu_get_buffer(f, s->palette, 768);
2202

    
2203
    s->bank_offset=qemu_get_be32(f);
2204
    is_vbe = qemu_get_byte(f);
2205
#ifdef CONFIG_BOCHS_VBE
2206
    if (!is_vbe)
2207
        return -EINVAL;
2208
    qemu_get_be16s(f, &s->vbe_index);
2209
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2210
        qemu_get_be16s(f, &s->vbe_regs[i]);
2211
    qemu_get_be32s(f, &s->vbe_start_addr);
2212
    qemu_get_be32s(f, &s->vbe_line_offset);
2213
    qemu_get_be32s(f, &s->vbe_bank_mask);
2214
#else
2215
    if (is_vbe)
2216
        return -EINVAL;
2217
#endif
2218

    
2219
    /* force refresh */
2220
    s->graphic_mode = -1;
2221
    return 0;
2222
}
2223

    
2224
typedef struct PCIVGAState {
2225
    PCIDevice dev;
2226
    VGAState vga_state;
2227
} PCIVGAState;
2228

    
2229
void vga_dirty_log_start(VGAState *s)
2230
{
2231
    if (kvm_enabled() && s->map_addr)
2232
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2233

    
2234
    if (kvm_enabled() && s->lfb_vram_mapped) {
2235
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2236
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2237
    }
2238
}
2239

    
2240
static void vga_map(PCIDevice *pci_dev, int region_num,
2241
                    uint32_t addr, uint32_t size, int type)
2242
{
2243
    PCIVGAState *d = (PCIVGAState *)pci_dev;
2244
    VGAState *s = &d->vga_state;
2245
    if (region_num == PCI_ROM_SLOT) {
2246
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2247
    } else {
2248
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2249
        s->map_addr = addr;
2250
        s->map_end = addr + s->vram_size;
2251
        vga_dirty_log_start(s);
2252
    }
2253
}
2254

    
2255
void vga_common_init(VGAState *s, int vga_ram_size)
2256
{
2257
    int i, j, v, b;
2258

    
2259
    for(i = 0;i < 256; i++) {
2260
        v = 0;
2261
        for(j = 0; j < 8; j++) {
2262
            v |= ((i >> j) & 1) << (j * 4);
2263
        }
2264
        expand4[i] = v;
2265

    
2266
        v = 0;
2267
        for(j = 0; j < 4; j++) {
2268
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2269
        }
2270
        expand2[i] = v;
2271
    }
2272
    for(i = 0; i < 16; i++) {
2273
        v = 0;
2274
        for(j = 0; j < 4; j++) {
2275
            b = ((i >> j) & 1);
2276
            v |= b << (2 * j);
2277
            v |= b << (2 * j + 1);
2278
        }
2279
        expand4to8[i] = v;
2280
    }
2281

    
2282
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2283
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2284
    s->vram_size = vga_ram_size;
2285
    s->get_bpp = vga_get_bpp;
2286
    s->get_offsets = vga_get_offsets;
2287
    s->get_resolution = vga_get_resolution;
2288
    s->update = vga_update_display;
2289
    s->invalidate = vga_invalidate_display;
2290
    s->screen_dump = vga_screen_dump;
2291
    s->text_update = vga_update_text;
2292
    switch (vga_retrace_method) {
2293
    case VGA_RETRACE_DUMB:
2294
        s->retrace = vga_dumb_retrace;
2295
        s->update_retrace_info = vga_dumb_update_retrace_info;
2296
        break;
2297

    
2298
    case VGA_RETRACE_PRECISE:
2299
        s->retrace = vga_precise_retrace;
2300
        s->update_retrace_info = vga_precise_update_retrace_info;
2301
        break;
2302
    }
2303
    vga_reset(s);
2304
}
2305

    
2306
/* used by both ISA and PCI */
2307
void vga_init(VGAState *s)
2308
{
2309
    int vga_io_memory;
2310

    
2311
    qemu_register_reset(vga_reset, s);
2312
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2313

    
2314
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2315

    
2316
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2317
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2318
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2319
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2320

    
2321
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2322

    
2323
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2324
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2325
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2326
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2327
    s->bank_offset = 0;
2328

    
2329
#ifdef CONFIG_BOCHS_VBE
2330
#if defined (TARGET_I386)
2331
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2332
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2333

    
2334
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2335
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2336

    
2337
    /* old Bochs IO ports */
2338
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2339
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2340

    
2341
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2342
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2343
#else
2344
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2345
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2346

    
2347
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2348
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2349
#endif
2350
#endif /* CONFIG_BOCHS_VBE */
2351

    
2352
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2353
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2354
                                 vga_io_memory);
2355
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2356
}
2357

    
2358
/* Memory mapped interface */
2359
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2360
{
2361
    VGAState *s = opaque;
2362

    
2363
    return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2364
}
2365

    
2366
static void vga_mm_writeb (void *opaque,
2367
                           target_phys_addr_t addr, uint32_t value)
2368
{
2369
    VGAState *s = opaque;
2370

    
2371
    vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2372
}
2373

    
2374
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2375
{
2376
    VGAState *s = opaque;
2377

    
2378
    return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2379
}
2380

    
2381
static void vga_mm_writew (void *opaque,
2382
                           target_phys_addr_t addr, uint32_t value)
2383
{
2384
    VGAState *s = opaque;
2385

    
2386
    vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2387
}
2388

    
2389
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2390
{
2391
    VGAState *s = opaque;
2392

    
2393
    return vga_ioport_read(s, addr >> s->it_shift);
2394
}
2395

    
2396
static void vga_mm_writel (void *opaque,
2397
                           target_phys_addr_t addr, uint32_t value)
2398
{
2399
    VGAState *s = opaque;
2400

    
2401
    vga_ioport_write(s, addr >> s->it_shift, value);
2402
}
2403

    
2404
static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
2405
    &vga_mm_readb,
2406
    &vga_mm_readw,
2407
    &vga_mm_readl,
2408
};
2409

    
2410
static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
2411
    &vga_mm_writeb,
2412
    &vga_mm_writew,
2413
    &vga_mm_writel,
2414
};
2415

    
2416
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2417
                        target_phys_addr_t ctrl_base, int it_shift)
2418
{
2419
    int s_ioport_ctrl, vga_io_memory;
2420

    
2421
    s->it_shift = it_shift;
2422
    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2423
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2424

    
2425
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2426

    
2427
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2428
    s->bank_offset = 0;
2429
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2430
    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2431
}
2432

    
2433
int isa_vga_init(void)
2434
{
2435
    VGAState *s;
2436

    
2437
    s = qemu_mallocz(sizeof(VGAState));
2438

    
2439
    vga_common_init(s, VGA_RAM_SIZE);
2440
    vga_init(s);
2441

    
2442
    s->ds = graphic_console_init(s->update, s->invalidate,
2443
                                 s->screen_dump, s->text_update, s);
2444

    
2445
#ifdef CONFIG_BOCHS_VBE
2446
    /* XXX: use optimized standard vga accesses */
2447
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2448
                                 VGA_RAM_SIZE, s->vram_offset);
2449
#endif
2450
    return 0;
2451
}
2452

    
2453
int isa_vga_mm_init(target_phys_addr_t vram_base,
2454
                    target_phys_addr_t ctrl_base, int it_shift)
2455
{
2456
    VGAState *s;
2457

    
2458
    s = qemu_mallocz(sizeof(VGAState));
2459

    
2460
    vga_common_init(s, VGA_RAM_SIZE);
2461
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
2462

    
2463
    s->ds = graphic_console_init(s->update, s->invalidate,
2464
                                 s->screen_dump, s->text_update, s);
2465

    
2466
#ifdef CONFIG_BOCHS_VBE
2467
    /* XXX: use optimized standard vga accesses */
2468
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2469
                                 VGA_RAM_SIZE, s->vram_offset);
2470
#endif
2471
    return 0;
2472
}
2473

    
2474
static void pci_vga_write_config(PCIDevice *d,
2475
                                 uint32_t address, uint32_t val, int len)
2476
{
2477
    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2478
    VGAState *s = &pvs->vga_state;
2479

    
2480
    pci_default_write_config(d, address, val, len);
2481
    if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
2482
        s->map_addr = 0;
2483
}
2484

    
2485
static void pci_vga_initfn(PCIDevice *dev)
2486
{
2487
     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
2488
     VGAState *s = &d->vga_state;
2489
     uint8_t *pci_conf = d->dev.config;
2490

    
2491
     // vga + console init
2492
     vga_common_init(s, VGA_RAM_SIZE);
2493
     vga_init(s);
2494
     s->pci_dev = &d->dev;
2495
     s->ds = graphic_console_init(s->update, s->invalidate,
2496
                                  s->screen_dump, s->text_update, s);
2497

    
2498
     // dummy VGA (same as Bochs ID)
2499
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2500
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2501
     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2502
     pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
2503

    
2504
     /* XXX: VGA_RAM_SIZE must be a power of two */
2505
     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
2506
                      PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2507

    
2508
     if (s->bios_size) {
2509
        unsigned int bios_total_size;
2510
        /* must be a power of two */
2511
        bios_total_size = 1;
2512
        while (bios_total_size < s->bios_size)
2513
            bios_total_size <<= 1;
2514
        pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
2515
                         PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2516
    }
2517
}
2518

    
2519
int pci_vga_init(PCIBus *bus,
2520
                 unsigned long vga_bios_offset, int vga_bios_size)
2521
{
2522
    PCIDevice *dev;
2523

    
2524
    dev = pci_create("VGA", NULL);
2525
    qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset);
2526
    qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_offset);
2527
    qdev_init(&dev->qdev);
2528

    
2529
    return 0;
2530
}
2531

    
2532
static PCIDeviceInfo vga_info = {
2533
    .qdev.name    = "VGA",
2534
    .qdev.size    = sizeof(PCIVGAState),
2535
    .init         = pci_vga_initfn,
2536
    .config_write = pci_vga_write_config,
2537
    .qdev.props   = (Property[]) {
2538
        DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga_state.bios_offset, 0),
2539
        DEFINE_PROP_HEX32("bios-size",   PCIVGAState, vga_state.bios_size,   0),
2540
        DEFINE_PROP_END_OF_LIST(),
2541
    }
2542
};
2543

    
2544
static void vga_register(void)
2545
{
2546
    pci_qdev_register(&vga_info);
2547
}
2548
device_init(vga_register);
2549

    
2550
/********************************************************/
2551
/* vga screen dump */
2552

    
2553
static void vga_save_dpy_update(DisplayState *ds,
2554
                                int x, int y, int w, int h)
2555
{
2556
    if (screen_dump_filename) {
2557
        ppm_save(screen_dump_filename, ds->surface);
2558
        screen_dump_filename = NULL;
2559
    }
2560
}
2561

    
2562
static void vga_save_dpy_resize(DisplayState *s)
2563
{
2564
}
2565

    
2566
static void vga_save_dpy_refresh(DisplayState *s)
2567
{
2568
}
2569

    
2570
int ppm_save(const char *filename, struct DisplaySurface *ds)
2571
{
2572
    FILE *f;
2573
    uint8_t *d, *d1;
2574
    uint32_t v;
2575
    int y, x;
2576
    uint8_t r, g, b;
2577

    
2578
    f = fopen(filename, "wb");
2579
    if (!f)
2580
        return -1;
2581
    fprintf(f, "P6\n%d %d\n%d\n",
2582
            ds->width, ds->height, 255);
2583
    d1 = ds->data;
2584
    for(y = 0; y < ds->height; y++) {
2585
        d = d1;
2586
        for(x = 0; x < ds->width; x++) {
2587
            if (ds->pf.bits_per_pixel == 32)
2588
                v = *(uint32_t *)d;
2589
            else
2590
                v = (uint32_t) (*(uint16_t *)d);
2591
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2592
                (ds->pf.rmax + 1);
2593
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2594
                (ds->pf.gmax + 1);
2595
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2596
                (ds->pf.bmax + 1);
2597
            fputc(r, f);
2598
            fputc(g, f);
2599
            fputc(b, f);
2600
            d += ds->pf.bytes_per_pixel;
2601
        }
2602
        d1 += ds->linesize;
2603
    }
2604
    fclose(f);
2605
    return 0;
2606
}
2607

    
2608
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2609
{
2610
    DisplayChangeListener *dcl;
2611

    
2612
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2613
    dcl->dpy_update = vga_save_dpy_update;
2614
    dcl->dpy_resize = vga_save_dpy_resize;
2615
    dcl->dpy_refresh = vga_save_dpy_refresh;
2616
    register_displaychangelistener(ds, dcl);
2617
    return dcl;
2618
}
2619

    
2620
/* save the vga display in a PPM image even if no display is
2621
   available */
2622
static void vga_screen_dump(void *opaque, const char *filename)
2623
{
2624
    VGAState *s = (VGAState *)opaque;
2625

    
2626
    if (!screen_dump_dcl)
2627
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2628

    
2629
    screen_dump_filename = (char *)filename;
2630
    vga_invalidate_display(s);
2631
    vga_hw_update();
2632
}
2633