Statistics
| Branch: | Revision:

root / hw / vga.c @ 67b915a5

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

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

    
30
//#define DEBUG_S3
31
//#define DEBUG_BOCHS_VBE
32

    
33
#define CONFIG_S3VGA
34

    
35
#define MSR_COLOR_EMULATION 0x01
36
#define MSR_PAGE_SELECT     0x20
37

    
38
#define ST01_V_RETRACE      0x08
39
#define ST01_DISP_ENABLE    0x01
40

    
41
/* bochs VBE support */
42
#define CONFIG_BOCHS_VBE
43

    
44
#define VBE_DISPI_MAX_XRES              1024
45
#define VBE_DISPI_MAX_YRES              768
46

    
47
#define VBE_DISPI_INDEX_ID              0x0
48
#define VBE_DISPI_INDEX_XRES            0x1
49
#define VBE_DISPI_INDEX_YRES            0x2
50
#define VBE_DISPI_INDEX_BPP             0x3
51
#define VBE_DISPI_INDEX_ENABLE          0x4
52
#define VBE_DISPI_INDEX_BANK            0x5
53
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
54
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
55
#define VBE_DISPI_INDEX_X_OFFSET        0x8
56
#define VBE_DISPI_INDEX_Y_OFFSET        0x9
57
#define VBE_DISPI_INDEX_NB              0xa
58
      
59
#define VBE_DISPI_ID0                   0xB0C0
60
#define VBE_DISPI_ID1                   0xB0C1
61
#define VBE_DISPI_ID2                   0xB0C2
62
  
63
#define VBE_DISPI_DISABLED              0x00
64
#define VBE_DISPI_ENABLED               0x01
65
#define VBE_DISPI_LFB_ENABLED           0x40
66
#define VBE_DISPI_NOCLEARMEM            0x80
67
  
68
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
69

    
70
typedef struct VGAState {
71
    uint8_t *vram_ptr;
72
    unsigned long vram_offset;
73
    unsigned int vram_size;
74
    uint32_t latch;
75
    uint8_t sr_index;
76
    uint8_t sr[8];
77
    uint8_t gr_index;
78
    uint8_t gr[16];
79
    uint8_t ar_index;
80
    uint8_t ar[21];
81
    int ar_flip_flop;
82
    uint8_t cr_index;
83
    uint8_t cr[256]; /* CRT registers */
84
    uint8_t msr; /* Misc Output Register */
85
    uint8_t fcr; /* Feature Control Register */
86
    uint8_t st00; /* status 0 */
87
    uint8_t st01; /* status 1 */
88
    uint8_t dac_state;
89
    uint8_t dac_sub_index;
90
    uint8_t dac_read_index;
91
    uint8_t dac_write_index;
92
    uint8_t dac_cache[3]; /* used when writing */
93
    uint8_t palette[768];
94
    uint32_t bank_offset;
95
#ifdef CONFIG_BOCHS_VBE
96
    uint16_t vbe_index;
97
    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
98
    uint32_t vbe_start_addr;
99
    uint32_t vbe_line_offset;
100
    uint32_t vbe_bank_mask;
101
#endif
102
    /* display refresh support */
103
    DisplayState *ds;
104
    uint32_t font_offsets[2];
105
    int graphic_mode;
106
    uint8_t shift_control;
107
    uint8_t double_scan;
108
    uint32_t line_offset;
109
    uint32_t line_compare;
110
    uint32_t start_addr;
111
    uint8_t last_cw, last_ch;
112
    uint32_t last_width, last_height;
113
    uint8_t cursor_start, cursor_end;
114
    uint32_t cursor_offset;
115
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
116
    /* tell for each page if it has been updated since the last time */
117
    uint32_t last_palette[256];
118
#define CH_ATTR_SIZE (160 * 100)
119
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
120
} VGAState;
121

    
122
/* force some bits to zero */
123
static const uint8_t sr_mask[8] = {
124
    (uint8_t)~0xfc,
125
    (uint8_t)~0xc2,
126
    (uint8_t)~0xf0,
127
    (uint8_t)~0xc0,
128
    (uint8_t)~0xf1,
129
    (uint8_t)~0xff,
130
    (uint8_t)~0xff,
131
    (uint8_t)~0x00,
132
};
133

    
134
static const uint8_t gr_mask[16] = {
135
    (uint8_t)~0xf0, /* 0x00 */
136
    (uint8_t)~0xf0, /* 0x01 */
137
    (uint8_t)~0xf0, /* 0x02 */
138
    (uint8_t)~0xe0, /* 0x03 */
139
    (uint8_t)~0xfc, /* 0x04 */
140
    (uint8_t)~0x84, /* 0x05 */
141
    (uint8_t)~0xf0, /* 0x06 */
142
    (uint8_t)~0xf0, /* 0x07 */
143
    (uint8_t)~0x00, /* 0x08 */
144
    (uint8_t)~0xff, /* 0x09 */
145
    (uint8_t)~0xff, /* 0x0a */
146
    (uint8_t)~0xff, /* 0x0b */
147
    (uint8_t)~0xff, /* 0x0c */
148
    (uint8_t)~0xff, /* 0x0d */
149
    (uint8_t)~0xff, /* 0x0e */
150
    (uint8_t)~0xff, /* 0x0f */
151
};
152

    
153
#define cbswap_32(__x) \
154
((uint32_t)( \
155
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
156
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
157
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
158
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
159

    
160
#ifdef WORDS_BIGENDIAN
161
#define PAT(x) cbswap_32(x)
162
#else
163
#define PAT(x) (x)
164
#endif
165

    
166
#ifdef WORDS_BIGENDIAN
167
#define BIG 1
168
#else
169
#define BIG 0
170
#endif
171

    
172
#ifdef WORDS_BIGENDIAN
173
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
174
#else
175
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
176
#endif
177

    
178
static const uint32_t mask16[16] = {
179
    PAT(0x00000000),
180
    PAT(0x000000ff),
181
    PAT(0x0000ff00),
182
    PAT(0x0000ffff),
183
    PAT(0x00ff0000),
184
    PAT(0x00ff00ff),
185
    PAT(0x00ffff00),
186
    PAT(0x00ffffff),
187
    PAT(0xff000000),
188
    PAT(0xff0000ff),
189
    PAT(0xff00ff00),
190
    PAT(0xff00ffff),
191
    PAT(0xffff0000),
192
    PAT(0xffff00ff),
193
    PAT(0xffffff00),
194
    PAT(0xffffffff),
195
};
196

    
197
#undef PAT
198

    
199
#ifdef WORDS_BIGENDIAN
200
#define PAT(x) (x)
201
#else
202
#define PAT(x) cbswap_32(x)
203
#endif
204

    
205
static const uint32_t dmask16[16] = {
206
    PAT(0x00000000),
207
    PAT(0x000000ff),
208
    PAT(0x0000ff00),
209
    PAT(0x0000ffff),
210
    PAT(0x00ff0000),
211
    PAT(0x00ff00ff),
212
    PAT(0x00ffff00),
213
    PAT(0x00ffffff),
214
    PAT(0xff000000),
215
    PAT(0xff0000ff),
216
    PAT(0xff00ff00),
217
    PAT(0xff00ffff),
218
    PAT(0xffff0000),
219
    PAT(0xffff00ff),
220
    PAT(0xffffff00),
221
    PAT(0xffffffff),
222
};
223

    
224
static const uint32_t dmask4[4] = {
225
    PAT(0x00000000),
226
    PAT(0x0000ffff),
227
    PAT(0xffff0000),
228
    PAT(0xffffffff),
229
};
230

    
231
static uint32_t expand4[256];
232
static uint16_t expand2[256];
233
static uint8_t expand4to8[16];
234

    
235
VGAState vga_state;
236
int vga_io_memory;
237

    
238
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
239
{
240
    VGAState *s = opaque;
241
    int val, index;
242

    
243
    /* check port range access depending on color/monochrome mode */
244
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
245
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
246
        val = 0xff;
247
    } else {
248
        switch(addr) {
249
        case 0x3c0:
250
            if (s->ar_flip_flop == 0) {
251
                val = s->ar_index;
252
            } else {
253
                val = 0;
254
            }
255
            break;
256
        case 0x3c1:
257
            index = s->ar_index & 0x1f;
258
            if (index < 21) 
259
                val = s->ar[index];
260
            else
261
                val = 0;
262
            break;
263
        case 0x3c2:
264
            val = s->st00;
265
            break;
266
        case 0x3c4:
267
            val = s->sr_index;
268
            break;
269
        case 0x3c5:
270
            val = s->sr[s->sr_index];
271
#ifdef DEBUG_VGA_REG
272
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
273
#endif
274
            break;
275
        case 0x3c7:
276
            val = s->dac_state;
277
            break;
278
        case 0x3c9:
279
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
280
            if (++s->dac_sub_index == 3) {
281
                s->dac_sub_index = 0;
282
                s->dac_read_index++;
283
            }
284
            break;
285
        case 0x3ca:
286
            val = s->fcr;
287
            break;
288
        case 0x3cc:
289
            val = s->msr;
290
            break;
291
        case 0x3ce:
292
            val = s->gr_index;
293
            break;
294
        case 0x3cf:
295
            val = s->gr[s->gr_index];
296
#ifdef DEBUG_VGA_REG
297
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
298
#endif
299
            break;
300
        case 0x3b4:
301
        case 0x3d4:
302
            val = s->cr_index;
303
            break;
304
        case 0x3b5:
305
        case 0x3d5:
306
            val = s->cr[s->cr_index];
307
#ifdef DEBUG_VGA_REG
308
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
309
#endif
310
#ifdef DEBUG_S3
311
            if (s->cr_index >= 0x20)
312
                printf("S3: CR read index=0x%x val=0x%x\n",
313
                       s->cr_index, val);
314
#endif
315
            break;
316
        case 0x3ba:
317
        case 0x3da:
318
            /* just toggle to fool polling */
319
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
320
            val = s->st01;
321
            s->ar_flip_flop = 0;
322
            break;
323
        default:
324
            val = 0x00;
325
            break;
326
        }
327
    }
328
#if defined(DEBUG_VGA)
329
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
330
#endif
331
    return val;
332
}
333

    
334
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
335
{
336
    VGAState *s = opaque;
337
    int index, v;
338

    
339
    /* check port range access depending on color/monochrome mode */
340
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
341
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
342
        return;
343

    
344
#ifdef DEBUG_VGA
345
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
346
#endif
347

    
348
    switch(addr) {
349
    case 0x3c0:
350
        if (s->ar_flip_flop == 0) {
351
            val &= 0x3f;
352
            s->ar_index = val;
353
        } else {
354
            index = s->ar_index & 0x1f;
355
            switch(index) {
356
            case 0x00 ... 0x0f:
357
                s->ar[index] = val & 0x3f;
358
                break;
359
            case 0x10:
360
                s->ar[index] = val & ~0x10;
361
                break;
362
            case 0x11:
363
                s->ar[index] = val;
364
                break;
365
            case 0x12:
366
                s->ar[index] = val & ~0xc0;
367
                break;
368
            case 0x13:
369
                s->ar[index] = val & ~0xf0;
370
                break;
371
            case 0x14:
372
                s->ar[index] = val & ~0xf0;
373
                break;
374
            default:
375
                break;
376
            }
377
        }
378
        s->ar_flip_flop ^= 1;
379
        break;
380
    case 0x3c2:
381
        s->msr = val & ~0x10;
382
        break;
383
    case 0x3c4:
384
        s->sr_index = val & 7;
385
        break;
386
    case 0x3c5:
387
#ifdef DEBUG_VGA_REG
388
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
389
#endif
390
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
391
        break;
392
    case 0x3c7:
393
        s->dac_read_index = val;
394
        s->dac_sub_index = 0;
395
        s->dac_state = 3;
396
        break;
397
    case 0x3c8:
398
        s->dac_write_index = val;
399
        s->dac_sub_index = 0;
400
        s->dac_state = 0;
401
        break;
402
    case 0x3c9:
403
        s->dac_cache[s->dac_sub_index] = val;
404
        if (++s->dac_sub_index == 3) {
405
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
406
            s->dac_sub_index = 0;
407
            s->dac_write_index++;
408
        }
409
        break;
410
    case 0x3ce:
411
        s->gr_index = val & 0x0f;
412
        break;
413
    case 0x3cf:
414
#ifdef DEBUG_VGA_REG
415
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
416
#endif
417
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
418
        break;
419
    case 0x3b4:
420
    case 0x3d4:
421
        s->cr_index = val;
422
        break;
423
    case 0x3b5:
424
    case 0x3d5:
425
#ifdef DEBUG_VGA_REG
426
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
427
#endif
428
        /* handle CR0-7 protection */
429
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
430
            /* can always write bit 4 of CR7 */
431
            if (s->cr_index == 7)
432
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
433
            return;
434
        }
435
        switch(s->cr_index) {
436
        case 0x01: /* horizontal display end */
437
        case 0x07:
438
        case 0x09:
439
        case 0x0c:
440
        case 0x0d:
441
        case 0x12: /* veritcal display end */
442
            s->cr[s->cr_index] = val;
443
            break;
444

    
445
#ifdef CONFIG_S3VGA
446
            /* S3 registers */
447
        case 0x2d:
448
        case 0x2e:
449
        case 0x2f:
450
        case 0x30:
451
            /* chip ID, cannot write */
452
            break;
453
        case 0x31:
454
            /* update start address */
455
            s->cr[s->cr_index] = val;
456
            v = (val >> 4) & 3;
457
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
458
            break;
459
        case 0x51:
460
            /* update start address */
461
            s->cr[s->cr_index] = val;
462
            v = val & 3;
463
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
464
            break;
465
#endif
466
        default:
467
            s->cr[s->cr_index] = val;
468
            break;
469
        }
470
#ifdef DEBUG_S3
471
        if (s->cr_index >= 0x20)
472
            printf("S3: CR write index=0x%x val=0x%x\n",
473
                   s->cr_index, val);
474
#endif
475
        break;
476
    case 0x3ba:
477
    case 0x3da:
478
        s->fcr = val & 0x10;
479
        break;
480
    }
481
}
482

    
483
#ifdef CONFIG_BOCHS_VBE
484
static uint32_t vbe_ioport_read(void *opaque, uint32_t addr)
485
{
486
    VGAState *s = opaque;
487
    uint32_t val;
488

    
489
    addr &= 1;
490
    if (addr == 0) {
491
        val = s->vbe_index;
492
    } else {
493
        if (s->vbe_index <= VBE_DISPI_INDEX_NB)
494
            val = s->vbe_regs[s->vbe_index];
495
        else
496
            val = 0;
497
#ifdef DEBUG_BOCHS_VBE
498
        printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
499
#endif
500
    }
501
    return val;
502
}
503

    
504
static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
505
{
506
    VGAState *s = opaque;
507

    
508
    addr &= 1;
509
    if (addr == 0) {
510
        s->vbe_index = val;
511
    } else if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
512
#ifdef DEBUG_BOCHS_VBE
513
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
514
#endif
515
        switch(s->vbe_index) {
516
        case VBE_DISPI_INDEX_ID:
517
            if (val == VBE_DISPI_ID0 ||
518
                val == VBE_DISPI_ID1 ||
519
                val == VBE_DISPI_ID2) {
520
                s->vbe_regs[s->vbe_index] = val;
521
            }
522
            break;
523
        case VBE_DISPI_INDEX_XRES:
524
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
525
                s->vbe_regs[s->vbe_index] = val;
526
            }
527
            break;
528
        case VBE_DISPI_INDEX_YRES:
529
            if (val <= VBE_DISPI_MAX_YRES) {
530
                s->vbe_regs[s->vbe_index] = val;
531
            }
532
            break;
533
        case VBE_DISPI_INDEX_BPP:
534
            if (val == 0)
535
                val = 8;
536
            if (val == 4 || val == 8 || val == 15 || 
537
                val == 16 || val == 24 || val == 32) {
538
                s->vbe_regs[s->vbe_index] = val;
539
            }
540
            break;
541
        case VBE_DISPI_INDEX_BANK:
542
            val &= s->vbe_bank_mask;
543
            s->vbe_regs[s->vbe_index] = val;
544
            s->bank_offset = (val << 16) - 0xa0000;
545
            break;
546
        case VBE_DISPI_INDEX_ENABLE:
547
            if (val & VBE_DISPI_ENABLED) {
548
                int h, shift_control;
549

    
550
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
551
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
552
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
553
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
554
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
555
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
556
                
557
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
558
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
559
                else
560
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
561
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
562
                s->vbe_start_addr = 0;
563
                
564
                /* clear the screen (should be done in BIOS) */
565
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
566
                    memset(s->vram_ptr, 0, 
567
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
568
                }
569
                
570
                /* we initialize the VGA graphic mode (should be done
571
                   in BIOS) */
572
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
573
                s->cr[0x17] |= 3; /* no CGA modes */
574
                s->cr[0x13] = s->vbe_line_offset >> 3;
575
                /* width */
576
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
577
                /* height */
578
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
579
                s->cr[0x12] = h;
580
                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
581
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
582
                /* line compare to 1023 */
583
                s->cr[0x18] = 0xff;
584
                s->cr[0x07] |= 0x10;
585
                s->cr[0x09] |= 0x40;
586
                
587
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
588
                    shift_control = 0;
589
                    s->sr[0x01] &= ~8; /* no double line */
590
                } else {
591
                    shift_control = 2;
592
                }
593
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
594
                s->cr[0x09] &= ~0x9f; /* no double scan */
595
                s->vbe_regs[s->vbe_index] = val;
596
            } else {
597
                /* XXX: the bios should do that */
598
                s->bank_offset = -0xa0000;
599
            }
600
            break;
601
        case VBE_DISPI_INDEX_VIRT_WIDTH:
602
            {
603
                int w, h, line_offset;
604

    
605
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
606
                    return;
607
                w = val;
608
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
609
                    line_offset = w >> 1;
610
                else
611
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
612
                h = s->vram_size / line_offset;
613
                /* XXX: support weird bochs semantics ? */
614
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
615
                    return;
616
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
617
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
618
                s->vbe_line_offset = line_offset;
619
            }
620
            break;
621
        case VBE_DISPI_INDEX_X_OFFSET:
622
        case VBE_DISPI_INDEX_Y_OFFSET:
623
            {
624
                int x;
625
                s->vbe_regs[s->vbe_index] = val;
626
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
627
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
628
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
629
                    s->vbe_start_addr += x >> 1;
630
                else
631
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
632
                s->vbe_start_addr >>= 2;
633
            }
634
            break;
635
        default:
636
            break;
637
        }
638
    }
639
}
640
#endif
641

    
642
/* called for accesses between 0xa0000 and 0xc0000 */
643
static uint32_t vga_mem_readb(uint32_t addr)
644
{
645
    VGAState *s = &vga_state;
646
    int memory_map_mode, plane;
647
    uint32_t ret;
648
    
649
    /* convert to VGA memory offset */
650
    memory_map_mode = (s->gr[6] >> 2) & 3;
651
    switch(memory_map_mode) {
652
    case 0:
653
        addr -= 0xa0000;
654
        break;
655
    case 1:
656
        if (addr >= 0xb0000)
657
            return 0xff;
658
        addr += s->bank_offset;
659
        break;
660
    case 2:
661
        addr -= 0xb0000;
662
        if (addr >= 0x8000)
663
            return 0xff;
664
        break;
665
    default:
666
    case 3:
667
        addr -= 0xb8000;
668
        if (addr >= 0x8000)
669
            return 0xff;
670
        break;
671
    }
672
    
673
    if (s->sr[4] & 0x08) {
674
        /* chain 4 mode : simplest access */
675
        ret = s->vram_ptr[addr];
676
    } else if (s->gr[5] & 0x10) {
677
        /* odd/even mode (aka text mode mapping) */
678
        plane = (s->gr[4] & 2) | (addr & 1);
679
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
680
    } else {
681
        /* standard VGA latched access */
682
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
683

    
684
        if (!(s->gr[5] & 0x08)) {
685
            /* read mode 0 */
686
            plane = s->gr[4];
687
            ret = GET_PLANE(s->latch, plane);
688
        } else {
689
            /* read mode 1 */
690
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
691
            ret |= ret >> 16;
692
            ret |= ret >> 8;
693
            ret = (~ret) & 0xff;
694
        }
695
    }
696
    return ret;
697
}
698

    
699
static uint32_t vga_mem_readw(uint32_t addr)
700
{
701
    uint32_t v;
702
    v = vga_mem_readb(addr);
703
    v |= vga_mem_readb(addr + 1) << 8;
704
    return v;
705
}
706

    
707
static uint32_t vga_mem_readl(uint32_t addr)
708
{
709
    uint32_t v;
710
    v = vga_mem_readb(addr);
711
    v |= vga_mem_readb(addr + 1) << 8;
712
    v |= vga_mem_readb(addr + 2) << 16;
713
    v |= vga_mem_readb(addr + 3) << 24;
714
    return v;
715
}
716

    
717
/* called for accesses between 0xa0000 and 0xc0000 */
718
static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
719
{
720
    VGAState *s = &vga_state;
721
    int memory_map_mode, plane, write_mode, b, func_select;
722
    uint32_t write_mask, bit_mask, set_mask;
723

    
724
#ifdef DEBUG_VGA_MEM
725
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
726
#endif
727
    /* convert to VGA memory offset */
728
    memory_map_mode = (s->gr[6] >> 2) & 3;
729
    switch(memory_map_mode) {
730
    case 0:
731
        addr -= 0xa0000;
732
        break;
733
    case 1:
734
        if (addr >= 0xb0000)
735
            return;
736
        addr += s->bank_offset;
737
        break;
738
    case 2:
739
        addr -= 0xb0000;
740
        if (addr >= 0x8000)
741
            return;
742
        break;
743
    default:
744
    case 3:
745
        addr -= 0xb8000;
746
        if (addr >= 0x8000)
747
            return;
748
        break;
749
    }
750
    
751
    if (s->sr[4] & 0x08) {
752
        /* chain 4 mode : simplest access */
753
        plane = addr & 3;
754
        if (s->sr[2] & (1 << plane)) {
755
            s->vram_ptr[addr] = val;
756
#ifdef DEBUG_VGA_MEM
757
            printf("vga: chain4: [0x%x]\n", addr);
758
#endif
759
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
760
        }
761
    } else if (s->gr[5] & 0x10) {
762
        /* odd/even mode (aka text mode mapping) */
763
        plane = (s->gr[4] & 2) | (addr & 1);
764
        if (s->sr[2] & (1 << plane)) {
765
            addr = ((addr & ~1) << 1) | plane;
766
            s->vram_ptr[addr] = val;
767
#ifdef DEBUG_VGA_MEM
768
            printf("vga: odd/even: [0x%x]\n", addr);
769
#endif
770
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
771
        }
772
    } else {
773
        /* standard VGA latched access */
774
        write_mode = s->gr[5] & 3;
775
        switch(write_mode) {
776
        default:
777
        case 0:
778
            /* rotate */
779
            b = s->gr[3] & 7;
780
            val = ((val >> b) | (val << (8 - b))) & 0xff;
781
            val |= val << 8;
782
            val |= val << 16;
783

    
784
            /* apply set/reset mask */
785
            set_mask = mask16[s->gr[1]];
786
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
787
            bit_mask = s->gr[8];
788
            break;
789
        case 1:
790
            val = s->latch;
791
            goto do_write;
792
        case 2:
793
            val = mask16[val & 0x0f];
794
            bit_mask = s->gr[8];
795
            break;
796
        case 3:
797
            /* rotate */
798
            b = s->gr[3] & 7;
799
            val = (val >> b) | (val << (8 - b));
800

    
801
            bit_mask = s->gr[8] & val;
802
            val = mask16[s->gr[0]];
803
            break;
804
        }
805

    
806
        /* apply logical operation */
807
        func_select = s->gr[3] >> 3;
808
        switch(func_select) {
809
        case 0:
810
        default:
811
            /* nothing to do */
812
            break;
813
        case 1:
814
            /* and */
815
            val &= s->latch;
816
            break;
817
        case 2:
818
            /* or */
819
            val |= s->latch;
820
            break;
821
        case 3:
822
            /* xor */
823
            val ^= s->latch;
824
            break;
825
        }
826

    
827
        /* apply bit mask */
828
        bit_mask |= bit_mask << 8;
829
        bit_mask |= bit_mask << 16;
830
        val = (val & bit_mask) | (s->latch & ~bit_mask);
831

    
832
    do_write:
833
        /* mask data according to sr[2] */
834
        write_mask = mask16[s->sr[2]];
835
        ((uint32_t *)s->vram_ptr)[addr] = 
836
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
837
            (val & write_mask);
838
#ifdef DEBUG_VGA_MEM
839
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
840
                   addr * 4, write_mask, val);
841
#endif
842
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
843
    }
844
}
845

    
846
static void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
847
{
848
    vga_mem_writeb(addr, val & 0xff, vaddr);
849
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
850
}
851

    
852
static void vga_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
853
{
854
    vga_mem_writeb(addr, val & 0xff, vaddr);
855
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
856
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff, vaddr);
857
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff, vaddr);
858
}
859

    
860
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
861
                             const uint8_t *font_ptr, int h,
862
                             uint32_t fgcol, uint32_t bgcol);
863
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
864
                                  const uint8_t *font_ptr, int h, 
865
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
866
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
867
                                const uint8_t *s, int width);
868

    
869
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
870
{
871
    /* XXX: TODO */
872
    return 0;
873
}
874

    
875
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
876
{
877
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
878
}
879

    
880
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
881
{
882
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
883
}
884

    
885
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
886
{
887
    return (r << 16) | (g << 8) | b;
888
}
889

    
890
#define DEPTH 8
891
#include "vga_template.h"
892

    
893
#define DEPTH 15
894
#include "vga_template.h"
895

    
896
#define DEPTH 16
897
#include "vga_template.h"
898

    
899
#define DEPTH 32
900
#include "vga_template.h"
901

    
902
static inline int c6_to_8(int v)
903
{
904
    int b;
905
    v &= 0x3f;
906
    b = v & 1;
907
    return (v << 2) | (b << 1) | b;
908
}
909

    
910
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
911
{
912
    unsigned int col;
913
    col = rgb_to_pixel8(r, g, b);
914
    col |= col << 8;
915
    col |= col << 16;
916
    return col;
917
}
918

    
919
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
920
{
921
    unsigned int col;
922
    col = rgb_to_pixel15(r, g, b);
923
    col |= col << 16;
924
    return col;
925
}
926

    
927
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
928
{
929
    unsigned int col;
930
    col = rgb_to_pixel16(r, g, b);
931
    col |= col << 16;
932
    return col;
933
}
934

    
935
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
936
{
937
    unsigned int col;
938
    col = rgb_to_pixel32(r, g, b);
939
    return col;
940
}
941

    
942
/* return true if the palette was modified */
943
static int update_palette16(VGAState *s)
944
{
945
    int full_update, i;
946
    uint32_t v, col, *palette;
947

    
948
    full_update = 0;
949
    palette = s->last_palette;
950
    for(i = 0; i < 16; i++) {
951
        v = s->ar[i];
952
        if (s->ar[0x10] & 0x80)
953
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
954
        else
955
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
956
        v = v * 3;
957
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
958
                              c6_to_8(s->palette[v + 1]), 
959
                              c6_to_8(s->palette[v + 2]));
960
        if (col != palette[i]) {
961
            full_update = 1;
962
            palette[i] = col;
963
        }
964
    }
965
    return full_update;
966
}
967

    
968
/* return true if the palette was modified */
969
static int update_palette256(VGAState *s)
970
{
971
    int full_update, i;
972
    uint32_t v, col, *palette;
973

    
974
    full_update = 0;
975
    palette = s->last_palette;
976
    v = 0;
977
    for(i = 0; i < 256; i++) {
978
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
979
                              c6_to_8(s->palette[v + 1]), 
980
                              c6_to_8(s->palette[v + 2]));
981
        if (col != palette[i]) {
982
            full_update = 1;
983
            palette[i] = col;
984
        }
985
        v += 3;
986
    }
987
    return full_update;
988
}
989

    
990
/* update start_addr and line_offset. Return TRUE if modified */
991
static int update_basic_params(VGAState *s)
992
{
993
    int full_update;
994
    uint32_t start_addr, line_offset, line_compare, v;
995
    
996
    full_update = 0;
997

    
998
#ifdef CONFIG_BOCHS_VBE
999
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1000
        line_offset = s->vbe_line_offset;
1001
        start_addr = s->vbe_start_addr;
1002
    } else
1003
#endif
1004
    {  
1005
        /* compute line_offset in bytes */
1006
        line_offset = s->cr[0x13];
1007
#ifdef CONFIG_S3VGA
1008
        v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
1009
        if (v == 0)
1010
            v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
1011
        line_offset |= (v << 8);
1012
#endif
1013
        line_offset <<= 3;
1014
        
1015
        /* starting address */
1016
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1017
#ifdef CONFIG_S3VGA
1018
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
1019
#endif
1020
    }
1021
    
1022
    /* line compare */
1023
    line_compare = s->cr[0x18] | 
1024
        ((s->cr[0x07] & 0x10) << 4) |
1025
        ((s->cr[0x09] & 0x40) << 3);
1026

    
1027
    if (line_offset != s->line_offset ||
1028
        start_addr != s->start_addr ||
1029
        line_compare != s->line_compare) {
1030
        s->line_offset = line_offset;
1031
        s->start_addr = start_addr;
1032
        s->line_compare = line_compare;
1033
        full_update = 1;
1034
    }
1035
    return full_update;
1036
}
1037

    
1038
static inline int get_depth_index(int depth)
1039
{
1040
    switch(depth) {
1041
    default:
1042
    case 8:
1043
        return 0;
1044
    case 15:
1045
        return 1;
1046
    case 16:
1047
        return 2;
1048
    case 32:
1049
        return 3;
1050
    }
1051
}
1052

    
1053
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1054
    vga_draw_glyph8_8,
1055
    vga_draw_glyph8_16,
1056
    vga_draw_glyph8_16,
1057
    vga_draw_glyph8_32,
1058
};
1059

    
1060
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1061
    vga_draw_glyph16_8,
1062
    vga_draw_glyph16_16,
1063
    vga_draw_glyph16_16,
1064
    vga_draw_glyph16_32,
1065
};
1066

    
1067
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1068
    vga_draw_glyph9_8,
1069
    vga_draw_glyph9_16,
1070
    vga_draw_glyph9_16,
1071
    vga_draw_glyph9_32,
1072
};
1073
    
1074
static const uint8_t cursor_glyph[32 * 4] = {
1075
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1076
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1077
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1078
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1079
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1080
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1081
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1082
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1084
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1085
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1086
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1088
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1089
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1090
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1091
};    
1092

    
1093
/* 
1094
 * Text mode update 
1095
 * Missing:
1096
 * - double scan
1097
 * - double width 
1098
 * - underline
1099
 * - flashing
1100
 */
1101
static void vga_draw_text(VGAState *s, int full_update)
1102
{
1103
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1104
    int cx_min, cx_max, linesize, x_incr;
1105
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1106
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1107
    const uint8_t *font_ptr, *font_base[2];
1108
    int dup9, line_offset, depth_index;
1109
    uint32_t *palette;
1110
    uint32_t *ch_attr_ptr;
1111
    vga_draw_glyph8_func *vga_draw_glyph8;
1112
    vga_draw_glyph9_func *vga_draw_glyph9;
1113

    
1114
    full_update |= update_palette16(s);
1115
    palette = s->last_palette;
1116
    
1117
    /* compute font data address (in plane 2) */
1118
    v = s->sr[3];
1119
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1120
    if (offset != s->font_offsets[0]) {
1121
        s->font_offsets[0] = offset;
1122
        full_update = 1;
1123
    }
1124
    font_base[0] = s->vram_ptr + offset;
1125

    
1126
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1127
    font_base[1] = s->vram_ptr + offset;
1128
    if (offset != s->font_offsets[1]) {
1129
        s->font_offsets[1] = offset;
1130
        full_update = 1;
1131
    }
1132

    
1133
    full_update |= update_basic_params(s);
1134

    
1135
    line_offset = s->line_offset;
1136
    s1 = s->vram_ptr + (s->start_addr * 4);
1137

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

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

    
1274
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1275
    vga_draw_line2_8,
1276
    vga_draw_line2_16,
1277
    vga_draw_line2_16,
1278
    vga_draw_line2_32,
1279

    
1280
    vga_draw_line2d2_8,
1281
    vga_draw_line2d2_16,
1282
    vga_draw_line2d2_16,
1283
    vga_draw_line2d2_32,
1284

    
1285
    vga_draw_line4_8,
1286
    vga_draw_line4_16,
1287
    vga_draw_line4_16,
1288
    vga_draw_line4_32,
1289

    
1290
    vga_draw_line4d2_8,
1291
    vga_draw_line4d2_16,
1292
    vga_draw_line4d2_16,
1293
    vga_draw_line4d2_32,
1294

    
1295
    vga_draw_line8d2_8,
1296
    vga_draw_line8d2_16,
1297
    vga_draw_line8d2_16,
1298
    vga_draw_line8d2_32,
1299

    
1300
    vga_draw_line8_8,
1301
    vga_draw_line8_16,
1302
    vga_draw_line8_16,
1303
    vga_draw_line8_32,
1304

    
1305
    vga_draw_line15_8,
1306
    vga_draw_line15_15,
1307
    vga_draw_line15_16,
1308
    vga_draw_line15_32,
1309

    
1310
    vga_draw_line16_8,
1311
    vga_draw_line16_15,
1312
    vga_draw_line16_16,
1313
    vga_draw_line16_32,
1314

    
1315
    vga_draw_line24_8,
1316
    vga_draw_line24_15,
1317
    vga_draw_line24_16,
1318
    vga_draw_line24_32,
1319

    
1320
    vga_draw_line32_8,
1321
    vga_draw_line32_15,
1322
    vga_draw_line32_16,
1323
    vga_draw_line32_32,
1324
};
1325

    
1326
/* 
1327
 * graphic modes
1328
 * Missing:
1329
 * - double scan
1330
 * - double width 
1331
 */
1332
static void vga_draw_graphic(VGAState *s, int full_update)
1333
{
1334
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1335
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1336
    int disp_width, multi_scan, multi_run;
1337
    uint8_t *d;
1338
    uint32_t v, addr1, addr;
1339
    vga_draw_line_func *vga_draw_line;
1340
    
1341
    full_update |= update_basic_params(s);
1342

    
1343
    width = (s->cr[0x01] + 1) * 8;
1344
    height = s->cr[0x12] | 
1345
        ((s->cr[0x07] & 0x02) << 7) | 
1346
        ((s->cr[0x07] & 0x40) << 3);
1347
    height = (height + 1);
1348
    disp_width = width;
1349
    
1350
    shift_control = (s->gr[0x05] >> 5) & 3;
1351
    double_scan = (s->cr[0x09] & 0x80);
1352
    if (shift_control > 1) {
1353
        multi_scan = (s->cr[0x09] & 0x1f);
1354
    } else {
1355
        multi_scan = 0;
1356
    }
1357
    multi_run = multi_scan;
1358
    if (shift_control != s->shift_control ||
1359
        double_scan != s->double_scan) {
1360
        full_update = 1;
1361
        s->shift_control = shift_control;
1362
        s->double_scan = double_scan;
1363
    }
1364
    
1365
    if (shift_control == 0) {
1366
        full_update |= update_palette16(s);
1367
        if (s->sr[0x01] & 8) {
1368
            v = VGA_DRAW_LINE4D2;
1369
            disp_width <<= 1;
1370
        } else {
1371
            v = VGA_DRAW_LINE4;
1372
        }
1373
    } else if (shift_control == 1) {
1374
        full_update |= update_palette16(s);
1375
        if (s->sr[0x01] & 8) {
1376
            v = VGA_DRAW_LINE2D2;
1377
            disp_width <<= 1;
1378
        } else {
1379
            v = VGA_DRAW_LINE2;
1380
        }
1381
    } else {
1382
#ifdef CONFIG_BOCHS_VBE
1383
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1384
            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
1385
            default:
1386
            case 8:
1387
                full_update |= update_palette256(s);
1388
                v = VGA_DRAW_LINE8;
1389
                break;
1390
            case 15:
1391
                v = VGA_DRAW_LINE15;
1392
                break;
1393
            case 16:
1394
                v = VGA_DRAW_LINE16;
1395
                break;
1396
            case 24:
1397
                v = VGA_DRAW_LINE24;
1398
                break;
1399
            case 32:
1400
                v = VGA_DRAW_LINE32;
1401
                break;
1402
            }
1403
        } else 
1404
#endif
1405
        {
1406
            full_update |= update_palette256(s);
1407
            v = VGA_DRAW_LINE8D2;
1408
        }
1409
    }
1410
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1411

    
1412
    if (disp_width != s->last_width ||
1413
        height != s->last_height) {
1414
        dpy_resize(s->ds, disp_width, height);
1415
        s->last_width = disp_width;
1416
        s->last_height = height;
1417
        full_update = 1;
1418
    }
1419

    
1420
    line_offset = s->line_offset;
1421
#if 0
1422
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1423
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1424
#endif
1425
    addr1 = (s->start_addr * 4);
1426
    bwidth = width * 4;
1427
    y_start = -1;
1428
    page_min = 0x7fffffff;
1429
    page_max = -1;
1430
    d = s->ds->data;
1431
    linesize = s->ds->linesize;
1432
    y1 = 0;
1433
    for(y = 0; y < height; y++) {
1434
        addr = addr1;
1435
        if (!(s->cr[0x17] & 1)) {
1436
            int shift;
1437
            /* CGA compatibility handling */
1438
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1439
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1440
        }
1441
        if (!(s->cr[0x17] & 2)) {
1442
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1443
        }
1444
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1445
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1446
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1447
            cpu_physical_memory_is_dirty(page1);
1448
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1449
            /* if wide line, can use another page */
1450
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1451
        }
1452
        if (update) {
1453
            if (y_start < 0)
1454
                y_start = y;
1455
            if (page0 < page_min)
1456
                page_min = page0;
1457
            if (page1 > page_max)
1458
                page_max = page1;
1459
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1460
        } else {
1461
            if (y_start >= 0) {
1462
                /* flush to display */
1463
                dpy_update(s->ds, 0, y_start, 
1464
                           disp_width, y - y_start);
1465
                y_start = -1;
1466
            }
1467
        }
1468
        if (!multi_run) {
1469
            if (!double_scan || (y & 1) != 0) {
1470
                if (y1 == s->line_compare) {
1471
                    addr1 = 0;
1472
                } else {
1473
                    mask = (s->cr[0x17] & 3) ^ 3;
1474
                    if ((y1 & mask) == mask)
1475
                        addr1 += line_offset;
1476
                }
1477
                y1++;
1478
            }
1479
            multi_run = multi_scan;
1480
        } else {
1481
            multi_run--;
1482
            y1++;
1483
        }
1484
        d += linesize;
1485
    }
1486
    if (y_start >= 0) {
1487
        /* flush to display */
1488
        dpy_update(s->ds, 0, y_start, 
1489
                   disp_width, y - y_start);
1490
    }
1491
    /* reset modified pages */
1492
    if (page_max != -1) {
1493
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1494
    }
1495
}
1496

    
1497
void vga_update_display(void)
1498
{
1499
    VGAState *s = &vga_state;
1500
    int full_update, graphic_mode;
1501

    
1502
    if (s->ds->depth == 0) {
1503
        /* nothing to do */
1504
    } else {
1505
        switch(s->ds->depth) {
1506
        case 8:
1507
            s->rgb_to_pixel = rgb_to_pixel8_dup;
1508
            break;
1509
        case 15:
1510
            s->rgb_to_pixel = rgb_to_pixel15_dup;
1511
            break;
1512
        default:
1513
        case 16:
1514
            s->rgb_to_pixel = rgb_to_pixel16_dup;
1515
            break;
1516
        case 32:
1517
            s->rgb_to_pixel = rgb_to_pixel32_dup;
1518
            break;
1519
        }
1520
        
1521
        full_update = 0;
1522
        graphic_mode = s->gr[6] & 1;
1523
        if (graphic_mode != s->graphic_mode) {
1524
            s->graphic_mode = graphic_mode;
1525
            full_update = 1;
1526
        }
1527
        if (graphic_mode)
1528
            vga_draw_graphic(s, full_update);
1529
        else
1530
            vga_draw_text(s, full_update);
1531
    }
1532
}
1533

    
1534
static void vga_reset(VGAState *s)
1535
{
1536
    memset(s, 0, sizeof(VGAState));
1537
#ifdef CONFIG_S3VGA
1538
    /* chip ID for 8c968 */
1539
    s->cr[0x2d] = 0x88;
1540
    s->cr[0x2e] = 0xb0;
1541
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1542
    s->cr[0x30] = 0xe1;
1543
#endif
1544
    s->graphic_mode = -1; /* force full update */
1545
}
1546

    
1547
static CPUReadMemoryFunc *vga_mem_read[3] = {
1548
    vga_mem_readb,
1549
    vga_mem_readw,
1550
    vga_mem_readl,
1551
};
1552

    
1553
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1554
    vga_mem_writeb,
1555
    vga_mem_writew,
1556
    vga_mem_writel,
1557
};
1558

    
1559
static void vga_save(QEMUFile *f, void *opaque)
1560
{
1561
    VGAState *s = opaque;
1562
    int i;
1563

    
1564
    qemu_put_be32s(f, &s->latch);
1565
    qemu_put_8s(f, &s->sr_index);
1566
    qemu_put_buffer(f, s->sr, 8);
1567
    qemu_put_8s(f, &s->gr_index);
1568
    qemu_put_buffer(f, s->gr, 16);
1569
    qemu_put_8s(f, &s->ar_index);
1570
    qemu_put_buffer(f, s->ar, 21);
1571
    qemu_put_be32s(f, &s->ar_flip_flop);
1572
    qemu_put_8s(f, &s->cr_index);
1573
    qemu_put_buffer(f, s->cr, 256);
1574
    qemu_put_8s(f, &s->msr);
1575
    qemu_put_8s(f, &s->fcr);
1576
    qemu_put_8s(f, &s->st00);
1577
    qemu_put_8s(f, &s->st01);
1578

    
1579
    qemu_put_8s(f, &s->dac_state);
1580
    qemu_put_8s(f, &s->dac_sub_index);
1581
    qemu_put_8s(f, &s->dac_read_index);
1582
    qemu_put_8s(f, &s->dac_write_index);
1583
    qemu_put_buffer(f, s->dac_cache, 3);
1584
    qemu_put_buffer(f, s->palette, 768);
1585

    
1586
    qemu_put_be32s(f, &s->bank_offset);
1587
#ifdef CONFIG_BOCHS_VBE
1588
    qemu_put_byte(f, 1);
1589
    qemu_put_be16s(f, &s->vbe_index);
1590
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1591
        qemu_put_be16s(f, &s->vbe_regs[i]);
1592
    qemu_put_be32s(f, &s->vbe_start_addr);
1593
    qemu_put_be32s(f, &s->vbe_line_offset);
1594
    qemu_put_be32s(f, &s->vbe_bank_mask);
1595
#else
1596
    qemu_put_byte(f, 0);
1597
#endif
1598
}
1599

    
1600
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1601
{
1602
    VGAState *s = opaque;
1603
    int is_vbe, i;
1604

    
1605
    if (version_id != 1)
1606
        return -EINVAL;
1607

    
1608
    qemu_get_be32s(f, &s->latch);
1609
    qemu_get_8s(f, &s->sr_index);
1610
    qemu_get_buffer(f, s->sr, 8);
1611
    qemu_get_8s(f, &s->gr_index);
1612
    qemu_get_buffer(f, s->gr, 16);
1613
    qemu_get_8s(f, &s->ar_index);
1614
    qemu_get_buffer(f, s->ar, 21);
1615
    qemu_get_be32s(f, &s->ar_flip_flop);
1616
    qemu_get_8s(f, &s->cr_index);
1617
    qemu_get_buffer(f, s->cr, 256);
1618
    qemu_get_8s(f, &s->msr);
1619
    qemu_get_8s(f, &s->fcr);
1620
    qemu_get_8s(f, &s->st00);
1621
    qemu_get_8s(f, &s->st01);
1622

    
1623
    qemu_get_8s(f, &s->dac_state);
1624
    qemu_get_8s(f, &s->dac_sub_index);
1625
    qemu_get_8s(f, &s->dac_read_index);
1626
    qemu_get_8s(f, &s->dac_write_index);
1627
    qemu_get_buffer(f, s->dac_cache, 3);
1628
    qemu_get_buffer(f, s->palette, 768);
1629

    
1630
    qemu_get_be32s(f, &s->bank_offset);
1631
    is_vbe = qemu_get_byte(f);
1632
#ifdef CONFIG_BOCHS_VBE
1633
    if (!is_vbe)
1634
        return -EINVAL;
1635
    qemu_get_be16s(f, &s->vbe_index);
1636
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1637
        qemu_get_be16s(f, &s->vbe_regs[i]);
1638
    qemu_get_be32s(f, &s->vbe_start_addr);
1639
    qemu_get_be32s(f, &s->vbe_line_offset);
1640
    qemu_get_be32s(f, &s->vbe_bank_mask);
1641
#else
1642
    if (is_vbe)
1643
        return -EINVAL;
1644
#endif
1645

    
1646
    /* force refresh */
1647
    s->graphic_mode = -1;
1648
    return 0;
1649
}
1650

    
1651
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1652
                   unsigned long vga_ram_offset, int vga_ram_size)
1653
{
1654
    VGAState *s = &vga_state;
1655
    int i, j, v, b;
1656

    
1657
    for(i = 0;i < 256; i++) {
1658
        v = 0;
1659
        for(j = 0; j < 8; j++) {
1660
            v |= ((i >> j) & 1) << (j * 4);
1661
        }
1662
        expand4[i] = v;
1663

    
1664
        v = 0;
1665
        for(j = 0; j < 4; j++) {
1666
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1667
        }
1668
        expand2[i] = v;
1669
    }
1670
    for(i = 0; i < 16; i++) {
1671
        v = 0;
1672
        for(j = 0; j < 4; j++) {
1673
            b = ((i >> j) & 1);
1674
            v |= b << (2 * j);
1675
            v |= b << (2 * j + 1);
1676
        }
1677
        expand4to8[i] = v;
1678
    }
1679

    
1680
    vga_reset(s);
1681

    
1682
    s->vram_ptr = vga_ram_base;
1683
    s->vram_offset = vga_ram_offset;
1684
    s->vram_size = vga_ram_size;
1685
    s->ds = ds;
1686

    
1687
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1688

    
1689
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1690

    
1691
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1692
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1693
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1694
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1695

    
1696
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1697

    
1698
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1699
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1700
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1701
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1702
    s->bank_offset = -0xa0000;
1703

    
1704
#ifdef CONFIG_BOCHS_VBE
1705
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1706
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1707
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read, s);
1708
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read, s);
1709

    
1710
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write, s);
1711
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write, s);
1712
#endif
1713

    
1714
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1715
#if defined (TARGET_I386)
1716
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1717
#ifdef CONFIG_BOCHS_VBE
1718
    /* XXX: use optimized standard vga accesses */
1719
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1720
                                 vga_ram_size, vga_ram_offset);
1721
#endif
1722
#elif defined (TARGET_PPC)
1723
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1724
#endif
1725
    return 0;
1726
}
1727

    
1728
/********************************************************/
1729
/* vga screen dump */
1730

    
1731
static int vga_save_w, vga_save_h;
1732

    
1733
static void vga_save_dpy_update(DisplayState *s, 
1734
                                int x, int y, int w, int h)
1735
{
1736
}
1737

    
1738
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1739
{
1740
    s->linesize = w * 4;
1741
    s->data = qemu_malloc(h * s->linesize);
1742
    vga_save_w = w;
1743
    vga_save_h = h;
1744
}
1745

    
1746
static void vga_save_dpy_refresh(DisplayState *s)
1747
{
1748
}
1749

    
1750
static int ppm_save(const char *filename, uint8_t *data, 
1751
                    int w, int h, int linesize)
1752
{
1753
    FILE *f;
1754
    uint8_t *d, *d1;
1755
    unsigned int v;
1756
    int y, x;
1757

    
1758
    f = fopen(filename, "wb");
1759
    if (!f)
1760
        return -1;
1761
    fprintf(f, "P6\n%d %d\n%d\n",
1762
            w, h, 255);
1763
    d1 = data;
1764
    for(y = 0; y < h; y++) {
1765
        d = d1;
1766
        for(x = 0; x < w; x++) {
1767
            v = *(uint32_t *)d;
1768
            fputc((v >> 16) & 0xff, f);
1769
            fputc((v >> 8) & 0xff, f);
1770
            fputc((v) & 0xff, f);
1771
            d += 4;
1772
        }
1773
        d1 += linesize;
1774
    }
1775
    fclose(f);
1776
    return 0;
1777
}
1778

    
1779
/* save the vga display in a PPM image even if no display is
1780
   available */
1781
void vga_screen_dump(const char *filename)
1782
{
1783
    VGAState *s = &vga_state;
1784
    DisplayState *saved_ds, ds1, *ds = &ds1;
1785
    
1786
    /* XXX: this is a little hackish */
1787
    s->last_width = -1;
1788
    s->last_height = -1;
1789
    saved_ds = s->ds;
1790

    
1791
    memset(ds, 0, sizeof(DisplayState));
1792
    ds->dpy_update = vga_save_dpy_update;
1793
    ds->dpy_resize = vga_save_dpy_resize;
1794
    ds->dpy_refresh = vga_save_dpy_refresh;
1795
    ds->depth = 32;
1796

    
1797
    s->ds = ds;
1798
    s->graphic_mode = -1;
1799
    vga_update_display();
1800
    
1801
    if (ds->data) {
1802
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1803
                 s->ds->linesize);
1804
        qemu_free(ds->data);
1805
    }
1806
    s->ds = saved_ds;
1807
}