Statistics
| Branch: | Revision:

root / hw / vga.c @ e91c8a77

History | View | Annotate | Download (59.3 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: /* vertical 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
                val == VBE_DISPI_ID3 ||
427
                val == VBE_DISPI_ID4) {
428
                s->vbe_regs[s->vbe_index] = val;
429
            }
430
            break;
431
        case VBE_DISPI_INDEX_XRES:
432
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
433
                s->vbe_regs[s->vbe_index] = val;
434
            }
435
            break;
436
        case VBE_DISPI_INDEX_YRES:
437
            if (val <= VBE_DISPI_MAX_YRES) {
438
                s->vbe_regs[s->vbe_index] = val;
439
            }
440
            break;
441
        case VBE_DISPI_INDEX_BPP:
442
            if (val == 0)
443
                val = 8;
444
            if (val == 4 || val == 8 || val == 15 || 
445
                val == 16 || val == 24 || val == 32) {
446
                s->vbe_regs[s->vbe_index] = val;
447
            }
448
            break;
449
        case VBE_DISPI_INDEX_BANK:
450
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
451
              val &= (s->vbe_bank_mask >> 2);
452
            } else {
453
              val &= s->vbe_bank_mask;
454
            }
455
            s->vbe_regs[s->vbe_index] = val;
456
            s->bank_offset = (val << 16);
457
            break;
458
        case VBE_DISPI_INDEX_ENABLE:
459
            if ((val & VBE_DISPI_ENABLED) &&
460
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
461
                int h, shift_control;
462

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
815
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
816
{
817
    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
818
}
819

    
820
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
821
{
822
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
823
}
824

    
825
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
826
{
827
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
828
}
829

    
830
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
831
{
832
    return (r << 16) | (g << 8) | b;
833
}
834

    
835
static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
836
{
837
    return (b << 16) | (g << 8) | r;
838
}
839

    
840
#define DEPTH 8
841
#include "vga_template.h"
842

    
843
#define DEPTH 15
844
#include "vga_template.h"
845

    
846
#define DEPTH 16
847
#include "vga_template.h"
848

    
849
#define DEPTH 32
850
#include "vga_template.h"
851

    
852
#define BGR_FORMAT
853
#define DEPTH 32
854
#include "vga_template.h"
855

    
856
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
857
{
858
    unsigned int col;
859
    col = rgb_to_pixel8(r, g, b);
860
    col |= col << 8;
861
    col |= col << 16;
862
    return col;
863
}
864

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

    
873
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
874
{
875
    unsigned int col;
876
    col = rgb_to_pixel16(r, g, b);
877
    col |= col << 16;
878
    return col;
879
}
880

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

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

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

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

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

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

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

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

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

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

    
988
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
989

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

    
1001
#define NB_DEPTHS 5
1002

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

    
1021
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1022
    vga_draw_glyph8_8,
1023
    vga_draw_glyph8_16,
1024
    vga_draw_glyph8_16,
1025
    vga_draw_glyph8_32,
1026
    vga_draw_glyph8_32,
1027
};
1028

    
1029
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1030
    vga_draw_glyph16_8,
1031
    vga_draw_glyph16_16,
1032
    vga_draw_glyph16_16,
1033
    vga_draw_glyph16_32,
1034
    vga_draw_glyph16_32,
1035
};
1036

    
1037
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1038
    vga_draw_glyph9_8,
1039
    vga_draw_glyph9_16,
1040
    vga_draw_glyph9_16,
1041
    vga_draw_glyph9_32,
1042
    vga_draw_glyph9_32,
1043
};
1044
    
1045
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1050
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1051
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1052
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1053
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1054
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1055
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1056
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1057
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1058
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1059
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1060
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1061
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1062
};    
1063

    
1064
/* 
1065
 * Text mode update 
1066
 * Missing:
1067
 * - double scan
1068
 * - double width 
1069
 * - underline
1070
 * - flashing
1071
 */
1072
static void vga_draw_text(VGAState *s, int full_update)
1073
{
1074
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1075
    int cx_min, cx_max, linesize, x_incr;
1076
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1077
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1078
    const uint8_t *font_ptr, *font_base[2];
1079
    int dup9, line_offset, depth_index;
1080
    uint32_t *palette;
1081
    uint32_t *ch_attr_ptr;
1082
    vga_draw_glyph8_func *vga_draw_glyph8;
1083
    vga_draw_glyph9_func *vga_draw_glyph9;
1084

    
1085
    full_update |= update_palette16(s);
1086
    palette = s->last_palette;
1087
    
1088
    /* compute font data address (in plane 2) */
1089
    v = s->sr[3];
1090
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1091
    if (offset != s->font_offsets[0]) {
1092
        s->font_offsets[0] = offset;
1093
        full_update = 1;
1094
    }
1095
    font_base[0] = s->vram_ptr + offset;
1096

    
1097
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1098
    font_base[1] = s->vram_ptr + offset;
1099
    if (offset != s->font_offsets[1]) {
1100
        s->font_offsets[1] = offset;
1101
        full_update = 1;
1102
    }
1103
    if (s->plane_updated & (1 << 2)) {
1104
        /* if the plane 2 was modified since the last display, it
1105
           indicates the font may have been modified */
1106
        s->plane_updated = 0;
1107
        full_update = 1;
1108
    }
1109
    full_update |= update_basic_params(s);
1110

    
1111
    line_offset = s->line_offset;
1112
    s1 = s->vram_ptr + (s->start_addr * 4);
1113

    
1114
    /* total width & height */
1115
    cheight = (s->cr[9] & 0x1f) + 1;
1116
    cw = 8;
1117
    if (!(s->sr[1] & 0x01))
1118
        cw = 9;
1119
    if (s->sr[1] & 0x08)
1120
        cw = 16; /* NOTE: no 18 pixel wide */
1121
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1122
    width = (s->cr[0x01] + 1);
1123
    if (s->cr[0x06] == 100) {
1124
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1125
        height = 100;
1126
    } else {
1127
        height = s->cr[0x12] | 
1128
            ((s->cr[0x07] & 0x02) << 7) | 
1129
            ((s->cr[0x07] & 0x40) << 3);
1130
        height = (height + 1) / cheight;
1131
    }
1132
    if ((height * width) > CH_ATTR_SIZE) {
1133
        /* better than nothing: exit if transient size is too big */
1134
        return;
1135
    }
1136

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

    
1243
enum {
1244
    VGA_DRAW_LINE2,
1245
    VGA_DRAW_LINE2D2,
1246
    VGA_DRAW_LINE4,
1247
    VGA_DRAW_LINE4D2,
1248
    VGA_DRAW_LINE8D2,
1249
    VGA_DRAW_LINE8,
1250
    VGA_DRAW_LINE15,
1251
    VGA_DRAW_LINE16,
1252
    VGA_DRAW_LINE24,
1253
    VGA_DRAW_LINE32,
1254
    VGA_DRAW_LINE_NB,
1255
};
1256

    
1257
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1258
    vga_draw_line2_8,
1259
    vga_draw_line2_16,
1260
    vga_draw_line2_16,
1261
    vga_draw_line2_32,
1262
    vga_draw_line2_32,
1263

    
1264
    vga_draw_line2d2_8,
1265
    vga_draw_line2d2_16,
1266
    vga_draw_line2d2_16,
1267
    vga_draw_line2d2_32,
1268
    vga_draw_line2d2_32,
1269

    
1270
    vga_draw_line4_8,
1271
    vga_draw_line4_16,
1272
    vga_draw_line4_16,
1273
    vga_draw_line4_32,
1274
    vga_draw_line4_32,
1275

    
1276
    vga_draw_line4d2_8,
1277
    vga_draw_line4d2_16,
1278
    vga_draw_line4d2_16,
1279
    vga_draw_line4d2_32,
1280
    vga_draw_line4d2_32,
1281

    
1282
    vga_draw_line8d2_8,
1283
    vga_draw_line8d2_16,
1284
    vga_draw_line8d2_16,
1285
    vga_draw_line8d2_32,
1286
    vga_draw_line8d2_32,
1287

    
1288
    vga_draw_line8_8,
1289
    vga_draw_line8_16,
1290
    vga_draw_line8_16,
1291
    vga_draw_line8_32,
1292
    vga_draw_line8_32,
1293

    
1294
    vga_draw_line15_8,
1295
    vga_draw_line15_15,
1296
    vga_draw_line15_16,
1297
    vga_draw_line15_32,
1298
    vga_draw_line15_32bgr,
1299

    
1300
    vga_draw_line16_8,
1301
    vga_draw_line16_15,
1302
    vga_draw_line16_16,
1303
    vga_draw_line16_32,
1304
    vga_draw_line16_32bgr,
1305

    
1306
    vga_draw_line24_8,
1307
    vga_draw_line24_15,
1308
    vga_draw_line24_16,
1309
    vga_draw_line24_32,
1310
    vga_draw_line24_32bgr,
1311

    
1312
    vga_draw_line32_8,
1313
    vga_draw_line32_15,
1314
    vga_draw_line32_16,
1315
    vga_draw_line32_32,
1316
    vga_draw_line32_32bgr,
1317
};
1318

    
1319
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1320

    
1321
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1322
    rgb_to_pixel8_dup,
1323
    rgb_to_pixel15_dup,
1324
    rgb_to_pixel16_dup,
1325
    rgb_to_pixel32_dup,
1326
    rgb_to_pixel32bgr_dup,
1327
};
1328

    
1329
static int vga_get_bpp(VGAState *s)
1330
{
1331
    int ret;
1332
#ifdef CONFIG_BOCHS_VBE
1333
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1334
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1335
    } else 
1336
#endif
1337
    {
1338
        ret = 0;
1339
    }
1340
    return ret;
1341
}
1342

    
1343
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1344
{
1345
    int width, height;
1346
    
1347
#ifdef CONFIG_BOCHS_VBE
1348
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1349
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1350
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1351
    } else 
1352
#endif
1353
    {
1354
        width = (s->cr[0x01] + 1) * 8;
1355
        height = s->cr[0x12] | 
1356
            ((s->cr[0x07] & 0x02) << 7) | 
1357
            ((s->cr[0x07] & 0x40) << 3);
1358
        height = (height + 1);
1359
    }
1360
    *pwidth = width;
1361
    *pheight = height;
1362
}
1363

    
1364
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1365
{
1366
    int y;
1367
    if (y1 >= VGA_MAX_HEIGHT)
1368
        return;
1369
    if (y2 >= VGA_MAX_HEIGHT)
1370
        y2 = VGA_MAX_HEIGHT;
1371
    for(y = y1; y < y2; y++) {
1372
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1373
    }
1374
}
1375

    
1376
/* 
1377
 * graphic modes
1378
 */
1379
static void vga_draw_graphic(VGAState *s, int full_update)
1380
{
1381
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1382
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1383
    int disp_width, multi_scan, multi_run;
1384
    uint8_t *d;
1385
    uint32_t v, addr1, addr;
1386
    vga_draw_line_func *vga_draw_line;
1387
    
1388
    full_update |= update_basic_params(s);
1389

    
1390
    s->get_resolution(s, &width, &height);
1391
    disp_width = width;
1392

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

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

    
1546
static void vga_draw_blank(VGAState *s, int full_update)
1547
{
1548
    int i, w, val;
1549
    uint8_t *d;
1550

    
1551
    if (!full_update)
1552
        return;
1553
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1554
        return;
1555
    if (s->ds->depth == 8) 
1556
        val = s->rgb_to_pixel(0, 0, 0);
1557
    else
1558
        val = 0;
1559
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1560
    d = s->ds->data;
1561
    for(i = 0; i < s->last_scr_height; i++) {
1562
        memset(d, val, w);
1563
        d += s->ds->linesize;
1564
    }
1565
    dpy_update(s->ds, 0, 0, 
1566
               s->last_scr_width, s->last_scr_height);
1567
}
1568

    
1569
#define GMODE_TEXT     0
1570
#define GMODE_GRAPH    1
1571
#define GMODE_BLANK 2 
1572

    
1573
static void vga_update_display(void *opaque)
1574
{
1575
    VGAState *s = (VGAState *)opaque;
1576
    int full_update, graphic_mode;
1577

    
1578
    if (s->ds->depth == 0) {
1579
        /* nothing to do */
1580
    } else {
1581
        s->rgb_to_pixel = 
1582
            rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1583
        
1584
        full_update = 0;
1585
        if (!(s->ar_index & 0x20)) {
1586
            graphic_mode = GMODE_BLANK;
1587
        } else {
1588
            graphic_mode = s->gr[6] & 1;
1589
        }
1590
        if (graphic_mode != s->graphic_mode) {
1591
            s->graphic_mode = graphic_mode;
1592
            full_update = 1;
1593
        }
1594
        switch(graphic_mode) {
1595
        case GMODE_TEXT:
1596
            vga_draw_text(s, full_update);
1597
            break;
1598
        case GMODE_GRAPH:
1599
            vga_draw_graphic(s, full_update);
1600
            break;
1601
        case GMODE_BLANK:
1602
        default:
1603
            vga_draw_blank(s, full_update);
1604
            break;
1605
        }
1606
    }
1607
}
1608

    
1609
/* force a full display refresh */
1610
static void vga_invalidate_display(void *opaque)
1611
{
1612
    VGAState *s = (VGAState *)opaque;
1613
    
1614
    s->last_width = -1;
1615
    s->last_height = -1;
1616
}
1617

    
1618
static void vga_reset(VGAState *s)
1619
{
1620
    memset(s, 0, sizeof(VGAState));
1621
    s->graphic_mode = -1; /* force full update */
1622
}
1623

    
1624
static CPUReadMemoryFunc *vga_mem_read[3] = {
1625
    vga_mem_readb,
1626
    vga_mem_readw,
1627
    vga_mem_readl,
1628
};
1629

    
1630
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1631
    vga_mem_writeb,
1632
    vga_mem_writew,
1633
    vga_mem_writel,
1634
};
1635

    
1636
static void vga_save(QEMUFile *f, void *opaque)
1637
{
1638
    VGAState *s = opaque;
1639
    int i;
1640

    
1641
    if (s->pci_dev)
1642
        pci_device_save(s->pci_dev, f);
1643

    
1644
    qemu_put_be32s(f, &s->latch);
1645
    qemu_put_8s(f, &s->sr_index);
1646
    qemu_put_buffer(f, s->sr, 8);
1647
    qemu_put_8s(f, &s->gr_index);
1648
    qemu_put_buffer(f, s->gr, 16);
1649
    qemu_put_8s(f, &s->ar_index);
1650
    qemu_put_buffer(f, s->ar, 21);
1651
    qemu_put_be32s(f, &s->ar_flip_flop);
1652
    qemu_put_8s(f, &s->cr_index);
1653
    qemu_put_buffer(f, s->cr, 256);
1654
    qemu_put_8s(f, &s->msr);
1655
    qemu_put_8s(f, &s->fcr);
1656
    qemu_put_8s(f, &s->st00);
1657
    qemu_put_8s(f, &s->st01);
1658

    
1659
    qemu_put_8s(f, &s->dac_state);
1660
    qemu_put_8s(f, &s->dac_sub_index);
1661
    qemu_put_8s(f, &s->dac_read_index);
1662
    qemu_put_8s(f, &s->dac_write_index);
1663
    qemu_put_buffer(f, s->dac_cache, 3);
1664
    qemu_put_buffer(f, s->palette, 768);
1665

    
1666
    qemu_put_be32s(f, &s->bank_offset);
1667
#ifdef CONFIG_BOCHS_VBE
1668
    qemu_put_byte(f, 1);
1669
    qemu_put_be16s(f, &s->vbe_index);
1670
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1671
        qemu_put_be16s(f, &s->vbe_regs[i]);
1672
    qemu_put_be32s(f, &s->vbe_start_addr);
1673
    qemu_put_be32s(f, &s->vbe_line_offset);
1674
    qemu_put_be32s(f, &s->vbe_bank_mask);
1675
#else
1676
    qemu_put_byte(f, 0);
1677
#endif
1678
}
1679

    
1680
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1681
{
1682
    VGAState *s = opaque;
1683
    int is_vbe, i, ret;
1684

    
1685
    if (version_id > 2)
1686
        return -EINVAL;
1687

    
1688
    if (s->pci_dev && version_id >= 2) {
1689
        ret = pci_device_load(s->pci_dev, f);
1690
        if (ret < 0)
1691
            return ret;
1692
    }
1693

    
1694
    qemu_get_be32s(f, &s->latch);
1695
    qemu_get_8s(f, &s->sr_index);
1696
    qemu_get_buffer(f, s->sr, 8);
1697
    qemu_get_8s(f, &s->gr_index);
1698
    qemu_get_buffer(f, s->gr, 16);
1699
    qemu_get_8s(f, &s->ar_index);
1700
    qemu_get_buffer(f, s->ar, 21);
1701
    qemu_get_be32s(f, &s->ar_flip_flop);
1702
    qemu_get_8s(f, &s->cr_index);
1703
    qemu_get_buffer(f, s->cr, 256);
1704
    qemu_get_8s(f, &s->msr);
1705
    qemu_get_8s(f, &s->fcr);
1706
    qemu_get_8s(f, &s->st00);
1707
    qemu_get_8s(f, &s->st01);
1708

    
1709
    qemu_get_8s(f, &s->dac_state);
1710
    qemu_get_8s(f, &s->dac_sub_index);
1711
    qemu_get_8s(f, &s->dac_read_index);
1712
    qemu_get_8s(f, &s->dac_write_index);
1713
    qemu_get_buffer(f, s->dac_cache, 3);
1714
    qemu_get_buffer(f, s->palette, 768);
1715

    
1716
    qemu_get_be32s(f, &s->bank_offset);
1717
    is_vbe = qemu_get_byte(f);
1718
#ifdef CONFIG_BOCHS_VBE
1719
    if (!is_vbe)
1720
        return -EINVAL;
1721
    qemu_get_be16s(f, &s->vbe_index);
1722
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1723
        qemu_get_be16s(f, &s->vbe_regs[i]);
1724
    qemu_get_be32s(f, &s->vbe_start_addr);
1725
    qemu_get_be32s(f, &s->vbe_line_offset);
1726
    qemu_get_be32s(f, &s->vbe_bank_mask);
1727
#else
1728
    if (is_vbe)
1729
        return -EINVAL;
1730
#endif
1731

    
1732
    /* force refresh */
1733
    s->graphic_mode = -1;
1734
    return 0;
1735
}
1736

    
1737
typedef struct PCIVGAState {
1738
    PCIDevice dev;
1739
    VGAState vga_state;
1740
} PCIVGAState;
1741

    
1742
static void vga_map(PCIDevice *pci_dev, int region_num, 
1743
                    uint32_t addr, uint32_t size, int type)
1744
{
1745
    PCIVGAState *d = (PCIVGAState *)pci_dev;
1746
    VGAState *s = &d->vga_state;
1747
    if (region_num == PCI_ROM_SLOT) {
1748
        cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1749
    } else {
1750
        cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1751
    }
1752
}
1753

    
1754
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1755
                     unsigned long vga_ram_offset, int vga_ram_size)
1756
{
1757
    int i, j, v, b;
1758

    
1759
    for(i = 0;i < 256; i++) {
1760
        v = 0;
1761
        for(j = 0; j < 8; j++) {
1762
            v |= ((i >> j) & 1) << (j * 4);
1763
        }
1764
        expand4[i] = v;
1765

    
1766
        v = 0;
1767
        for(j = 0; j < 4; j++) {
1768
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1769
        }
1770
        expand2[i] = v;
1771
    }
1772
    for(i = 0; i < 16; i++) {
1773
        v = 0;
1774
        for(j = 0; j < 4; j++) {
1775
            b = ((i >> j) & 1);
1776
            v |= b << (2 * j);
1777
            v |= b << (2 * j + 1);
1778
        }
1779
        expand4to8[i] = v;
1780
    }
1781

    
1782
    vga_reset(s);
1783

    
1784
    s->vram_ptr = vga_ram_base;
1785
    s->vram_offset = vga_ram_offset;
1786
    s->vram_size = vga_ram_size;
1787
    s->ds = ds;
1788
    s->get_bpp = vga_get_bpp;
1789
    s->get_offsets = vga_get_offsets;
1790
    s->get_resolution = vga_get_resolution;
1791
    s->update = vga_update_display;
1792
    s->invalidate = vga_invalidate_display;
1793
    s->screen_dump = vga_screen_dump;
1794
}
1795

    
1796
/* used by both ISA and PCI */
1797
void vga_init(VGAState *s)
1798
{
1799
    int vga_io_memory;
1800

    
1801
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1802

    
1803
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1804

    
1805
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1806
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1807
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1808
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1809

    
1810
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1811

    
1812
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1813
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1814
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1815
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1816
    s->bank_offset = 0;
1817

    
1818
#ifdef CONFIG_BOCHS_VBE
1819
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1820
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1821
#if defined (TARGET_I386)
1822
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1823
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1824

    
1825
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1826
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1827

    
1828
    /* old Bochs IO ports */
1829
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1830
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1831

    
1832
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1833
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1834
#else
1835
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1836
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1837

    
1838
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1839
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1840
#endif
1841
#endif /* CONFIG_BOCHS_VBE */
1842

    
1843
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1844
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1845
                                 vga_io_memory);
1846
}
1847

    
1848
/* Memory mapped interface */
1849
static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
1850
{
1851
    VGAState *s = opaque;
1852

    
1853
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
1854
}
1855

    
1856
static void vga_mm_writeb (void *opaque,
1857
                           target_phys_addr_t addr, uint32_t value)
1858
{
1859
    VGAState *s = opaque;
1860

    
1861
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
1862
}
1863

    
1864
static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
1865
{
1866
    VGAState *s = opaque;
1867

    
1868
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
1869
}
1870

    
1871
static void vga_mm_writew (void *opaque,
1872
                           target_phys_addr_t addr, uint32_t value)
1873
{
1874
    VGAState *s = opaque;
1875

    
1876
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
1877
}
1878

    
1879
static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
1880
{
1881
    VGAState *s = opaque;
1882

    
1883
    return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
1884
}
1885

    
1886
static void vga_mm_writel (void *opaque,
1887
                           target_phys_addr_t addr, uint32_t value)
1888
{
1889
    VGAState *s = opaque;
1890

    
1891
    vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
1892
}
1893

    
1894
static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
1895
    &vga_mm_readb,
1896
    &vga_mm_readw,
1897
    &vga_mm_readl,
1898
};
1899

    
1900
static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
1901
    &vga_mm_writeb,
1902
    &vga_mm_writew,
1903
    &vga_mm_writel,
1904
};
1905

    
1906
static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
1907
                        target_phys_addr_t ctrl_base, int it_shift)
1908
{
1909
    int s_ioport_ctrl, vga_io_memory;
1910

    
1911
    s->base_ctrl = ctrl_base;
1912
    s->it_shift = it_shift;
1913
    s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
1914
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1915

    
1916
    register_savevm("vga", 0, 2, vga_save, vga_load, s);
1917

    
1918
    cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
1919
    s->bank_offset = 0;
1920
    cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
1921
}
1922

    
1923
int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, 
1924
                 unsigned long vga_ram_offset, int vga_ram_size)
1925
{
1926
    VGAState *s;
1927

    
1928
    s = qemu_mallocz(sizeof(VGAState));
1929
    if (!s)
1930
        return -1;
1931

    
1932
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1933
    vga_init(s);
1934

    
1935
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1936

    
1937
#ifdef CONFIG_BOCHS_VBE
1938
    /* XXX: use optimized standard vga accesses */
1939
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1940
                                 vga_ram_size, vga_ram_offset);
1941
#endif
1942
    return 0;
1943
}
1944

    
1945
int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
1946
                    unsigned long vga_ram_offset, int vga_ram_size,
1947
                    target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
1948
                    int it_shift)
1949
{
1950
    VGAState *s;
1951

    
1952
    s = qemu_mallocz(sizeof(VGAState));
1953
    if (!s)
1954
        return -1;
1955

    
1956
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1957
    vga_mm_init(s, vram_base, ctrl_base, it_shift);
1958

    
1959
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1960

    
1961
#ifdef CONFIG_BOCHS_VBE
1962
    /* XXX: use optimized standard vga accesses */
1963
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1964
                                 vga_ram_size, vga_ram_offset);
1965
#endif
1966
    return 0;
1967
}
1968

    
1969
int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1970
                 unsigned long vga_ram_offset, int vga_ram_size,
1971
                 unsigned long vga_bios_offset, int vga_bios_size)
1972
{
1973
    PCIVGAState *d;
1974
    VGAState *s;
1975
    uint8_t *pci_conf;
1976
    
1977
    d = (PCIVGAState *)pci_register_device(bus, "VGA", 
1978
                                           sizeof(PCIVGAState),
1979
                                           -1, NULL, NULL);
1980
    if (!d)
1981
        return -1;
1982
    s = &d->vga_state;
1983
    
1984
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1985
    vga_init(s);
1986

    
1987
    graphic_console_init(s->ds, s->update, s->invalidate, s->screen_dump, s);
1988

    
1989
    s->pci_dev = &d->dev;
1990
    
1991
    pci_conf = d->dev.config;
1992
    pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1993
    pci_conf[0x01] = 0x12;
1994
    pci_conf[0x02] = 0x11;
1995
    pci_conf[0x03] = 0x11;
1996
    pci_conf[0x0a] = 0x00; // VGA controller 
1997
    pci_conf[0x0b] = 0x03;
1998
    pci_conf[0x0e] = 0x00; // header_type
1999
    
2000
    /* XXX: vga_ram_size must be a power of two */
2001
    pci_register_io_region(&d->dev, 0, vga_ram_size, 
2002
                           PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2003
    if (vga_bios_size != 0) {
2004
        unsigned int bios_total_size;
2005
        s->bios_offset = vga_bios_offset;
2006
        s->bios_size = vga_bios_size;
2007
        /* must be a power of two */
2008
        bios_total_size = 1;
2009
        while (bios_total_size < vga_bios_size)
2010
            bios_total_size <<= 1;
2011
        pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size, 
2012
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2013
    }
2014
    return 0;
2015
}
2016

    
2017
/********************************************************/
2018
/* vga screen dump */
2019

    
2020
static int vga_save_w, vga_save_h;
2021

    
2022
static void vga_save_dpy_update(DisplayState *s, 
2023
                                int x, int y, int w, int h)
2024
{
2025
}
2026

    
2027
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2028
{
2029
    s->linesize = w * 4;
2030
    s->data = qemu_malloc(h * s->linesize);
2031
    vga_save_w = w;
2032
    vga_save_h = h;
2033
}
2034

    
2035
static void vga_save_dpy_refresh(DisplayState *s)
2036
{
2037
}
2038

    
2039
int ppm_save(const char *filename, uint8_t *data, 
2040
             int w, int h, int linesize)
2041
{
2042
    FILE *f;
2043
    uint8_t *d, *d1;
2044
    unsigned int v;
2045
    int y, x;
2046

    
2047
    f = fopen(filename, "wb");
2048
    if (!f)
2049
        return -1;
2050
    fprintf(f, "P6\n%d %d\n%d\n",
2051
            w, h, 255);
2052
    d1 = data;
2053
    for(y = 0; y < h; y++) {
2054
        d = d1;
2055
        for(x = 0; x < w; x++) {
2056
            v = *(uint32_t *)d;
2057
            fputc((v >> 16) & 0xff, f);
2058
            fputc((v >> 8) & 0xff, f);
2059
            fputc((v) & 0xff, f);
2060
            d += 4;
2061
        }
2062
        d1 += linesize;
2063
    }
2064
    fclose(f);
2065
    return 0;
2066
}
2067

    
2068
/* save the vga display in a PPM image even if no display is
2069
   available */
2070
static void vga_screen_dump(void *opaque, const char *filename)
2071
{
2072
    VGAState *s = (VGAState *)opaque;
2073
    DisplayState *saved_ds, ds1, *ds = &ds1;
2074
    
2075
    /* XXX: this is a little hackish */
2076
    vga_invalidate_display(s);
2077
    saved_ds = s->ds;
2078

    
2079
    memset(ds, 0, sizeof(DisplayState));
2080
    ds->dpy_update = vga_save_dpy_update;
2081
    ds->dpy_resize = vga_save_dpy_resize;
2082
    ds->dpy_refresh = vga_save_dpy_refresh;
2083
    ds->depth = 32;
2084

    
2085
    s->ds = ds;
2086
    s->graphic_mode = -1;
2087
    vga_update_display(s);
2088
    
2089
    if (ds->data) {
2090
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
2091
                 s->ds->linesize);
2092
        qemu_free(ds->data);
2093
    }
2094
    s->ds = saved_ds;
2095
}