Statistics
| Branch: | Revision:

root / hw / vga.c @ 44486a89

History | View | Annotate | Download (60 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 "vl.h"
25
#include "vga_int.h"
26
#include "pixel_ops.h"
27

    
28
//#define DEBUG_VGA
29
//#define DEBUG_VGA_MEM
30
//#define DEBUG_VGA_REG
31

    
32
//#define DEBUG_BOCHS_VBE
33

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

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

    
65
#define cbswap_32(__x) \
66
((uint32_t)( \
67
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
68
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
69
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
70
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
71

    
72
#ifdef WORDS_BIGENDIAN
73
#define PAT(x) cbswap_32(x)
74
#else
75
#define PAT(x) (x)
76
#endif
77

    
78
#ifdef WORDS_BIGENDIAN
79
#define BIG 1
80
#else
81
#define BIG 0
82
#endif
83

    
84
#ifdef WORDS_BIGENDIAN
85
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
86
#else
87
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
88
#endif
89

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

    
109
#undef PAT
110

    
111
#ifdef WORDS_BIGENDIAN
112
#define PAT(x) (x)
113
#else
114
#define PAT(x) cbswap_32(x)
115
#endif
116

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

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

    
143
static uint32_t expand4[256];
144
static uint16_t expand2[256];
145
static uint8_t expand4to8[16];
146

    
147
static void vga_screen_dump(void *opaque, const char *filename);
148

    
149
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
150
{
151
    VGAState *s = opaque;
152
    int val, index;
153

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

    
243
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
244
{
245
    VGAState *s = opaque;
246
    int index;
247

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

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

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

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

    
374
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
375
{
376
    VGAState *s = opaque;
377
    uint32_t val;
378

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

    
408
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
409
{
410
    VGAState *s = opaque;
411
    s->vbe_index = val;
412
}
413

    
414
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
415
{
416
    VGAState *s = opaque;
417

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

    
464
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
465
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
466
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
467
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
468
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
469
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
470
                
471
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
472
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
473
                else
474
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
475
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
476
                s->vbe_start_addr = 0;
477

    
478
                /* clear the screen (should be done in BIOS) */
479
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
480
                    memset(s->vram_ptr, 0, 
481
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
482
                }
483
                
484
                /* we initialize the VGA graphic mode (should be done
485
                   in BIOS) */
486
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
487
                s->cr[0x17] |= 3; /* no CGA modes */
488
                s->cr[0x13] = s->vbe_line_offset >> 3;
489
                /* width */
490
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
491
                /* height (only meaningful if < 1024) */
492
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
493
                s->cr[0x12] = h;
494
                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
495
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
496
                /* line compare to 1023 */
497
                s->cr[0x18] = 0xff;
498
                s->cr[0x07] |= 0x10;
499
                s->cr[0x09] |= 0x40;
500
                
501
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
502
                    shift_control = 0;
503
                    s->sr[0x01] &= ~8; /* no double line */
504
                } else {
505
                    shift_control = 2;
506
                    s->sr[4] |= 0x08; /* set chain 4 mode */
507
                    s->sr[2] |= 0x0f; /* activate all planes */
508
                }
509
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
510
                s->cr[0x09] &= ~0x9f; /* no double scan */
511
            } else {
512
                /* XXX: the bios should do that */
513
                s->bank_offset = 0;
514
            }
515
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
516
            s->vbe_regs[s->vbe_index] = val;
517
            break;
518
        case VBE_DISPI_INDEX_VIRT_WIDTH:
519
            {
520
                int w, h, line_offset;
521

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

    
559
/* called for accesses between 0xa0000 and 0xc0000 */
560
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
561
{
562
    VGAState *s = opaque;
563
    int memory_map_mode, plane;
564
    uint32_t ret;
565
    
566
    /* convert to VGA memory offset */
567
    memory_map_mode = (s->gr[6] >> 2) & 3;
568
    addr &= 0x1ffff;
569
    switch(memory_map_mode) {
570
    case 0:
571
        break;
572
    case 1:
573
        if (addr >= 0x10000)
574
            return 0xff;
575
        addr += s->bank_offset;
576
        break;
577
    case 2:
578
        addr -= 0x10000;
579
        if (addr >= 0x8000)
580
            return 0xff;
581
        break;
582
    default:
583
    case 3:
584
        addr -= 0x18000;
585
        if (addr >= 0x8000)
586
            return 0xff;
587
        break;
588
    }
589
    
590
    if (s->sr[4] & 0x08) {
591
        /* chain 4 mode : simplest access */
592
        ret = s->vram_ptr[addr];
593
    } else if (s->gr[5] & 0x10) {
594
        /* odd/even mode (aka text mode mapping) */
595
        plane = (s->gr[4] & 2) | (addr & 1);
596
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
597
    } else {
598
        /* standard VGA latched access */
599
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
600

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

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

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

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

    
653
#ifdef DEBUG_VGA_MEM
654
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
655
#endif
656
    /* convert to VGA memory offset */
657
    memory_map_mode = (s->gr[6] >> 2) & 3;
658
    addr &= 0x1ffff;
659
    switch(memory_map_mode) {
660
    case 0:
661
        break;
662
    case 1:
663
        if (addr >= 0x10000)
664
            return;
665
        addr += s->bank_offset;
666
        break;
667
    case 2:
668
        addr -= 0x10000;
669
        if (addr >= 0x8000)
670
            return;
671
        break;
672
    default:
673
    case 3:
674
        addr -= 0x18000;
675
        if (addr >= 0x8000)
676
            return;
677
        break;
678
    }
679
    
680
    if (s->sr[4] & 0x08) {
681
        /* chain 4 mode : simplest access */
682
        plane = addr & 3;
683
        mask = (1 << plane);
684
        if (s->sr[2] & mask) {
685
            s->vram_ptr[addr] = val;
686
#ifdef DEBUG_VGA_MEM
687
            printf("vga: chain4: [0x%x]\n", addr);
688
#endif
689
            s->plane_updated |= mask; /* only used to detect font change */
690
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
691
        }
692
    } else if (s->gr[5] & 0x10) {
693
        /* odd/even mode (aka text mode mapping) */
694
        plane = (s->gr[4] & 2) | (addr & 1);
695
        mask = (1 << plane);
696
        if (s->sr[2] & mask) {
697
            addr = ((addr & ~1) << 1) | plane;
698
            s->vram_ptr[addr] = val;
699
#ifdef DEBUG_VGA_MEM
700
            printf("vga: odd/even: [0x%x]\n", addr);
701
#endif
702
            s->plane_updated |= mask; /* only used to detect font change */
703
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
704
        }
705
    } else {
706
        /* standard VGA latched access */
707
        write_mode = s->gr[5] & 3;
708
        switch(write_mode) {
709
        default:
710
        case 0:
711
            /* rotate */
712
            b = s->gr[3] & 7;
713
            val = ((val >> b) | (val << (8 - b))) & 0xff;
714
            val |= val << 8;
715
            val |= val << 16;
716

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

    
734
            bit_mask = s->gr[8] & val;
735
            val = mask16[s->gr[0]];
736
            break;
737
        }
738

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

    
760
        /* apply bit mask */
761
        bit_mask |= bit_mask << 8;
762
        bit_mask |= bit_mask << 16;
763
        val = (val & bit_mask) | (s->latch & ~bit_mask);
764

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

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

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

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

    
816
#define DEPTH 8
817
#include "vga_template.h"
818

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

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

    
826
#define DEPTH 16
827
#include "vga_template.h"
828

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

    
833
#define DEPTH 32
834
#include "vga_template.h"
835

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

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

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

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

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

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

    
883
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
884
{
885
    unsigned int col;
886
    col = rgb_to_pixel32(r, g, b);
887
    return col;
888
}
889

    
890
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
891
{
892
    unsigned int col;
893
    col = rgb_to_pixel32bgr(r, g, b);
894
    return col;
895
}
896

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

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

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

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

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

    
969
        /* starting address */
970
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
971

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

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

    
990
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
991

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

    
1003
#define NB_DEPTHS 7
1004

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

    
1029
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1030
    vga_draw_glyph8_8,
1031
    vga_draw_glyph8_16,
1032
    vga_draw_glyph8_16,
1033
    vga_draw_glyph8_32,
1034
    vga_draw_glyph8_32,
1035
    vga_draw_glyph8_16,
1036
    vga_draw_glyph8_16,
1037
};
1038

    
1039
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1040
    vga_draw_glyph16_8,
1041
    vga_draw_glyph16_16,
1042
    vga_draw_glyph16_16,
1043
    vga_draw_glyph16_32,
1044
    vga_draw_glyph16_32,
1045
    vga_draw_glyph16_16,
1046
    vga_draw_glyph16_16,
1047
};
1048

    
1049
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1050
    vga_draw_glyph9_8,
1051
    vga_draw_glyph9_16,
1052
    vga_draw_glyph9_16,
1053
    vga_draw_glyph9_32,
1054
    vga_draw_glyph9_32,
1055
    vga_draw_glyph9_16,
1056
    vga_draw_glyph9_16,
1057
};
1058
    
1059
static const uint8_t cursor_glyph[32 * 4] = {
1060
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1061
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1062
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
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
};    
1077

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

    
1099
    full_update |= update_palette16(s);
1100
    palette = s->last_palette;
1101
    
1102
    /* compute font data address (in plane 2) */
1103
    v = s->sr[3];
1104
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1105
    if (offset != s->font_offsets[0]) {
1106
        s->font_offsets[0] = offset;
1107
        full_update = 1;
1108
    }
1109
    font_base[0] = s->vram_ptr + offset;
1110

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

    
1125
    line_offset = s->line_offset;
1126
    s1 = s->vram_ptr + (s->start_addr * 4);
1127

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

    
1151
    if (width != s->last_width || height != s->last_height ||
1152
        cw != s->last_cw || cheight != s->last_ch) {
1153
        s->last_scr_width = width * cw;
1154
        s->last_scr_height = height * cheight;
1155
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1156
        s->last_width = width;
1157
        s->last_height = height;
1158
        s->last_ch = cheight;
1159
        s->last_cw = cw;
1160
        full_update = 1;
1161
    }
1162
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1163
    if (cursor_offset != s->cursor_offset ||
1164
        s->cr[0xa] != s->cursor_start ||
1165
        s->cr[0xb] != s->cursor_end) {
1166
      /* if the cursor position changed, we update the old and new
1167
         chars */
1168
        if (s->cursor_offset < CH_ATTR_SIZE)
1169
            s->last_ch_attr[s->cursor_offset] = -1;
1170
        if (cursor_offset < CH_ATTR_SIZE)
1171
            s->last_ch_attr[cursor_offset] = -1;
1172
        s->cursor_offset = cursor_offset;
1173
        s->cursor_start = s->cr[0xa];
1174
        s->cursor_end = s->cr[0xb];
1175
    }
1176
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1177
    
1178
    depth_index = get_depth_index(s->ds);
1179
    if (cw == 16)
1180
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1181
    else
1182
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1183
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1184
    
1185
    dest = s->ds->data;
1186
    linesize = s->ds->linesize;
1187
    ch_attr_ptr = s->last_ch_attr;
1188
    for(cy = 0; cy < height; cy++) {
1189
        d1 = dest;
1190
        src = s1;
1191
        cx_min = width;
1192
        cx_max = -1;
1193
        for(cx = 0; cx < width; cx++) {
1194
            ch_attr = *(uint16_t *)src;
1195
            if (full_update || ch_attr != *ch_attr_ptr) {
1196
                if (cx < cx_min)
1197
                    cx_min = cx;
1198
                if (cx > cx_max)
1199
                    cx_max = cx;
1200
                *ch_attr_ptr = ch_attr;
1201
#ifdef WORDS_BIGENDIAN
1202
                ch = ch_attr >> 8;
1203
                cattr = ch_attr & 0xff;
1204
#else
1205
                ch = ch_attr & 0xff;
1206
                cattr = ch_attr >> 8;
1207
#endif
1208
                font_ptr = font_base[(cattr >> 3) & 1];
1209
                font_ptr += 32 * 4 * ch;
1210
                bgcol = palette[cattr >> 4];
1211
                fgcol = palette[cattr & 0x0f];
1212
                if (cw != 9) {
1213
                    vga_draw_glyph8(d1, linesize, 
1214
                                    font_ptr, cheight, fgcol, bgcol);
1215
                } else {
1216
                    dup9 = 0;
1217
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1218
                        dup9 = 1;
1219
                    vga_draw_glyph9(d1, linesize, 
1220
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1221
                }
1222
                if (src == cursor_ptr &&
1223
                    !(s->cr[0x0a] & 0x20)) {
1224
                    int line_start, line_last, h;
1225
                    /* draw the cursor */
1226
                    line_start = s->cr[0x0a] & 0x1f;
1227
                    line_last = s->cr[0x0b] & 0x1f;
1228
                    /* XXX: check that */
1229
                    if (line_last > cheight - 1)
1230
                        line_last = cheight - 1;
1231
                    if (line_last >= line_start && line_start < cheight) {
1232
                        h = line_last - line_start + 1;
1233
                        d = d1 + linesize * line_start;
1234
                        if (cw != 9) {
1235
                            vga_draw_glyph8(d, linesize, 
1236
                                            cursor_glyph, h, fgcol, bgcol);
1237
                        } else {
1238
                            vga_draw_glyph9(d, linesize, 
1239
                                            cursor_glyph, h, fgcol, bgcol, 1);
1240
                        }
1241
                    }
1242
                }
1243
            }
1244
            d1 += x_incr;
1245
            src += 4;
1246
            ch_attr_ptr++;
1247
        }
1248
        if (cx_max != -1) {
1249
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1250
                       (cx_max - cx_min + 1) * cw, cheight);
1251
        }
1252
        dest += linesize * cheight;
1253
        s1 += line_offset;
1254
    }
1255
}
1256

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

    
1271
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1272
    vga_draw_line2_8,
1273
    vga_draw_line2_16,
1274
    vga_draw_line2_16,
1275
    vga_draw_line2_32,
1276
    vga_draw_line2_32,
1277
    vga_draw_line2_16,
1278
    vga_draw_line2_16,
1279

    
1280
    vga_draw_line2d2_8,
1281
    vga_draw_line2d2_16,
1282
    vga_draw_line2d2_16,
1283
    vga_draw_line2d2_32,
1284
    vga_draw_line2d2_32,
1285
    vga_draw_line2d2_16,
1286
    vga_draw_line2d2_16,
1287

    
1288
    vga_draw_line4_8,
1289
    vga_draw_line4_16,
1290
    vga_draw_line4_16,
1291
    vga_draw_line4_32,
1292
    vga_draw_line4_32,
1293
    vga_draw_line4_16,
1294
    vga_draw_line4_16,
1295

    
1296
    vga_draw_line4d2_8,
1297
    vga_draw_line4d2_16,
1298
    vga_draw_line4d2_16,
1299
    vga_draw_line4d2_32,
1300
    vga_draw_line4d2_32,
1301
    vga_draw_line4d2_16,
1302
    vga_draw_line4d2_16,
1303

    
1304
    vga_draw_line8d2_8,
1305
    vga_draw_line8d2_16,
1306
    vga_draw_line8d2_16,
1307
    vga_draw_line8d2_32,
1308
    vga_draw_line8d2_32,
1309
    vga_draw_line8d2_16,
1310
    vga_draw_line8d2_16,
1311

    
1312
    vga_draw_line8_8,
1313
    vga_draw_line8_16,
1314
    vga_draw_line8_16,
1315
    vga_draw_line8_32,
1316
    vga_draw_line8_32,
1317
    vga_draw_line8_16,
1318
    vga_draw_line8_16,
1319

    
1320
    vga_draw_line15_8,
1321
    vga_draw_line15_15,
1322
    vga_draw_line15_16,
1323
    vga_draw_line15_32,
1324
    vga_draw_line15_32bgr,
1325
    vga_draw_line15_15bgr,
1326
    vga_draw_line15_16bgr,
1327

    
1328
    vga_draw_line16_8,
1329
    vga_draw_line16_15,
1330
    vga_draw_line16_16,
1331
    vga_draw_line16_32,
1332
    vga_draw_line16_32bgr,
1333
    vga_draw_line16_15bgr,
1334
    vga_draw_line16_16bgr,
1335

    
1336
    vga_draw_line24_8,
1337
    vga_draw_line24_15,
1338
    vga_draw_line24_16,
1339
    vga_draw_line24_32,
1340
    vga_draw_line24_32bgr,
1341
    vga_draw_line24_15bgr,
1342
    vga_draw_line24_16bgr,
1343

    
1344
    vga_draw_line32_8,
1345
    vga_draw_line32_15,
1346
    vga_draw_line32_16,
1347
    vga_draw_line32_32,
1348
    vga_draw_line32_32bgr,
1349
    vga_draw_line32_15bgr,
1350
    vga_draw_line32_16bgr,
1351
};
1352

    
1353
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1354

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

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

    
1379
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1380
{
1381
    int width, height;
1382
    
1383
#ifdef CONFIG_BOCHS_VBE
1384
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1385
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1386
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1387
    } else 
1388
#endif
1389
    {
1390
        width = (s->cr[0x01] + 1) * 8;
1391
        height = s->cr[0x12] | 
1392
            ((s->cr[0x07] & 0x02) << 7) | 
1393
            ((s->cr[0x07] & 0x40) << 3);
1394
        height = (height + 1);
1395
    }
1396
    *pwidth = width;
1397
    *pheight = height;
1398
}
1399

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

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

    
1426
    s->get_resolution(s, &width, &height);
1427
    disp_width = width;
1428

    
1429
    shift_control = (s->gr[0x05] >> 5) & 3;
1430
    double_scan = (s->cr[0x09] >> 7);
1431
    if (shift_control != 1) {
1432
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1433
    } else {
1434
        /* in CGA modes, multi_scan is ignored */
1435
        /* XXX: is it correct ? */
1436
        multi_scan = double_scan;
1437
    }
1438
    multi_run = multi_scan;
1439
    if (shift_control != s->shift_control ||
1440
        double_scan != s->double_scan) {
1441
        full_update = 1;
1442
        s->shift_control = shift_control;
1443
        s->double_scan = double_scan;
1444
    }
1445
    
1446
    if (shift_control == 0) {
1447
        full_update |= update_palette16(s);
1448
        if (s->sr[0x01] & 8) {
1449
            v = VGA_DRAW_LINE4D2;
1450
            disp_width <<= 1;
1451
        } else {
1452
            v = VGA_DRAW_LINE4;
1453
        }
1454
    } else if (shift_control == 1) {
1455
        full_update |= update_palette16(s);
1456
        if (s->sr[0x01] & 8) {
1457
            v = VGA_DRAW_LINE2D2;
1458
            disp_width <<= 1;
1459
        } else {
1460
            v = VGA_DRAW_LINE2;
1461
        }
1462
    } else {
1463
        switch(s->get_bpp(s)) {
1464
        default:
1465
        case 0:
1466
            full_update |= update_palette256(s);
1467
            v = VGA_DRAW_LINE8D2;
1468
            break;
1469
        case 8:
1470
            full_update |= update_palette256(s);
1471
            v = VGA_DRAW_LINE8;
1472
            break;
1473
        case 15:
1474
            v = VGA_DRAW_LINE15;
1475
            break;
1476
        case 16:
1477
            v = VGA_DRAW_LINE16;
1478
            break;
1479
        case 24:
1480
            v = VGA_DRAW_LINE24;
1481
            break;
1482
        case 32:
1483
            v = VGA_DRAW_LINE32;
1484
            break;
1485
        }
1486
    }
1487
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1488

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

    
1582
static void vga_draw_blank(VGAState *s, int full_update)
1583
{
1584
    int i, w, val;
1585
    uint8_t *d;
1586

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

    
1605
#define GMODE_TEXT     0
1606
#define GMODE_GRAPH    1
1607
#define GMODE_BLANK 2 
1608

    
1609
static void vga_update_display(void *opaque)
1610
{
1611
    VGAState *s = (VGAState *)opaque;
1612
    int full_update, graphic_mode;
1613

    
1614
    if (s->ds->depth == 0) {
1615
        /* nothing to do */
1616
    } else {
1617
        s->rgb_to_pixel = 
1618
            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1619
        
1620
        full_update = 0;
1621
        if (!(s->ar_index & 0x20)) {
1622
            graphic_mode = GMODE_BLANK;
1623
        } else {
1624
            graphic_mode = s->gr[6] & 1;
1625
        }
1626
        if (graphic_mode != s->graphic_mode) {
1627
            s->graphic_mode = graphic_mode;
1628
            full_update = 1;
1629
        }
1630
        switch(graphic_mode) {
1631
        case GMODE_TEXT:
1632
            vga_draw_text(s, full_update);
1633
            break;
1634
        case GMODE_GRAPH:
1635
            vga_draw_graphic(s, full_update);
1636
            break;
1637
        case GMODE_BLANK:
1638
        default:
1639
            vga_draw_blank(s, full_update);
1640
            break;
1641
        }
1642
    }
1643
}
1644

    
1645
/* force a full display refresh */
1646
static void vga_invalidate_display(void *opaque)
1647
{
1648
    VGAState *s = (VGAState *)opaque;
1649
    
1650
    s->last_width = -1;
1651
    s->last_height = -1;
1652
}
1653

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

    
1660
static CPUReadMemoryFunc *vga_mem_read[3] = {
1661
    vga_mem_readb,
1662
    vga_mem_readw,
1663
    vga_mem_readl,
1664
};
1665

    
1666
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1667
    vga_mem_writeb,
1668
    vga_mem_writew,
1669
    vga_mem_writel,
1670
};
1671

    
1672
static void vga_save(QEMUFile *f, void *opaque)
1673
{
1674
    VGAState *s = opaque;
1675
    int i;
1676

    
1677
    if (s->pci_dev)
1678
        pci_device_save(s->pci_dev, f);
1679

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

    
1695
    qemu_put_8s(f, &s->dac_state);
1696
    qemu_put_8s(f, &s->dac_sub_index);
1697
    qemu_put_8s(f, &s->dac_read_index);
1698
    qemu_put_8s(f, &s->dac_write_index);
1699
    qemu_put_buffer(f, s->dac_cache, 3);
1700
    qemu_put_buffer(f, s->palette, 768);
1701

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

    
1716
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1717
{
1718
    VGAState *s = opaque;
1719
    int is_vbe, i, ret;
1720

    
1721
    if (version_id > 2)
1722
        return -EINVAL;
1723

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

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

    
1745
    qemu_get_8s(f, &s->dac_state);
1746
    qemu_get_8s(f, &s->dac_sub_index);
1747
    qemu_get_8s(f, &s->dac_read_index);
1748
    qemu_get_8s(f, &s->dac_write_index);
1749
    qemu_get_buffer(f, s->dac_cache, 3);
1750
    qemu_get_buffer(f, s->palette, 768);
1751

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

    
1768
    /* force refresh */
1769
    s->graphic_mode = -1;
1770
    return 0;
1771
}
1772

    
1773
typedef struct PCIVGAState {
1774
    PCIDevice dev;
1775
    VGAState vga_state;
1776
} PCIVGAState;
1777

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

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

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

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

    
1818
    vga_reset(s);
1819

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

    
1832
/* used by both ISA and PCI */
1833
void vga_init(VGAState *s)
1834
{
1835
    int vga_io_memory;
1836

    
1837
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1838

    
1839
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1840

    
1841
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1842
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1843
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1844
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1845

    
1846
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1847

    
1848
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1849
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1850
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1851
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1852
    s->bank_offset = 0;
1853

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

    
1861
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1862
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1863

    
1864
    /* old Bochs IO ports */
1865
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1866
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1867

    
1868
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1869
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1870
#else
1871
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1872
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1873

    
1874
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1875
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1876
#endif
1877
#endif /* CONFIG_BOCHS_VBE */
1878

    
1879
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1880
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1881
                                 vga_io_memory);
1882
}
1883

    
1884
/* Memory mapped interface */
1885
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
1886
{
1887
    VGAState *s = opaque;
1888

    
1889
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
1890
}
1891

    
1892
static void vga_mm_writeb (void *opaque,
1893
                           target_phys_addr_t addr, uint32_t value)
1894
{
1895
    VGAState *s = opaque;
1896

    
1897
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
1898
}
1899

    
1900
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
1901
{
1902
    VGAState *s = opaque;
1903

    
1904
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
1905
}
1906

    
1907
static void vga_mm_writew (void *opaque,
1908
                           target_phys_addr_t addr, uint32_t value)
1909
{
1910
    VGAState *s = opaque;
1911

    
1912
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
1913
}
1914

    
1915
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
1916
{
1917
    VGAState *s = opaque;
1918

    
1919
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
1920
}
1921

    
1922
static void vga_mm_writel (void *opaque,
1923
                           target_phys_addr_t addr, uint32_t value)
1924
{
1925
    VGAState *s = opaque;
1926

    
1927
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
1928
}
1929

    
1930
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
1931
    &vga_mm_readb,
1932
    &vga_mm_readw,
1933
    &vga_mm_readl,
1934
};
1935

    
1936
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
1937
    &vga_mm_writeb,
1938
    &vga_mm_writew,
1939
    &vga_mm_writel,
1940
};
1941

    
1942
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
1943
                        target_phys_addr_t ctrl_base, int it_shift)
1944
{
1945
    int s_ioport_ctrl, vga_io_memory;
1946

    
1947
    s->base_ctrl = ctrl_base;
1948
    s->it_shift = it_shift;
1949
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
1950
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1951

    
1952
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1953

    
1954
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
1955
    s->bank_offset = 0;
1956
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
1957
}
1958

    
1959
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
1960
                 unsigned long vga_ram_offset, int vga_ram_size)
1961
{
1962
    VGAState *s;
1963

    
1964
    s = qemu_mallocz(sizeof(VGAState));
1965
    if (!s)
1966
        return -1;
1967

    
1968
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1969
    vga_init(s);
1970

    
1971
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1972

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

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

    
1988
    s = qemu_mallocz(sizeof(VGAState));
1989
    if (!s)
1990
        return -1;
1991

    
1992
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1993
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
1994

    
1995
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1996

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

    
2005
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
2006
                 unsigned long vga_ram_offset, int vga_ram_size,
2007
                 unsigned long vga_bios_offset, int vga_bios_size)
2008
{
2009
    PCIVGAState *d;
2010
    VGAState *s;
2011
    uint8_t *pci_conf;
2012
    
2013
    d = (PCIVGAState *)pci_register_device(bus, "VGA", 
2014
                                           sizeof(PCIVGAState),
2015
                                           -1, NULL, NULL);
2016
    if (!d)
2017
        return -1;
2018
    s = &d->vga_state;
2019
    
2020
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2021
    vga_init(s);
2022

    
2023
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
2024

    
2025
    s->pci_dev = &d->dev;
2026
    
2027
    pci_conf = d->dev.config;
2028
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2029
    pci_conf[0x01] = 0x12;
2030
    pci_conf[0x02] = 0x11;
2031
    pci_conf[0x03] = 0x11;
2032
    pci_conf[0x0a] = 0x00; // VGA controller 
2033
    pci_conf[0x0b] = 0x03;
2034
    pci_conf[0x0e] = 0x00; // header_type
2035
    
2036
    /* XXX: vga_ram_size must be a power of two */
2037
    pci_register_io_region(&d->dev, 0, vga_ram_size, 
2038
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2039
    if (vga_bios_size != 0) {
2040
        unsigned int bios_total_size;
2041
        s->bios_offset = vga_bios_offset;
2042
        s->bios_size = vga_bios_size;
2043
        /* must be a power of two */
2044
        bios_total_size = 1;
2045
        while (bios_total_size < vga_bios_size)
2046
            bios_total_size <<= 1;
2047
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size, 
2048
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2049
    }
2050
    return 0;
2051
}
2052

    
2053
/********************************************************/
2054
/* vga screen dump */
2055

    
2056
static int vga_save_w, vga_save_h;
2057

    
2058
static void vga_save_dpy_update(DisplayState *s, 
2059
                                int x, int y, int w, int h)
2060
{
2061
}
2062

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

    
2071
static void vga_save_dpy_refresh(DisplayState *s)
2072
{
2073
}
2074

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

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

    
2104
/* save the vga display in a PPM image even if no display is
2105
   available */
2106
static void vga_screen_dump(void *opaque, const char *filename)
2107
{
2108
    VGAState *s = (VGAState *)opaque;
2109
    DisplayState *saved_ds, ds1, *ds = &ds1;
2110
    
2111
    /* XXX: this is a little hackish */
2112
    vga_invalidate_display(s);
2113
    saved_ds = s->ds;
2114

    
2115
    memset(ds, 0, sizeof(DisplayState));
2116
    ds->dpy_update = vga_save_dpy_update;
2117
    ds->dpy_resize = vga_save_dpy_resize;
2118
    ds->dpy_refresh = vga_save_dpy_refresh;
2119
    ds->depth = 32;
2120

    
2121
    s->ds = ds;
2122
    s->graphic_mode = -1;
2123
    vga_update_display(s);
2124
    
2125
    if (ds->data) {
2126
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
2127
                 s->ds->linesize);
2128
        qemu_free(ds->data);
2129
    }
2130
    s->ds = saved_ds;
2131
}