Statistics
| Branch: | Revision:

root / hw / vga.c @ 03c18475

History | View | Annotate | Download (55.9 kB)

1
/*
2
 * QEMU VGA Emulator.
3
 * 
4
 * Copyright (c) 2003 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "vl.h"
25
#include "vga_int.h"
26

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

    
31
//#define DEBUG_BOCHS_VBE
32

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

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

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

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

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

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

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

    
108
#undef PAT
109

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
457
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
458
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
459
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
460
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
461
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
462
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
463
                
464
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
465
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
466
                else
467
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
468
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
469
                s->vbe_start_addr = 0;
470

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

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

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

    
593
        if (!(s->gr[5] & 0x08)) {
594
            /* read mode 0 */
595
            plane = s->gr[4];
596
            ret = GET_PLANE(s->latch, plane);
597
        } else {
598
            /* read mode 1 */
599
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
600
            ret |= ret >> 16;
601
            ret |= ret >> 8;
602
            ret = (~ret) & 0xff;
603
        }
604
    }
605
    return ret;
606
}
607

    
608
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
609
{
610
    uint32_t v;
611
#ifdef TARGET_WORDS_BIGENDIAN
612
    v = vga_mem_readb(opaque, addr) << 8;
613
    v |= vga_mem_readb(opaque, addr + 1);
614
#else
615
    v = vga_mem_readb(opaque, addr);
616
    v |= vga_mem_readb(opaque, addr + 1) << 8;
617
#endif
618
    return v;
619
}
620

    
621
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
622
{
623
    uint32_t v;
624
#ifdef TARGET_WORDS_BIGENDIAN
625
    v = vga_mem_readb(opaque, addr) << 24;
626
    v |= vga_mem_readb(opaque, addr + 1) << 16;
627
    v |= vga_mem_readb(opaque, addr + 2) << 8;
628
    v |= vga_mem_readb(opaque, addr + 3);
629
#else
630
    v = vga_mem_readb(opaque, addr);
631
    v |= vga_mem_readb(opaque, addr + 1) << 8;
632
    v |= vga_mem_readb(opaque, addr + 2) << 16;
633
    v |= vga_mem_readb(opaque, addr + 3) << 24;
634
#endif
635
    return v;
636
}
637

    
638
/* called for accesses between 0xa0000 and 0xc0000 */
639
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
640
{
641
    VGAState *s = opaque;
642
    int memory_map_mode, plane, write_mode, b, func_select, mask;
643
    uint32_t write_mask, bit_mask, set_mask;
644

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

    
709
            /* apply set/reset mask */
710
            set_mask = mask16[s->gr[1]];
711
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
712
            bit_mask = s->gr[8];
713
            break;
714
        case 1:
715
            val = s->latch;
716
            goto do_write;
717
        case 2:
718
            val = mask16[val & 0x0f];
719
            bit_mask = s->gr[8];
720
            break;
721
        case 3:
722
            /* rotate */
723
            b = s->gr[3] & 7;
724
            val = (val >> b) | (val << (8 - b));
725

    
726
            bit_mask = s->gr[8] & val;
727
            val = mask16[s->gr[0]];
728
            break;
729
        }
730

    
731
        /* apply logical operation */
732
        func_select = s->gr[3] >> 3;
733
        switch(func_select) {
734
        case 0:
735
        default:
736
            /* nothing to do */
737
            break;
738
        case 1:
739
            /* and */
740
            val &= s->latch;
741
            break;
742
        case 2:
743
            /* or */
744
            val |= s->latch;
745
            break;
746
        case 3:
747
            /* xor */
748
            val ^= s->latch;
749
            break;
750
        }
751

    
752
        /* apply bit mask */
753
        bit_mask |= bit_mask << 8;
754
        bit_mask |= bit_mask << 16;
755
        val = (val & bit_mask) | (s->latch & ~bit_mask);
756

    
757
    do_write:
758
        /* mask data according to sr[2] */
759
        mask = s->sr[2];
760
        s->plane_updated |= mask; /* only used to detect font change */
761
        write_mask = mask16[mask];
762
        ((uint32_t *)s->vram_ptr)[addr] = 
763
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
764
            (val & write_mask);
765
#ifdef DEBUG_VGA_MEM
766
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
767
                   addr * 4, write_mask, val);
768
#endif
769
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
770
    }
771
}
772

    
773
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
774
{
775
#ifdef TARGET_WORDS_BIGENDIAN
776
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
777
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
778
#else
779
    vga_mem_writeb(opaque, addr, val & 0xff);
780
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
781
#endif
782
}
783

    
784
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
785
{
786
#ifdef TARGET_WORDS_BIGENDIAN
787
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
788
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
789
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
790
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
791
#else
792
    vga_mem_writeb(opaque, addr, val & 0xff);
793
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
794
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
795
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
796
#endif
797
}
798

    
799
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
800
                             const uint8_t *font_ptr, int h,
801
                             uint32_t fgcol, uint32_t bgcol);
802
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
803
                                  const uint8_t *font_ptr, int h, 
804
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
805
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
806
                                const uint8_t *s, int width);
807

    
808
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
809
{
810
    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
811
}
812

    
813
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
814
{
815
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
816
}
817

    
818
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
819
{
820
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
821
}
822

    
823
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
824
{
825
    return (r << 16) | (g << 8) | b;
826
}
827

    
828
static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
829
{
830
    return (b << 16) | (g << 8) | r;
831
}
832

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

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

    
839
#define DEPTH 16
840
#include "vga_template.h"
841

    
842
#define DEPTH 32
843
#include "vga_template.h"
844

    
845
#define BGR_FORMAT
846
#define DEPTH 32
847
#include "vga_template.h"
848

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

    
858
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
859
{
860
    unsigned int col;
861
    col = rgb_to_pixel15(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_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
875
{
876
    unsigned int col;
877
    col = rgb_to_pixel32(r, g, b);
878
    return col;
879
}
880

    
881
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
882
{
883
    unsigned int col;
884
    col = rgb_to_pixel32bgr(r, g, b);
885
    return col;
886
}
887

    
888
/* return true if the palette was modified */
889
static int update_palette16(VGAState *s)
890
{
891
    int full_update, i;
892
    uint32_t v, col, *palette;
893

    
894
    full_update = 0;
895
    palette = s->last_palette;
896
    for(i = 0; i < 16; i++) {
897
        v = s->ar[i];
898
        if (s->ar[0x10] & 0x80)
899
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
900
        else
901
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
902
        v = v * 3;
903
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
904
                              c6_to_8(s->palette[v + 1]), 
905
                              c6_to_8(s->palette[v + 2]));
906
        if (col != palette[i]) {
907
            full_update = 1;
908
            palette[i] = col;
909
        }
910
    }
911
    return full_update;
912
}
913

    
914
/* return true if the palette was modified */
915
static int update_palette256(VGAState *s)
916
{
917
    int full_update, i;
918
    uint32_t v, col, *palette;
919

    
920
    full_update = 0;
921
    palette = s->last_palette;
922
    v = 0;
923
    for(i = 0; i < 256; i++) {
924
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
925
                              c6_to_8(s->palette[v + 1]), 
926
                              c6_to_8(s->palette[v + 2]));
927
        if (col != palette[i]) {
928
            full_update = 1;
929
            palette[i] = col;
930
        }
931
        v += 3;
932
    }
933
    return full_update;
934
}
935

    
936
static void vga_get_offsets(VGAState *s, 
937
                            uint32_t *pline_offset, 
938
                            uint32_t *pstart_addr,
939
                            uint32_t *pline_compare)
940
{
941
    uint32_t start_addr, line_offset, line_compare;
942
#ifdef CONFIG_BOCHS_VBE
943
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
944
        line_offset = s->vbe_line_offset;
945
        start_addr = s->vbe_start_addr;
946
        line_compare = 65535;
947
    } else
948
#endif
949
    {  
950
        /* compute line_offset in bytes */
951
        line_offset = s->cr[0x13];
952
        line_offset <<= 3;
953

    
954
        /* starting address */
955
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
956

    
957
        /* line compare */
958
        line_compare = s->cr[0x18] | 
959
            ((s->cr[0x07] & 0x10) << 4) |
960
            ((s->cr[0x09] & 0x40) << 3);
961
    }
962
    *pline_offset = line_offset;
963
    *pstart_addr = start_addr;
964
    *pline_compare = line_compare;
965
}
966

    
967
/* update start_addr and line_offset. Return TRUE if modified */
968
static int update_basic_params(VGAState *s)
969
{
970
    int full_update;
971
    uint32_t start_addr, line_offset, line_compare;
972
    
973
    full_update = 0;
974

    
975
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
976

    
977
    if (line_offset != s->line_offset ||
978
        start_addr != s->start_addr ||
979
        line_compare != s->line_compare) {
980
        s->line_offset = line_offset;
981
        s->start_addr = start_addr;
982
        s->line_compare = line_compare;
983
        full_update = 1;
984
    }
985
    return full_update;
986
}
987

    
988
#define NB_DEPTHS 5
989

    
990
static inline int get_depth_index(DisplayState *s)
991
{
992
    switch(s->depth) {
993
    default:
994
    case 8:
995
        return 0;
996
    case 15:
997
        return 1;
998
    case 16:
999
        return 2;
1000
    case 32:
1001
        if (s->bgr)
1002
            return 4;
1003
        else
1004
            return 3;
1005
    }
1006
}
1007

    
1008
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1009
    vga_draw_glyph8_8,
1010
    vga_draw_glyph8_16,
1011
    vga_draw_glyph8_16,
1012
    vga_draw_glyph8_32,
1013
    vga_draw_glyph8_32,
1014
};
1015

    
1016
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1017
    vga_draw_glyph16_8,
1018
    vga_draw_glyph16_16,
1019
    vga_draw_glyph16_16,
1020
    vga_draw_glyph16_32,
1021
    vga_draw_glyph16_32,
1022
};
1023

    
1024
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1025
    vga_draw_glyph9_8,
1026
    vga_draw_glyph9_16,
1027
    vga_draw_glyph9_16,
1028
    vga_draw_glyph9_32,
1029
    vga_draw_glyph9_32,
1030
};
1031
    
1032
static const uint8_t cursor_glyph[32 * 4] = {
1033
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1034
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1035
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1036
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1037
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1038
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1039
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1040
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1041
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1042
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1043
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1044
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1045
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1046
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1047
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1048
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1049
};    
1050

    
1051
/* 
1052
 * Text mode update 
1053
 * Missing:
1054
 * - double scan
1055
 * - double width 
1056
 * - underline
1057
 * - flashing
1058
 */
1059
static void vga_draw_text(VGAState *s, int full_update)
1060
{
1061
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1062
    int cx_min, cx_max, linesize, x_incr;
1063
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1064
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1065
    const uint8_t *font_ptr, *font_base[2];
1066
    int dup9, line_offset, depth_index;
1067
    uint32_t *palette;
1068
    uint32_t *ch_attr_ptr;
1069
    vga_draw_glyph8_func *vga_draw_glyph8;
1070
    vga_draw_glyph9_func *vga_draw_glyph9;
1071

    
1072
    full_update |= update_palette16(s);
1073
    palette = s->last_palette;
1074
    
1075
    /* compute font data address (in plane 2) */
1076
    v = s->sr[3];
1077
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1078
    if (offset != s->font_offsets[0]) {
1079
        s->font_offsets[0] = offset;
1080
        full_update = 1;
1081
    }
1082
    font_base[0] = s->vram_ptr + offset;
1083

    
1084
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1085
    font_base[1] = s->vram_ptr + offset;
1086
    if (offset != s->font_offsets[1]) {
1087
        s->font_offsets[1] = offset;
1088
        full_update = 1;
1089
    }
1090
    if (s->plane_updated & (1 << 2)) {
1091
        /* if the plane 2 was modified since the last display, it
1092
           indicates the font may have been modified */
1093
        s->plane_updated = 0;
1094
        full_update = 1;
1095
    }
1096
    full_update |= update_basic_params(s);
1097

    
1098
    line_offset = s->line_offset;
1099
    s1 = s->vram_ptr + (s->start_addr * 4);
1100

    
1101
    /* total width & height */
1102
    cheight = (s->cr[9] & 0x1f) + 1;
1103
    cw = 8;
1104
    if (!(s->sr[1] & 0x01))
1105
        cw = 9;
1106
    if (s->sr[1] & 0x08)
1107
        cw = 16; /* NOTE: no 18 pixel wide */
1108
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1109
    width = (s->cr[0x01] + 1);
1110
    if (s->cr[0x06] == 100) {
1111
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1112
        height = 100;
1113
    } else {
1114
        height = s->cr[0x12] | 
1115
            ((s->cr[0x07] & 0x02) << 7) | 
1116
            ((s->cr[0x07] & 0x40) << 3);
1117
        height = (height + 1) / cheight;
1118
    }
1119
    if ((height * width) > CH_ATTR_SIZE) {
1120
        /* better than nothing: exit if transient size is too big */
1121
        return;
1122
    }
1123

    
1124
    if (width != s->last_width || height != s->last_height ||
1125
        cw != s->last_cw || cheight != s->last_ch) {
1126
        s->last_scr_width = width * cw;
1127
        s->last_scr_height = height * cheight;
1128
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1129
        s->last_width = width;
1130
        s->last_height = height;
1131
        s->last_ch = cheight;
1132
        s->last_cw = cw;
1133
        full_update = 1;
1134
    }
1135
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1136
    if (cursor_offset != s->cursor_offset ||
1137
        s->cr[0xa] != s->cursor_start ||
1138
        s->cr[0xb] != s->cursor_end) {
1139
      /* if the cursor position changed, we update the old and new
1140
         chars */
1141
        if (s->cursor_offset < CH_ATTR_SIZE)
1142
            s->last_ch_attr[s->cursor_offset] = -1;
1143
        if (cursor_offset < CH_ATTR_SIZE)
1144
            s->last_ch_attr[cursor_offset] = -1;
1145
        s->cursor_offset = cursor_offset;
1146
        s->cursor_start = s->cr[0xa];
1147
        s->cursor_end = s->cr[0xb];
1148
    }
1149
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1150
    
1151
    depth_index = get_depth_index(s->ds);
1152
    if (cw == 16)
1153
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1154
    else
1155
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1156
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1157
    
1158
    dest = s->ds->data;
1159
    linesize = s->ds->linesize;
1160
    ch_attr_ptr = s->last_ch_attr;
1161
    for(cy = 0; cy < height; cy++) {
1162
        d1 = dest;
1163
        src = s1;
1164
        cx_min = width;
1165
        cx_max = -1;
1166
        for(cx = 0; cx < width; cx++) {
1167
            ch_attr = *(uint16_t *)src;
1168
            if (full_update || ch_attr != *ch_attr_ptr) {
1169
                if (cx < cx_min)
1170
                    cx_min = cx;
1171
                if (cx > cx_max)
1172
                    cx_max = cx;
1173
                *ch_attr_ptr = ch_attr;
1174
#ifdef WORDS_BIGENDIAN
1175
                ch = ch_attr >> 8;
1176
                cattr = ch_attr & 0xff;
1177
#else
1178
                ch = ch_attr & 0xff;
1179
                cattr = ch_attr >> 8;
1180
#endif
1181
                font_ptr = font_base[(cattr >> 3) & 1];
1182
                font_ptr += 32 * 4 * ch;
1183
                bgcol = palette[cattr >> 4];
1184
                fgcol = palette[cattr & 0x0f];
1185
                if (cw != 9) {
1186
                    vga_draw_glyph8(d1, linesize, 
1187
                                    font_ptr, cheight, fgcol, bgcol);
1188
                } else {
1189
                    dup9 = 0;
1190
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1191
                        dup9 = 1;
1192
                    vga_draw_glyph9(d1, linesize, 
1193
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1194
                }
1195
                if (src == cursor_ptr &&
1196
                    !(s->cr[0x0a] & 0x20)) {
1197
                    int line_start, line_last, h;
1198
                    /* draw the cursor */
1199
                    line_start = s->cr[0x0a] & 0x1f;
1200
                    line_last = s->cr[0x0b] & 0x1f;
1201
                    /* XXX: check that */
1202
                    if (line_last > cheight - 1)
1203
                        line_last = cheight - 1;
1204
                    if (line_last >= line_start && line_start < cheight) {
1205
                        h = line_last - line_start + 1;
1206
                        d = d1 + linesize * line_start;
1207
                        if (cw != 9) {
1208
                            vga_draw_glyph8(d, linesize, 
1209
                                            cursor_glyph, h, fgcol, bgcol);
1210
                        } else {
1211
                            vga_draw_glyph9(d, linesize, 
1212
                                            cursor_glyph, h, fgcol, bgcol, 1);
1213
                        }
1214
                    }
1215
                }
1216
            }
1217
            d1 += x_incr;
1218
            src += 4;
1219
            ch_attr_ptr++;
1220
        }
1221
        if (cx_max != -1) {
1222
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1223
                       (cx_max - cx_min + 1) * cw, cheight);
1224
        }
1225
        dest += linesize * cheight;
1226
        s1 += line_offset;
1227
    }
1228
}
1229

    
1230
enum {
1231
    VGA_DRAW_LINE2,
1232
    VGA_DRAW_LINE2D2,
1233
    VGA_DRAW_LINE4,
1234
    VGA_DRAW_LINE4D2,
1235
    VGA_DRAW_LINE8D2,
1236
    VGA_DRAW_LINE8,
1237
    VGA_DRAW_LINE15,
1238
    VGA_DRAW_LINE16,
1239
    VGA_DRAW_LINE24,
1240
    VGA_DRAW_LINE32,
1241
    VGA_DRAW_LINE_NB,
1242
};
1243

    
1244
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1245
    vga_draw_line2_8,
1246
    vga_draw_line2_16,
1247
    vga_draw_line2_16,
1248
    vga_draw_line2_32,
1249
    vga_draw_line2_32,
1250

    
1251
    vga_draw_line2d2_8,
1252
    vga_draw_line2d2_16,
1253
    vga_draw_line2d2_16,
1254
    vga_draw_line2d2_32,
1255
    vga_draw_line2d2_32,
1256

    
1257
    vga_draw_line4_8,
1258
    vga_draw_line4_16,
1259
    vga_draw_line4_16,
1260
    vga_draw_line4_32,
1261
    vga_draw_line4_32,
1262

    
1263
    vga_draw_line4d2_8,
1264
    vga_draw_line4d2_16,
1265
    vga_draw_line4d2_16,
1266
    vga_draw_line4d2_32,
1267
    vga_draw_line4d2_32,
1268

    
1269
    vga_draw_line8d2_8,
1270
    vga_draw_line8d2_16,
1271
    vga_draw_line8d2_16,
1272
    vga_draw_line8d2_32,
1273
    vga_draw_line8d2_32,
1274

    
1275
    vga_draw_line8_8,
1276
    vga_draw_line8_16,
1277
    vga_draw_line8_16,
1278
    vga_draw_line8_32,
1279
    vga_draw_line8_32,
1280

    
1281
    vga_draw_line15_8,
1282
    vga_draw_line15_15,
1283
    vga_draw_line15_16,
1284
    vga_draw_line15_32,
1285
    vga_draw_line15_32bgr,
1286

    
1287
    vga_draw_line16_8,
1288
    vga_draw_line16_15,
1289
    vga_draw_line16_16,
1290
    vga_draw_line16_32,
1291
    vga_draw_line16_32bgr,
1292

    
1293
    vga_draw_line24_8,
1294
    vga_draw_line24_15,
1295
    vga_draw_line24_16,
1296
    vga_draw_line24_32,
1297
    vga_draw_line24_32bgr,
1298

    
1299
    vga_draw_line32_8,
1300
    vga_draw_line32_15,
1301
    vga_draw_line32_16,
1302
    vga_draw_line32_32,
1303
    vga_draw_line32_32bgr,
1304
};
1305

    
1306
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1307

    
1308
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1309
    rgb_to_pixel8_dup,
1310
    rgb_to_pixel15_dup,
1311
    rgb_to_pixel16_dup,
1312
    rgb_to_pixel32_dup,
1313
    rgb_to_pixel32bgr_dup,
1314
};
1315

    
1316
static int vga_get_bpp(VGAState *s)
1317
{
1318
    int ret;
1319
#ifdef CONFIG_BOCHS_VBE
1320
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1321
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1322
    } else 
1323
#endif
1324
    {
1325
        ret = 0;
1326
    }
1327
    return ret;
1328
}
1329

    
1330
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1331
{
1332
    int width, height;
1333
    
1334
#ifdef CONFIG_BOCHS_VBE
1335
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1336
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1337
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1338
    } else 
1339
#endif
1340
    {
1341
        width = (s->cr[0x01] + 1) * 8;
1342
        height = s->cr[0x12] | 
1343
            ((s->cr[0x07] & 0x02) << 7) | 
1344
            ((s->cr[0x07] & 0x40) << 3);
1345
        height = (height + 1);
1346
    }
1347
    *pwidth = width;
1348
    *pheight = height;
1349
}
1350

    
1351
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1352
{
1353
    int y;
1354
    if (y1 >= VGA_MAX_HEIGHT)
1355
        return;
1356
    if (y2 >= VGA_MAX_HEIGHT)
1357
        y2 = VGA_MAX_HEIGHT;
1358
    for(y = y1; y < y2; y++) {
1359
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1360
    }
1361
}
1362

    
1363
/* 
1364
 * graphic modes
1365
 */
1366
static void vga_draw_graphic(VGAState *s, int full_update)
1367
{
1368
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1369
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1370
    int disp_width, multi_scan, multi_run;
1371
    uint8_t *d;
1372
    uint32_t v, addr1, addr;
1373
    vga_draw_line_func *vga_draw_line;
1374
    
1375
    full_update |= update_basic_params(s);
1376

    
1377
    s->get_resolution(s, &width, &height);
1378
    disp_width = width;
1379

    
1380
    shift_control = (s->gr[0x05] >> 5) & 3;
1381
    double_scan = (s->cr[0x09] >> 7);
1382
    if (shift_control != 1) {
1383
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1384
    } else {
1385
        /* in CGA modes, multi_scan is ignored */
1386
        /* XXX: is it correct ? */
1387
        multi_scan = double_scan;
1388
    }
1389
    multi_run = multi_scan;
1390
    if (shift_control != s->shift_control ||
1391
        double_scan != s->double_scan) {
1392
        full_update = 1;
1393
        s->shift_control = shift_control;
1394
        s->double_scan = double_scan;
1395
    }
1396
    
1397
    if (shift_control == 0) {
1398
        full_update |= update_palette16(s);
1399
        if (s->sr[0x01] & 8) {
1400
            v = VGA_DRAW_LINE4D2;
1401
            disp_width <<= 1;
1402
        } else {
1403
            v = VGA_DRAW_LINE4;
1404
        }
1405
    } else if (shift_control == 1) {
1406
        full_update |= update_palette16(s);
1407
        if (s->sr[0x01] & 8) {
1408
            v = VGA_DRAW_LINE2D2;
1409
            disp_width <<= 1;
1410
        } else {
1411
            v = VGA_DRAW_LINE2;
1412
        }
1413
    } else {
1414
        switch(s->get_bpp(s)) {
1415
        default:
1416
        case 0:
1417
            full_update |= update_palette256(s);
1418
            v = VGA_DRAW_LINE8D2;
1419
            break;
1420
        case 8:
1421
            full_update |= update_palette256(s);
1422
            v = VGA_DRAW_LINE8;
1423
            break;
1424
        case 15:
1425
            v = VGA_DRAW_LINE15;
1426
            break;
1427
        case 16:
1428
            v = VGA_DRAW_LINE16;
1429
            break;
1430
        case 24:
1431
            v = VGA_DRAW_LINE24;
1432
            break;
1433
        case 32:
1434
            v = VGA_DRAW_LINE32;
1435
            break;
1436
        }
1437
    }
1438
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1439

    
1440
    if (disp_width != s->last_width ||
1441
        height != s->last_height) {
1442
        dpy_resize(s->ds, disp_width, height);
1443
        s->last_scr_width = disp_width;
1444
        s->last_scr_height = height;
1445
        s->last_width = disp_width;
1446
        s->last_height = height;
1447
        full_update = 1;
1448
    }
1449
    if (s->cursor_invalidate)
1450
        s->cursor_invalidate(s);
1451
    
1452
    line_offset = s->line_offset;
1453
#if 0
1454
    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",
1455
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1456
#endif
1457
    addr1 = (s->start_addr * 4);
1458
    bwidth = width * 4;
1459
    y_start = -1;
1460
    page_min = 0x7fffffff;
1461
    page_max = -1;
1462
    d = s->ds->data;
1463
    linesize = s->ds->linesize;
1464
    y1 = 0;
1465
    for(y = 0; y < height; y++) {
1466
        addr = addr1;
1467
        if (!(s->cr[0x17] & 1)) {
1468
            int shift;
1469
            /* CGA compatibility handling */
1470
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1471
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1472
        }
1473
        if (!(s->cr[0x17] & 2)) {
1474
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1475
        }
1476
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1477
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1478
        update = full_update | 
1479
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1480
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1481
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1482
            /* if wide line, can use another page */
1483
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, 
1484
                                                    VGA_DIRTY_FLAG);
1485
        }
1486
        /* explicit invalidation for the hardware cursor */
1487
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1488
        if (update) {
1489
            if (y_start < 0)
1490
                y_start = y;
1491
            if (page0 < page_min)
1492
                page_min = page0;
1493
            if (page1 > page_max)
1494
                page_max = page1;
1495
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1496
            if (s->cursor_draw_line)
1497
                s->cursor_draw_line(s, d, y);
1498
        } else {
1499
            if (y_start >= 0) {
1500
                /* flush to display */
1501
                dpy_update(s->ds, 0, y_start, 
1502
                           disp_width, y - y_start);
1503
                y_start = -1;
1504
            }
1505
        }
1506
        if (!multi_run) {
1507
            mask = (s->cr[0x17] & 3) ^ 3;
1508
            if ((y1 & mask) == mask)
1509
                addr1 += line_offset;
1510
            y1++;
1511
            multi_run = multi_scan;
1512
        } else {
1513
            multi_run--;
1514
        }
1515
        /* line compare acts on the displayed lines */
1516
        if (y == s->line_compare)
1517
            addr1 = 0;
1518
        d += linesize;
1519
    }
1520
    if (y_start >= 0) {
1521
        /* flush to display */
1522
        dpy_update(s->ds, 0, y_start, 
1523
                   disp_width, y - y_start);
1524
    }
1525
    /* reset modified pages */
1526
    if (page_max != -1) {
1527
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1528
                                        VGA_DIRTY_FLAG);
1529
    }
1530
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1531
}
1532

    
1533
static void vga_draw_blank(VGAState *s, int full_update)
1534
{
1535
    int i, w, val;
1536
    uint8_t *d;
1537

    
1538
    if (!full_update)
1539
        return;
1540
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1541
        return;
1542
    if (s->ds->depth == 8) 
1543
        val = s->rgb_to_pixel(0, 0, 0);
1544
    else
1545
        val = 0;
1546
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1547
    d = s->ds->data;
1548
    for(i = 0; i < s->last_scr_height; i++) {
1549
        memset(d, val, w);
1550
        d += s->ds->linesize;
1551
    }
1552
    dpy_update(s->ds, 0, 0, 
1553
               s->last_scr_width, s->last_scr_height);
1554
}
1555

    
1556
#define GMODE_TEXT     0
1557
#define GMODE_GRAPH    1
1558
#define GMODE_BLANK 2 
1559

    
1560
static void vga_update_display(void *opaque)
1561
{
1562
    VGAState *s = (VGAState *)opaque;
1563
    int full_update, graphic_mode;
1564

    
1565
    if (s->ds->depth == 0) {
1566
        /* nothing to do */
1567
    } else {
1568
        s->rgb_to_pixel = 
1569
            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1570
        
1571
        full_update = 0;
1572
        if (!(s->ar_index & 0x20)) {
1573
            graphic_mode = GMODE_BLANK;
1574
        } else {
1575
            graphic_mode = s->gr[6] & 1;
1576
        }
1577
        if (graphic_mode != s->graphic_mode) {
1578
            s->graphic_mode = graphic_mode;
1579
            full_update = 1;
1580
        }
1581
        switch(graphic_mode) {
1582
        case GMODE_TEXT:
1583
            vga_draw_text(s, full_update);
1584
            break;
1585
        case GMODE_GRAPH:
1586
            vga_draw_graphic(s, full_update);
1587
            break;
1588
        case GMODE_BLANK:
1589
        default:
1590
            vga_draw_blank(s, full_update);
1591
            break;
1592
        }
1593
    }
1594
}
1595

    
1596
/* force a full display refresh */
1597
static void vga_invalidate_display(void *opaque)
1598
{
1599
    VGAState *s = (VGAState *)opaque;
1600
    
1601
    s->last_width = -1;
1602
    s->last_height = -1;
1603
}
1604

    
1605
static void vga_reset(VGAState *s)
1606
{
1607
    memset(s, 0, sizeof(VGAState));
1608
    s->graphic_mode = -1; /* force full update */
1609
}
1610

    
1611
static CPUReadMemoryFunc *vga_mem_read[3] = {
1612
    vga_mem_readb,
1613
    vga_mem_readw,
1614
    vga_mem_readl,
1615
};
1616

    
1617
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1618
    vga_mem_writeb,
1619
    vga_mem_writew,
1620
    vga_mem_writel,
1621
};
1622

    
1623
static void vga_save(QEMUFile *f, void *opaque)
1624
{
1625
    VGAState *s = opaque;
1626
    int i;
1627

    
1628
    if (s->pci_dev)
1629
        pci_device_save(s->pci_dev, f);
1630

    
1631
    qemu_put_be32s(f, &s->latch);
1632
    qemu_put_8s(f, &s->sr_index);
1633
    qemu_put_buffer(f, s->sr, 8);
1634
    qemu_put_8s(f, &s->gr_index);
1635
    qemu_put_buffer(f, s->gr, 16);
1636
    qemu_put_8s(f, &s->ar_index);
1637
    qemu_put_buffer(f, s->ar, 21);
1638
    qemu_put_be32s(f, &s->ar_flip_flop);
1639
    qemu_put_8s(f, &s->cr_index);
1640
    qemu_put_buffer(f, s->cr, 256);
1641
    qemu_put_8s(f, &s->msr);
1642
    qemu_put_8s(f, &s->fcr);
1643
    qemu_put_8s(f, &s->st00);
1644
    qemu_put_8s(f, &s->st01);
1645

    
1646
    qemu_put_8s(f, &s->dac_state);
1647
    qemu_put_8s(f, &s->dac_sub_index);
1648
    qemu_put_8s(f, &s->dac_read_index);
1649
    qemu_put_8s(f, &s->dac_write_index);
1650
    qemu_put_buffer(f, s->dac_cache, 3);
1651
    qemu_put_buffer(f, s->palette, 768);
1652

    
1653
    qemu_put_be32s(f, &s->bank_offset);
1654
#ifdef CONFIG_BOCHS_VBE
1655
    qemu_put_byte(f, 1);
1656
    qemu_put_be16s(f, &s->vbe_index);
1657
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1658
        qemu_put_be16s(f, &s->vbe_regs[i]);
1659
    qemu_put_be32s(f, &s->vbe_start_addr);
1660
    qemu_put_be32s(f, &s->vbe_line_offset);
1661
    qemu_put_be32s(f, &s->vbe_bank_mask);
1662
#else
1663
    qemu_put_byte(f, 0);
1664
#endif
1665
}
1666

    
1667
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1668
{
1669
    VGAState *s = opaque;
1670
    int is_vbe, i, ret;
1671

    
1672
    if (version_id > 2)
1673
        return -EINVAL;
1674

    
1675
    if (s->pci_dev && version_id >= 2) {
1676
        ret = pci_device_load(s->pci_dev, f);
1677
        if (ret < 0)
1678
            return ret;
1679
    }
1680

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

    
1696
    qemu_get_8s(f, &s->dac_state);
1697
    qemu_get_8s(f, &s->dac_sub_index);
1698
    qemu_get_8s(f, &s->dac_read_index);
1699
    qemu_get_8s(f, &s->dac_write_index);
1700
    qemu_get_buffer(f, s->dac_cache, 3);
1701
    qemu_get_buffer(f, s->palette, 768);
1702

    
1703
    qemu_get_be32s(f, &s->bank_offset);
1704
    is_vbe = qemu_get_byte(f);
1705
#ifdef CONFIG_BOCHS_VBE
1706
    if (!is_vbe)
1707
        return -EINVAL;
1708
    qemu_get_be16s(f, &s->vbe_index);
1709
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1710
        qemu_get_be16s(f, &s->vbe_regs[i]);
1711
    qemu_get_be32s(f, &s->vbe_start_addr);
1712
    qemu_get_be32s(f, &s->vbe_line_offset);
1713
    qemu_get_be32s(f, &s->vbe_bank_mask);
1714
#else
1715
    if (is_vbe)
1716
        return -EINVAL;
1717
#endif
1718

    
1719
    /* force refresh */
1720
    s->graphic_mode = -1;
1721
    return 0;
1722
}
1723

    
1724
typedef struct PCIVGAState {
1725
    PCIDevice dev;
1726
    VGAState vga_state;
1727
} PCIVGAState;
1728

    
1729
static void vga_map(PCIDevice *pci_dev, int region_num, 
1730
                    uint32_t addr, uint32_t size, int type)
1731
{
1732
    PCIVGAState *d = (PCIVGAState *)pci_dev;
1733
    VGAState *s = &d->vga_state;
1734
    if (region_num == PCI_ROM_SLOT) {
1735
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1736
    } else {
1737
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1738
    }
1739
}
1740

    
1741
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1742
                     unsigned long vga_ram_offset, int vga_ram_size)
1743
{
1744
    int i, j, v, b;
1745

    
1746
    for(i = 0;i < 256; i++) {
1747
        v = 0;
1748
        for(j = 0; j < 8; j++) {
1749
            v |= ((i >> j) & 1) << (j * 4);
1750
        }
1751
        expand4[i] = v;
1752

    
1753
        v = 0;
1754
        for(j = 0; j < 4; j++) {
1755
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1756
        }
1757
        expand2[i] = v;
1758
    }
1759
    for(i = 0; i < 16; i++) {
1760
        v = 0;
1761
        for(j = 0; j < 4; j++) {
1762
            b = ((i >> j) & 1);
1763
            v |= b << (2 * j);
1764
            v |= b << (2 * j + 1);
1765
        }
1766
        expand4to8[i] = v;
1767
    }
1768

    
1769
    vga_reset(s);
1770

    
1771
    s->vram_ptr = vga_ram_base;
1772
    s->vram_offset = vga_ram_offset;
1773
    s->vram_size = vga_ram_size;
1774
    s->ds = ds;
1775
    s->get_bpp = vga_get_bpp;
1776
    s->get_offsets = vga_get_offsets;
1777
    s->get_resolution = vga_get_resolution;
1778
    graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
1779
                         vga_screen_dump, s);
1780
}
1781

    
1782
/* used by both ISA and PCI */
1783
static void vga_init(VGAState *s)
1784
{
1785
    int vga_io_memory;
1786

    
1787
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1788

    
1789
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1790

    
1791
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1792
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1793
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1794
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1795

    
1796
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1797

    
1798
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1799
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1800
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1801
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1802
    s->bank_offset = 0;
1803

    
1804
#ifdef CONFIG_BOCHS_VBE
1805
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1806
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1807
#if defined (TARGET_I386)
1808
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1809
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1810

    
1811
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1812
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1813

    
1814
    /* old Bochs IO ports */
1815
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1816
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1817

    
1818
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1819
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1820
#else
1821
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1822
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1823

    
1824
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1825
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1826
#endif
1827
#endif /* CONFIG_BOCHS_VBE */
1828

    
1829
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1830
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1831
                                 vga_io_memory);
1832
}
1833

    
1834
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
1835
                 unsigned long vga_ram_offset, int vga_ram_size)
1836
{
1837
    VGAState *s;
1838

    
1839
    s = qemu_mallocz(sizeof(VGAState));
1840
    if (!s)
1841
        return -1;
1842

    
1843
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1844
    vga_init(s);
1845

    
1846
#ifdef CONFIG_BOCHS_VBE
1847
    /* XXX: use optimized standard vga accesses */
1848
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1849
                                 vga_ram_size, vga_ram_offset);
1850
#endif
1851
    return 0;
1852
}
1853

    
1854
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1855
                 unsigned long vga_ram_offset, int vga_ram_size,
1856
                 unsigned long vga_bios_offset, int vga_bios_size)
1857
{
1858
    PCIVGAState *d;
1859
    VGAState *s;
1860
    uint8_t *pci_conf;
1861
    
1862
    d = (PCIVGAState *)pci_register_device(bus, "VGA", 
1863
                                           sizeof(PCIVGAState),
1864
                                           -1, NULL, NULL);
1865
    if (!d)
1866
        return -1;
1867
    s = &d->vga_state;
1868
    
1869
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1870
    vga_init(s);
1871
    s->pci_dev = &d->dev;
1872
    
1873
    pci_conf = d->dev.config;
1874
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1875
    pci_conf[0x01] = 0x12;
1876
    pci_conf[0x02] = 0x11;
1877
    pci_conf[0x03] = 0x11;
1878
    pci_conf[0x0a] = 0x00; // VGA controller 
1879
    pci_conf[0x0b] = 0x03;
1880
    pci_conf[0x0e] = 0x00; // header_type
1881
    
1882
    /* XXX: vga_ram_size must be a power of two */
1883
    pci_register_io_region(&d->dev, 0, vga_ram_size, 
1884
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1885
    if (vga_bios_size != 0) {
1886
        unsigned int bios_total_size;
1887
        s->bios_offset = vga_bios_offset;
1888
        s->bios_size = vga_bios_size;
1889
        /* must be a power of two */
1890
        bios_total_size = 1;
1891
        while (bios_total_size < vga_bios_size)
1892
            bios_total_size <<= 1;
1893
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size, 
1894
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1895
    }
1896
    return 0;
1897
}
1898

    
1899
/********************************************************/
1900
/* vga screen dump */
1901

    
1902
static int vga_save_w, vga_save_h;
1903

    
1904
static void vga_save_dpy_update(DisplayState *s, 
1905
                                int x, int y, int w, int h)
1906
{
1907
}
1908

    
1909
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1910
{
1911
    s->linesize = w * 4;
1912
    s->data = qemu_malloc(h * s->linesize);
1913
    vga_save_w = w;
1914
    vga_save_h = h;
1915
}
1916

    
1917
static void vga_save_dpy_refresh(DisplayState *s)
1918
{
1919
}
1920

    
1921
static int ppm_save(const char *filename, uint8_t *data, 
1922
                    int w, int h, int linesize)
1923
{
1924
    FILE *f;
1925
    uint8_t *d, *d1;
1926
    unsigned int v;
1927
    int y, x;
1928

    
1929
    f = fopen(filename, "wb");
1930
    if (!f)
1931
        return -1;
1932
    fprintf(f, "P6\n%d %d\n%d\n",
1933
            w, h, 255);
1934
    d1 = data;
1935
    for(y = 0; y < h; y++) {
1936
        d = d1;
1937
        for(x = 0; x < w; x++) {
1938
            v = *(uint32_t *)d;
1939
            fputc((v >> 16) & 0xff, f);
1940
            fputc((v >> 8) & 0xff, f);
1941
            fputc((v) & 0xff, f);
1942
            d += 4;
1943
        }
1944
        d1 += linesize;
1945
    }
1946
    fclose(f);
1947
    return 0;
1948
}
1949

    
1950
/* save the vga display in a PPM image even if no display is
1951
   available */
1952
static void vga_screen_dump(void *opaque, const char *filename)
1953
{
1954
    VGAState *s = (VGAState *)opaque;
1955
    DisplayState *saved_ds, ds1, *ds = &ds1;
1956
    
1957
    /* XXX: this is a little hackish */
1958
    vga_invalidate_display(s);
1959
    saved_ds = s->ds;
1960

    
1961
    memset(ds, 0, sizeof(DisplayState));
1962
    ds->dpy_update = vga_save_dpy_update;
1963
    ds->dpy_resize = vga_save_dpy_resize;
1964
    ds->dpy_refresh = vga_save_dpy_refresh;
1965
    ds->depth = 32;
1966

    
1967
    s->ds = ds;
1968
    s->graphic_mode = -1;
1969
    vga_update_display(s);
1970
    
1971
    if (ds->data) {
1972
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1973
                 s->ds->linesize);
1974
        qemu_free(ds->data);
1975
    }
1976
    s->ds = saved_ds;
1977
}