Statistics
| Branch: | Revision:

root / hw / vga.c @ 5bc89ef6

History | View | Annotate | Download (74.4 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
typedef VGACommonState VGAState;
153

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

    
158
static void vga_dumb_update_retrace_info(VGAState *s)
159
{
160
    (void) s;
161
}
162

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

    
170
    int vtotal_lines;
171
    int vretr_start_line;
172
    int vretr_end_line;
173

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

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

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

    
194

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

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

    
202
    chars_per_sec = clk_hz[clock_sel] / dots;
203

    
204
    htotal_chars <<= clocking_mode;
205

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

    
213
    r->vstart = vretr_start_line;
214
    r->vend = r->vstart + vretr_end_line + 1;
215

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

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

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

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

    
263
        cur_tick = qemu_get_clock(vm_clock);
264

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
968
#define DEPTH 8
969
#include "vga_template.h"
970

    
971
#define DEPTH 15
972
#include "vga_template.h"
973

    
974
#define BGR_FORMAT
975
#define DEPTH 15
976
#include "vga_template.h"
977

    
978
#define DEPTH 16
979
#include "vga_template.h"
980

    
981
#define BGR_FORMAT
982
#define DEPTH 16
983
#include "vga_template.h"
984

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1140
    full_update = 0;
1141

    
1142
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1143

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

    
1155
#define NB_DEPTHS 7
1156

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

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

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

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

    
1205
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222
};
1223

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

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

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

    
1253
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1254

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

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

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

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

    
1309
    line_offset = s->line_offset;
1310
    s1 = s->vram_ptr + (s->start_addr * 4);
1311

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

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

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

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

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

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

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

    
1455
    vga_draw_line2d2_8,
1456
    vga_draw_line2d2_16,
1457
    vga_draw_line2d2_16,
1458
    vga_draw_line2d2_32,
1459
    vga_draw_line2d2_32,
1460
    vga_draw_line2d2_16,
1461
    vga_draw_line2d2_16,
1462

    
1463
    vga_draw_line4_8,
1464
    vga_draw_line4_16,
1465
    vga_draw_line4_16,
1466
    vga_draw_line4_32,
1467
    vga_draw_line4_32,
1468
    vga_draw_line4_16,
1469
    vga_draw_line4_16,
1470

    
1471
    vga_draw_line4d2_8,
1472
    vga_draw_line4d2_16,
1473
    vga_draw_line4d2_16,
1474
    vga_draw_line4d2_32,
1475
    vga_draw_line4d2_32,
1476
    vga_draw_line4d2_16,
1477
    vga_draw_line4d2_16,
1478

    
1479
    vga_draw_line8d2_8,
1480
    vga_draw_line8d2_16,
1481
    vga_draw_line8d2_16,
1482
    vga_draw_line8d2_32,
1483
    vga_draw_line8d2_32,
1484
    vga_draw_line8d2_16,
1485
    vga_draw_line8d2_16,
1486

    
1487
    vga_draw_line8_8,
1488
    vga_draw_line8_16,
1489
    vga_draw_line8_16,
1490
    vga_draw_line8_32,
1491
    vga_draw_line8_32,
1492
    vga_draw_line8_16,
1493
    vga_draw_line8_16,
1494

    
1495
    vga_draw_line15_8,
1496
    vga_draw_line15_15,
1497
    vga_draw_line15_16,
1498
    vga_draw_line15_32,
1499
    vga_draw_line15_32bgr,
1500
    vga_draw_line15_15bgr,
1501
    vga_draw_line15_16bgr,
1502

    
1503
    vga_draw_line16_8,
1504
    vga_draw_line16_15,
1505
    vga_draw_line16_16,
1506
    vga_draw_line16_32,
1507
    vga_draw_line16_32bgr,
1508
    vga_draw_line16_15bgr,
1509
    vga_draw_line16_16bgr,
1510

    
1511
    vga_draw_line24_8,
1512
    vga_draw_line24_15,
1513
    vga_draw_line24_16,
1514
    vga_draw_line24_32,
1515
    vga_draw_line24_32bgr,
1516
    vga_draw_line24_15bgr,
1517
    vga_draw_line24_16bgr,
1518

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

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

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

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

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

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

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

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

    
1599
    full_update |= update_basic_params(s);
1600

    
1601
    if (!full_update)
1602
        vga_sync_dirty_bitmap(s);
1603

    
1604
    s->get_resolution(s, &width, &height);
1605
    disp_width = width;
1606

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

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

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

    
1668
    s->rgb_to_pixel =
1669
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1670

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

    
1720
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1721
        s->cursor_invalidate(s);
1722

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

    
1806
static void vga_draw_blank(VGAState *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
    VGAState *s = (VGAState *)opaque;
1839
    int full_update, graphic_mode;
1840

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

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

    
1875
    s->full_update = 1;
1876
}
1877

    
1878
void vga_common_reset(VGACommonState *s)
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
static void vga_reset(void *opaque)
1946
{
1947
    VGAState *s = (VGAState *) opaque;
1948
    vga_common_reset(s);
1949
}
1950

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2117
static CPUReadMemoryFunc * const vga_mem_read[3] = {
2118
    vga_mem_readb,
2119
    vga_mem_readw,
2120
    vga_mem_readl,
2121
};
2122

    
2123
static CPUWriteMemoryFunc * const vga_mem_write[3] = {
2124
    vga_mem_writeb,
2125
    vga_mem_writew,
2126
    vga_mem_writel,
2127
};
2128

    
2129
static void vga_save(QEMUFile *f, void *opaque)
2130
{
2131
    VGAState *s = opaque;
2132
    int i;
2133

    
2134
    if (s->pci_dev)
2135
        pci_device_save(s->pci_dev, f);
2136

    
2137
    qemu_put_be32s(f, &s->latch);
2138
    qemu_put_8s(f, &s->sr_index);
2139
    qemu_put_buffer(f, s->sr, 8);
2140
    qemu_put_8s(f, &s->gr_index);
2141
    qemu_put_buffer(f, s->gr, 16);
2142
    qemu_put_8s(f, &s->ar_index);
2143
    qemu_put_buffer(f, s->ar, 21);
2144
    qemu_put_be32(f, s->ar_flip_flop);
2145
    qemu_put_8s(f, &s->cr_index);
2146
    qemu_put_buffer(f, s->cr, 256);
2147
    qemu_put_8s(f, &s->msr);
2148
    qemu_put_8s(f, &s->fcr);
2149
    qemu_put_byte(f, s->st00);
2150
    qemu_put_8s(f, &s->st01);
2151

    
2152
    qemu_put_8s(f, &s->dac_state);
2153
    qemu_put_8s(f, &s->dac_sub_index);
2154
    qemu_put_8s(f, &s->dac_read_index);
2155
    qemu_put_8s(f, &s->dac_write_index);
2156
    qemu_put_buffer(f, s->dac_cache, 3);
2157
    qemu_put_buffer(f, s->palette, 768);
2158

    
2159
    qemu_put_be32(f, s->bank_offset);
2160
#ifdef CONFIG_BOCHS_VBE
2161
    qemu_put_byte(f, 1);
2162
    qemu_put_be16s(f, &s->vbe_index);
2163
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2164
        qemu_put_be16s(f, &s->vbe_regs[i]);
2165
    qemu_put_be32s(f, &s->vbe_start_addr);
2166
    qemu_put_be32s(f, &s->vbe_line_offset);
2167
    qemu_put_be32s(f, &s->vbe_bank_mask);
2168
#else
2169
    qemu_put_byte(f, 0);
2170
#endif
2171
}
2172

    
2173
static int vga_load(QEMUFile *f, void *opaque, int version_id)
2174
{
2175
    VGAState *s = opaque;
2176
    int is_vbe, i, ret;
2177

    
2178
    if (version_id > 2)
2179
        return -EINVAL;
2180

    
2181
    if (s->pci_dev && version_id >= 2) {
2182
        ret = pci_device_load(s->pci_dev, f);
2183
        if (ret < 0)
2184
            return ret;
2185
    }
2186

    
2187
    qemu_get_be32s(f, &s->latch);
2188
    qemu_get_8s(f, &s->sr_index);
2189
    qemu_get_buffer(f, s->sr, 8);
2190
    qemu_get_8s(f, &s->gr_index);
2191
    qemu_get_buffer(f, s->gr, 16);
2192
    qemu_get_8s(f, &s->ar_index);
2193
    qemu_get_buffer(f, s->ar, 21);
2194
    s->ar_flip_flop=qemu_get_be32(f);
2195
    qemu_get_8s(f, &s->cr_index);
2196
    qemu_get_buffer(f, s->cr, 256);
2197
    qemu_get_8s(f, &s->msr);
2198
    qemu_get_8s(f, &s->fcr);
2199
    qemu_get_8s(f, &s->st00);
2200
    qemu_get_8s(f, &s->st01);
2201

    
2202
    qemu_get_8s(f, &s->dac_state);
2203
    qemu_get_8s(f, &s->dac_sub_index);
2204
    qemu_get_8s(f, &s->dac_read_index);
2205
    qemu_get_8s(f, &s->dac_write_index);
2206
    qemu_get_buffer(f, s->dac_cache, 3);
2207
    qemu_get_buffer(f, s->palette, 768);
2208

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

    
2225
    /* force refresh */
2226
    s->graphic_mode = -1;
2227
    return 0;
2228
}
2229

    
2230
typedef struct PCIVGAState {
2231
    PCIDevice dev;
2232
    VGAState vga;
2233
} PCIVGAState;
2234

    
2235
void vga_dirty_log_start(VGAState *s)
2236
{
2237
    if (kvm_enabled() && s->map_addr)
2238
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2239

    
2240
    if (kvm_enabled() && s->lfb_vram_mapped) {
2241
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2242
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2243
    }
2244
}
2245

    
2246
static void vga_map(PCIDevice *pci_dev, int region_num,
2247
                    uint32_t addr, uint32_t size, int type)
2248
{
2249
    PCIVGAState *d = (PCIVGAState *)pci_dev;
2250
    VGAState *s = &d->vga;
2251
    if (region_num == PCI_ROM_SLOT) {
2252
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2253
    } else {
2254
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2255
        s->map_addr = addr;
2256
        s->map_end = addr + s->vram_size;
2257
        vga_dirty_log_start(s);
2258
    }
2259
}
2260

    
2261
void vga_common_init(VGACommonState *s, int vga_ram_size)
2262
{
2263
    int i, j, v, b;
2264

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

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

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

    
2304
    case VGA_RETRACE_PRECISE:
2305
        s->retrace = vga_precise_retrace;
2306
        s->update_retrace_info = vga_precise_update_retrace_info;
2307
        break;
2308
    }
2309
    vga_reset(s);
2310
}
2311

    
2312
/* used by both ISA and PCI */
2313
void vga_init(VGAState *s)
2314
{
2315
    int vga_io_memory;
2316

    
2317
    qemu_register_reset(vga_reset, s);
2318
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2319

    
2320
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2321

    
2322
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2323
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2324
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2325
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2326

    
2327
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2328

    
2329
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2330
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2331
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2332
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2333
    s->bank_offset = 0;
2334

    
2335
#ifdef CONFIG_BOCHS_VBE
2336
#if defined (TARGET_I386)
2337
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2338
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2339

    
2340
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2341
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2342

    
2343
    /* old Bochs IO ports */
2344
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2345
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2346

    
2347
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2348
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2349
#else
2350
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2351
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2352

    
2353
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2354
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2355
#endif
2356
#endif /* CONFIG_BOCHS_VBE */
2357

    
2358
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2359
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2360
                                 vga_io_memory);
2361
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2362
}
2363

    
2364
/* Memory mapped interface */
2365
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2366
{
2367
    VGAState *s = opaque;
2368

    
2369
    return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2370
}
2371

    
2372
static void vga_mm_writeb (void *opaque,
2373
                           target_phys_addr_t addr, uint32_t value)
2374
{
2375
    VGAState *s = opaque;
2376

    
2377
    vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2378
}
2379

    
2380
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2381
{
2382
    VGAState *s = opaque;
2383

    
2384
    return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2385
}
2386

    
2387
static void vga_mm_writew (void *opaque,
2388
                           target_phys_addr_t addr, uint32_t value)
2389
{
2390
    VGAState *s = opaque;
2391

    
2392
    vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2393
}
2394

    
2395
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2396
{
2397
    VGAState *s = opaque;
2398

    
2399
    return vga_ioport_read(s, addr >> s->it_shift);
2400
}
2401

    
2402
static void vga_mm_writel (void *opaque,
2403
                           target_phys_addr_t addr, uint32_t value)
2404
{
2405
    VGAState *s = opaque;
2406

    
2407
    vga_ioport_write(s, addr >> s->it_shift, value);
2408
}
2409

    
2410
static CPUReadMemoryFunc * const vga_mm_read_ctrl[] = {
2411
    &vga_mm_readb,
2412
    &vga_mm_readw,
2413
    &vga_mm_readl,
2414
};
2415

    
2416
static CPUWriteMemoryFunc * const vga_mm_write_ctrl[] = {
2417
    &vga_mm_writeb,
2418
    &vga_mm_writew,
2419
    &vga_mm_writel,
2420
};
2421

    
2422
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2423
                        target_phys_addr_t ctrl_base, int it_shift)
2424
{
2425
    int s_ioport_ctrl, vga_io_memory;
2426

    
2427
    s->it_shift = it_shift;
2428
    s_ioport_ctrl = cpu_register_io_memory(vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2429
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2430

    
2431
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2432

    
2433
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2434
    s->bank_offset = 0;
2435
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2436
    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2437
}
2438

    
2439
int isa_vga_init(void)
2440
{
2441
    VGAState *s;
2442

    
2443
    s = qemu_mallocz(sizeof(VGAState));
2444

    
2445
    vga_common_init(s, VGA_RAM_SIZE);
2446
    vga_init(s);
2447

    
2448
    s->ds = graphic_console_init(s->update, s->invalidate,
2449
                                 s->screen_dump, s->text_update, s);
2450

    
2451
#ifdef CONFIG_BOCHS_VBE
2452
    /* XXX: use optimized standard vga accesses */
2453
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2454
                                 VGA_RAM_SIZE, s->vram_offset);
2455
#endif
2456
    return 0;
2457
}
2458

    
2459
int isa_vga_mm_init(target_phys_addr_t vram_base,
2460
                    target_phys_addr_t ctrl_base, int it_shift)
2461
{
2462
    VGAState *s;
2463

    
2464
    s = qemu_mallocz(sizeof(VGAState));
2465

    
2466
    vga_common_init(s, VGA_RAM_SIZE);
2467
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
2468

    
2469
    s->ds = graphic_console_init(s->update, s->invalidate,
2470
                                 s->screen_dump, s->text_update, s);
2471

    
2472
#ifdef CONFIG_BOCHS_VBE
2473
    /* XXX: use optimized standard vga accesses */
2474
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2475
                                 VGA_RAM_SIZE, s->vram_offset);
2476
#endif
2477
    return 0;
2478
}
2479

    
2480
static void pci_vga_write_config(PCIDevice *d,
2481
                                 uint32_t address, uint32_t val, int len)
2482
{
2483
    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2484
    VGAState *s = &pvs->vga;
2485

    
2486
    pci_default_write_config(d, address, val, len);
2487
    if (s->map_addr && pvs->dev.io_regions[0].addr == -1)
2488
        s->map_addr = 0;
2489
}
2490

    
2491
static int pci_vga_initfn(PCIDevice *dev)
2492
{
2493
     PCIVGAState *d = DO_UPCAST(PCIVGAState, dev, dev);
2494
     VGAState *s = &d->vga;
2495
     uint8_t *pci_conf = d->dev.config;
2496

    
2497
     // vga + console init
2498
     vga_common_init(s, VGA_RAM_SIZE);
2499
     vga_init(s);
2500
     s->pci_dev = &d->dev;
2501
     s->ds = graphic_console_init(s->update, s->invalidate,
2502
                                  s->screen_dump, s->text_update, s);
2503

    
2504
     // dummy VGA (same as Bochs ID)
2505
     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2506
     pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2507
     pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2508
     pci_conf[PCI_HEADER_TYPE] = PCI_HEADER_TYPE_NORMAL; // header_type
2509

    
2510
     /* XXX: VGA_RAM_SIZE must be a power of two */
2511
     pci_register_bar(&d->dev, 0, VGA_RAM_SIZE,
2512
                      PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2513

    
2514
     if (s->bios_size) {
2515
        unsigned int bios_total_size;
2516
        /* must be a power of two */
2517
        bios_total_size = 1;
2518
        while (bios_total_size < s->bios_size)
2519
            bios_total_size <<= 1;
2520
        pci_register_bar(&d->dev, PCI_ROM_SLOT, bios_total_size,
2521
                         PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2522
     }
2523
     return 0;
2524
}
2525

    
2526
int pci_vga_init(PCIBus *bus,
2527
                 unsigned long vga_bios_offset, int vga_bios_size)
2528
{
2529
    PCIDevice *dev;
2530

    
2531
    dev = pci_create("VGA", NULL);
2532
    qdev_prop_set_uint32(&dev->qdev, "bios-offset", vga_bios_offset);
2533
    qdev_prop_set_uint32(&dev->qdev, "bios-size", vga_bios_offset);
2534
    qdev_init(&dev->qdev);
2535

    
2536
    return 0;
2537
}
2538

    
2539
static PCIDeviceInfo vga_info = {
2540
    .qdev.name    = "VGA",
2541
    .qdev.size    = sizeof(PCIVGAState),
2542
    .init         = pci_vga_initfn,
2543
    .config_write = pci_vga_write_config,
2544
    .qdev.props   = (Property[]) {
2545
        DEFINE_PROP_HEX32("bios-offset", PCIVGAState, vga.bios_offset, 0),
2546
        DEFINE_PROP_HEX32("bios-size",   PCIVGAState, vga.bios_size,   0),
2547
        DEFINE_PROP_END_OF_LIST(),
2548
    }
2549
};
2550

    
2551
static void vga_register(void)
2552
{
2553
    pci_qdev_register(&vga_info);
2554
}
2555
device_init(vga_register);
2556

    
2557
/********************************************************/
2558
/* vga screen dump */
2559

    
2560
static void vga_save_dpy_update(DisplayState *ds,
2561
                                int x, int y, int w, int h)
2562
{
2563
    if (screen_dump_filename) {
2564
        ppm_save(screen_dump_filename, ds->surface);
2565
        screen_dump_filename = NULL;
2566
    }
2567
}
2568

    
2569
static void vga_save_dpy_resize(DisplayState *s)
2570
{
2571
}
2572

    
2573
static void vga_save_dpy_refresh(DisplayState *s)
2574
{
2575
}
2576

    
2577
int ppm_save(const char *filename, struct DisplaySurface *ds)
2578
{
2579
    FILE *f;
2580
    uint8_t *d, *d1;
2581
    uint32_t v;
2582
    int y, x;
2583
    uint8_t r, g, b;
2584

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

    
2615
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2616
{
2617
    DisplayChangeListener *dcl;
2618

    
2619
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2620
    dcl->dpy_update = vga_save_dpy_update;
2621
    dcl->dpy_resize = vga_save_dpy_resize;
2622
    dcl->dpy_refresh = vga_save_dpy_refresh;
2623
    register_displaychangelistener(ds, dcl);
2624
    return dcl;
2625
}
2626

    
2627
/* save the vga display in a PPM image even if no display is
2628
   available */
2629
static void vga_screen_dump(void *opaque, const char *filename)
2630
{
2631
    VGAState *s = (VGAState *)opaque;
2632

    
2633
    if (!screen_dump_dcl)
2634
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2635

    
2636
    screen_dump_filename = (char *)filename;
2637
    vga_invalidate_display(s);
2638
    vga_hw_update();
2639
}
2640