Statistics
| Branch: | Revision:

root / hw / vga.c @ b584726d

History | View | Annotate | Download (75.2 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 WORDS_BIGENDIAN
78
#define PAT(x) cbswap_32(x)
79
#else
80
#define PAT(x) (x)
81
#endif
82

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

    
89
#ifdef 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 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

    
154
static void vga_dumb_update_retrace_info(VGAState *s)
155
{
156
    (void) s;
157
}
158

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

    
166
    int vtotal_lines;
167
    int vretr_start_line;
168
    int vretr_end_line;
169

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

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

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

    
190

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

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

    
198
    chars_per_sec = clk_hz[clock_sel] / dots;
199

    
200
    htotal_chars <<= clocking_mode;
201

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

    
209
    r->vstart = vretr_start_line;
210
    r->vend = r->vstart + vretr_end_line + 1;
211

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

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

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

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

    
259
        cur_tick = qemu_get_clock(vm_clock);
260

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
964
#define DEPTH 8
965
#include "vga_template.h"
966

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

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

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

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

    
981
#define DEPTH 32
982
#include "vga_template.h"
983

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1136
    full_update = 0;
1137

    
1138
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1139

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

    
1151
#define NB_DEPTHS 7
1152

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

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

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

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

    
1201
static const uint8_t cursor_glyph[32 * 4] = {
1202
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1203
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1204
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1205
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211
    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
};
1219

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

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

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

    
1249
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1250

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

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

    
1282
    vga_dirty_log_stop(s);
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 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
    vga_dirty_log_start(s);
1583
}
1584

    
1585
/*
1586
 * graphic modes
1587
 */
1588
static void vga_draw_graphic(VGAState *s, int full_update)
1589
{
1590
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask, depth;
1591
    int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
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(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(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 = 0x7fffffff;
1730
    page_max = -1;
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 != -1) {
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
    vga_dirty_log_stop(s);
1814

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

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

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

    
1840
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1841
        /* nothing to do */
1842
    } else {
1843
        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->last_width = -1;
1874
    s->last_height = -1;
1875
}
1876

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2241
void vga_dirty_log_stop(VGAState *s)
2242
{
2243
    if (kvm_enabled() && s->map_addr)
2244
        kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2245

    
2246
    if (kvm_enabled() && s->lfb_vram_mapped) {
2247
        kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2248
        kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2249
    }
2250
}
2251

    
2252
static void vga_map(PCIDevice *pci_dev, int region_num,
2253
                    uint32_t addr, uint32_t size, int type)
2254
{
2255
    PCIVGAState *d = (PCIVGAState *)pci_dev;
2256
    VGAState *s = &d->vga_state;
2257
    if (region_num == PCI_ROM_SLOT) {
2258
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2259
    } else {
2260
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2261
    }
2262

    
2263
    s->map_addr = addr;
2264
    s->map_end = addr + VGA_RAM_SIZE;
2265

    
2266
    vga_dirty_log_start(s);
2267
}
2268

    
2269
void vga_common_init(VGAState *s, int vga_ram_size)
2270
{
2271
    int i, j, v, b;
2272

    
2273
    for(i = 0;i < 256; i++) {
2274
        v = 0;
2275
        for(j = 0; j < 8; j++) {
2276
            v |= ((i >> j) & 1) << (j * 4);
2277
        }
2278
        expand4[i] = v;
2279

    
2280
        v = 0;
2281
        for(j = 0; j < 4; j++) {
2282
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2283
        }
2284
        expand2[i] = v;
2285
    }
2286
    for(i = 0; i < 16; i++) {
2287
        v = 0;
2288
        for(j = 0; j < 4; j++) {
2289
            b = ((i >> j) & 1);
2290
            v |= b << (2 * j);
2291
            v |= b << (2 * j + 1);
2292
        }
2293
        expand4to8[i] = v;
2294
    }
2295

    
2296
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2297
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2298
    s->vram_size = vga_ram_size;
2299
    s->get_bpp = vga_get_bpp;
2300
    s->get_offsets = vga_get_offsets;
2301
    s->get_resolution = vga_get_resolution;
2302
    s->update = vga_update_display;
2303
    s->invalidate = vga_invalidate_display;
2304
    s->screen_dump = vga_screen_dump;
2305
    s->text_update = vga_update_text;
2306
    switch (vga_retrace_method) {
2307
    case VGA_RETRACE_DUMB:
2308
        s->retrace = vga_dumb_retrace;
2309
        s->update_retrace_info = vga_dumb_update_retrace_info;
2310
        break;
2311

    
2312
    case VGA_RETRACE_PRECISE:
2313
        s->retrace = vga_precise_retrace;
2314
        s->update_retrace_info = vga_precise_update_retrace_info;
2315
        break;
2316
    }
2317
    vga_reset(s);
2318
}
2319

    
2320
/* used by both ISA and PCI */
2321
void vga_init(VGAState *s)
2322
{
2323
    int vga_io_memory;
2324

    
2325
    qemu_register_reset(vga_reset, s);
2326
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2327

    
2328
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2329

    
2330
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2331
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2332
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2333
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2334

    
2335
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2336

    
2337
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2338
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2339
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2340
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2341
    s->bank_offset = 0;
2342

    
2343
#ifdef CONFIG_BOCHS_VBE
2344
#if defined (TARGET_I386)
2345
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2346
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2347

    
2348
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2349
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2350

    
2351
    /* old Bochs IO ports */
2352
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2353
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2354

    
2355
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2356
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2357
#else
2358
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2359
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2360

    
2361
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2362
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2363
#endif
2364
#endif /* CONFIG_BOCHS_VBE */
2365

    
2366
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2367
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2368
                                 vga_io_memory);
2369
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2370
}
2371

    
2372
/* Memory mapped interface */
2373
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2374
{
2375
    VGAState *s = opaque;
2376

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

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

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

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

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

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

    
2400
    vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2401
}
2402

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

    
2407
    return vga_ioport_read(s, addr >> s->it_shift);
2408
}
2409

    
2410
static void vga_mm_writel (void *opaque,
2411
                           target_phys_addr_t addr, uint32_t value)
2412
{
2413
    VGAState *s = opaque;
2414

    
2415
    vga_ioport_write(s, addr >> s->it_shift, value);
2416
}
2417

    
2418
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2419
    &vga_mm_readb,
2420
    &vga_mm_readw,
2421
    &vga_mm_readl,
2422
};
2423

    
2424
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2425
    &vga_mm_writeb,
2426
    &vga_mm_writew,
2427
    &vga_mm_writel,
2428
};
2429

    
2430
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2431
                        target_phys_addr_t ctrl_base, int it_shift)
2432
{
2433
    int s_ioport_ctrl, vga_io_memory;
2434

    
2435
    s->it_shift = it_shift;
2436
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2437
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2438

    
2439
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2440

    
2441
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2442
    s->bank_offset = 0;
2443
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2444
    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2445
}
2446

    
2447
int isa_vga_init(int vga_ram_size)
2448
{
2449
    VGAState *s;
2450

    
2451
    s = qemu_mallocz(sizeof(VGAState));
2452

    
2453
    vga_common_init(s, vga_ram_size);
2454
    vga_init(s);
2455

    
2456
    s->ds = graphic_console_init(s->update, s->invalidate,
2457
                                 s->screen_dump, s->text_update, s);
2458

    
2459
#ifdef CONFIG_BOCHS_VBE
2460
    /* XXX: use optimized standard vga accesses */
2461
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2462
                                 vga_ram_size, s->vram_offset);
2463
#endif
2464
    return 0;
2465
}
2466

    
2467
int isa_vga_mm_init(int vga_ram_size, target_phys_addr_t vram_base,
2468
                    target_phys_addr_t ctrl_base, int it_shift)
2469
{
2470
    VGAState *s;
2471

    
2472
    s = qemu_mallocz(sizeof(VGAState));
2473

    
2474
    vga_common_init(s, vga_ram_size);
2475
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
2476

    
2477
    s->ds = graphic_console_init(s->update, s->invalidate,
2478
                                 s->screen_dump, s->text_update, s);
2479

    
2480
#ifdef CONFIG_BOCHS_VBE
2481
    /* XXX: use optimized standard vga accesses */
2482
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2483
                                 vga_ram_size, s->vram_offset);
2484
#endif
2485
    return 0;
2486
}
2487

    
2488
static void pci_vga_write_config(PCIDevice *d,
2489
                                 uint32_t address, uint32_t val, int len)
2490
{
2491
    PCIVGAState *pvs = container_of(d, PCIVGAState, dev);
2492
    VGAState *s = &pvs->vga_state;
2493

    
2494
    vga_dirty_log_stop(s);
2495
    pci_default_write_config(d, address, val, len);
2496
    vga_dirty_log_start(s);
2497
}
2498

    
2499
int pci_vga_init(PCIBus *bus, int vga_ram_size,
2500
                 unsigned long vga_bios_offset, int vga_bios_size)
2501
{
2502
    PCIVGAState *d;
2503
    VGAState *s;
2504
    uint8_t *pci_conf;
2505

    
2506
    d = (PCIVGAState *)pci_register_device(bus, "VGA",
2507
                                           sizeof(PCIVGAState),
2508
                                           -1, NULL, pci_vga_write_config);
2509
    if (!d)
2510
        return -1;
2511
    s = &d->vga_state;
2512

    
2513
    vga_common_init(s, vga_ram_size);
2514
    vga_init(s);
2515

    
2516
    s->ds = graphic_console_init(s->update, s->invalidate,
2517
                                 s->screen_dump, s->text_update, s);
2518

    
2519
    s->pci_dev = &d->dev;
2520

    
2521
    pci_conf = d->dev.config;
2522
    // dummy VGA (same as Bochs ID)
2523
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_QEMU);
2524
    pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_QEMU_VGA);
2525
    pci_config_set_class(pci_conf, PCI_CLASS_DISPLAY_VGA);
2526
    pci_conf[0x0e] = 0x00; // header_type
2527

    
2528
    /* XXX: vga_ram_size must be a power of two */
2529
    pci_register_io_region(&d->dev, 0, vga_ram_size,
2530
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2531
    if (vga_bios_size != 0) {
2532
        unsigned int bios_total_size;
2533
        s->bios_offset = vga_bios_offset;
2534
        s->bios_size = vga_bios_size;
2535
        /* must be a power of two */
2536
        bios_total_size = 1;
2537
        while (bios_total_size < vga_bios_size)
2538
            bios_total_size <<= 1;
2539
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2540
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2541
    }
2542
    return 0;
2543
}
2544

    
2545
/********************************************************/
2546
/* vga screen dump */
2547

    
2548
static void vga_save_dpy_update(DisplayState *s,
2549
                                int x, int y, int w, int h)
2550
{
2551
}
2552

    
2553
static void vga_save_dpy_resize(DisplayState *s)
2554
{
2555
}
2556

    
2557
static void vga_save_dpy_refresh(DisplayState *s)
2558
{
2559
}
2560

    
2561
int ppm_save(const char *filename, struct DisplaySurface *ds)
2562
{
2563
    FILE *f;
2564
    uint8_t *d, *d1;
2565
    uint32_t v;
2566
    int y, x;
2567
    uint8_t r, g, b;
2568

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

    
2599
static void vga_screen_dump_blank(VGAState *s, const char *filename)
2600
{
2601
    FILE *f;
2602
    unsigned int y, x, w, h;
2603

    
2604
    w = s->last_scr_width * sizeof(uint32_t);
2605
    h = s->last_scr_height;
2606

    
2607
    f = fopen(filename, "wb");
2608
    if (!f)
2609
        return;
2610
    fprintf(f, "P6\n%d %d\n%d\n", w, h, 255);
2611
    for (y = 0; y < h; y++) {
2612
        for (x = 0; x < w; x++) {
2613
            fputc(0, f);
2614
        }
2615
    }
2616
    fclose(f);
2617
}
2618

    
2619
static void vga_screen_dump_common(VGAState *s, const char *filename,
2620
                                   int w, int h)
2621
{
2622
    DisplayState *saved_ds, ds1, *ds = &ds1;
2623
    DisplayChangeListener dcl;
2624

    
2625
    /* XXX: this is a little hackish */
2626
    vga_invalidate_display(s);
2627
    saved_ds = s->ds;
2628

    
2629
    memset(ds, 0, sizeof(DisplayState));
2630
    memset(&dcl, 0, sizeof(DisplayChangeListener));
2631
    dcl.dpy_update = vga_save_dpy_update;
2632
    dcl.dpy_resize = vga_save_dpy_resize;
2633
    dcl.dpy_refresh = vga_save_dpy_refresh;
2634
    register_displaychangelistener(ds, &dcl);
2635
    ds->allocator = &default_allocator;
2636
    ds->surface = qemu_create_displaysurface(ds, w, h);
2637

    
2638
    s->ds = ds;
2639
    s->graphic_mode = -1;
2640
    vga_update_display(s);
2641

    
2642
    ppm_save(filename, ds->surface);
2643

    
2644
    qemu_free_displaysurface(ds);
2645
    s->ds = saved_ds;
2646
}
2647

    
2648
static void vga_screen_dump_graphic(VGAState *s, const char *filename)
2649
{
2650
    int w, h;
2651

    
2652
    s->get_resolution(s, &w, &h);
2653
    vga_screen_dump_common(s, filename, w, h);
2654
}
2655

    
2656
static void vga_screen_dump_text(VGAState *s, const char *filename)
2657
{
2658
    int w, h, cwidth, cheight;
2659

    
2660
    vga_get_text_resolution(s, &w, &h, &cwidth, &cheight);
2661
    vga_screen_dump_common(s, filename, w * cwidth, h * cheight);
2662
}
2663

    
2664
/* save the vga display in a PPM image even if no display is
2665
   available */
2666
static void vga_screen_dump(void *opaque, const char *filename)
2667
{
2668
    VGAState *s = (VGAState *)opaque;
2669

    
2670
    if (!(s->ar_index & 0x20))
2671
        vga_screen_dump_blank(s, filename);
2672
    else if (s->gr[6] & 1)
2673
        vga_screen_dump_graphic(s, filename);
2674
    else
2675
        vga_screen_dump_text(s, filename);
2676
    vga_invalidate_display(s);
2677
}