Statistics
| Branch: | Revision:

root / hw / vga.c @ f65ed4c1

History | View | Annotate | Download (70.6 kB)

1
/*
2
 * QEMU VGA Emulator.
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "console.h"
26
#include "pc.h"
27
#include "pci.h"
28
#include "vga_int.h"
29
#include "pixel_ops.h"
30
#include "qemu-timer.h"
31
#include "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
    (uint8_t)~0xfc,
42
    (uint8_t)~0xc2,
43
    (uint8_t)~0xf0,
44
    (uint8_t)~0xc0,
45
    (uint8_t)~0xf1,
46
    (uint8_t)~0xff,
47
    (uint8_t)~0xff,
48
    (uint8_t)~0x00,
49
};
50

    
51
const uint8_t gr_mask[16] = {
52
    (uint8_t)~0xf0, /* 0x00 */
53
    (uint8_t)~0xf0, /* 0x01 */
54
    (uint8_t)~0xf0, /* 0x02 */
55
    (uint8_t)~0xe0, /* 0x03 */
56
    (uint8_t)~0xfc, /* 0x04 */
57
    (uint8_t)~0x84, /* 0x05 */
58
    (uint8_t)~0xf0, /* 0x06 */
59
    (uint8_t)~0xf0, /* 0x07 */
60
    (uint8_t)~0x00, /* 0x08 */
61
    (uint8_t)~0xff, /* 0x09 */
62
    (uint8_t)~0xff, /* 0x0a */
63
    (uint8_t)~0xff, /* 0x0b */
64
    (uint8_t)~0xff, /* 0x0c */
65
    (uint8_t)~0xff, /* 0x0d */
66
    (uint8_t)~0xff, /* 0x0e */
67
    (uint8_t)~0xff, /* 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
        if (s->bgr)
1161
            return 5;
1162
        else
1163
            return 1;
1164
    case 16:
1165
        if (s->bgr)
1166
            return 6;
1167
        else
1168
            return 2;
1169
    case 32:
1170
        if (s->bgr)
1171
            return 4;
1172
        else
1173
            return 3;
1174
    }
1175
}
1176

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

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

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

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

    
1226
/*
1227
 * Text mode update
1228
 * Missing:
1229
 * - double scan
1230
 * - double width
1231
 * - underline
1232
 * - flashing
1233
 */
1234
static void vga_draw_text(VGAState *s, int full_update)
1235
{
1236
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1237
    int cx_min, cx_max, linesize, x_incr;
1238
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1239
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1240
    const uint8_t *font_ptr, *font_base[2];
1241
    int dup9, line_offset, depth_index;
1242
    uint32_t *palette;
1243
    uint32_t *ch_attr_ptr;
1244
    vga_draw_glyph8_func *vga_draw_glyph8;
1245
    vga_draw_glyph9_func *vga_draw_glyph9;
1246

    
1247
    vga_dirty_log_stop(s);
1248

    
1249
    full_update |= update_palette16(s);
1250
    palette = s->last_palette;
1251

    
1252
    /* compute font data address (in plane 2) */
1253
    v = s->sr[3];
1254
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1255
    if (offset != s->font_offsets[0]) {
1256
        s->font_offsets[0] = offset;
1257
        full_update = 1;
1258
    }
1259
    font_base[0] = s->vram_ptr + offset;
1260

    
1261
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1262
    font_base[1] = s->vram_ptr + offset;
1263
    if (offset != s->font_offsets[1]) {
1264
        s->font_offsets[1] = offset;
1265
        full_update = 1;
1266
    }
1267
    if (s->plane_updated & (1 << 2)) {
1268
        /* if the plane 2 was modified since the last display, it
1269
           indicates the font may have been modified */
1270
        s->plane_updated = 0;
1271
        full_update = 1;
1272
    }
1273
    full_update |= update_basic_params(s);
1274

    
1275
    line_offset = s->line_offset;
1276
    s1 = s->vram_ptr + (s->start_addr * 4);
1277

    
1278
    /* total width & height */
1279
    cheight = (s->cr[9] & 0x1f) + 1;
1280
    cw = 8;
1281
    if (!(s->sr[1] & 0x01))
1282
        cw = 9;
1283
    if (s->sr[1] & 0x08)
1284
        cw = 16; /* NOTE: no 18 pixel wide */
1285
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1286
    width = (s->cr[0x01] + 1);
1287
    if (s->cr[0x06] == 100) {
1288
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1289
        height = 100;
1290
    } else {
1291
        height = s->cr[0x12] |
1292
            ((s->cr[0x07] & 0x02) << 7) |
1293
            ((s->cr[0x07] & 0x40) << 3);
1294
        height = (height + 1) / cheight;
1295
    }
1296
    if ((height * width) > CH_ATTR_SIZE) {
1297
        /* better than nothing: exit if transient size is too big */
1298
        return;
1299
    }
1300

    
1301
    if (width != s->last_width || height != s->last_height ||
1302
        cw != s->last_cw || cheight != s->last_ch) {
1303
        s->last_scr_width = width * cw;
1304
        s->last_scr_height = height * cheight;
1305
        qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
1306
        s->last_width = width;
1307
        s->last_height = height;
1308
        s->last_ch = cheight;
1309
        s->last_cw = cw;
1310
        full_update = 1;
1311
    }
1312
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1313
    if (cursor_offset != s->cursor_offset ||
1314
        s->cr[0xa] != s->cursor_start ||
1315
        s->cr[0xb] != s->cursor_end) {
1316
      /* if the cursor position changed, we update the old and new
1317
         chars */
1318
        if (s->cursor_offset < CH_ATTR_SIZE)
1319
            s->last_ch_attr[s->cursor_offset] = -1;
1320
        if (cursor_offset < CH_ATTR_SIZE)
1321
            s->last_ch_attr[cursor_offset] = -1;
1322
        s->cursor_offset = cursor_offset;
1323
        s->cursor_start = s->cr[0xa];
1324
        s->cursor_end = s->cr[0xb];
1325
    }
1326
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1327

    
1328
    depth_index = get_depth_index(s->ds);
1329
    if (cw == 16)
1330
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1331
    else
1332
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1333
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1334

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

    
1407
enum {
1408
    VGA_DRAW_LINE2,
1409
    VGA_DRAW_LINE2D2,
1410
    VGA_DRAW_LINE4,
1411
    VGA_DRAW_LINE4D2,
1412
    VGA_DRAW_LINE8D2,
1413
    VGA_DRAW_LINE8,
1414
    VGA_DRAW_LINE15,
1415
    VGA_DRAW_LINE16,
1416
    VGA_DRAW_LINE24,
1417
    VGA_DRAW_LINE32,
1418
    VGA_DRAW_LINE_NB,
1419
};
1420

    
1421
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1422
    vga_draw_line2_8,
1423
    vga_draw_line2_16,
1424
    vga_draw_line2_16,
1425
    vga_draw_line2_32,
1426
    vga_draw_line2_32,
1427
    vga_draw_line2_16,
1428
    vga_draw_line2_16,
1429

    
1430
    vga_draw_line2d2_8,
1431
    vga_draw_line2d2_16,
1432
    vga_draw_line2d2_16,
1433
    vga_draw_line2d2_32,
1434
    vga_draw_line2d2_32,
1435
    vga_draw_line2d2_16,
1436
    vga_draw_line2d2_16,
1437

    
1438
    vga_draw_line4_8,
1439
    vga_draw_line4_16,
1440
    vga_draw_line4_16,
1441
    vga_draw_line4_32,
1442
    vga_draw_line4_32,
1443
    vga_draw_line4_16,
1444
    vga_draw_line4_16,
1445

    
1446
    vga_draw_line4d2_8,
1447
    vga_draw_line4d2_16,
1448
    vga_draw_line4d2_16,
1449
    vga_draw_line4d2_32,
1450
    vga_draw_line4d2_32,
1451
    vga_draw_line4d2_16,
1452
    vga_draw_line4d2_16,
1453

    
1454
    vga_draw_line8d2_8,
1455
    vga_draw_line8d2_16,
1456
    vga_draw_line8d2_16,
1457
    vga_draw_line8d2_32,
1458
    vga_draw_line8d2_32,
1459
    vga_draw_line8d2_16,
1460
    vga_draw_line8d2_16,
1461

    
1462
    vga_draw_line8_8,
1463
    vga_draw_line8_16,
1464
    vga_draw_line8_16,
1465
    vga_draw_line8_32,
1466
    vga_draw_line8_32,
1467
    vga_draw_line8_16,
1468
    vga_draw_line8_16,
1469

    
1470
    vga_draw_line15_8,
1471
    vga_draw_line15_15,
1472
    vga_draw_line15_16,
1473
    vga_draw_line15_32,
1474
    vga_draw_line15_32bgr,
1475
    vga_draw_line15_15bgr,
1476
    vga_draw_line15_16bgr,
1477

    
1478
    vga_draw_line16_8,
1479
    vga_draw_line16_15,
1480
    vga_draw_line16_16,
1481
    vga_draw_line16_32,
1482
    vga_draw_line16_32bgr,
1483
    vga_draw_line16_15bgr,
1484
    vga_draw_line16_16bgr,
1485

    
1486
    vga_draw_line24_8,
1487
    vga_draw_line24_15,
1488
    vga_draw_line24_16,
1489
    vga_draw_line24_32,
1490
    vga_draw_line24_32bgr,
1491
    vga_draw_line24_15bgr,
1492
    vga_draw_line24_16bgr,
1493

    
1494
    vga_draw_line32_8,
1495
    vga_draw_line32_15,
1496
    vga_draw_line32_16,
1497
    vga_draw_line32_32,
1498
    vga_draw_line32_32bgr,
1499
    vga_draw_line32_15bgr,
1500
    vga_draw_line32_16bgr,
1501
};
1502

    
1503
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1504

    
1505
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1506
    rgb_to_pixel8_dup,
1507
    rgb_to_pixel15_dup,
1508
    rgb_to_pixel16_dup,
1509
    rgb_to_pixel32_dup,
1510
    rgb_to_pixel32bgr_dup,
1511
    rgb_to_pixel15bgr_dup,
1512
    rgb_to_pixel16bgr_dup,
1513
};
1514

    
1515
static int vga_get_bpp(VGAState *s)
1516
{
1517
    int ret;
1518
#ifdef CONFIG_BOCHS_VBE
1519
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1520
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1521
    } else
1522
#endif
1523
    {
1524
        ret = 0;
1525
    }
1526
    return ret;
1527
}
1528

    
1529
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1530
{
1531
    int width, height;
1532

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

    
1550
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1551
{
1552
    int y;
1553
    if (y1 >= VGA_MAX_HEIGHT)
1554
        return;
1555
    if (y2 >= VGA_MAX_HEIGHT)
1556
        y2 = VGA_MAX_HEIGHT;
1557
    for(y = y1; y < y2; y++) {
1558
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1559
    }
1560
}
1561

    
1562
static void vga_sync_dirty_bitmap(VGAState *s)
1563
{
1564
    if (s->map_addr)
1565
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1566

    
1567
    if (s->lfb_vram_mapped) {
1568
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1569
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1570
    }
1571
    vga_dirty_log_start(s);
1572
}
1573

    
1574
/*
1575
 * graphic modes
1576
 */
1577
static void vga_draw_graphic(VGAState *s, int full_update)
1578
{
1579
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1580
    int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1581
    int disp_width, multi_scan, multi_run;
1582
    uint8_t *d;
1583
    uint32_t v, addr1, addr;
1584
    vga_draw_line_func *vga_draw_line;
1585

    
1586
    full_update |= update_basic_params(s);
1587

    
1588
    if (!full_update)
1589
        vga_sync_dirty_bitmap(s);
1590

    
1591
    s->get_resolution(s, &width, &height);
1592
    disp_width = width;
1593

    
1594
    shift_control = (s->gr[0x05] >> 5) & 3;
1595
    double_scan = (s->cr[0x09] >> 7);
1596
    if (shift_control != 1) {
1597
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1598
    } else {
1599
        /* in CGA modes, multi_scan is ignored */
1600
        /* XXX: is it correct ? */
1601
        multi_scan = double_scan;
1602
    }
1603
    multi_run = multi_scan;
1604
    if (shift_control != s->shift_control ||
1605
        double_scan != s->double_scan) {
1606
        full_update = 1;
1607
        s->shift_control = shift_control;
1608
        s->double_scan = double_scan;
1609
    }
1610

    
1611
    if (shift_control == 0) {
1612
        full_update |= update_palette16(s);
1613
        if (s->sr[0x01] & 8) {
1614
            v = VGA_DRAW_LINE4D2;
1615
            disp_width <<= 1;
1616
        } else {
1617
            v = VGA_DRAW_LINE4;
1618
        }
1619
        bits = 4;
1620
    } else if (shift_control == 1) {
1621
        full_update |= update_palette16(s);
1622
        if (s->sr[0x01] & 8) {
1623
            v = VGA_DRAW_LINE2D2;
1624
            disp_width <<= 1;
1625
        } else {
1626
            v = VGA_DRAW_LINE2;
1627
        }
1628
        bits = 4;
1629
    } else {
1630
        switch(s->get_bpp(s)) {
1631
        default:
1632
        case 0:
1633
            full_update |= update_palette256(s);
1634
            v = VGA_DRAW_LINE8D2;
1635
            bits = 4;
1636
            break;
1637
        case 8:
1638
            full_update |= update_palette256(s);
1639
            v = VGA_DRAW_LINE8;
1640
            bits = 8;
1641
            break;
1642
        case 15:
1643
            v = VGA_DRAW_LINE15;
1644
            bits = 16;
1645
            break;
1646
        case 16:
1647
            v = VGA_DRAW_LINE16;
1648
            bits = 16;
1649
            break;
1650
        case 24:
1651
            v = VGA_DRAW_LINE24;
1652
            bits = 24;
1653
            break;
1654
        case 32:
1655
            v = VGA_DRAW_LINE32;
1656
            bits = 32;
1657
            break;
1658
        }
1659
    }
1660
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1661

    
1662
    if (disp_width != s->last_width ||
1663
        height != s->last_height) {
1664
        qemu_console_resize(s->console, disp_width, height);
1665
        s->last_scr_width = disp_width;
1666
        s->last_scr_height = height;
1667
        s->last_width = disp_width;
1668
        s->last_height = height;
1669
        full_update = 1;
1670
    }
1671
    if (s->cursor_invalidate)
1672
        s->cursor_invalidate(s);
1673

    
1674
    line_offset = s->line_offset;
1675
#if 0
1676
    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",
1677
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1678
#endif
1679
    addr1 = (s->start_addr * 4);
1680
    bwidth = (width * bits + 7) / 8;
1681
    y_start = -1;
1682
    page_min = 0x7fffffff;
1683
    page_max = -1;
1684
    d = ds_get_data(s->ds);
1685
    linesize = ds_get_linesize(s->ds);
1686
    y1 = 0;
1687
    for(y = 0; y < height; y++) {
1688
        addr = addr1;
1689
        if (!(s->cr[0x17] & 1)) {
1690
            int shift;
1691
            /* CGA compatibility handling */
1692
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1693
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1694
        }
1695
        if (!(s->cr[0x17] & 2)) {
1696
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1697
        }
1698
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1699
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1700
        update = full_update |
1701
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1702
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1703
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1704
            /* if wide line, can use another page */
1705
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1706
                                                    VGA_DIRTY_FLAG);
1707
        }
1708
        /* explicit invalidation for the hardware cursor */
1709
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1710
        if (update) {
1711
            if (y_start < 0)
1712
                y_start = y;
1713
            if (page0 < page_min)
1714
                page_min = page0;
1715
            if (page1 > page_max)
1716
                page_max = page1;
1717
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1718
            if (s->cursor_draw_line)
1719
                s->cursor_draw_line(s, d, y);
1720
        } else {
1721
            if (y_start >= 0) {
1722
                /* flush to display */
1723
                dpy_update(s->ds, 0, y_start,
1724
                           disp_width, y - y_start);
1725
                y_start = -1;
1726
            }
1727
        }
1728
        if (!multi_run) {
1729
            mask = (s->cr[0x17] & 3) ^ 3;
1730
            if ((y1 & mask) == mask)
1731
                addr1 += line_offset;
1732
            y1++;
1733
            multi_run = multi_scan;
1734
        } else {
1735
            multi_run--;
1736
        }
1737
        /* line compare acts on the displayed lines */
1738
        if (y == s->line_compare)
1739
            addr1 = 0;
1740
        d += linesize;
1741
    }
1742
    if (y_start >= 0) {
1743
        /* flush to display */
1744
        dpy_update(s->ds, 0, y_start,
1745
                   disp_width, y - y_start);
1746
    }
1747
    /* reset modified pages */
1748
    if (page_max != -1) {
1749
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1750
                                        VGA_DIRTY_FLAG);
1751
    }
1752
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1753
}
1754

    
1755
static void vga_draw_blank(VGAState *s, int full_update)
1756
{
1757
    int i, w, val;
1758
    uint8_t *d;
1759

    
1760
    if (!full_update)
1761
        return;
1762
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1763
        return;
1764
    vga_dirty_log_stop(s);
1765

    
1766
    if (ds_get_bits_per_pixel(s->ds) == 8)
1767
        val = s->rgb_to_pixel(0, 0, 0);
1768
    else
1769
        val = 0;
1770
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1771
    d = ds_get_data(s->ds);
1772
    for(i = 0; i < s->last_scr_height; i++) {
1773
        memset(d, val, w);
1774
        d += ds_get_linesize(s->ds);
1775
    }
1776
    dpy_update(s->ds, 0, 0,
1777
               s->last_scr_width, s->last_scr_height);
1778
}
1779

    
1780
#define GMODE_TEXT     0
1781
#define GMODE_GRAPH    1
1782
#define GMODE_BLANK 2
1783

    
1784
static void vga_update_display(void *opaque)
1785
{
1786
    VGAState *s = (VGAState *)opaque;
1787
    int full_update, graphic_mode;
1788

    
1789
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1790
        /* nothing to do */
1791
    } else {
1792
        s->rgb_to_pixel =
1793
            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1794

    
1795
        full_update = 0;
1796
        if (!(s->ar_index & 0x20)) {
1797
            graphic_mode = GMODE_BLANK;
1798
        } else {
1799
            graphic_mode = s->gr[6] & 1;
1800
        }
1801
        if (graphic_mode != s->graphic_mode) {
1802
            s->graphic_mode = graphic_mode;
1803
            full_update = 1;
1804
        }
1805
        switch(graphic_mode) {
1806
        case GMODE_TEXT:
1807
            vga_draw_text(s, full_update);
1808
            break;
1809
        case GMODE_GRAPH:
1810
            vga_draw_graphic(s, full_update);
1811
            break;
1812
        case GMODE_BLANK:
1813
        default:
1814
            vga_draw_blank(s, full_update);
1815
            break;
1816
        }
1817
    }
1818
}
1819

    
1820
/* force a full display refresh */
1821
static void vga_invalidate_display(void *opaque)
1822
{
1823
    VGAState *s = (VGAState *)opaque;
1824

    
1825
    s->last_width = -1;
1826
    s->last_height = -1;
1827
}
1828

    
1829
static void vga_reset(VGAState *s)
1830
{
1831
    memset(s, 0, sizeof(VGAState));
1832
    s->graphic_mode = -1; /* force full update */
1833
}
1834

    
1835
#define TEXTMODE_X(x)        ((x) % width)
1836
#define TEXTMODE_Y(x)        ((x) / width)
1837
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1838
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1839
/* relay text rendering to the display driver
1840
 * instead of doing a full vga_update_display() */
1841
static void vga_update_text(void *opaque, console_ch_t *chardata)
1842
{
1843
    VGAState *s = (VGAState *) opaque;
1844
    int graphic_mode, i, cursor_offset, cursor_visible;
1845
    int cw, cheight, width, height, size, c_min, c_max;
1846
    uint32_t *src;
1847
    console_ch_t *dst, val;
1848
    char msg_buffer[80];
1849
    int full_update = 0;
1850

    
1851
    if (!(s->ar_index & 0x20)) {
1852
        graphic_mode = GMODE_BLANK;
1853
    } else {
1854
        graphic_mode = s->gr[6] & 1;
1855
    }
1856
    if (graphic_mode != s->graphic_mode) {
1857
        s->graphic_mode = graphic_mode;
1858
        full_update = 1;
1859
    }
1860
    if (s->last_width == -1) {
1861
        s->last_width = 0;
1862
        full_update = 1;
1863
    }
1864

    
1865
    switch (graphic_mode) {
1866
    case GMODE_TEXT:
1867
        /* TODO: update palette */
1868
        full_update |= update_basic_params(s);
1869

    
1870
        /* total width & height */
1871
        cheight = (s->cr[9] & 0x1f) + 1;
1872
        cw = 8;
1873
        if (!(s->sr[1] & 0x01))
1874
            cw = 9;
1875
        if (s->sr[1] & 0x08)
1876
            cw = 16; /* NOTE: no 18 pixel wide */
1877
        width = (s->cr[0x01] + 1);
1878
        if (s->cr[0x06] == 100) {
1879
            /* ugly hack for CGA 160x100x16 - explain me the logic */
1880
            height = 100;
1881
        } else {
1882
            height = s->cr[0x12] | 
1883
                ((s->cr[0x07] & 0x02) << 7) | 
1884
                ((s->cr[0x07] & 0x40) << 3);
1885
            height = (height + 1) / cheight;
1886
        }
1887

    
1888
        size = (height * width);
1889
        if (size > CH_ATTR_SIZE) {
1890
            if (!full_update)
1891
                return;
1892

    
1893
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1894
                     width, height);
1895
            break;
1896
        }
1897

    
1898
        if (width != s->last_width || height != s->last_height ||
1899
            cw != s->last_cw || cheight != s->last_ch) {
1900
            s->last_scr_width = width * cw;
1901
            s->last_scr_height = height * cheight;
1902
            qemu_console_resize(s->console, width, height);
1903
            s->last_width = width;
1904
            s->last_height = height;
1905
            s->last_ch = cheight;
1906
            s->last_cw = cw;
1907
            full_update = 1;
1908
        }
1909

    
1910
        /* Update "hardware" cursor */
1911
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1912
        if (cursor_offset != s->cursor_offset ||
1913
            s->cr[0xa] != s->cursor_start ||
1914
            s->cr[0xb] != s->cursor_end || full_update) {
1915
            cursor_visible = !(s->cr[0xa] & 0x20);
1916
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1917
                dpy_cursor(s->ds,
1918
                           TEXTMODE_X(cursor_offset),
1919
                           TEXTMODE_Y(cursor_offset));
1920
            else
1921
                dpy_cursor(s->ds, -1, -1);
1922
            s->cursor_offset = cursor_offset;
1923
            s->cursor_start = s->cr[0xa];
1924
            s->cursor_end = s->cr[0xb];
1925
        }
1926

    
1927
        src = (uint32_t *) s->vram_ptr + s->start_addr;
1928
        dst = chardata;
1929

    
1930
        if (full_update) {
1931
            for (i = 0; i < size; src ++, dst ++, i ++)
1932
                console_write_ch(dst, VMEM2CHTYPE(*src));
1933

    
1934
            dpy_update(s->ds, 0, 0, width, height);
1935
        } else {
1936
            c_max = 0;
1937

    
1938
            for (i = 0; i < size; src ++, dst ++, i ++) {
1939
                console_write_ch(&val, VMEM2CHTYPE(*src));
1940
                if (*dst != val) {
1941
                    *dst = val;
1942
                    c_max = i;
1943
                    break;
1944
                }
1945
            }
1946
            c_min = i;
1947
            for (; i < size; src ++, dst ++, i ++) {
1948
                console_write_ch(&val, VMEM2CHTYPE(*src));
1949
                if (*dst != val) {
1950
                    *dst = val;
1951
                    c_max = i;
1952
                }
1953
            }
1954

    
1955
            if (c_min <= c_max) {
1956
                i = TEXTMODE_Y(c_min);
1957
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1958
            }
1959
        }
1960

    
1961
        return;
1962
    case GMODE_GRAPH:
1963
        if (!full_update)
1964
            return;
1965

    
1966
        s->get_resolution(s, &width, &height);
1967
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
1968
                 width, height);
1969
        break;
1970
    case GMODE_BLANK:
1971
    default:
1972
        if (!full_update)
1973
            return;
1974

    
1975
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
1976
        break;
1977
    }
1978

    
1979
    /* Display a message */
1980
    s->last_width = 60;
1981
    s->last_height = height = 3;
1982
    dpy_cursor(s->ds, -1, -1);
1983
    qemu_console_resize(s->console, s->last_width, height);
1984

    
1985
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
1986
        console_write_ch(dst ++, ' ');
1987

    
1988
    size = strlen(msg_buffer);
1989
    width = (s->last_width - size) / 2;
1990
    dst = chardata + s->last_width + width;
1991
    for (i = 0; i < size; i ++)
1992
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
1993

    
1994
    dpy_update(s->ds, 0, 0, s->last_width, height);
1995
}
1996

    
1997
static CPUReadMemoryFunc *vga_mem_read[3] = {
1998
    vga_mem_readb,
1999
    vga_mem_readw,
2000
    vga_mem_readl,
2001
};
2002

    
2003
static CPUWriteMemoryFunc *vga_mem_write[3] = {
2004
    vga_mem_writeb,
2005
    vga_mem_writew,
2006
    vga_mem_writel,
2007
};
2008

    
2009
static void vga_save(QEMUFile *f, void *opaque)
2010
{
2011
    VGAState *s = opaque;
2012
    int i;
2013

    
2014
    if (s->pci_dev)
2015
        pci_device_save(s->pci_dev, f);
2016

    
2017
    qemu_put_be32s(f, &s->latch);
2018
    qemu_put_8s(f, &s->sr_index);
2019
    qemu_put_buffer(f, s->sr, 8);
2020
    qemu_put_8s(f, &s->gr_index);
2021
    qemu_put_buffer(f, s->gr, 16);
2022
    qemu_put_8s(f, &s->ar_index);
2023
    qemu_put_buffer(f, s->ar, 21);
2024
    qemu_put_be32(f, s->ar_flip_flop);
2025
    qemu_put_8s(f, &s->cr_index);
2026
    qemu_put_buffer(f, s->cr, 256);
2027
    qemu_put_8s(f, &s->msr);
2028
    qemu_put_8s(f, &s->fcr);
2029
    qemu_put_byte(f, s->st00);
2030
    qemu_put_8s(f, &s->st01);
2031

    
2032
    qemu_put_8s(f, &s->dac_state);
2033
    qemu_put_8s(f, &s->dac_sub_index);
2034
    qemu_put_8s(f, &s->dac_read_index);
2035
    qemu_put_8s(f, &s->dac_write_index);
2036
    qemu_put_buffer(f, s->dac_cache, 3);
2037
    qemu_put_buffer(f, s->palette, 768);
2038

    
2039
    qemu_put_be32(f, s->bank_offset);
2040
#ifdef CONFIG_BOCHS_VBE
2041
    qemu_put_byte(f, 1);
2042
    qemu_put_be16s(f, &s->vbe_index);
2043
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2044
        qemu_put_be16s(f, &s->vbe_regs[i]);
2045
    qemu_put_be32s(f, &s->vbe_start_addr);
2046
    qemu_put_be32s(f, &s->vbe_line_offset);
2047
    qemu_put_be32s(f, &s->vbe_bank_mask);
2048
#else
2049
    qemu_put_byte(f, 0);
2050
#endif
2051
}
2052

    
2053
static int vga_load(QEMUFile *f, void *opaque, int version_id)
2054
{
2055
    VGAState *s = opaque;
2056
    int is_vbe, i, ret;
2057

    
2058
    if (version_id > 2)
2059
        return -EINVAL;
2060

    
2061
    if (s->pci_dev && version_id >= 2) {
2062
        ret = pci_device_load(s->pci_dev, f);
2063
        if (ret < 0)
2064
            return ret;
2065
    }
2066

    
2067
    qemu_get_be32s(f, &s->latch);
2068
    qemu_get_8s(f, &s->sr_index);
2069
    qemu_get_buffer(f, s->sr, 8);
2070
    qemu_get_8s(f, &s->gr_index);
2071
    qemu_get_buffer(f, s->gr, 16);
2072
    qemu_get_8s(f, &s->ar_index);
2073
    qemu_get_buffer(f, s->ar, 21);
2074
    s->ar_flip_flop=qemu_get_be32(f);
2075
    qemu_get_8s(f, &s->cr_index);
2076
    qemu_get_buffer(f, s->cr, 256);
2077
    qemu_get_8s(f, &s->msr);
2078
    qemu_get_8s(f, &s->fcr);
2079
    qemu_get_8s(f, &s->st00);
2080
    qemu_get_8s(f, &s->st01);
2081

    
2082
    qemu_get_8s(f, &s->dac_state);
2083
    qemu_get_8s(f, &s->dac_sub_index);
2084
    qemu_get_8s(f, &s->dac_read_index);
2085
    qemu_get_8s(f, &s->dac_write_index);
2086
    qemu_get_buffer(f, s->dac_cache, 3);
2087
    qemu_get_buffer(f, s->palette, 768);
2088

    
2089
    s->bank_offset=qemu_get_be32(f);
2090
    is_vbe = qemu_get_byte(f);
2091
#ifdef CONFIG_BOCHS_VBE
2092
    if (!is_vbe)
2093
        return -EINVAL;
2094
    qemu_get_be16s(f, &s->vbe_index);
2095
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2096
        qemu_get_be16s(f, &s->vbe_regs[i]);
2097
    qemu_get_be32s(f, &s->vbe_start_addr);
2098
    qemu_get_be32s(f, &s->vbe_line_offset);
2099
    qemu_get_be32s(f, &s->vbe_bank_mask);
2100
#else
2101
    if (is_vbe)
2102
        return -EINVAL;
2103
#endif
2104

    
2105
    /* force refresh */
2106
    s->graphic_mode = -1;
2107
    return 0;
2108
}
2109

    
2110
typedef struct PCIVGAState {
2111
    PCIDevice dev;
2112
    VGAState vga_state;
2113
} PCIVGAState;
2114

    
2115
void vga_dirty_log_start(VGAState *s)
2116
{
2117
    if (kvm_enabled() && s->map_addr)
2118
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
2119

    
2120
    if (kvm_enabled() && s->lfb_vram_mapped) {
2121
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
2122
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
2123
    }
2124
}
2125

    
2126
void vga_dirty_log_stop(VGAState *s)
2127
{
2128
    if (kvm_enabled() && s->map_addr)
2129
        kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
2130

    
2131
    if (kvm_enabled() && s->lfb_vram_mapped) {
2132
        kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
2133
        kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
2134
    }
2135
}
2136

    
2137
static void vga_map(PCIDevice *pci_dev, int region_num,
2138
                    uint32_t addr, uint32_t size, int type)
2139
{
2140
    PCIVGAState *d = (PCIVGAState *)pci_dev;
2141
    VGAState *s = &d->vga_state;
2142
    if (region_num == PCI_ROM_SLOT) {
2143
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2144
    } else {
2145
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2146
    }
2147

    
2148
    s->map_addr = addr;
2149
    s->map_end = addr + VGA_RAM_SIZE;
2150

    
2151
    vga_dirty_log_start(s);
2152
}
2153

    
2154
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
2155
                     ram_addr_t vga_ram_offset, int vga_ram_size)
2156
{
2157
    int i, j, v, b;
2158

    
2159
    for(i = 0;i < 256; i++) {
2160
        v = 0;
2161
        for(j = 0; j < 8; j++) {
2162
            v |= ((i >> j) & 1) << (j * 4);
2163
        }
2164
        expand4[i] = v;
2165

    
2166
        v = 0;
2167
        for(j = 0; j < 4; j++) {
2168
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2169
        }
2170
        expand2[i] = v;
2171
    }
2172
    for(i = 0; i < 16; i++) {
2173
        v = 0;
2174
        for(j = 0; j < 4; j++) {
2175
            b = ((i >> j) & 1);
2176
            v |= b << (2 * j);
2177
            v |= b << (2 * j + 1);
2178
        }
2179
        expand4to8[i] = v;
2180
    }
2181

    
2182
    vga_reset(s);
2183

    
2184
    s->vram_ptr = vga_ram_base;
2185
    s->vram_offset = vga_ram_offset;
2186
    s->vram_size = vga_ram_size;
2187
    s->ds = ds;
2188
    s->get_bpp = vga_get_bpp;
2189
    s->get_offsets = vga_get_offsets;
2190
    s->get_resolution = vga_get_resolution;
2191
    s->update = vga_update_display;
2192
    s->invalidate = vga_invalidate_display;
2193
    s->screen_dump = vga_screen_dump;
2194
    s->text_update = vga_update_text;
2195
    switch (vga_retrace_method) {
2196
    case VGA_RETRACE_DUMB:
2197
        s->retrace = vga_dumb_retrace;
2198
        s->update_retrace_info = vga_dumb_update_retrace_info;
2199
        break;
2200

    
2201
    case VGA_RETRACE_PRECISE:
2202
        s->retrace = vga_precise_retrace;
2203
        s->update_retrace_info = vga_precise_update_retrace_info;
2204
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
2205
        break;
2206
    }
2207
}
2208

    
2209
/* used by both ISA and PCI */
2210
void vga_init(VGAState *s)
2211
{
2212
    int vga_io_memory;
2213

    
2214
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2215

    
2216
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2217

    
2218
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2219
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2220
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2221
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2222

    
2223
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2224

    
2225
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2226
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2227
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2228
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2229
    s->bank_offset = 0;
2230

    
2231
#ifdef CONFIG_BOCHS_VBE
2232
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
2233
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
2234
#if defined (TARGET_I386)
2235
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2236
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2237

    
2238
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2239
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2240

    
2241
    /* old Bochs IO ports */
2242
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2243
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2244

    
2245
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2246
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2247
#else
2248
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2249
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2250

    
2251
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2252
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2253
#endif
2254
#endif /* CONFIG_BOCHS_VBE */
2255

    
2256
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2257
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2258
                                 vga_io_memory);
2259
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2260
}
2261

    
2262
/* Memory mapped interface */
2263
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2264
{
2265
    VGAState *s = opaque;
2266

    
2267
    return vga_ioport_read(s, addr >> s->it_shift) & 0xff;
2268
}
2269

    
2270
static void vga_mm_writeb (void *opaque,
2271
                           target_phys_addr_t addr, uint32_t value)
2272
{
2273
    VGAState *s = opaque;
2274

    
2275
    vga_ioport_write(s, addr >> s->it_shift, value & 0xff);
2276
}
2277

    
2278
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2279
{
2280
    VGAState *s = opaque;
2281

    
2282
    return vga_ioport_read(s, addr >> s->it_shift) & 0xffff;
2283
}
2284

    
2285
static void vga_mm_writew (void *opaque,
2286
                           target_phys_addr_t addr, uint32_t value)
2287
{
2288
    VGAState *s = opaque;
2289

    
2290
    vga_ioport_write(s, addr >> s->it_shift, value & 0xffff);
2291
}
2292

    
2293
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2294
{
2295
    VGAState *s = opaque;
2296

    
2297
    return vga_ioport_read(s, addr >> s->it_shift);
2298
}
2299

    
2300
static void vga_mm_writel (void *opaque,
2301
                           target_phys_addr_t addr, uint32_t value)
2302
{
2303
    VGAState *s = opaque;
2304

    
2305
    vga_ioport_write(s, addr >> s->it_shift, value);
2306
}
2307

    
2308
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2309
    &vga_mm_readb,
2310
    &vga_mm_readw,
2311
    &vga_mm_readl,
2312
};
2313

    
2314
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2315
    &vga_mm_writeb,
2316
    &vga_mm_writew,
2317
    &vga_mm_writel,
2318
};
2319

    
2320
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2321
                        target_phys_addr_t ctrl_base, int it_shift)
2322
{
2323
    int s_ioport_ctrl, vga_io_memory;
2324

    
2325
    s->it_shift = it_shift;
2326
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2327
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2328

    
2329
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2330

    
2331
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2332
    s->bank_offset = 0;
2333
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2334
    qemu_register_coalesced_mmio(vram_base + 0x000a0000, 0x20000);
2335
}
2336

    
2337
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2338
                 unsigned long vga_ram_offset, int vga_ram_size)
2339
{
2340
    VGAState *s;
2341

    
2342
    s = qemu_mallocz(sizeof(VGAState));
2343
    if (!s)
2344
        return -1;
2345

    
2346
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2347
    vga_init(s);
2348

    
2349
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2350
                                      s->screen_dump, s->text_update, s);
2351

    
2352
#ifdef CONFIG_BOCHS_VBE
2353
    /* XXX: use optimized standard vga accesses */
2354
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2355
                                 vga_ram_size, vga_ram_offset);
2356
#endif
2357
    return 0;
2358
}
2359

    
2360
int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2361
                    unsigned long vga_ram_offset, int vga_ram_size,
2362
                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2363
                    int it_shift)
2364
{
2365
    VGAState *s;
2366

    
2367
    s = qemu_mallocz(sizeof(VGAState));
2368
    if (!s)
2369
        return -1;
2370

    
2371
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2372
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
2373

    
2374
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2375
                                      s->screen_dump, s->text_update, s);
2376

    
2377
#ifdef CONFIG_BOCHS_VBE
2378
    /* XXX: use optimized standard vga accesses */
2379
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2380
                                 vga_ram_size, vga_ram_offset);
2381
#endif
2382
    return 0;
2383
}
2384

    
2385
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2386
                 unsigned long vga_ram_offset, int vga_ram_size,
2387
                 unsigned long vga_bios_offset, int vga_bios_size)
2388
{
2389
    PCIVGAState *d;
2390
    VGAState *s;
2391
    uint8_t *pci_conf;
2392

    
2393
    d = (PCIVGAState *)pci_register_device(bus, "VGA",
2394
                                           sizeof(PCIVGAState),
2395
                                           -1, NULL, NULL);
2396
    if (!d)
2397
        return -1;
2398
    s = &d->vga_state;
2399

    
2400
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2401
    vga_init(s);
2402

    
2403
    s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2404
                                      s->screen_dump, s->text_update, s);
2405

    
2406
    s->pci_dev = &d->dev;
2407

    
2408
    pci_conf = d->dev.config;
2409
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2410
    pci_conf[0x01] = 0x12;
2411
    pci_conf[0x02] = 0x11;
2412
    pci_conf[0x03] = 0x11;
2413
    pci_conf[0x0a] = 0x00; // VGA controller
2414
    pci_conf[0x0b] = 0x03;
2415
    pci_conf[0x0e] = 0x00; // header_type
2416

    
2417
    /* XXX: vga_ram_size must be a power of two */
2418
    pci_register_io_region(&d->dev, 0, vga_ram_size,
2419
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2420
    if (vga_bios_size != 0) {
2421
        unsigned int bios_total_size;
2422
        s->bios_offset = vga_bios_offset;
2423
        s->bios_size = vga_bios_size;
2424
        /* must be a power of two */
2425
        bios_total_size = 1;
2426
        while (bios_total_size < vga_bios_size)
2427
            bios_total_size <<= 1;
2428
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2429
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2430
    }
2431
    return 0;
2432
}
2433

    
2434
/********************************************************/
2435
/* vga screen dump */
2436

    
2437
static int vga_save_w, vga_save_h;
2438

    
2439
static void vga_save_dpy_update(DisplayState *s,
2440
                                int x, int y, int w, int h)
2441
{
2442
}
2443

    
2444
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2445
{
2446
    s->linesize = w * 4;
2447
    s->data = qemu_mallocz(h * s->linesize);
2448
    vga_save_w = w;
2449
    vga_save_h = h;
2450
}
2451

    
2452
static void vga_save_dpy_refresh(DisplayState *s)
2453
{
2454
}
2455

    
2456
int ppm_save(const char *filename, uint8_t *data,
2457
             int w, int h, int linesize)
2458
{
2459
    FILE *f;
2460
    uint8_t *d, *d1;
2461
    unsigned int v;
2462
    int y, x;
2463

    
2464
    f = fopen(filename, "wb");
2465
    if (!f)
2466
        return -1;
2467
    fprintf(f, "P6\n%d %d\n%d\n",
2468
            w, h, 255);
2469
    d1 = data;
2470
    for(y = 0; y < h; y++) {
2471
        d = d1;
2472
        for(x = 0; x < w; x++) {
2473
            v = *(uint32_t *)d;
2474
            fputc((v >> 16) & 0xff, f);
2475
            fputc((v >> 8) & 0xff, f);
2476
            fputc((v) & 0xff, f);
2477
            d += 4;
2478
        }
2479
        d1 += linesize;
2480
    }
2481
    fclose(f);
2482
    return 0;
2483
}
2484

    
2485
/* save the vga display in a PPM image even if no display is
2486
   available */
2487
static void vga_screen_dump(void *opaque, const char *filename)
2488
{
2489
    VGAState *s = (VGAState *)opaque;
2490
    DisplayState *saved_ds, ds1, *ds = &ds1;
2491

    
2492
    /* XXX: this is a little hackish */
2493
    vga_invalidate_display(s);
2494
    saved_ds = s->ds;
2495

    
2496
    memset(ds, 0, sizeof(DisplayState));
2497
    ds->dpy_update = vga_save_dpy_update;
2498
    ds->dpy_resize = vga_save_dpy_resize;
2499
    ds->dpy_refresh = vga_save_dpy_refresh;
2500
    ds->depth = 32;
2501

    
2502
    s->ds = ds;
2503
    s->graphic_mode = -1;
2504
    vga_update_display(s);
2505

    
2506
    if (ds_get_data(ds)) {
2507
        ppm_save(filename, ds_get_data(ds), vga_save_w, vga_save_h,
2508
                 ds_get_linesize(s->ds));
2509
        qemu_free(ds_get_data(ds));
2510
    }
2511
    s->ds = saved_ds;
2512
}