Statistics
| Branch: | Revision:

root / hw / vga.c @ 4d3b6f6e

History | View | Annotate | Download (64.8 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
#define TEXTMODE_X(x)        ((x) % width)
1664
#define TEXTMODE_Y(x)        ((x) / width)
1665
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1666
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1667
/* relay text rendering to the display driver
1668
 * instead of doing a full vga_update_display() */
1669
static void vga_update_text(void *opaque, console_ch_t *chardata)
1670
{
1671
    VGAState *s = (VGAState *) opaque;
1672
    int graphic_mode, i, cursor_offset, cursor_visible;
1673
    int cw, cheight, width, height, size, c_min, c_max;
1674
    uint32_t *src;
1675
    console_ch_t *dst, val;
1676
    char msg_buffer[80];
1677
    int full_update;
1678
    full_update = 0;
1679

    
1680
    if (!(s->ar_index & 0x20)) {
1681
        graphic_mode = GMODE_BLANK;
1682
    } else {
1683
        graphic_mode = s->gr[6] & 1;
1684
    }
1685
    if (graphic_mode != s->graphic_mode) {
1686
        s->graphic_mode = graphic_mode;
1687
        full_update = 1;
1688
    }
1689
    if (s->last_width == -1) {
1690
        s->last_width = 0;
1691
        full_update = 1;
1692
    }
1693

    
1694
    switch (graphic_mode) {
1695
    case GMODE_TEXT:
1696
        /* TODO: update palette */
1697
        full_update |= update_basic_params(s);
1698

    
1699
        /* total width & height */
1700
        cheight = (s->cr[9] & 0x1f) + 1;
1701
        cw = 8;
1702
        if (!(s->sr[1] & 0x01))
1703
            cw = 9;
1704
        if (s->sr[1] & 0x08)
1705
            cw = 16; /* NOTE: no 18 pixel wide */
1706
        width = (s->cr[0x01] + 1);
1707
        if (s->cr[0x06] == 100) {
1708
            /* ugly hack for CGA 160x100x16 - explain me the logic */
1709
            height = 100;
1710
        } else {
1711
            height = s->cr[0x12] | 
1712
                ((s->cr[0x07] & 0x02) << 7) | 
1713
                ((s->cr[0x07] & 0x40) << 3);
1714
            height = (height + 1) / cheight;
1715
        }
1716

    
1717
        size = (height * width);
1718
        if (size > CH_ATTR_SIZE) {
1719
            if (!full_update)
1720
                return;
1721

    
1722
            sprintf(msg_buffer, "%i x %i Text mode", width, height);
1723
            break;
1724
        }
1725

    
1726
        if (width != s->last_width || height != s->last_height ||
1727
            cw != s->last_cw || cheight != s->last_ch) {
1728
            s->last_scr_width = width * cw;
1729
            s->last_scr_height = height * cheight;
1730
            dpy_resize(s->ds, width, height);
1731
            s->last_width = width;
1732
            s->last_height = height;
1733
            s->last_ch = cheight;
1734
            s->last_cw = cw;
1735
            full_update = 1;
1736
        }
1737

    
1738
        /* Update "hardware" cursor */
1739
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1740
        if (cursor_offset != s->cursor_offset ||
1741
            s->cr[0xa] != s->cursor_start ||
1742
            s->cr[0xb] != s->cursor_end || full_update) {
1743
            cursor_visible = !(s->cr[0xa] & 0x20);
1744
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1745
                dpy_cursor(s->ds,
1746
                           TEXTMODE_X(cursor_offset),
1747
                           TEXTMODE_Y(cursor_offset));
1748
            else
1749
                dpy_cursor(s->ds, -1, -1);
1750
            s->cursor_offset = cursor_offset;
1751
            s->cursor_start = s->cr[0xa];
1752
            s->cursor_end = s->cr[0xb];
1753
        }
1754

    
1755
        src = (uint32_t *) s->vram_ptr + s->start_addr;
1756
        dst = chardata;
1757

    
1758
        if (full_update) {
1759
            for (i = 0; i < size; src ++, dst ++, i ++)
1760
                console_write_ch(dst, VMEM2CHTYPE(*src));
1761

    
1762
            dpy_update(s->ds, 0, 0, width, height);
1763
        } else {
1764
            c_max = 0;
1765

    
1766
            for (i = 0; i < size; src ++, dst ++, i ++) {
1767
                console_write_ch(&val, VMEM2CHTYPE(*src));
1768
                if (*dst != val) {
1769
                    *dst = val;
1770
                    c_max = i;
1771
                    break;
1772
                }
1773
            }
1774
            c_min = i;
1775
            for (; i < size; src ++, dst ++, i ++) {
1776
                console_write_ch(&val, VMEM2CHTYPE(*src));
1777
                if (*dst != val) {
1778
                    *dst = val;
1779
                    c_max = i;
1780
                }
1781
            }
1782

    
1783
            if (c_min <= c_max) {
1784
                i = TEXTMODE_Y(c_min);
1785
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1786
            }
1787
        }
1788

    
1789
        return;
1790
    case GMODE_GRAPH:
1791
        if (!full_update)
1792
            return;
1793

    
1794
        s->get_resolution(s, &width, &height);
1795
        sprintf(msg_buffer, "%i x %i Graphic mode", width, height);
1796
        break;
1797
    case GMODE_BLANK:
1798
    default:
1799
        if (!full_update)
1800
            return;
1801

    
1802
        sprintf(msg_buffer, "VGA Blank mode");
1803
        break;
1804
    }
1805

    
1806
    /* Display a message */
1807
    dpy_cursor(s->ds, -1, -1);
1808
    dpy_resize(s->ds, 60, 3);
1809

    
1810
    for (dst = chardata, i = 0; i < 60 * 3; i ++)
1811
        console_write_ch(dst ++, ' ');
1812

    
1813
    size = strlen(msg_buffer);
1814
    width = (60 - size) / 2;
1815
    dst = chardata + 60 + width;
1816
    for (i = 0; i < size; i ++)
1817
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
1818

    
1819
    dpy_update(s->ds, 0, 0, 60, 3);
1820
}
1821

    
1822
static CPUReadMemoryFunc *vga_mem_read[3] = {
1823
    vga_mem_readb,
1824
    vga_mem_readw,
1825
    vga_mem_readl,
1826
};
1827

    
1828
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1829
    vga_mem_writeb,
1830
    vga_mem_writew,
1831
    vga_mem_writel,
1832
};
1833

    
1834
static void vga_save(QEMUFile *f, void *opaque)
1835
{
1836
    VGAState *s = opaque;
1837
    int i;
1838

    
1839
    if (s->pci_dev)
1840
        pci_device_save(s->pci_dev, f);
1841

    
1842
    qemu_put_be32s(f, &s->latch);
1843
    qemu_put_8s(f, &s->sr_index);
1844
    qemu_put_buffer(f, s->sr, 8);
1845
    qemu_put_8s(f, &s->gr_index);
1846
    qemu_put_buffer(f, s->gr, 16);
1847
    qemu_put_8s(f, &s->ar_index);
1848
    qemu_put_buffer(f, s->ar, 21);
1849
    qemu_put_be32(f, s->ar_flip_flop);
1850
    qemu_put_8s(f, &s->cr_index);
1851
    qemu_put_buffer(f, s->cr, 256);
1852
    qemu_put_8s(f, &s->msr);
1853
    qemu_put_8s(f, &s->fcr);
1854
    qemu_put_byte(f, s->st00);
1855
    qemu_put_8s(f, &s->st01);
1856

    
1857
    qemu_put_8s(f, &s->dac_state);
1858
    qemu_put_8s(f, &s->dac_sub_index);
1859
    qemu_put_8s(f, &s->dac_read_index);
1860
    qemu_put_8s(f, &s->dac_write_index);
1861
    qemu_put_buffer(f, s->dac_cache, 3);
1862
    qemu_put_buffer(f, s->palette, 768);
1863

    
1864
    qemu_put_be32(f, s->bank_offset);
1865
#ifdef CONFIG_BOCHS_VBE
1866
    qemu_put_byte(f, 1);
1867
    qemu_put_be16s(f, &s->vbe_index);
1868
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1869
        qemu_put_be16s(f, &s->vbe_regs[i]);
1870
    qemu_put_be32s(f, &s->vbe_start_addr);
1871
    qemu_put_be32s(f, &s->vbe_line_offset);
1872
    qemu_put_be32s(f, &s->vbe_bank_mask);
1873
#else
1874
    qemu_put_byte(f, 0);
1875
#endif
1876
}
1877

    
1878
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1879
{
1880
    VGAState *s = opaque;
1881
    int is_vbe, i, ret;
1882

    
1883
    if (version_id > 2)
1884
        return -EINVAL;
1885

    
1886
    if (s->pci_dev && version_id >= 2) {
1887
        ret = pci_device_load(s->pci_dev, f);
1888
        if (ret < 0)
1889
            return ret;
1890
    }
1891

    
1892
    qemu_get_be32s(f, &s->latch);
1893
    qemu_get_8s(f, &s->sr_index);
1894
    qemu_get_buffer(f, s->sr, 8);
1895
    qemu_get_8s(f, &s->gr_index);
1896
    qemu_get_buffer(f, s->gr, 16);
1897
    qemu_get_8s(f, &s->ar_index);
1898
    qemu_get_buffer(f, s->ar, 21);
1899
    s->ar_flip_flop=qemu_get_be32(f);
1900
    qemu_get_8s(f, &s->cr_index);
1901
    qemu_get_buffer(f, s->cr, 256);
1902
    qemu_get_8s(f, &s->msr);
1903
    qemu_get_8s(f, &s->fcr);
1904
    qemu_get_8s(f, &s->st00);
1905
    qemu_get_8s(f, &s->st01);
1906

    
1907
    qemu_get_8s(f, &s->dac_state);
1908
    qemu_get_8s(f, &s->dac_sub_index);
1909
    qemu_get_8s(f, &s->dac_read_index);
1910
    qemu_get_8s(f, &s->dac_write_index);
1911
    qemu_get_buffer(f, s->dac_cache, 3);
1912
    qemu_get_buffer(f, s->palette, 768);
1913

    
1914
    s->bank_offset=qemu_get_be32(f);
1915
    is_vbe = qemu_get_byte(f);
1916
#ifdef CONFIG_BOCHS_VBE
1917
    if (!is_vbe)
1918
        return -EINVAL;
1919
    qemu_get_be16s(f, &s->vbe_index);
1920
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1921
        qemu_get_be16s(f, &s->vbe_regs[i]);
1922
    qemu_get_be32s(f, &s->vbe_start_addr);
1923
    qemu_get_be32s(f, &s->vbe_line_offset);
1924
    qemu_get_be32s(f, &s->vbe_bank_mask);
1925
#else
1926
    if (is_vbe)
1927
        return -EINVAL;
1928
#endif
1929

    
1930
    /* force refresh */
1931
    s->graphic_mode = -1;
1932
    return 0;
1933
}
1934

    
1935
typedef struct PCIVGAState {
1936
    PCIDevice dev;
1937
    VGAState vga_state;
1938
} PCIVGAState;
1939

    
1940
static void vga_map(PCIDevice *pci_dev, int region_num,
1941
                    uint32_t addr, uint32_t size, int type)
1942
{
1943
    PCIVGAState *d = (PCIVGAState *)pci_dev;
1944
    VGAState *s = &d->vga_state;
1945
    if (region_num == PCI_ROM_SLOT) {
1946
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1947
    } else {
1948
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1949
    }
1950
}
1951

    
1952
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
1953
                     unsigned long vga_ram_offset, int vga_ram_size)
1954
{
1955
    int i, j, v, b;
1956

    
1957
    for(i = 0;i < 256; i++) {
1958
        v = 0;
1959
        for(j = 0; j < 8; j++) {
1960
            v |= ((i >> j) & 1) << (j * 4);
1961
        }
1962
        expand4[i] = v;
1963

    
1964
        v = 0;
1965
        for(j = 0; j < 4; j++) {
1966
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1967
        }
1968
        expand2[i] = v;
1969
    }
1970
    for(i = 0; i < 16; i++) {
1971
        v = 0;
1972
        for(j = 0; j < 4; j++) {
1973
            b = ((i >> j) & 1);
1974
            v |= b << (2 * j);
1975
            v |= b << (2 * j + 1);
1976
        }
1977
        expand4to8[i] = v;
1978
    }
1979

    
1980
    vga_reset(s);
1981

    
1982
    s->vram_ptr = vga_ram_base;
1983
    s->vram_offset = vga_ram_offset;
1984
    s->vram_size = vga_ram_size;
1985
    s->ds = ds;
1986
    s->get_bpp = vga_get_bpp;
1987
    s->get_offsets = vga_get_offsets;
1988
    s->get_resolution = vga_get_resolution;
1989
    s->update = vga_update_display;
1990
    s->invalidate = vga_invalidate_display;
1991
    s->screen_dump = vga_screen_dump;
1992
    s->text_update = vga_update_text;
1993
}
1994

    
1995
/* used by both ISA and PCI */
1996
void vga_init(VGAState *s)
1997
{
1998
    int vga_io_memory;
1999

    
2000
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2001

    
2002
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2003

    
2004
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2005
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2006
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2007
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2008

    
2009
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2010

    
2011
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2012
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2013
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2014
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2015
    s->bank_offset = 0;
2016

    
2017
#ifdef CONFIG_BOCHS_VBE
2018
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
2019
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
2020
#if defined (TARGET_I386)
2021
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2022
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2023

    
2024
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2025
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2026

    
2027
    /* old Bochs IO ports */
2028
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2029
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2030

    
2031
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2032
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2033
#else
2034
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2035
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2036

    
2037
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2038
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2039
#endif
2040
#endif /* CONFIG_BOCHS_VBE */
2041

    
2042
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2043
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2044
                                 vga_io_memory);
2045
}
2046

    
2047
/* Memory mapped interface */
2048
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2049
{
2050
    VGAState *s = opaque;
2051

    
2052
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
2053
}
2054

    
2055
static void vga_mm_writeb (void *opaque,
2056
                           target_phys_addr_t addr, uint32_t value)
2057
{
2058
    VGAState *s = opaque;
2059

    
2060
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
2061
}
2062

    
2063
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2064
{
2065
    VGAState *s = opaque;
2066

    
2067
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
2068
}
2069

    
2070
static void vga_mm_writew (void *opaque,
2071
                           target_phys_addr_t addr, uint32_t value)
2072
{
2073
    VGAState *s = opaque;
2074

    
2075
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
2076
}
2077

    
2078
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2079
{
2080
    VGAState *s = opaque;
2081

    
2082
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
2083
}
2084

    
2085
static void vga_mm_writel (void *opaque,
2086
                           target_phys_addr_t addr, uint32_t value)
2087
{
2088
    VGAState *s = opaque;
2089

    
2090
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
2091
}
2092

    
2093
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2094
    &vga_mm_readb,
2095
    &vga_mm_readw,
2096
    &vga_mm_readl,
2097
};
2098

    
2099
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2100
    &vga_mm_writeb,
2101
    &vga_mm_writew,
2102
    &vga_mm_writel,
2103
};
2104

    
2105
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2106
                        target_phys_addr_t ctrl_base, int it_shift)
2107
{
2108
    int s_ioport_ctrl, vga_io_memory;
2109

    
2110
    s->base_ctrl = ctrl_base;
2111
    s->it_shift = it_shift;
2112
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2113
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2114

    
2115
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
2116

    
2117
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2118
    s->bank_offset = 0;
2119
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2120
}
2121

    
2122
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2123
                 unsigned long vga_ram_offset, int vga_ram_size)
2124
{
2125
    VGAState *s;
2126

    
2127
    s = qemu_mallocz(sizeof(VGAState));
2128
    if (!s)
2129
        return -1;
2130

    
2131
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2132
    vga_init(s);
2133

    
2134
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
2135
                         s->text_update, s);
2136

    
2137
#ifdef CONFIG_BOCHS_VBE
2138
    /* XXX: use optimized standard vga accesses */
2139
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2140
                                 vga_ram_size, vga_ram_offset);
2141
#endif
2142
    return 0;
2143
}
2144

    
2145
int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2146
                    unsigned long vga_ram_offset, int vga_ram_size,
2147
                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2148
                    int it_shift)
2149
{
2150
    VGAState *s;
2151

    
2152
    s = qemu_mallocz(sizeof(VGAState));
2153
    if (!s)
2154
        return -1;
2155

    
2156
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2157
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
2158

    
2159
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
2160
                         s->text_update, s);
2161

    
2162
#ifdef CONFIG_BOCHS_VBE
2163
    /* XXX: use optimized standard vga accesses */
2164
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2165
                                 vga_ram_size, vga_ram_offset);
2166
#endif
2167
    return 0;
2168
}
2169

    
2170
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2171
                 unsigned long vga_ram_offset, int vga_ram_size,
2172
                 unsigned long vga_bios_offset, int vga_bios_size)
2173
{
2174
    PCIVGAState *d;
2175
    VGAState *s;
2176
    uint8_t *pci_conf;
2177

    
2178
    d = (PCIVGAState *)pci_register_device(bus, "VGA",
2179
                                           sizeof(PCIVGAState),
2180
                                           -1, NULL, NULL);
2181
    if (!d)
2182
        return -1;
2183
    s = &d->vga_state;
2184

    
2185
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2186
    vga_init(s);
2187

    
2188
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump,
2189
                         s->text_update, s);
2190

    
2191
    s->pci_dev = &d->dev;
2192

    
2193
    pci_conf = d->dev.config;
2194
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2195
    pci_conf[0x01] = 0x12;
2196
    pci_conf[0x02] = 0x11;
2197
    pci_conf[0x03] = 0x11;
2198
    pci_conf[0x0a] = 0x00; // VGA controller
2199
    pci_conf[0x0b] = 0x03;
2200
    pci_conf[0x0e] = 0x00; // header_type
2201

    
2202
    /* XXX: vga_ram_size must be a power of two */
2203
    pci_register_io_region(&d->dev, 0, vga_ram_size,
2204
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2205
    if (vga_bios_size != 0) {
2206
        unsigned int bios_total_size;
2207
        s->bios_offset = vga_bios_offset;
2208
        s->bios_size = vga_bios_size;
2209
        /* must be a power of two */
2210
        bios_total_size = 1;
2211
        while (bios_total_size < vga_bios_size)
2212
            bios_total_size <<= 1;
2213
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2214
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2215
    }
2216
    return 0;
2217
}
2218

    
2219
/********************************************************/
2220
/* vga screen dump */
2221

    
2222
static int vga_save_w, vga_save_h;
2223

    
2224
static void vga_save_dpy_update(DisplayState *s,
2225
                                int x, int y, int w, int h)
2226
{
2227
}
2228

    
2229
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2230
{
2231
    s->linesize = w * 4;
2232
    s->data = qemu_malloc(h * s->linesize);
2233
    vga_save_w = w;
2234
    vga_save_h = h;
2235
}
2236

    
2237
static void vga_save_dpy_refresh(DisplayState *s)
2238
{
2239
}
2240

    
2241
int ppm_save(const char *filename, uint8_t *data,
2242
             int w, int h, int linesize)
2243
{
2244
    FILE *f;
2245
    uint8_t *d, *d1;
2246
    unsigned int v;
2247
    int y, x;
2248

    
2249
    f = fopen(filename, "wb");
2250
    if (!f)
2251
        return -1;
2252
    fprintf(f, "P6\n%d %d\n%d\n",
2253
            w, h, 255);
2254
    d1 = data;
2255
    for(y = 0; y < h; y++) {
2256
        d = d1;
2257
        for(x = 0; x < w; x++) {
2258
            v = *(uint32_t *)d;
2259
            fputc((v >> 16) & 0xff, f);
2260
            fputc((v >> 8) & 0xff, f);
2261
            fputc((v) & 0xff, f);
2262
            d += 4;
2263
        }
2264
        d1 += linesize;
2265
    }
2266
    fclose(f);
2267
    return 0;
2268
}
2269

    
2270
/* save the vga display in a PPM image even if no display is
2271
   available */
2272
static void vga_screen_dump(void *opaque, const char *filename)
2273
{
2274
    VGAState *s = (VGAState *)opaque;
2275
    DisplayState *saved_ds, ds1, *ds = &ds1;
2276

    
2277
    /* XXX: this is a little hackish */
2278
    vga_invalidate_display(s);
2279
    saved_ds = s->ds;
2280

    
2281
    memset(ds, 0, sizeof(DisplayState));
2282
    ds->dpy_update = vga_save_dpy_update;
2283
    ds->dpy_resize = vga_save_dpy_resize;
2284
    ds->dpy_refresh = vga_save_dpy_refresh;
2285
    ds->depth = 32;
2286

    
2287
    s->ds = ds;
2288
    s->graphic_mode = -1;
2289
    vga_update_display(s);
2290

    
2291
    if (ds->data) {
2292
        ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2293
                 s->ds->linesize);
2294
        qemu_free(ds->data);
2295
    }
2296
    s->ds = saved_ds;
2297
}