Statistics
| Branch: | Revision:

root / hw / vga.c @ 87ecb68b

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

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

    
35
//#define DEBUG_BOCHS_VBE
36

    
37
/* force some bits to zero */
38
const uint8_t sr_mask[8] = {
39
    (uint8_t)~0xfc,
40
    (uint8_t)~0xc2,
41
    (uint8_t)~0xf0,
42
    (uint8_t)~0xc0,
43
    (uint8_t)~0xf1,
44
    (uint8_t)~0xff,
45
    (uint8_t)~0xff,
46
    (uint8_t)~0x00,
47
};
48

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

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

    
75
#ifdef WORDS_BIGENDIAN
76
#define PAT(x) cbswap_32(x)
77
#else
78
#define PAT(x) (x)
79
#endif
80

    
81
#ifdef WORDS_BIGENDIAN
82
#define BIG 1
83
#else
84
#define BIG 0
85
#endif
86

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

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

    
112
#undef PAT
113

    
114
#ifdef WORDS_BIGENDIAN
115
#define PAT(x) (x)
116
#else
117
#define PAT(x) cbswap_32(x)
118
#endif
119

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

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

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

    
150
static void vga_screen_dump(void *opaque, const char *filename);
151

    
152
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
153
{
154
    VGAState *s = opaque;
155
    int val, index;
156

    
157
    /* check port range access depending on color/monochrome mode */
158
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
159
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
160
        val = 0xff;
161
    } else {
162
        switch(addr) {
163
        case 0x3c0:
164
            if (s->ar_flip_flop == 0) {
165
                val = s->ar_index;
166
            } else {
167
                val = 0;
168
            }
169
            break;
170
        case 0x3c1:
171
            index = s->ar_index & 0x1f;
172
            if (index < 21)
173
                val = s->ar[index];
174
            else
175
                val = 0;
176
            break;
177
        case 0x3c2:
178
            val = s->st00;
179
            break;
180
        case 0x3c4:
181
            val = s->sr_index;
182
            break;
183
        case 0x3c5:
184
            val = s->sr[s->sr_index];
185
#ifdef DEBUG_VGA_REG
186
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
187
#endif
188
            break;
189
        case 0x3c7:
190
            val = s->dac_state;
191
            break;
192
        case 0x3c8:
193
            val = s->dac_write_index;
194
            break;
195
        case 0x3c9:
196
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
197
            if (++s->dac_sub_index == 3) {
198
                s->dac_sub_index = 0;
199
                s->dac_read_index++;
200
            }
201
            break;
202
        case 0x3ca:
203
            val = s->fcr;
204
            break;
205
        case 0x3cc:
206
            val = s->msr;
207
            break;
208
        case 0x3ce:
209
            val = s->gr_index;
210
            break;
211
        case 0x3cf:
212
            val = s->gr[s->gr_index];
213
#ifdef DEBUG_VGA_REG
214
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
215
#endif
216
            break;
217
        case 0x3b4:
218
        case 0x3d4:
219
            val = s->cr_index;
220
            break;
221
        case 0x3b5:
222
        case 0x3d5:
223
            val = s->cr[s->cr_index];
224
#ifdef DEBUG_VGA_REG
225
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
226
#endif
227
            break;
228
        case 0x3ba:
229
        case 0x3da:
230
            /* just toggle to fool polling */
231
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
232
            val = s->st01;
233
            s->ar_flip_flop = 0;
234
            break;
235
        default:
236
            val = 0x00;
237
            break;
238
        }
239
    }
240
#if defined(DEBUG_VGA)
241
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
242
#endif
243
    return val;
244
}
245

    
246
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
247
{
248
    VGAState *s = opaque;
249
    int index;
250

    
251
    /* check port range access depending on color/monochrome mode */
252
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
253
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
254
        return;
255

    
256
#ifdef DEBUG_VGA
257
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
258
#endif
259

    
260
    switch(addr) {
261
    case 0x3c0:
262
        if (s->ar_flip_flop == 0) {
263
            val &= 0x3f;
264
            s->ar_index = val;
265
        } else {
266
            index = s->ar_index & 0x1f;
267
            switch(index) {
268
            case 0x00 ... 0x0f:
269
                s->ar[index] = val & 0x3f;
270
                break;
271
            case 0x10:
272
                s->ar[index] = val & ~0x10;
273
                break;
274
            case 0x11:
275
                s->ar[index] = val;
276
                break;
277
            case 0x12:
278
                s->ar[index] = val & ~0xc0;
279
                break;
280
            case 0x13:
281
                s->ar[index] = val & ~0xf0;
282
                break;
283
            case 0x14:
284
                s->ar[index] = val & ~0xf0;
285
                break;
286
            default:
287
                break;
288
            }
289
        }
290
        s->ar_flip_flop ^= 1;
291
        break;
292
    case 0x3c2:
293
        s->msr = val & ~0x10;
294
        break;
295
    case 0x3c4:
296
        s->sr_index = val & 7;
297
        break;
298
    case 0x3c5:
299
#ifdef DEBUG_VGA_REG
300
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
301
#endif
302
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
303
        break;
304
    case 0x3c7:
305
        s->dac_read_index = val;
306
        s->dac_sub_index = 0;
307
        s->dac_state = 3;
308
        break;
309
    case 0x3c8:
310
        s->dac_write_index = val;
311
        s->dac_sub_index = 0;
312
        s->dac_state = 0;
313
        break;
314
    case 0x3c9:
315
        s->dac_cache[s->dac_sub_index] = val;
316
        if (++s->dac_sub_index == 3) {
317
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
318
            s->dac_sub_index = 0;
319
            s->dac_write_index++;
320
        }
321
        break;
322
    case 0x3ce:
323
        s->gr_index = val & 0x0f;
324
        break;
325
    case 0x3cf:
326
#ifdef DEBUG_VGA_REG
327
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
328
#endif
329
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
330
        break;
331
    case 0x3b4:
332
    case 0x3d4:
333
        s->cr_index = val;
334
        break;
335
    case 0x3b5:
336
    case 0x3d5:
337
#ifdef DEBUG_VGA_REG
338
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
339
#endif
340
        /* handle CR0-7 protection */
341
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
342
            /* can always write bit 4 of CR7 */
343
            if (s->cr_index == 7)
344
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
345
            return;
346
        }
347
        switch(s->cr_index) {
348
        case 0x01: /* horizontal display end */
349
        case 0x07:
350
        case 0x09:
351
        case 0x0c:
352
        case 0x0d:
353
        case 0x12: /* vertical display end */
354
            s->cr[s->cr_index] = val;
355
            break;
356
        default:
357
            s->cr[s->cr_index] = val;
358
            break;
359
        }
360
        break;
361
    case 0x3ba:
362
    case 0x3da:
363
        s->fcr = val & 0x10;
364
        break;
365
    }
366
}
367

    
368
#ifdef CONFIG_BOCHS_VBE
369
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
370
{
371
    VGAState *s = opaque;
372
    uint32_t val;
373
    val = s->vbe_index;
374
    return val;
375
}
376

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

    
382
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
383
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
384
            switch(s->vbe_index) {
385
                /* XXX: do not hardcode ? */
386
            case VBE_DISPI_INDEX_XRES:
387
                val = VBE_DISPI_MAX_XRES;
388
                break;
389
            case VBE_DISPI_INDEX_YRES:
390
                val = VBE_DISPI_MAX_YRES;
391
                break;
392
            case VBE_DISPI_INDEX_BPP:
393
                val = VBE_DISPI_MAX_BPP;
394
                break;
395
            default:
396
                val = s->vbe_regs[s->vbe_index];
397
                break;
398
            }
399
        } else {
400
            val = s->vbe_regs[s->vbe_index];
401
        }
402
    } else {
403
        val = 0;
404
    }
405
#ifdef DEBUG_BOCHS_VBE
406
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
407
#endif
408
    return val;
409
}
410

    
411
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
412
{
413
    VGAState *s = opaque;
414
    s->vbe_index = val;
415
}
416

    
417
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
418
{
419
    VGAState *s = opaque;
420

    
421
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
422
#ifdef DEBUG_BOCHS_VBE
423
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
424
#endif
425
        switch(s->vbe_index) {
426
        case VBE_DISPI_INDEX_ID:
427
            if (val == VBE_DISPI_ID0 ||
428
                val == VBE_DISPI_ID1 ||
429
                val == VBE_DISPI_ID2 ||
430
                val == VBE_DISPI_ID3 ||
431
                val == VBE_DISPI_ID4) {
432
                s->vbe_regs[s->vbe_index] = val;
433
            }
434
            break;
435
        case VBE_DISPI_INDEX_XRES:
436
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
437
                s->vbe_regs[s->vbe_index] = val;
438
            }
439
            break;
440
        case VBE_DISPI_INDEX_YRES:
441
            if (val <= VBE_DISPI_MAX_YRES) {
442
                s->vbe_regs[s->vbe_index] = val;
443
            }
444
            break;
445
        case VBE_DISPI_INDEX_BPP:
446
            if (val == 0)
447
                val = 8;
448
            if (val == 4 || val == 8 || val == 15 ||
449
                val == 16 || val == 24 || val == 32) {
450
                s->vbe_regs[s->vbe_index] = val;
451
            }
452
            break;
453
        case VBE_DISPI_INDEX_BANK:
454
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
455
              val &= (s->vbe_bank_mask >> 2);
456
            } else {
457
              val &= s->vbe_bank_mask;
458
            }
459
            s->vbe_regs[s->vbe_index] = val;
460
            s->bank_offset = (val << 16);
461
            break;
462
        case VBE_DISPI_INDEX_ENABLE:
463
            if ((val & VBE_DISPI_ENABLED) &&
464
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
465
                int h, shift_control;
466

    
467
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
468
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
469
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
470
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
471
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
472
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
473

    
474
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
475
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
476
                else
477
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
478
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
479
                s->vbe_start_addr = 0;
480

    
481
                /* clear the screen (should be done in BIOS) */
482
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
483
                    memset(s->vram_ptr, 0,
484
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
485
                }
486

    
487
                /* we initialize the VGA graphic mode (should be done
488
                   in BIOS) */
489
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
490
                s->cr[0x17] |= 3; /* no CGA modes */
491
                s->cr[0x13] = s->vbe_line_offset >> 3;
492
                /* width */
493
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
494
                /* height (only meaningful if < 1024) */
495
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
496
                s->cr[0x12] = h;
497
                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
498
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
499
                /* line compare to 1023 */
500
                s->cr[0x18] = 0xff;
501
                s->cr[0x07] |= 0x10;
502
                s->cr[0x09] |= 0x40;
503

    
504
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
505
                    shift_control = 0;
506
                    s->sr[0x01] &= ~8; /* no double line */
507
                } else {
508
                    shift_control = 2;
509
                    s->sr[4] |= 0x08; /* set chain 4 mode */
510
                    s->sr[2] |= 0x0f; /* activate all planes */
511
                }
512
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
513
                s->cr[0x09] &= ~0x9f; /* no double scan */
514
            } else {
515
                /* XXX: the bios should do that */
516
                s->bank_offset = 0;
517
            }
518
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
519
            s->vbe_regs[s->vbe_index] = val;
520
            break;
521
        case VBE_DISPI_INDEX_VIRT_WIDTH:
522
            {
523
                int w, h, line_offset;
524

    
525
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
526
                    return;
527
                w = val;
528
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
529
                    line_offset = w >> 1;
530
                else
531
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
532
                h = s->vram_size / line_offset;
533
                /* XXX: support weird bochs semantics ? */
534
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
535
                    return;
536
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
537
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
538
                s->vbe_line_offset = line_offset;
539
            }
540
            break;
541
        case VBE_DISPI_INDEX_X_OFFSET:
542
        case VBE_DISPI_INDEX_Y_OFFSET:
543
            {
544
                int x;
545
                s->vbe_regs[s->vbe_index] = val;
546
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
547
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
548
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
549
                    s->vbe_start_addr += x >> 1;
550
                else
551
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
552
                s->vbe_start_addr >>= 2;
553
            }
554
            break;
555
        default:
556
            break;
557
        }
558
    }
559
}
560
#endif
561

    
562
/* called for accesses between 0xa0000 and 0xc0000 */
563
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
564
{
565
    VGAState *s = opaque;
566
    int memory_map_mode, plane;
567
    uint32_t ret;
568

    
569
    /* convert to VGA memory offset */
570
    memory_map_mode = (s->gr[6] >> 2) & 3;
571
    addr &= 0x1ffff;
572
    switch(memory_map_mode) {
573
    case 0:
574
        break;
575
    case 1:
576
        if (addr >= 0x10000)
577
            return 0xff;
578
        addr += s->bank_offset;
579
        break;
580
    case 2:
581
        addr -= 0x10000;
582
        if (addr >= 0x8000)
583
            return 0xff;
584
        break;
585
    default:
586
    case 3:
587
        addr -= 0x18000;
588
        if (addr >= 0x8000)
589
            return 0xff;
590
        break;
591
    }
592

    
593
    if (s->sr[4] & 0x08) {
594
        /* chain 4 mode : simplest access */
595
        ret = s->vram_ptr[addr];
596
    } else if (s->gr[5] & 0x10) {
597
        /* odd/even mode (aka text mode mapping) */
598
        plane = (s->gr[4] & 2) | (addr & 1);
599
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
600
    } else {
601
        /* standard VGA latched access */
602
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
603

    
604
        if (!(s->gr[5] & 0x08)) {
605
            /* read mode 0 */
606
            plane = s->gr[4];
607
            ret = GET_PLANE(s->latch, plane);
608
        } else {
609
            /* read mode 1 */
610
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
611
            ret |= ret >> 16;
612
            ret |= ret >> 8;
613
            ret = (~ret) & 0xff;
614
        }
615
    }
616
    return ret;
617
}
618

    
619
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
620
{
621
    uint32_t v;
622
#ifdef TARGET_WORDS_BIGENDIAN
623
    v = vga_mem_readb(opaque, addr) << 8;
624
    v |= vga_mem_readb(opaque, addr + 1);
625
#else
626
    v = vga_mem_readb(opaque, addr);
627
    v |= vga_mem_readb(opaque, addr + 1) << 8;
628
#endif
629
    return v;
630
}
631

    
632
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
633
{
634
    uint32_t v;
635
#ifdef TARGET_WORDS_BIGENDIAN
636
    v = vga_mem_readb(opaque, addr) << 24;
637
    v |= vga_mem_readb(opaque, addr + 1) << 16;
638
    v |= vga_mem_readb(opaque, addr + 2) << 8;
639
    v |= vga_mem_readb(opaque, addr + 3);
640
#else
641
    v = vga_mem_readb(opaque, addr);
642
    v |= vga_mem_readb(opaque, addr + 1) << 8;
643
    v |= vga_mem_readb(opaque, addr + 2) << 16;
644
    v |= vga_mem_readb(opaque, addr + 3) << 24;
645
#endif
646
    return v;
647
}
648

    
649
/* called for accesses between 0xa0000 and 0xc0000 */
650
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
651
{
652
    VGAState *s = opaque;
653
    int memory_map_mode, plane, write_mode, b, func_select, mask;
654
    uint32_t write_mask, bit_mask, set_mask;
655

    
656
#ifdef DEBUG_VGA_MEM
657
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
658
#endif
659
    /* convert to VGA memory offset */
660
    memory_map_mode = (s->gr[6] >> 2) & 3;
661
    addr &= 0x1ffff;
662
    switch(memory_map_mode) {
663
    case 0:
664
        break;
665
    case 1:
666
        if (addr >= 0x10000)
667
            return;
668
        addr += s->bank_offset;
669
        break;
670
    case 2:
671
        addr -= 0x10000;
672
        if (addr >= 0x8000)
673
            return;
674
        break;
675
    default:
676
    case 3:
677
        addr -= 0x18000;
678
        if (addr >= 0x8000)
679
            return;
680
        break;
681
    }
682

    
683
    if (s->sr[4] & 0x08) {
684
        /* chain 4 mode : simplest access */
685
        plane = addr & 3;
686
        mask = (1 << plane);
687
        if (s->sr[2] & mask) {
688
            s->vram_ptr[addr] = val;
689
#ifdef DEBUG_VGA_MEM
690
            printf("vga: chain4: [0x%x]\n", addr);
691
#endif
692
            s->plane_updated |= mask; /* only used to detect font change */
693
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
694
        }
695
    } else if (s->gr[5] & 0x10) {
696
        /* odd/even mode (aka text mode mapping) */
697
        plane = (s->gr[4] & 2) | (addr & 1);
698
        mask = (1 << plane);
699
        if (s->sr[2] & mask) {
700
            addr = ((addr & ~1) << 1) | plane;
701
            s->vram_ptr[addr] = val;
702
#ifdef DEBUG_VGA_MEM
703
            printf("vga: odd/even: [0x%x]\n", addr);
704
#endif
705
            s->plane_updated |= mask; /* only used to detect font change */
706
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
707
        }
708
    } else {
709
        /* standard VGA latched access */
710
        write_mode = s->gr[5] & 3;
711
        switch(write_mode) {
712
        default:
713
        case 0:
714
            /* rotate */
715
            b = s->gr[3] & 7;
716
            val = ((val >> b) | (val << (8 - b))) & 0xff;
717
            val |= val << 8;
718
            val |= val << 16;
719

    
720
            /* apply set/reset mask */
721
            set_mask = mask16[s->gr[1]];
722
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
723
            bit_mask = s->gr[8];
724
            break;
725
        case 1:
726
            val = s->latch;
727
            goto do_write;
728
        case 2:
729
            val = mask16[val & 0x0f];
730
            bit_mask = s->gr[8];
731
            break;
732
        case 3:
733
            /* rotate */
734
            b = s->gr[3] & 7;
735
            val = (val >> b) | (val << (8 - b));
736

    
737
            bit_mask = s->gr[8] & val;
738
            val = mask16[s->gr[0]];
739
            break;
740
        }
741

    
742
        /* apply logical operation */
743
        func_select = s->gr[3] >> 3;
744
        switch(func_select) {
745
        case 0:
746
        default:
747
            /* nothing to do */
748
            break;
749
        case 1:
750
            /* and */
751
            val &= s->latch;
752
            break;
753
        case 2:
754
            /* or */
755
            val |= s->latch;
756
            break;
757
        case 3:
758
            /* xor */
759
            val ^= s->latch;
760
            break;
761
        }
762

    
763
        /* apply bit mask */
764
        bit_mask |= bit_mask << 8;
765
        bit_mask |= bit_mask << 16;
766
        val = (val & bit_mask) | (s->latch & ~bit_mask);
767

    
768
    do_write:
769
        /* mask data according to sr[2] */
770
        mask = s->sr[2];
771
        s->plane_updated |= mask; /* only used to detect font change */
772
        write_mask = mask16[mask];
773
        ((uint32_t *)s->vram_ptr)[addr] =
774
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
775
            (val & write_mask);
776
#ifdef DEBUG_VGA_MEM
777
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
778
                   addr * 4, write_mask, val);
779
#endif
780
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
781
    }
782
}
783

    
784
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
785
{
786
#ifdef TARGET_WORDS_BIGENDIAN
787
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
788
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
789
#else
790
    vga_mem_writeb(opaque, addr, val & 0xff);
791
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
792
#endif
793
}
794

    
795
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
796
{
797
#ifdef TARGET_WORDS_BIGENDIAN
798
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
799
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
800
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
801
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
802
#else
803
    vga_mem_writeb(opaque, addr, val & 0xff);
804
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
805
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
806
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
807
#endif
808
}
809

    
810
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
811
                             const uint8_t *font_ptr, int h,
812
                             uint32_t fgcol, uint32_t bgcol);
813
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
814
                                  const uint8_t *font_ptr, int h,
815
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
816
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
817
                                const uint8_t *s, int width);
818

    
819
#define DEPTH 8
820
#include "vga_template.h"
821

    
822
#define DEPTH 15
823
#include "vga_template.h"
824

    
825
#define BGR_FORMAT
826
#define DEPTH 15
827
#include "vga_template.h"
828

    
829
#define DEPTH 16
830
#include "vga_template.h"
831

    
832
#define BGR_FORMAT
833
#define DEPTH 16
834
#include "vga_template.h"
835

    
836
#define DEPTH 32
837
#include "vga_template.h"
838

    
839
#define BGR_FORMAT
840
#define DEPTH 32
841
#include "vga_template.h"
842

    
843
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
844
{
845
    unsigned int col;
846
    col = rgb_to_pixel8(r, g, b);
847
    col |= col << 8;
848
    col |= col << 16;
849
    return col;
850
}
851

    
852
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
853
{
854
    unsigned int col;
855
    col = rgb_to_pixel15(r, g, b);
856
    col |= col << 16;
857
    return col;
858
}
859

    
860
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
861
                                          unsigned int b)
862
{
863
    unsigned int col;
864
    col = rgb_to_pixel15bgr(r, g, b);
865
    col |= col << 16;
866
    return col;
867
}
868

    
869
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
870
{
871
    unsigned int col;
872
    col = rgb_to_pixel16(r, g, b);
873
    col |= col << 16;
874
    return col;
875
}
876

    
877
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
878
                                          unsigned int b)
879
{
880
    unsigned int col;
881
    col = rgb_to_pixel16bgr(r, g, b);
882
    col |= col << 16;
883
    return col;
884
}
885

    
886
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
887
{
888
    unsigned int col;
889
    col = rgb_to_pixel32(r, g, b);
890
    return col;
891
}
892

    
893
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
894
{
895
    unsigned int col;
896
    col = rgb_to_pixel32bgr(r, g, b);
897
    return col;
898
}
899

    
900
/* return true if the palette was modified */
901
static int update_palette16(VGAState *s)
902
{
903
    int full_update, i;
904
    uint32_t v, col, *palette;
905

    
906
    full_update = 0;
907
    palette = s->last_palette;
908
    for(i = 0; i < 16; i++) {
909
        v = s->ar[i];
910
        if (s->ar[0x10] & 0x80)
911
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
912
        else
913
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
914
        v = v * 3;
915
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
916
                              c6_to_8(s->palette[v + 1]),
917
                              c6_to_8(s->palette[v + 2]));
918
        if (col != palette[i]) {
919
            full_update = 1;
920
            palette[i] = col;
921
        }
922
    }
923
    return full_update;
924
}
925

    
926
/* return true if the palette was modified */
927
static int update_palette256(VGAState *s)
928
{
929
    int full_update, i;
930
    uint32_t v, col, *palette;
931

    
932
    full_update = 0;
933
    palette = s->last_palette;
934
    v = 0;
935
    for(i = 0; i < 256; i++) {
936
        if (s->dac_8bit) {
937
          col = s->rgb_to_pixel(s->palette[v],
938
                                s->palette[v + 1],
939
                                s->palette[v + 2]);
940
        } else {
941
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
942
                                c6_to_8(s->palette[v + 1]),
943
                                c6_to_8(s->palette[v + 2]));
944
        }
945
        if (col != palette[i]) {
946
            full_update = 1;
947
            palette[i] = col;
948
        }
949
        v += 3;
950
    }
951
    return full_update;
952
}
953

    
954
static void vga_get_offsets(VGAState *s,
955
                            uint32_t *pline_offset,
956
                            uint32_t *pstart_addr,
957
                            uint32_t *pline_compare)
958
{
959
    uint32_t start_addr, line_offset, line_compare;
960
#ifdef CONFIG_BOCHS_VBE
961
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
962
        line_offset = s->vbe_line_offset;
963
        start_addr = s->vbe_start_addr;
964
        line_compare = 65535;
965
    } else
966
#endif
967
    {
968
        /* compute line_offset in bytes */
969
        line_offset = s->cr[0x13];
970
        line_offset <<= 3;
971

    
972
        /* starting address */
973
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
974

    
975
        /* line compare */
976
        line_compare = s->cr[0x18] |
977
            ((s->cr[0x07] & 0x10) << 4) |
978
            ((s->cr[0x09] & 0x40) << 3);
979
    }
980
    *pline_offset = line_offset;
981
    *pstart_addr = start_addr;
982
    *pline_compare = line_compare;
983
}
984

    
985
/* update start_addr and line_offset. Return TRUE if modified */
986
static int update_basic_params(VGAState *s)
987
{
988
    int full_update;
989
    uint32_t start_addr, line_offset, line_compare;
990

    
991
    full_update = 0;
992

    
993
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
994

    
995
    if (line_offset != s->line_offset ||
996
        start_addr != s->start_addr ||
997
        line_compare != s->line_compare) {
998
        s->line_offset = line_offset;
999
        s->start_addr = start_addr;
1000
        s->line_compare = line_compare;
1001
        full_update = 1;
1002
    }
1003
    return full_update;
1004
}
1005

    
1006
#define NB_DEPTHS 7
1007

    
1008
static inline int get_depth_index(DisplayState *s)
1009
{
1010
    switch(s->depth) {
1011
    default:
1012
    case 8:
1013
        return 0;
1014
    case 15:
1015
        if (s->bgr)
1016
            return 5;
1017
        else
1018
            return 1;
1019
    case 16:
1020
        if (s->bgr)
1021
            return 6;
1022
        else
1023
            return 2;
1024
    case 32:
1025
        if (s->bgr)
1026
            return 4;
1027
        else
1028
            return 3;
1029
    }
1030
}
1031

    
1032
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1033
    vga_draw_glyph8_8,
1034
    vga_draw_glyph8_16,
1035
    vga_draw_glyph8_16,
1036
    vga_draw_glyph8_32,
1037
    vga_draw_glyph8_32,
1038
    vga_draw_glyph8_16,
1039
    vga_draw_glyph8_16,
1040
};
1041

    
1042
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1043
    vga_draw_glyph16_8,
1044
    vga_draw_glyph16_16,
1045
    vga_draw_glyph16_16,
1046
    vga_draw_glyph16_32,
1047
    vga_draw_glyph16_32,
1048
    vga_draw_glyph16_16,
1049
    vga_draw_glyph16_16,
1050
};
1051

    
1052
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1053
    vga_draw_glyph9_8,
1054
    vga_draw_glyph9_16,
1055
    vga_draw_glyph9_16,
1056
    vga_draw_glyph9_32,
1057
    vga_draw_glyph9_32,
1058
    vga_draw_glyph9_16,
1059
    vga_draw_glyph9_16,
1060
};
1061

    
1062
static const uint8_t cursor_glyph[32 * 4] = {
1063
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1064
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1065
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1066
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1067
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1068
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1070
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1071
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1072
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1073
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1074
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1075
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1076
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1077
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1078
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1079
};
1080

    
1081
/*
1082
 * Text mode update
1083
 * Missing:
1084
 * - double scan
1085
 * - double width
1086
 * - underline
1087
 * - flashing
1088
 */
1089
static void vga_draw_text(VGAState *s, int full_update)
1090
{
1091
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1092
    int cx_min, cx_max, linesize, x_incr;
1093
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1094
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1095
    const uint8_t *font_ptr, *font_base[2];
1096
    int dup9, line_offset, depth_index;
1097
    uint32_t *palette;
1098
    uint32_t *ch_attr_ptr;
1099
    vga_draw_glyph8_func *vga_draw_glyph8;
1100
    vga_draw_glyph9_func *vga_draw_glyph9;
1101

    
1102
    full_update |= update_palette16(s);
1103
    palette = s->last_palette;
1104

    
1105
    /* compute font data address (in plane 2) */
1106
    v = s->sr[3];
1107
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1108
    if (offset != s->font_offsets[0]) {
1109
        s->font_offsets[0] = offset;
1110
        full_update = 1;
1111
    }
1112
    font_base[0] = s->vram_ptr + offset;
1113

    
1114
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1115
    font_base[1] = s->vram_ptr + offset;
1116
    if (offset != s->font_offsets[1]) {
1117
        s->font_offsets[1] = offset;
1118
        full_update = 1;
1119
    }
1120
    if (s->plane_updated & (1 << 2)) {
1121
        /* if the plane 2 was modified since the last display, it
1122
           indicates the font may have been modified */
1123
        s->plane_updated = 0;
1124
        full_update = 1;
1125
    }
1126
    full_update |= update_basic_params(s);
1127

    
1128
    line_offset = s->line_offset;
1129
    s1 = s->vram_ptr + (s->start_addr * 4);
1130

    
1131
    /* total width & height */
1132
    cheight = (s->cr[9] & 0x1f) + 1;
1133
    cw = 8;
1134
    if (!(s->sr[1] & 0x01))
1135
        cw = 9;
1136
    if (s->sr[1] & 0x08)
1137
        cw = 16; /* NOTE: no 18 pixel wide */
1138
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1139
    width = (s->cr[0x01] + 1);
1140
    if (s->cr[0x06] == 100) {
1141
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1142
        height = 100;
1143
    } else {
1144
        height = s->cr[0x12] |
1145
            ((s->cr[0x07] & 0x02) << 7) |
1146
            ((s->cr[0x07] & 0x40) << 3);
1147
        height = (height + 1) / cheight;
1148
    }
1149
    if ((height * width) > CH_ATTR_SIZE) {
1150
        /* better than nothing: exit if transient size is too big */
1151
        return;
1152
    }
1153

    
1154
    if (width != s->last_width || height != s->last_height ||
1155
        cw != s->last_cw || cheight != s->last_ch) {
1156
        s->last_scr_width = width * cw;
1157
        s->last_scr_height = height * cheight;
1158
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1159
        s->last_width = width;
1160
        s->last_height = height;
1161
        s->last_ch = cheight;
1162
        s->last_cw = cw;
1163
        full_update = 1;
1164
    }
1165
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1166
    if (cursor_offset != s->cursor_offset ||
1167
        s->cr[0xa] != s->cursor_start ||
1168
        s->cr[0xb] != s->cursor_end) {
1169
      /* if the cursor position changed, we update the old and new
1170
         chars */
1171
        if (s->cursor_offset < CH_ATTR_SIZE)
1172
            s->last_ch_attr[s->cursor_offset] = -1;
1173
        if (cursor_offset < CH_ATTR_SIZE)
1174
            s->last_ch_attr[cursor_offset] = -1;
1175
        s->cursor_offset = cursor_offset;
1176
        s->cursor_start = s->cr[0xa];
1177
        s->cursor_end = s->cr[0xb];
1178
    }
1179
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1180

    
1181
    depth_index = get_depth_index(s->ds);
1182
    if (cw == 16)
1183
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1184
    else
1185
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1186
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1187

    
1188
    dest = s->ds->data;
1189
    linesize = s->ds->linesize;
1190
    ch_attr_ptr = s->last_ch_attr;
1191
    for(cy = 0; cy < height; cy++) {
1192
        d1 = dest;
1193
        src = s1;
1194
        cx_min = width;
1195
        cx_max = -1;
1196
        for(cx = 0; cx < width; cx++) {
1197
            ch_attr = *(uint16_t *)src;
1198
            if (full_update || ch_attr != *ch_attr_ptr) {
1199
                if (cx < cx_min)
1200
                    cx_min = cx;
1201
                if (cx > cx_max)
1202
                    cx_max = cx;
1203
                *ch_attr_ptr = ch_attr;
1204
#ifdef WORDS_BIGENDIAN
1205
                ch = ch_attr >> 8;
1206
                cattr = ch_attr & 0xff;
1207
#else
1208
                ch = ch_attr & 0xff;
1209
                cattr = ch_attr >> 8;
1210
#endif
1211
                font_ptr = font_base[(cattr >> 3) & 1];
1212
                font_ptr += 32 * 4 * ch;
1213
                bgcol = palette[cattr >> 4];
1214
                fgcol = palette[cattr & 0x0f];
1215
                if (cw != 9) {
1216
                    vga_draw_glyph8(d1, linesize,
1217
                                    font_ptr, cheight, fgcol, bgcol);
1218
                } else {
1219
                    dup9 = 0;
1220
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1221
                        dup9 = 1;
1222
                    vga_draw_glyph9(d1, linesize,
1223
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1224
                }
1225
                if (src == cursor_ptr &&
1226
                    !(s->cr[0x0a] & 0x20)) {
1227
                    int line_start, line_last, h;
1228
                    /* draw the cursor */
1229
                    line_start = s->cr[0x0a] & 0x1f;
1230
                    line_last = s->cr[0x0b] & 0x1f;
1231
                    /* XXX: check that */
1232
                    if (line_last > cheight - 1)
1233
                        line_last = cheight - 1;
1234
                    if (line_last >= line_start && line_start < cheight) {
1235
                        h = line_last - line_start + 1;
1236
                        d = d1 + linesize * line_start;
1237
                        if (cw != 9) {
1238
                            vga_draw_glyph8(d, linesize,
1239
                                            cursor_glyph, h, fgcol, bgcol);
1240
                        } else {
1241
                            vga_draw_glyph9(d, linesize,
1242
                                            cursor_glyph, h, fgcol, bgcol, 1);
1243
                        }
1244
                    }
1245
                }
1246
            }
1247
            d1 += x_incr;
1248
            src += 4;
1249
            ch_attr_ptr++;
1250
        }
1251
        if (cx_max != -1) {
1252
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1253
                       (cx_max - cx_min + 1) * cw, cheight);
1254
        }
1255
        dest += linesize * cheight;
1256
        s1 += line_offset;
1257
    }
1258
}
1259

    
1260
enum {
1261
    VGA_DRAW_LINE2,
1262
    VGA_DRAW_LINE2D2,
1263
    VGA_DRAW_LINE4,
1264
    VGA_DRAW_LINE4D2,
1265
    VGA_DRAW_LINE8D2,
1266
    VGA_DRAW_LINE8,
1267
    VGA_DRAW_LINE15,
1268
    VGA_DRAW_LINE16,
1269
    VGA_DRAW_LINE24,
1270
    VGA_DRAW_LINE32,
1271
    VGA_DRAW_LINE_NB,
1272
};
1273

    
1274
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1275
    vga_draw_line2_8,
1276
    vga_draw_line2_16,
1277
    vga_draw_line2_16,
1278
    vga_draw_line2_32,
1279
    vga_draw_line2_32,
1280
    vga_draw_line2_16,
1281
    vga_draw_line2_16,
1282

    
1283
    vga_draw_line2d2_8,
1284
    vga_draw_line2d2_16,
1285
    vga_draw_line2d2_16,
1286
    vga_draw_line2d2_32,
1287
    vga_draw_line2d2_32,
1288
    vga_draw_line2d2_16,
1289
    vga_draw_line2d2_16,
1290

    
1291
    vga_draw_line4_8,
1292
    vga_draw_line4_16,
1293
    vga_draw_line4_16,
1294
    vga_draw_line4_32,
1295
    vga_draw_line4_32,
1296
    vga_draw_line4_16,
1297
    vga_draw_line4_16,
1298

    
1299
    vga_draw_line4d2_8,
1300
    vga_draw_line4d2_16,
1301
    vga_draw_line4d2_16,
1302
    vga_draw_line4d2_32,
1303
    vga_draw_line4d2_32,
1304
    vga_draw_line4d2_16,
1305
    vga_draw_line4d2_16,
1306

    
1307
    vga_draw_line8d2_8,
1308
    vga_draw_line8d2_16,
1309
    vga_draw_line8d2_16,
1310
    vga_draw_line8d2_32,
1311
    vga_draw_line8d2_32,
1312
    vga_draw_line8d2_16,
1313
    vga_draw_line8d2_16,
1314

    
1315
    vga_draw_line8_8,
1316
    vga_draw_line8_16,
1317
    vga_draw_line8_16,
1318
    vga_draw_line8_32,
1319
    vga_draw_line8_32,
1320
    vga_draw_line8_16,
1321
    vga_draw_line8_16,
1322

    
1323
    vga_draw_line15_8,
1324
    vga_draw_line15_15,
1325
    vga_draw_line15_16,
1326
    vga_draw_line15_32,
1327
    vga_draw_line15_32bgr,
1328
    vga_draw_line15_15bgr,
1329
    vga_draw_line15_16bgr,
1330

    
1331
    vga_draw_line16_8,
1332
    vga_draw_line16_15,
1333
    vga_draw_line16_16,
1334
    vga_draw_line16_32,
1335
    vga_draw_line16_32bgr,
1336
    vga_draw_line16_15bgr,
1337
    vga_draw_line16_16bgr,
1338

    
1339
    vga_draw_line24_8,
1340
    vga_draw_line24_15,
1341
    vga_draw_line24_16,
1342
    vga_draw_line24_32,
1343
    vga_draw_line24_32bgr,
1344
    vga_draw_line24_15bgr,
1345
    vga_draw_line24_16bgr,
1346

    
1347
    vga_draw_line32_8,
1348
    vga_draw_line32_15,
1349
    vga_draw_line32_16,
1350
    vga_draw_line32_32,
1351
    vga_draw_line32_32bgr,
1352
    vga_draw_line32_15bgr,
1353
    vga_draw_line32_16bgr,
1354
};
1355

    
1356
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1357

    
1358
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1359
    rgb_to_pixel8_dup,
1360
    rgb_to_pixel15_dup,
1361
    rgb_to_pixel16_dup,
1362
    rgb_to_pixel32_dup,
1363
    rgb_to_pixel32bgr_dup,
1364
    rgb_to_pixel15bgr_dup,
1365
    rgb_to_pixel16bgr_dup,
1366
};
1367

    
1368
static int vga_get_bpp(VGAState *s)
1369
{
1370
    int ret;
1371
#ifdef CONFIG_BOCHS_VBE
1372
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1373
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1374
    } else
1375
#endif
1376
    {
1377
        ret = 0;
1378
    }
1379
    return ret;
1380
}
1381

    
1382
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1383
{
1384
    int width, height;
1385

    
1386
#ifdef CONFIG_BOCHS_VBE
1387
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1388
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1389
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1390
    } else
1391
#endif
1392
    {
1393
        width = (s->cr[0x01] + 1) * 8;
1394
        height = s->cr[0x12] |
1395
            ((s->cr[0x07] & 0x02) << 7) |
1396
            ((s->cr[0x07] & 0x40) << 3);
1397
        height = (height + 1);
1398
    }
1399
    *pwidth = width;
1400
    *pheight = height;
1401
}
1402

    
1403
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1404
{
1405
    int y;
1406
    if (y1 >= VGA_MAX_HEIGHT)
1407
        return;
1408
    if (y2 >= VGA_MAX_HEIGHT)
1409
        y2 = VGA_MAX_HEIGHT;
1410
    for(y = y1; y < y2; y++) {
1411
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1412
    }
1413
}
1414

    
1415
/*
1416
 * graphic modes
1417
 */
1418
static void vga_draw_graphic(VGAState *s, int full_update)
1419
{
1420
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1421
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1422
    int disp_width, multi_scan, multi_run;
1423
    uint8_t *d;
1424
    uint32_t v, addr1, addr;
1425
    vga_draw_line_func *vga_draw_line;
1426

    
1427
    full_update |= update_basic_params(s);
1428

    
1429
    s->get_resolution(s, &width, &height);
1430
    disp_width = width;
1431

    
1432
    shift_control = (s->gr[0x05] >> 5) & 3;
1433
    double_scan = (s->cr[0x09] >> 7);
1434
    if (shift_control != 1) {
1435
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1436
    } else {
1437
        /* in CGA modes, multi_scan is ignored */
1438
        /* XXX: is it correct ? */
1439
        multi_scan = double_scan;
1440
    }
1441
    multi_run = multi_scan;
1442
    if (shift_control != s->shift_control ||
1443
        double_scan != s->double_scan) {
1444
        full_update = 1;
1445
        s->shift_control = shift_control;
1446
        s->double_scan = double_scan;
1447
    }
1448

    
1449
    if (shift_control == 0) {
1450
        full_update |= update_palette16(s);
1451
        if (s->sr[0x01] & 8) {
1452
            v = VGA_DRAW_LINE4D2;
1453
            disp_width <<= 1;
1454
        } else {
1455
            v = VGA_DRAW_LINE4;
1456
        }
1457
    } else if (shift_control == 1) {
1458
        full_update |= update_palette16(s);
1459
        if (s->sr[0x01] & 8) {
1460
            v = VGA_DRAW_LINE2D2;
1461
            disp_width <<= 1;
1462
        } else {
1463
            v = VGA_DRAW_LINE2;
1464
        }
1465
    } else {
1466
        switch(s->get_bpp(s)) {
1467
        default:
1468
        case 0:
1469
            full_update |= update_palette256(s);
1470
            v = VGA_DRAW_LINE8D2;
1471
            break;
1472
        case 8:
1473
            full_update |= update_palette256(s);
1474
            v = VGA_DRAW_LINE8;
1475
            break;
1476
        case 15:
1477
            v = VGA_DRAW_LINE15;
1478
            break;
1479
        case 16:
1480
            v = VGA_DRAW_LINE16;
1481
            break;
1482
        case 24:
1483
            v = VGA_DRAW_LINE24;
1484
            break;
1485
        case 32:
1486
            v = VGA_DRAW_LINE32;
1487
            break;
1488
        }
1489
    }
1490
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1491

    
1492
    if (disp_width != s->last_width ||
1493
        height != s->last_height) {
1494
        dpy_resize(s->ds, disp_width, height);
1495
        s->last_scr_width = disp_width;
1496
        s->last_scr_height = height;
1497
        s->last_width = disp_width;
1498
        s->last_height = height;
1499
        full_update = 1;
1500
    }
1501
    if (s->cursor_invalidate)
1502
        s->cursor_invalidate(s);
1503

    
1504
    line_offset = s->line_offset;
1505
#if 0
1506
    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",
1507
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1508
#endif
1509
    addr1 = (s->start_addr * 4);
1510
    bwidth = width * 4;
1511
    y_start = -1;
1512
    page_min = 0x7fffffff;
1513
    page_max = -1;
1514
    d = s->ds->data;
1515
    linesize = s->ds->linesize;
1516
    y1 = 0;
1517
    for(y = 0; y < height; y++) {
1518
        addr = addr1;
1519
        if (!(s->cr[0x17] & 1)) {
1520
            int shift;
1521
            /* CGA compatibility handling */
1522
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1523
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1524
        }
1525
        if (!(s->cr[0x17] & 2)) {
1526
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1527
        }
1528
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1529
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1530
        update = full_update |
1531
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1532
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1533
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1534
            /* if wide line, can use another page */
1535
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1536
                                                    VGA_DIRTY_FLAG);
1537
        }
1538
        /* explicit invalidation for the hardware cursor */
1539
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1540
        if (update) {
1541
            if (y_start < 0)
1542
                y_start = y;
1543
            if (page0 < page_min)
1544
                page_min = page0;
1545
            if (page1 > page_max)
1546
                page_max = page1;
1547
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1548
            if (s->cursor_draw_line)
1549
                s->cursor_draw_line(s, d, y);
1550
        } else {
1551
            if (y_start >= 0) {
1552
                /* flush to display */
1553
                dpy_update(s->ds, 0, y_start,
1554
                           disp_width, y - y_start);
1555
                y_start = -1;
1556
            }
1557
        }
1558
        if (!multi_run) {
1559
            mask = (s->cr[0x17] & 3) ^ 3;
1560
            if ((y1 & mask) == mask)
1561
                addr1 += line_offset;
1562
            y1++;
1563
            multi_run = multi_scan;
1564
        } else {
1565
            multi_run--;
1566
        }
1567
        /* line compare acts on the displayed lines */
1568
        if (y == s->line_compare)
1569
            addr1 = 0;
1570
        d += linesize;
1571
    }
1572
    if (y_start >= 0) {
1573
        /* flush to display */
1574
        dpy_update(s->ds, 0, y_start,
1575
                   disp_width, y - y_start);
1576
    }
1577
    /* reset modified pages */
1578
    if (page_max != -1) {
1579
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1580
                                        VGA_DIRTY_FLAG);
1581
    }
1582
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1583
}
1584

    
1585
static void vga_draw_blank(VGAState *s, int full_update)
1586
{
1587
    int i, w, val;
1588
    uint8_t *d;
1589

    
1590
    if (!full_update)
1591
        return;
1592
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1593
        return;
1594
    if (s->ds->depth == 8)
1595
        val = s->rgb_to_pixel(0, 0, 0);
1596
    else
1597
        val = 0;
1598
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1599
    d = s->ds->data;
1600
    for(i = 0; i < s->last_scr_height; i++) {
1601
        memset(d, val, w);
1602
        d += s->ds->linesize;
1603
    }
1604
    dpy_update(s->ds, 0, 0,
1605
               s->last_scr_width, s->last_scr_height);
1606
}
1607

    
1608
#define GMODE_TEXT     0
1609
#define GMODE_GRAPH    1
1610
#define GMODE_BLANK 2
1611

    
1612
static void vga_update_display(void *opaque)
1613
{
1614
    VGAState *s = (VGAState *)opaque;
1615
    int full_update, graphic_mode;
1616

    
1617
    if (s->ds->depth == 0) {
1618
        /* nothing to do */
1619
    } else {
1620
        s->rgb_to_pixel =
1621
            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1622

    
1623
        full_update = 0;
1624
        if (!(s->ar_index & 0x20)) {
1625
            graphic_mode = GMODE_BLANK;
1626
        } else {
1627
            graphic_mode = s->gr[6] & 1;
1628
        }
1629
        if (graphic_mode != s->graphic_mode) {
1630
            s->graphic_mode = graphic_mode;
1631
            full_update = 1;
1632
        }
1633
        switch(graphic_mode) {
1634
        case GMODE_TEXT:
1635
            vga_draw_text(s, full_update);
1636
            break;
1637
        case GMODE_GRAPH:
1638
            vga_draw_graphic(s, full_update);
1639
            break;
1640
        case GMODE_BLANK:
1641
        default:
1642
            vga_draw_blank(s, full_update);
1643
            break;
1644
        }
1645
    }
1646
}
1647

    
1648
/* force a full display refresh */
1649
static void vga_invalidate_display(void *opaque)
1650
{
1651
    VGAState *s = (VGAState *)opaque;
1652

    
1653
    s->last_width = -1;
1654
    s->last_height = -1;
1655
}
1656

    
1657
static void vga_reset(VGAState *s)
1658
{
1659
    memset(s, 0, sizeof(VGAState));
1660
    s->graphic_mode = -1; /* force full update */
1661
}
1662

    
1663
static CPUReadMemoryFunc *vga_mem_read[3] = {
1664
    vga_mem_readb,
1665
    vga_mem_readw,
1666
    vga_mem_readl,
1667
};
1668

    
1669
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1670
    vga_mem_writeb,
1671
    vga_mem_writew,
1672
    vga_mem_writel,
1673
};
1674

    
1675
static void vga_save(QEMUFile *f, void *opaque)
1676
{
1677
    VGAState *s = opaque;
1678
    int i;
1679

    
1680
    if (s->pci_dev)
1681
        pci_device_save(s->pci_dev, f);
1682

    
1683
    qemu_put_be32s(f, &s->latch);
1684
    qemu_put_8s(f, &s->sr_index);
1685
    qemu_put_buffer(f, s->sr, 8);
1686
    qemu_put_8s(f, &s->gr_index);
1687
    qemu_put_buffer(f, s->gr, 16);
1688
    qemu_put_8s(f, &s->ar_index);
1689
    qemu_put_buffer(f, s->ar, 21);
1690
    qemu_put_be32s(f, &s->ar_flip_flop);
1691
    qemu_put_8s(f, &s->cr_index);
1692
    qemu_put_buffer(f, s->cr, 256);
1693
    qemu_put_8s(f, &s->msr);
1694
    qemu_put_8s(f, &s->fcr);
1695
    qemu_put_8s(f, &s->st00);
1696
    qemu_put_8s(f, &s->st01);
1697

    
1698
    qemu_put_8s(f, &s->dac_state);
1699
    qemu_put_8s(f, &s->dac_sub_index);
1700
    qemu_put_8s(f, &s->dac_read_index);
1701
    qemu_put_8s(f, &s->dac_write_index);
1702
    qemu_put_buffer(f, s->dac_cache, 3);
1703
    qemu_put_buffer(f, s->palette, 768);
1704

    
1705
    qemu_put_be32s(f, &s->bank_offset);
1706
#ifdef CONFIG_BOCHS_VBE
1707
    qemu_put_byte(f, 1);
1708
    qemu_put_be16s(f, &s->vbe_index);
1709
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1710
        qemu_put_be16s(f, &s->vbe_regs[i]);
1711
    qemu_put_be32s(f, &s->vbe_start_addr);
1712
    qemu_put_be32s(f, &s->vbe_line_offset);
1713
    qemu_put_be32s(f, &s->vbe_bank_mask);
1714
#else
1715
    qemu_put_byte(f, 0);
1716
#endif
1717
}
1718

    
1719
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1720
{
1721
    VGAState *s = opaque;
1722
    int is_vbe, i, ret;
1723

    
1724
    if (version_id > 2)
1725
        return -EINVAL;
1726

    
1727
    if (s->pci_dev && version_id >= 2) {
1728
        ret = pci_device_load(s->pci_dev, f);
1729
        if (ret < 0)
1730
            return ret;
1731
    }
1732

    
1733
    qemu_get_be32s(f, &s->latch);
1734
    qemu_get_8s(f, &s->sr_index);
1735
    qemu_get_buffer(f, s->sr, 8);
1736
    qemu_get_8s(f, &s->gr_index);
1737
    qemu_get_buffer(f, s->gr, 16);
1738
    qemu_get_8s(f, &s->ar_index);
1739
    qemu_get_buffer(f, s->ar, 21);
1740
    qemu_get_be32s(f, &s->ar_flip_flop);
1741
    qemu_get_8s(f, &s->cr_index);
1742
    qemu_get_buffer(f, s->cr, 256);
1743
    qemu_get_8s(f, &s->msr);
1744
    qemu_get_8s(f, &s->fcr);
1745
    qemu_get_8s(f, &s->st00);
1746
    qemu_get_8s(f, &s->st01);
1747

    
1748
    qemu_get_8s(f, &s->dac_state);
1749
    qemu_get_8s(f, &s->dac_sub_index);
1750
    qemu_get_8s(f, &s->dac_read_index);
1751
    qemu_get_8s(f, &s->dac_write_index);
1752
    qemu_get_buffer(f, s->dac_cache, 3);
1753
    qemu_get_buffer(f, s->palette, 768);
1754

    
1755
    qemu_get_be32s(f, &s->bank_offset);
1756
    is_vbe = qemu_get_byte(f);
1757
#ifdef CONFIG_BOCHS_VBE
1758
    if (!is_vbe)
1759
        return -EINVAL;
1760
    qemu_get_be16s(f, &s->vbe_index);
1761
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1762
        qemu_get_be16s(f, &s->vbe_regs[i]);
1763
    qemu_get_be32s(f, &s->vbe_start_addr);
1764
    qemu_get_be32s(f, &s->vbe_line_offset);
1765
    qemu_get_be32s(f, &s->vbe_bank_mask);
1766
#else
1767
    if (is_vbe)
1768
        return -EINVAL;
1769
#endif
1770

    
1771
    /* force refresh */
1772
    s->graphic_mode = -1;
1773
    return 0;
1774
}
1775

    
1776
typedef struct PCIVGAState {
1777
    PCIDevice dev;
1778
    VGAState vga_state;
1779
} PCIVGAState;
1780

    
1781
static void vga_map(PCIDevice *pci_dev, int region_num,
1782
                    uint32_t addr, uint32_t size, int type)
1783
{
1784
    PCIVGAState *d = (PCIVGAState *)pci_dev;
1785
    VGAState *s = &d->vga_state;
1786
    if (region_num == PCI_ROM_SLOT) {
1787
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1788
    } else {
1789
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1790
    }
1791
}
1792

    
1793
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1794
                     unsigned long vga_ram_offset, int vga_ram_size)
1795
{
1796
    int i, j, v, b;
1797

    
1798
    for(i = 0;i < 256; i++) {
1799
        v = 0;
1800
        for(j = 0; j < 8; j++) {
1801
            v |= ((i >> j) & 1) << (j * 4);
1802
        }
1803
        expand4[i] = v;
1804

    
1805
        v = 0;
1806
        for(j = 0; j < 4; j++) {
1807
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1808
        }
1809
        expand2[i] = v;
1810
    }
1811
    for(i = 0; i < 16; i++) {
1812
        v = 0;
1813
        for(j = 0; j < 4; j++) {
1814
            b = ((i >> j) & 1);
1815
            v |= b << (2 * j);
1816
            v |= b << (2 * j + 1);
1817
        }
1818
        expand4to8[i] = v;
1819
    }
1820

    
1821
    vga_reset(s);
1822

    
1823
    s->vram_ptr = vga_ram_base;
1824
    s->vram_offset = vga_ram_offset;
1825
    s->vram_size = vga_ram_size;
1826
    s->ds = ds;
1827
    s->get_bpp = vga_get_bpp;
1828
    s->get_offsets = vga_get_offsets;
1829
    s->get_resolution = vga_get_resolution;
1830
    s->update = vga_update_display;
1831
    s->invalidate = vga_invalidate_display;
1832
    s->screen_dump = vga_screen_dump;
1833
}
1834

    
1835
/* used by both ISA and PCI */
1836
void vga_init(VGAState *s)
1837
{
1838
    int vga_io_memory;
1839

    
1840
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1841

    
1842
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1843

    
1844
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1845
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1846
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1847
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1848

    
1849
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1850

    
1851
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1852
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1853
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1854
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1855
    s->bank_offset = 0;
1856

    
1857
#ifdef CONFIG_BOCHS_VBE
1858
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1859
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1860
#if defined (TARGET_I386)
1861
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1862
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1863

    
1864
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1865
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1866

    
1867
    /* old Bochs IO ports */
1868
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1869
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1870

    
1871
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1872
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
1873
#else
1874
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1875
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1876

    
1877
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1878
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1879
#endif
1880
#endif /* CONFIG_BOCHS_VBE */
1881

    
1882
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1883
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
1884
                                 vga_io_memory);
1885
}
1886

    
1887
/* Memory mapped interface */
1888
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
1889
{
1890
    VGAState *s = opaque;
1891

    
1892
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
1893
}
1894

    
1895
static void vga_mm_writeb (void *opaque,
1896
                           target_phys_addr_t addr, uint32_t value)
1897
{
1898
    VGAState *s = opaque;
1899

    
1900
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
1901
}
1902

    
1903
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
1904
{
1905
    VGAState *s = opaque;
1906

    
1907
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
1908
}
1909

    
1910
static void vga_mm_writew (void *opaque,
1911
                           target_phys_addr_t addr, uint32_t value)
1912
{
1913
    VGAState *s = opaque;
1914

    
1915
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
1916
}
1917

    
1918
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
1919
{
1920
    VGAState *s = opaque;
1921

    
1922
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
1923
}
1924

    
1925
static void vga_mm_writel (void *opaque,
1926
                           target_phys_addr_t addr, uint32_t value)
1927
{
1928
    VGAState *s = opaque;
1929

    
1930
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
1931
}
1932

    
1933
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
1934
    &vga_mm_readb,
1935
    &vga_mm_readw,
1936
    &vga_mm_readl,
1937
};
1938

    
1939
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
1940
    &vga_mm_writeb,
1941
    &vga_mm_writew,
1942
    &vga_mm_writel,
1943
};
1944

    
1945
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
1946
                        target_phys_addr_t ctrl_base, int it_shift)
1947
{
1948
    int s_ioport_ctrl, vga_io_memory;
1949

    
1950
    s->base_ctrl = ctrl_base;
1951
    s->it_shift = it_shift;
1952
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
1953
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1954

    
1955
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1956

    
1957
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
1958
    s->bank_offset = 0;
1959
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
1960
}
1961

    
1962
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
1963
                 unsigned long vga_ram_offset, int vga_ram_size)
1964
{
1965
    VGAState *s;
1966

    
1967
    s = qemu_mallocz(sizeof(VGAState));
1968
    if (!s)
1969
        return -1;
1970

    
1971
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1972
    vga_init(s);
1973

    
1974
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1975

    
1976
#ifdef CONFIG_BOCHS_VBE
1977
    /* XXX: use optimized standard vga accesses */
1978
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1979
                                 vga_ram_size, vga_ram_offset);
1980
#endif
1981
    return 0;
1982
}
1983

    
1984
int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
1985
                    unsigned long vga_ram_offset, int vga_ram_size,
1986
                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
1987
                    int it_shift)
1988
{
1989
    VGAState *s;
1990

    
1991
    s = qemu_mallocz(sizeof(VGAState));
1992
    if (!s)
1993
        return -1;
1994

    
1995
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1996
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
1997

    
1998
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1999

    
2000
#ifdef CONFIG_BOCHS_VBE
2001
    /* XXX: use optimized standard vga accesses */
2002
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2003
                                 vga_ram_size, vga_ram_offset);
2004
#endif
2005
    return 0;
2006
}
2007

    
2008
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2009
                 unsigned long vga_ram_offset, int vga_ram_size,
2010
                 unsigned long vga_bios_offset, int vga_bios_size)
2011
{
2012
    PCIVGAState *d;
2013
    VGAState *s;
2014
    uint8_t *pci_conf;
2015

    
2016
    d = (PCIVGAState *)pci_register_device(bus, "VGA",
2017
                                           sizeof(PCIVGAState),
2018
                                           -1, NULL, NULL);
2019
    if (!d)
2020
        return -1;
2021
    s = &d->vga_state;
2022

    
2023
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2024
    vga_init(s);
2025

    
2026
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
2027

    
2028
    s->pci_dev = &d->dev;
2029

    
2030
    pci_conf = d->dev.config;
2031
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2032
    pci_conf[0x01] = 0x12;
2033
    pci_conf[0x02] = 0x11;
2034
    pci_conf[0x03] = 0x11;
2035
    pci_conf[0x0a] = 0x00; // VGA controller
2036
    pci_conf[0x0b] = 0x03;
2037
    pci_conf[0x0e] = 0x00; // header_type
2038

    
2039
    /* XXX: vga_ram_size must be a power of two */
2040
    pci_register_io_region(&d->dev, 0, vga_ram_size,
2041
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2042
    if (vga_bios_size != 0) {
2043
        unsigned int bios_total_size;
2044
        s->bios_offset = vga_bios_offset;
2045
        s->bios_size = vga_bios_size;
2046
        /* must be a power of two */
2047
        bios_total_size = 1;
2048
        while (bios_total_size < vga_bios_size)
2049
            bios_total_size <<= 1;
2050
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2051
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2052
    }
2053
    return 0;
2054
}
2055

    
2056
/********************************************************/
2057
/* vga screen dump */
2058

    
2059
static int vga_save_w, vga_save_h;
2060

    
2061
static void vga_save_dpy_update(DisplayState *s,
2062
                                int x, int y, int w, int h)
2063
{
2064
}
2065

    
2066
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2067
{
2068
    s->linesize = w * 4;
2069
    s->data = qemu_malloc(h * s->linesize);
2070
    vga_save_w = w;
2071
    vga_save_h = h;
2072
}
2073

    
2074
static void vga_save_dpy_refresh(DisplayState *s)
2075
{
2076
}
2077

    
2078
int ppm_save(const char *filename, uint8_t *data,
2079
             int w, int h, int linesize)
2080
{
2081
    FILE *f;
2082
    uint8_t *d, *d1;
2083
    unsigned int v;
2084
    int y, x;
2085

    
2086
    f = fopen(filename, "wb");
2087
    if (!f)
2088
        return -1;
2089
    fprintf(f, "P6\n%d %d\n%d\n",
2090
            w, h, 255);
2091
    d1 = data;
2092
    for(y = 0; y < h; y++) {
2093
        d = d1;
2094
        for(x = 0; x < w; x++) {
2095
            v = *(uint32_t *)d;
2096
            fputc((v >> 16) & 0xff, f);
2097
            fputc((v >> 8) & 0xff, f);
2098
            fputc((v) & 0xff, f);
2099
            d += 4;
2100
        }
2101
        d1 += linesize;
2102
    }
2103
    fclose(f);
2104
    return 0;
2105
}
2106

    
2107
/* save the vga display in a PPM image even if no display is
2108
   available */
2109
static void vga_screen_dump(void *opaque, const char *filename)
2110
{
2111
    VGAState *s = (VGAState *)opaque;
2112
    DisplayState *saved_ds, ds1, *ds = &ds1;
2113

    
2114
    /* XXX: this is a little hackish */
2115
    vga_invalidate_display(s);
2116
    saved_ds = s->ds;
2117

    
2118
    memset(ds, 0, sizeof(DisplayState));
2119
    ds->dpy_update = vga_save_dpy_update;
2120
    ds->dpy_resize = vga_save_dpy_resize;
2121
    ds->dpy_refresh = vga_save_dpy_refresh;
2122
    ds->depth = 32;
2123

    
2124
    s->ds = ds;
2125
    s->graphic_mode = -1;
2126
    vga_update_display(s);
2127

    
2128
    if (ds->data) {
2129
        ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2130
                 s->ds->linesize);
2131
        qemu_free(ds->data);
2132
    }
2133
    s->ds = saved_ds;
2134
}