Statistics
| Branch: | Revision:

root / hw / vga.c @ b0a21b53

History | View | Annotate | Download (50.9 kB)

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

    
43
#include "cpu.h"
44
#include "exec-all.h"
45

    
46
#include "vl.h"
47

    
48
//#define DEBUG_VGA
49
//#define DEBUG_VGA_MEM
50
//#define DEBUG_VGA_REG
51

    
52
//#define DEBUG_S3
53
//#define DEBUG_BOCHS_VBE
54

    
55
#define CONFIG_S3VGA
56

    
57
#define MSR_COLOR_EMULATION 0x01
58
#define MSR_PAGE_SELECT     0x20
59

    
60
#define ST01_V_RETRACE      0x08
61
#define ST01_DISP_ENABLE    0x01
62

    
63
/* bochs VBE support */
64
#define CONFIG_BOCHS_VBE
65

    
66
#define VBE_DISPI_MAX_XRES              1024
67
#define VBE_DISPI_MAX_YRES              768
68

    
69
#define VBE_DISPI_INDEX_ID              0x0
70
#define VBE_DISPI_INDEX_XRES            0x1
71
#define VBE_DISPI_INDEX_YRES            0x2
72
#define VBE_DISPI_INDEX_BPP             0x3
73
#define VBE_DISPI_INDEX_ENABLE          0x4
74
#define VBE_DISPI_INDEX_BANK            0x5
75
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
76
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
77
#define VBE_DISPI_INDEX_X_OFFSET        0x8
78
#define VBE_DISPI_INDEX_Y_OFFSET        0x9
79
#define VBE_DISPI_INDEX_NB              0xa
80
      
81
#define VBE_DISPI_ID0                   0xB0C0
82
#define VBE_DISPI_ID1                   0xB0C1
83
#define VBE_DISPI_ID2                   0xB0C2
84
  
85
#define VBE_DISPI_DISABLED              0x00
86
#define VBE_DISPI_ENABLED               0x01
87
#define VBE_DISPI_LFB_ENABLED           0x40
88
#define VBE_DISPI_NOCLEARMEM            0x80
89
  
90
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
91

    
92
typedef struct VGAState {
93
    uint8_t *vram_ptr;
94
    unsigned long vram_offset;
95
    unsigned int vram_size;
96
    uint32_t latch;
97
    uint8_t sr_index;
98
    uint8_t sr[8];
99
    uint8_t gr_index;
100
    uint8_t gr[16];
101
    uint8_t ar_index;
102
    uint8_t ar[21];
103
    int ar_flip_flop;
104
    uint8_t cr_index;
105
    uint8_t cr[256]; /* CRT registers */
106
    uint8_t msr; /* Misc Output Register */
107
    uint8_t fcr; /* Feature Control Register */
108
    uint8_t st00; /* status 0 */
109
    uint8_t st01; /* status 1 */
110
    uint8_t dac_state;
111
    uint8_t dac_sub_index;
112
    uint8_t dac_read_index;
113
    uint8_t dac_write_index;
114
    uint8_t dac_cache[3]; /* used when writing */
115
    uint8_t palette[768];
116
    uint32_t bank_offset;
117
#ifdef CONFIG_BOCHS_VBE
118
    uint16_t vbe_index;
119
    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
120
    uint32_t vbe_start_addr;
121
    uint32_t vbe_line_offset;
122
    uint32_t vbe_bank_mask;
123
#endif
124
    /* display refresh support */
125
    DisplayState *ds;
126
    uint32_t font_offsets[2];
127
    int graphic_mode;
128
    uint8_t shift_control;
129
    uint8_t double_scan;
130
    uint32_t line_offset;
131
    uint32_t line_compare;
132
    uint32_t start_addr;
133
    uint8_t last_cw, last_ch;
134
    uint32_t last_width, last_height;
135
    uint8_t cursor_start, cursor_end;
136
    uint32_t cursor_offset;
137
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
138
    /* tell for each page if it has been updated since the last time */
139
    uint32_t last_palette[256];
140
#define CH_ATTR_SIZE (160 * 100)
141
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
142
} VGAState;
143

    
144
/* force some bits to zero */
145
static const uint8_t sr_mask[8] = {
146
    (uint8_t)~0xfc,
147
    (uint8_t)~0xc2,
148
    (uint8_t)~0xf0,
149
    (uint8_t)~0xc0,
150
    (uint8_t)~0xf1,
151
    (uint8_t)~0xff,
152
    (uint8_t)~0xff,
153
    (uint8_t)~0x00,
154
};
155

    
156
static const uint8_t gr_mask[16] = {
157
    (uint8_t)~0xf0, /* 0x00 */
158
    (uint8_t)~0xf0, /* 0x01 */
159
    (uint8_t)~0xf0, /* 0x02 */
160
    (uint8_t)~0xe0, /* 0x03 */
161
    (uint8_t)~0xfc, /* 0x04 */
162
    (uint8_t)~0x84, /* 0x05 */
163
    (uint8_t)~0xf0, /* 0x06 */
164
    (uint8_t)~0xf0, /* 0x07 */
165
    (uint8_t)~0x00, /* 0x08 */
166
    (uint8_t)~0xff, /* 0x09 */
167
    (uint8_t)~0xff, /* 0x0a */
168
    (uint8_t)~0xff, /* 0x0b */
169
    (uint8_t)~0xff, /* 0x0c */
170
    (uint8_t)~0xff, /* 0x0d */
171
    (uint8_t)~0xff, /* 0x0e */
172
    (uint8_t)~0xff, /* 0x0f */
173
};
174

    
175
#define cbswap_32(__x) \
176
((uint32_t)( \
177
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
178
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
179
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
180
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
181

    
182
#ifdef WORDS_BIGENDIAN
183
#define PAT(x) cbswap_32(x)
184
#else
185
#define PAT(x) (x)
186
#endif
187

    
188
#ifdef WORDS_BIGENDIAN
189
#define BIG 1
190
#else
191
#define BIG 0
192
#endif
193

    
194
#ifdef WORDS_BIGENDIAN
195
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
196
#else
197
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
198
#endif
199

    
200
static const uint32_t mask16[16] = {
201
    PAT(0x00000000),
202
    PAT(0x000000ff),
203
    PAT(0x0000ff00),
204
    PAT(0x0000ffff),
205
    PAT(0x00ff0000),
206
    PAT(0x00ff00ff),
207
    PAT(0x00ffff00),
208
    PAT(0x00ffffff),
209
    PAT(0xff000000),
210
    PAT(0xff0000ff),
211
    PAT(0xff00ff00),
212
    PAT(0xff00ffff),
213
    PAT(0xffff0000),
214
    PAT(0xffff00ff),
215
    PAT(0xffffff00),
216
    PAT(0xffffffff),
217
};
218

    
219
#undef PAT
220

    
221
#ifdef WORDS_BIGENDIAN
222
#define PAT(x) (x)
223
#else
224
#define PAT(x) cbswap_32(x)
225
#endif
226

    
227
static const uint32_t dmask16[16] = {
228
    PAT(0x00000000),
229
    PAT(0x000000ff),
230
    PAT(0x0000ff00),
231
    PAT(0x0000ffff),
232
    PAT(0x00ff0000),
233
    PAT(0x00ff00ff),
234
    PAT(0x00ffff00),
235
    PAT(0x00ffffff),
236
    PAT(0xff000000),
237
    PAT(0xff0000ff),
238
    PAT(0xff00ff00),
239
    PAT(0xff00ffff),
240
    PAT(0xffff0000),
241
    PAT(0xffff00ff),
242
    PAT(0xffffff00),
243
    PAT(0xffffffff),
244
};
245

    
246
static const uint32_t dmask4[4] = {
247
    PAT(0x00000000),
248
    PAT(0x0000ffff),
249
    PAT(0xffff0000),
250
    PAT(0xffffffff),
251
};
252

    
253
static uint32_t expand4[256];
254
static uint16_t expand2[256];
255
static uint8_t expand4to8[16];
256

    
257
VGAState vga_state;
258
int vga_io_memory;
259

    
260
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
261
{
262
    VGAState *s = opaque;
263
    int val, index;
264

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

    
356
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
357
{
358
    VGAState *s = opaque;
359
    int index, v;
360

    
361
    /* check port range access depending on color/monochrome mode */
362
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
363
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
364
        return;
365

    
366
#ifdef DEBUG_VGA
367
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
368
#endif
369

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

    
467
#ifdef CONFIG_S3VGA
468
            /* S3 registers */
469
        case 0x2d:
470
        case 0x2e:
471
        case 0x2f:
472
        case 0x30:
473
            /* chip ID, cannot write */
474
            break;
475
        case 0x31:
476
            /* update start address */
477
            s->cr[s->cr_index] = val;
478
            v = (val >> 4) & 3;
479
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
480
            break;
481
        case 0x51:
482
            /* update start address */
483
            s->cr[s->cr_index] = val;
484
            v = val & 3;
485
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
486
            break;
487
#endif
488
        default:
489
            s->cr[s->cr_index] = val;
490
            break;
491
        }
492
#ifdef DEBUG_S3
493
        if (s->cr_index >= 0x20)
494
            printf("S3: CR write index=0x%x val=0x%x\n",
495
                   s->cr_index, val);
496
#endif
497
        break;
498
    case 0x3ba:
499
    case 0x3da:
500
        s->fcr = val & 0x10;
501
        break;
502
    }
503
}
504

    
505
#ifdef CONFIG_BOCHS_VBE
506
static uint32_t vbe_ioport_read(void *opaque, uint32_t addr)
507
{
508
    VGAState *s = opaque;
509
    uint32_t val;
510

    
511
    addr &= 1;
512
    if (addr == 0) {
513
        val = s->vbe_index;
514
    } else {
515
        if (s->vbe_index <= VBE_DISPI_INDEX_NB)
516
            val = s->vbe_regs[s->vbe_index];
517
        else
518
            val = 0;
519
#ifdef DEBUG_BOCHS_VBE
520
        printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
521
#endif
522
    }
523
    return val;
524
}
525

    
526
static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
527
{
528
    VGAState *s = opaque;
529

    
530
    addr &= 1;
531
    if (addr == 0) {
532
        s->vbe_index = val;
533
    } else if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
534
#ifdef DEBUG_BOCHS_VBE
535
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
536
#endif
537
        switch(s->vbe_index) {
538
        case VBE_DISPI_INDEX_ID:
539
            if (val == VBE_DISPI_ID0 ||
540
                val == VBE_DISPI_ID1 ||
541
                val == VBE_DISPI_ID2) {
542
                s->vbe_regs[s->vbe_index] = val;
543
            }
544
            break;
545
        case VBE_DISPI_INDEX_XRES:
546
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
547
                s->vbe_regs[s->vbe_index] = val;
548
            }
549
            break;
550
        case VBE_DISPI_INDEX_YRES:
551
            if (val <= VBE_DISPI_MAX_YRES) {
552
                s->vbe_regs[s->vbe_index] = val;
553
            }
554
            break;
555
        case VBE_DISPI_INDEX_BPP:
556
            if (val == 0)
557
                val = 8;
558
            if (val == 4 || val == 8 || val == 15 || 
559
                val == 16 || val == 24 || val == 32) {
560
                s->vbe_regs[s->vbe_index] = val;
561
            }
562
            break;
563
        case VBE_DISPI_INDEX_BANK:
564
            val &= s->vbe_bank_mask;
565
            s->vbe_regs[s->vbe_index] = val;
566
            s->bank_offset = (val << 16) - 0xa0000;
567
            break;
568
        case VBE_DISPI_INDEX_ENABLE:
569
            if (val & VBE_DISPI_ENABLED) {
570
                int h, shift_control;
571

    
572
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
573
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
574
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
575
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
576
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
577
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
578
                
579
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
580
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
581
                else
582
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
583
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
584
                s->vbe_start_addr = 0;
585
                
586
                /* clear the screen (should be done in BIOS) */
587
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
588
                    memset(s->vram_ptr, 0, 
589
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
590
                }
591
                
592
                /* we initialize the VGA graphic mode (should be done
593
                   in BIOS) */
594
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
595
                s->cr[0x17] |= 3; /* no CGA modes */
596
                s->cr[0x13] = s->vbe_line_offset >> 3;
597
                /* width */
598
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
599
                /* height */
600
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
601
                s->cr[0x12] = h;
602
                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
603
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
604
                /* line compare to 1023 */
605
                s->cr[0x18] = 0xff;
606
                s->cr[0x07] |= 0x10;
607
                s->cr[0x09] |= 0x40;
608
                
609
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
610
                    shift_control = 0;
611
                    s->sr[0x01] &= ~8; /* no double line */
612
                } else {
613
                    shift_control = 2;
614
                }
615
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
616
                s->cr[0x09] &= ~0x9f; /* no double scan */
617
                s->vbe_regs[s->vbe_index] = val;
618
            } else {
619
                /* XXX: the bios should do that */
620
                s->bank_offset = -0xa0000;
621
            }
622
            break;
623
        case VBE_DISPI_INDEX_VIRT_WIDTH:
624
            {
625
                int w, h, line_offset;
626

    
627
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
628
                    return;
629
                w = val;
630
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
631
                    line_offset = w >> 1;
632
                else
633
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
634
                h = s->vram_size / line_offset;
635
                /* XXX: support weird bochs semantics ? */
636
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
637
                    return;
638
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
639
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
640
                s->vbe_line_offset = line_offset;
641
            }
642
            break;
643
        case VBE_DISPI_INDEX_X_OFFSET:
644
        case VBE_DISPI_INDEX_Y_OFFSET:
645
            {
646
                int x;
647
                s->vbe_regs[s->vbe_index] = val;
648
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
649
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
650
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
651
                    s->vbe_start_addr += x >> 1;
652
                else
653
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
654
                s->vbe_start_addr >>= 2;
655
            }
656
            break;
657
        default:
658
            break;
659
        }
660
    }
661
}
662
#endif
663

    
664
/* called for accesses between 0xa0000 and 0xc0000 */
665
static uint32_t vga_mem_readb(uint32_t addr)
666
{
667
    VGAState *s = &vga_state;
668
    int memory_map_mode, plane;
669
    uint32_t ret;
670
    
671
    /* convert to VGA memory offset */
672
    memory_map_mode = (s->gr[6] >> 2) & 3;
673
    switch(memory_map_mode) {
674
    case 0:
675
        addr -= 0xa0000;
676
        break;
677
    case 1:
678
        if (addr >= 0xb0000)
679
            return 0xff;
680
        addr += s->bank_offset;
681
        break;
682
    case 2:
683
        addr -= 0xb0000;
684
        if (addr >= 0x8000)
685
            return 0xff;
686
        break;
687
    default:
688
    case 3:
689
        addr -= 0xb8000;
690
        if (addr >= 0x8000)
691
            return 0xff;
692
        break;
693
    }
694
    
695
    if (s->sr[4] & 0x08) {
696
        /* chain 4 mode : simplest access */
697
        ret = s->vram_ptr[addr];
698
    } else if (s->gr[5] & 0x10) {
699
        /* odd/even mode (aka text mode mapping) */
700
        plane = (s->gr[4] & 2) | (addr & 1);
701
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
702
    } else {
703
        /* standard VGA latched access */
704
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
705

    
706
        if (!(s->gr[5] & 0x08)) {
707
            /* read mode 0 */
708
            plane = s->gr[4];
709
            ret = GET_PLANE(s->latch, plane);
710
        } else {
711
            /* read mode 1 */
712
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
713
            ret |= ret >> 16;
714
            ret |= ret >> 8;
715
            ret = (~ret) & 0xff;
716
        }
717
    }
718
    return ret;
719
}
720

    
721
static uint32_t vga_mem_readw(uint32_t addr)
722
{
723
    uint32_t v;
724
    v = vga_mem_readb(addr);
725
    v |= vga_mem_readb(addr + 1) << 8;
726
    return v;
727
}
728

    
729
static uint32_t vga_mem_readl(uint32_t addr)
730
{
731
    uint32_t v;
732
    v = vga_mem_readb(addr);
733
    v |= vga_mem_readb(addr + 1) << 8;
734
    v |= vga_mem_readb(addr + 2) << 16;
735
    v |= vga_mem_readb(addr + 3) << 24;
736
    return v;
737
}
738

    
739
/* called for accesses between 0xa0000 and 0xc0000 */
740
static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
741
{
742
    VGAState *s = &vga_state;
743
    int memory_map_mode, plane, write_mode, b, func_select;
744
    uint32_t write_mask, bit_mask, set_mask;
745

    
746
#ifdef DEBUG_VGA_MEM
747
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
748
#endif
749
    /* convert to VGA memory offset */
750
    memory_map_mode = (s->gr[6] >> 2) & 3;
751
    switch(memory_map_mode) {
752
    case 0:
753
        addr -= 0xa0000;
754
        break;
755
    case 1:
756
        if (addr >= 0xb0000)
757
            return;
758
        addr += s->bank_offset;
759
        break;
760
    case 2:
761
        addr -= 0xb0000;
762
        if (addr >= 0x8000)
763
            return;
764
        break;
765
    default:
766
    case 3:
767
        addr -= 0xb8000;
768
        if (addr >= 0x8000)
769
            return;
770
        break;
771
    }
772
    
773
    if (s->sr[4] & 0x08) {
774
        /* chain 4 mode : simplest access */
775
        plane = addr & 3;
776
        if (s->sr[2] & (1 << plane)) {
777
            s->vram_ptr[addr] = val;
778
#ifdef DEBUG_VGA_MEM
779
            printf("vga: chain4: [0x%x]\n", addr);
780
#endif
781
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
782
        }
783
    } else if (s->gr[5] & 0x10) {
784
        /* odd/even mode (aka text mode mapping) */
785
        plane = (s->gr[4] & 2) | (addr & 1);
786
        if (s->sr[2] & (1 << plane)) {
787
            addr = ((addr & ~1) << 1) | plane;
788
            s->vram_ptr[addr] = val;
789
#ifdef DEBUG_VGA_MEM
790
            printf("vga: odd/even: [0x%x]\n", addr);
791
#endif
792
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
793
        }
794
    } else {
795
        /* standard VGA latched access */
796
        write_mode = s->gr[5] & 3;
797
        switch(write_mode) {
798
        default:
799
        case 0:
800
            /* rotate */
801
            b = s->gr[3] & 7;
802
            val = ((val >> b) | (val << (8 - b))) & 0xff;
803
            val |= val << 8;
804
            val |= val << 16;
805

    
806
            /* apply set/reset mask */
807
            set_mask = mask16[s->gr[1]];
808
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
809
            bit_mask = s->gr[8];
810
            break;
811
        case 1:
812
            val = s->latch;
813
            goto do_write;
814
        case 2:
815
            val = mask16[val & 0x0f];
816
            bit_mask = s->gr[8];
817
            break;
818
        case 3:
819
            /* rotate */
820
            b = s->gr[3] & 7;
821
            val = (val >> b) | (val << (8 - b));
822

    
823
            bit_mask = s->gr[8] & val;
824
            val = mask16[s->gr[0]];
825
            break;
826
        }
827

    
828
        /* apply logical operation */
829
        func_select = s->gr[3] >> 3;
830
        switch(func_select) {
831
        case 0:
832
        default:
833
            /* nothing to do */
834
            break;
835
        case 1:
836
            /* and */
837
            val &= s->latch;
838
            break;
839
        case 2:
840
            /* or */
841
            val |= s->latch;
842
            break;
843
        case 3:
844
            /* xor */
845
            val ^= s->latch;
846
            break;
847
        }
848

    
849
        /* apply bit mask */
850
        bit_mask |= bit_mask << 8;
851
        bit_mask |= bit_mask << 16;
852
        val = (val & bit_mask) | (s->latch & ~bit_mask);
853

    
854
    do_write:
855
        /* mask data according to sr[2] */
856
        write_mask = mask16[s->sr[2]];
857
        ((uint32_t *)s->vram_ptr)[addr] = 
858
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
859
            (val & write_mask);
860
#ifdef DEBUG_VGA_MEM
861
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
862
                   addr * 4, write_mask, val);
863
#endif
864
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
865
    }
866
}
867

    
868
static void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
869
{
870
    vga_mem_writeb(addr, val & 0xff, vaddr);
871
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
872
}
873

    
874
static void vga_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
875
{
876
    vga_mem_writeb(addr, val & 0xff, vaddr);
877
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
878
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff, vaddr);
879
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff, vaddr);
880
}
881

    
882
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
883
                             const uint8_t *font_ptr, int h,
884
                             uint32_t fgcol, uint32_t bgcol);
885
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
886
                                  const uint8_t *font_ptr, int h, 
887
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
888
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
889
                                const uint8_t *s, int width);
890

    
891
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
892
{
893
    /* XXX: TODO */
894
    return 0;
895
}
896

    
897
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
898
{
899
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
900
}
901

    
902
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
903
{
904
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
905
}
906

    
907
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
908
{
909
    return (r << 16) | (g << 8) | b;
910
}
911

    
912
#define DEPTH 8
913
#include "vga_template.h"
914

    
915
#define DEPTH 15
916
#include "vga_template.h"
917

    
918
#define DEPTH 16
919
#include "vga_template.h"
920

    
921
#define DEPTH 32
922
#include "vga_template.h"
923

    
924
static inline int c6_to_8(int v)
925
{
926
    int b;
927
    v &= 0x3f;
928
    b = v & 1;
929
    return (v << 2) | (b << 1) | b;
930
}
931

    
932
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
933
{
934
    unsigned int col;
935
    col = rgb_to_pixel8(r, g, b);
936
    col |= col << 8;
937
    col |= col << 16;
938
    return col;
939
}
940

    
941
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
942
{
943
    unsigned int col;
944
    col = rgb_to_pixel15(r, g, b);
945
    col |= col << 16;
946
    return col;
947
}
948

    
949
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
950
{
951
    unsigned int col;
952
    col = rgb_to_pixel16(r, g, b);
953
    col |= col << 16;
954
    return col;
955
}
956

    
957
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
958
{
959
    unsigned int col;
960
    col = rgb_to_pixel32(r, g, b);
961
    return col;
962
}
963

    
964
/* return true if the palette was modified */
965
static int update_palette16(VGAState *s)
966
{
967
    int full_update, i;
968
    uint32_t v, col, *palette;
969

    
970
    full_update = 0;
971
    palette = s->last_palette;
972
    for(i = 0; i < 16; i++) {
973
        v = s->ar[i];
974
        if (s->ar[0x10] & 0x80)
975
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
976
        else
977
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
978
        v = v * 3;
979
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
980
                              c6_to_8(s->palette[v + 1]), 
981
                              c6_to_8(s->palette[v + 2]));
982
        if (col != palette[i]) {
983
            full_update = 1;
984
            palette[i] = col;
985
        }
986
    }
987
    return full_update;
988
}
989

    
990
/* return true if the palette was modified */
991
static int update_palette256(VGAState *s)
992
{
993
    int full_update, i;
994
    uint32_t v, col, *palette;
995

    
996
    full_update = 0;
997
    palette = s->last_palette;
998
    v = 0;
999
    for(i = 0; i < 256; i++) {
1000
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
1001
                              c6_to_8(s->palette[v + 1]), 
1002
                              c6_to_8(s->palette[v + 2]));
1003
        if (col != palette[i]) {
1004
            full_update = 1;
1005
            palette[i] = col;
1006
        }
1007
        v += 3;
1008
    }
1009
    return full_update;
1010
}
1011

    
1012
/* update start_addr and line_offset. Return TRUE if modified */
1013
static int update_basic_params(VGAState *s)
1014
{
1015
    int full_update;
1016
    uint32_t start_addr, line_offset, line_compare, v;
1017
    
1018
    full_update = 0;
1019

    
1020
#ifdef CONFIG_BOCHS_VBE
1021
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1022
        line_offset = s->vbe_line_offset;
1023
        start_addr = s->vbe_start_addr;
1024
    } else
1025
#endif
1026
    {  
1027
        /* compute line_offset in bytes */
1028
        line_offset = s->cr[0x13];
1029
#ifdef CONFIG_S3VGA
1030
        v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
1031
        if (v == 0)
1032
            v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
1033
        line_offset |= (v << 8);
1034
#endif
1035
        line_offset <<= 3;
1036
        
1037
        /* starting address */
1038
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1039
#ifdef CONFIG_S3VGA
1040
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
1041
#endif
1042
    }
1043
    
1044
    /* line compare */
1045
    line_compare = s->cr[0x18] | 
1046
        ((s->cr[0x07] & 0x10) << 4) |
1047
        ((s->cr[0x09] & 0x40) << 3);
1048

    
1049
    if (line_offset != s->line_offset ||
1050
        start_addr != s->start_addr ||
1051
        line_compare != s->line_compare) {
1052
        s->line_offset = line_offset;
1053
        s->start_addr = start_addr;
1054
        s->line_compare = line_compare;
1055
        full_update = 1;
1056
    }
1057
    return full_update;
1058
}
1059

    
1060
static inline int get_depth_index(int depth)
1061
{
1062
    switch(depth) {
1063
    default:
1064
    case 8:
1065
        return 0;
1066
    case 15:
1067
        return 1;
1068
    case 16:
1069
        return 2;
1070
    case 32:
1071
        return 3;
1072
    }
1073
}
1074

    
1075
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1076
    vga_draw_glyph8_8,
1077
    vga_draw_glyph8_16,
1078
    vga_draw_glyph8_16,
1079
    vga_draw_glyph8_32,
1080
};
1081

    
1082
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1083
    vga_draw_glyph16_8,
1084
    vga_draw_glyph16_16,
1085
    vga_draw_glyph16_16,
1086
    vga_draw_glyph16_32,
1087
};
1088

    
1089
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1090
    vga_draw_glyph9_8,
1091
    vga_draw_glyph9_16,
1092
    vga_draw_glyph9_16,
1093
    vga_draw_glyph9_32,
1094
};
1095
    
1096
static const uint8_t cursor_glyph[32 * 4] = {
1097
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1098
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1099
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1100
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1101
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1102
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1103
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1104
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1105
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1106
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1107
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1108
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1109
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1110
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1111
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1112
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1113
};    
1114

    
1115
/* 
1116
 * Text mode update 
1117
 * Missing:
1118
 * - double scan
1119
 * - double width 
1120
 * - underline
1121
 * - flashing
1122
 */
1123
static void vga_draw_text(VGAState *s, int full_update)
1124
{
1125
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1126
    int cx_min, cx_max, linesize, x_incr;
1127
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1128
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1129
    const uint8_t *font_ptr, *font_base[2];
1130
    int dup9, line_offset, depth_index;
1131
    uint32_t *palette;
1132
    uint32_t *ch_attr_ptr;
1133
    vga_draw_glyph8_func *vga_draw_glyph8;
1134
    vga_draw_glyph9_func *vga_draw_glyph9;
1135

    
1136
    full_update |= update_palette16(s);
1137
    palette = s->last_palette;
1138
    
1139
    /* compute font data address (in plane 2) */
1140
    v = s->sr[3];
1141
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1142
    if (offset != s->font_offsets[0]) {
1143
        s->font_offsets[0] = offset;
1144
        full_update = 1;
1145
    }
1146
    font_base[0] = s->vram_ptr + offset;
1147

    
1148
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1149
    font_base[1] = s->vram_ptr + offset;
1150
    if (offset != s->font_offsets[1]) {
1151
        s->font_offsets[1] = offset;
1152
        full_update = 1;
1153
    }
1154

    
1155
    full_update |= update_basic_params(s);
1156

    
1157
    line_offset = s->line_offset;
1158
    s1 = s->vram_ptr + (s->start_addr * 4);
1159

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

    
1282
enum {
1283
    VGA_DRAW_LINE2,
1284
    VGA_DRAW_LINE2D2,
1285
    VGA_DRAW_LINE4,
1286
    VGA_DRAW_LINE4D2,
1287
    VGA_DRAW_LINE8D2,
1288
    VGA_DRAW_LINE8,
1289
    VGA_DRAW_LINE15,
1290
    VGA_DRAW_LINE16,
1291
    VGA_DRAW_LINE24,
1292
    VGA_DRAW_LINE32,
1293
    VGA_DRAW_LINE_NB,
1294
};
1295

    
1296
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1297
    vga_draw_line2_8,
1298
    vga_draw_line2_16,
1299
    vga_draw_line2_16,
1300
    vga_draw_line2_32,
1301

    
1302
    vga_draw_line2d2_8,
1303
    vga_draw_line2d2_16,
1304
    vga_draw_line2d2_16,
1305
    vga_draw_line2d2_32,
1306

    
1307
    vga_draw_line4_8,
1308
    vga_draw_line4_16,
1309
    vga_draw_line4_16,
1310
    vga_draw_line4_32,
1311

    
1312
    vga_draw_line4d2_8,
1313
    vga_draw_line4d2_16,
1314
    vga_draw_line4d2_16,
1315
    vga_draw_line4d2_32,
1316

    
1317
    vga_draw_line8d2_8,
1318
    vga_draw_line8d2_16,
1319
    vga_draw_line8d2_16,
1320
    vga_draw_line8d2_32,
1321

    
1322
    vga_draw_line8_8,
1323
    vga_draw_line8_16,
1324
    vga_draw_line8_16,
1325
    vga_draw_line8_32,
1326

    
1327
    vga_draw_line15_8,
1328
    vga_draw_line15_15,
1329
    vga_draw_line15_16,
1330
    vga_draw_line15_32,
1331

    
1332
    vga_draw_line16_8,
1333
    vga_draw_line16_15,
1334
    vga_draw_line16_16,
1335
    vga_draw_line16_32,
1336

    
1337
    vga_draw_line24_8,
1338
    vga_draw_line24_15,
1339
    vga_draw_line24_16,
1340
    vga_draw_line24_32,
1341

    
1342
    vga_draw_line32_8,
1343
    vga_draw_line32_15,
1344
    vga_draw_line32_16,
1345
    vga_draw_line32_32,
1346
};
1347

    
1348
/* 
1349
 * graphic modes
1350
 * Missing:
1351
 * - double scan
1352
 * - double width 
1353
 */
1354
static void vga_draw_graphic(VGAState *s, int full_update)
1355
{
1356
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1357
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1358
    int disp_width, multi_scan, multi_run;
1359
    uint8_t *d;
1360
    uint32_t v, addr1, addr;
1361
    vga_draw_line_func *vga_draw_line;
1362
    
1363
    full_update |= update_basic_params(s);
1364

    
1365
    width = (s->cr[0x01] + 1) * 8;
1366
    height = s->cr[0x12] | 
1367
        ((s->cr[0x07] & 0x02) << 7) | 
1368
        ((s->cr[0x07] & 0x40) << 3);
1369
    height = (height + 1);
1370
    disp_width = width;
1371
    
1372
    shift_control = (s->gr[0x05] >> 5) & 3;
1373
    double_scan = (s->cr[0x09] & 0x80);
1374
    if (shift_control > 1) {
1375
        multi_scan = (s->cr[0x09] & 0x1f);
1376
    } else {
1377
        multi_scan = 0;
1378
    }
1379
    multi_run = multi_scan;
1380
    if (shift_control != s->shift_control ||
1381
        double_scan != s->double_scan) {
1382
        full_update = 1;
1383
        s->shift_control = shift_control;
1384
        s->double_scan = double_scan;
1385
    }
1386
    
1387
    if (shift_control == 0) {
1388
        full_update |= update_palette16(s);
1389
        if (s->sr[0x01] & 8) {
1390
            v = VGA_DRAW_LINE4D2;
1391
            disp_width <<= 1;
1392
        } else {
1393
            v = VGA_DRAW_LINE4;
1394
        }
1395
    } else if (shift_control == 1) {
1396
        full_update |= update_palette16(s);
1397
        if (s->sr[0x01] & 8) {
1398
            v = VGA_DRAW_LINE2D2;
1399
            disp_width <<= 1;
1400
        } else {
1401
            v = VGA_DRAW_LINE2;
1402
        }
1403
    } else {
1404
#ifdef CONFIG_BOCHS_VBE
1405
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1406
            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
1407
            default:
1408
            case 8:
1409
                full_update |= update_palette256(s);
1410
                v = VGA_DRAW_LINE8;
1411
                break;
1412
            case 15:
1413
                v = VGA_DRAW_LINE15;
1414
                break;
1415
            case 16:
1416
                v = VGA_DRAW_LINE16;
1417
                break;
1418
            case 24:
1419
                v = VGA_DRAW_LINE24;
1420
                break;
1421
            case 32:
1422
                v = VGA_DRAW_LINE32;
1423
                break;
1424
            }
1425
        } else 
1426
#endif
1427
        {
1428
            full_update |= update_palette256(s);
1429
            v = VGA_DRAW_LINE8D2;
1430
        }
1431
    }
1432
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1433

    
1434
    if (disp_width != s->last_width ||
1435
        height != s->last_height) {
1436
        dpy_resize(s->ds, disp_width, height);
1437
        s->last_width = disp_width;
1438
        s->last_height = height;
1439
        full_update = 1;
1440
    }
1441

    
1442
    line_offset = s->line_offset;
1443
#if 0
1444
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1445
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1446
#endif
1447
    addr1 = (s->start_addr * 4);
1448
    bwidth = width * 4;
1449
    y_start = -1;
1450
    page_min = 0x7fffffff;
1451
    page_max = -1;
1452
    d = s->ds->data;
1453
    linesize = s->ds->linesize;
1454
    y1 = 0;
1455
    for(y = 0; y < height; y++) {
1456
        addr = addr1;
1457
        if (!(s->cr[0x17] & 1)) {
1458
            int shift;
1459
            /* CGA compatibility handling */
1460
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1461
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1462
        }
1463
        if (!(s->cr[0x17] & 2)) {
1464
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1465
        }
1466
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1467
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1468
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1469
            cpu_physical_memory_is_dirty(page1);
1470
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1471
            /* if wide line, can use another page */
1472
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1473
        }
1474
        if (update) {
1475
            if (y_start < 0)
1476
                y_start = y;
1477
            if (page0 < page_min)
1478
                page_min = page0;
1479
            if (page1 > page_max)
1480
                page_max = page1;
1481
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1482
        } else {
1483
            if (y_start >= 0) {
1484
                /* flush to display */
1485
                dpy_update(s->ds, 0, y_start, 
1486
                           disp_width, y - y_start);
1487
                y_start = -1;
1488
            }
1489
        }
1490
        if (!multi_run) {
1491
            if (!double_scan || (y & 1) != 0) {
1492
                if (y1 == s->line_compare) {
1493
                    addr1 = 0;
1494
                } else {
1495
                    mask = (s->cr[0x17] & 3) ^ 3;
1496
                    if ((y1 & mask) == mask)
1497
                        addr1 += line_offset;
1498
                }
1499
                y1++;
1500
            }
1501
            multi_run = multi_scan;
1502
        } else {
1503
            multi_run--;
1504
            y1++;
1505
        }
1506
        d += linesize;
1507
    }
1508
    if (y_start >= 0) {
1509
        /* flush to display */
1510
        dpy_update(s->ds, 0, y_start, 
1511
                   disp_width, y - y_start);
1512
    }
1513
    /* reset modified pages */
1514
    if (page_max != -1) {
1515
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1516
    }
1517
}
1518

    
1519
void vga_update_display(void)
1520
{
1521
    VGAState *s = &vga_state;
1522
    int full_update, graphic_mode;
1523

    
1524
    if (s->ds->depth == 0) {
1525
        /* nothing to do */
1526
    } else {
1527
        switch(s->ds->depth) {
1528
        case 8:
1529
            s->rgb_to_pixel = rgb_to_pixel8_dup;
1530
            break;
1531
        case 15:
1532
            s->rgb_to_pixel = rgb_to_pixel15_dup;
1533
            break;
1534
        default:
1535
        case 16:
1536
            s->rgb_to_pixel = rgb_to_pixel16_dup;
1537
            break;
1538
        case 32:
1539
            s->rgb_to_pixel = rgb_to_pixel32_dup;
1540
            break;
1541
        }
1542
        
1543
        full_update = 0;
1544
        graphic_mode = s->gr[6] & 1;
1545
        if (graphic_mode != s->graphic_mode) {
1546
            s->graphic_mode = graphic_mode;
1547
            full_update = 1;
1548
        }
1549
        if (graphic_mode)
1550
            vga_draw_graphic(s, full_update);
1551
        else
1552
            vga_draw_text(s, full_update);
1553
    }
1554
}
1555

    
1556
static void vga_reset(VGAState *s)
1557
{
1558
    memset(s, 0, sizeof(VGAState));
1559
#ifdef CONFIG_S3VGA
1560
    /* chip ID for 8c968 */
1561
    s->cr[0x2d] = 0x88;
1562
    s->cr[0x2e] = 0xb0;
1563
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1564
    s->cr[0x30] = 0xe1;
1565
#endif
1566
    s->graphic_mode = -1; /* force full update */
1567
}
1568

    
1569
static CPUReadMemoryFunc *vga_mem_read[3] = {
1570
    vga_mem_readb,
1571
    vga_mem_readw,
1572
    vga_mem_readl,
1573
};
1574

    
1575
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1576
    vga_mem_writeb,
1577
    vga_mem_writew,
1578
    vga_mem_writel,
1579
};
1580

    
1581
static void vga_save(QEMUFile *f, void *opaque)
1582
{
1583
    VGAState *s = opaque;
1584
    int i;
1585

    
1586
    qemu_put_be32s(f, &s->latch);
1587
    qemu_put_8s(f, &s->sr_index);
1588
    qemu_put_buffer(f, s->sr, 8);
1589
    qemu_put_8s(f, &s->gr_index);
1590
    qemu_put_buffer(f, s->gr, 16);
1591
    qemu_put_8s(f, &s->ar_index);
1592
    qemu_put_buffer(f, s->ar, 21);
1593
    qemu_put_be32s(f, &s->ar_flip_flop);
1594
    qemu_put_8s(f, &s->cr_index);
1595
    qemu_put_buffer(f, s->cr, 256);
1596
    qemu_put_8s(f, &s->msr);
1597
    qemu_put_8s(f, &s->fcr);
1598
    qemu_put_8s(f, &s->st00);
1599
    qemu_put_8s(f, &s->st01);
1600

    
1601
    qemu_put_8s(f, &s->dac_state);
1602
    qemu_put_8s(f, &s->dac_sub_index);
1603
    qemu_put_8s(f, &s->dac_read_index);
1604
    qemu_put_8s(f, &s->dac_write_index);
1605
    qemu_put_buffer(f, s->dac_cache, 3);
1606
    qemu_put_buffer(f, s->palette, 768);
1607

    
1608
    qemu_put_be32s(f, &s->bank_offset);
1609
#ifdef CONFIG_BOCHS_VBE
1610
    qemu_put_byte(f, 1);
1611
    qemu_put_be16s(f, &s->vbe_index);
1612
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1613
        qemu_put_be16s(f, &s->vbe_regs[i]);
1614
    qemu_put_be32s(f, &s->vbe_start_addr);
1615
    qemu_put_be32s(f, &s->vbe_line_offset);
1616
    qemu_put_be32s(f, &s->vbe_bank_mask);
1617
#else
1618
    qemu_put_byte(f, 0);
1619
#endif
1620
}
1621

    
1622
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1623
{
1624
    VGAState *s = opaque;
1625
    int is_vbe, i;
1626

    
1627
    if (version_id != 1)
1628
        return -EINVAL;
1629

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

    
1645
    qemu_get_8s(f, &s->dac_state);
1646
    qemu_get_8s(f, &s->dac_sub_index);
1647
    qemu_get_8s(f, &s->dac_read_index);
1648
    qemu_get_8s(f, &s->dac_write_index);
1649
    qemu_get_buffer(f, s->dac_cache, 3);
1650
    qemu_get_buffer(f, s->palette, 768);
1651

    
1652
    qemu_get_be32s(f, &s->bank_offset);
1653
    is_vbe = qemu_get_byte(f);
1654
#ifdef CONFIG_BOCHS_VBE
1655
    if (!is_vbe)
1656
        return -EINVAL;
1657
    qemu_get_be16s(f, &s->vbe_index);
1658
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1659
        qemu_get_be16s(f, &s->vbe_regs[i]);
1660
    qemu_get_be32s(f, &s->vbe_start_addr);
1661
    qemu_get_be32s(f, &s->vbe_line_offset);
1662
    qemu_get_be32s(f, &s->vbe_bank_mask);
1663
#else
1664
    if (is_vbe)
1665
        return -EINVAL;
1666
#endif
1667

    
1668
    /* force refresh */
1669
    s->graphic_mode = -1;
1670
    return 0;
1671
}
1672

    
1673
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1674
                   unsigned long vga_ram_offset, int vga_ram_size)
1675
{
1676
    VGAState *s = &vga_state;
1677
    int i, j, v, b;
1678

    
1679
    for(i = 0;i < 256; i++) {
1680
        v = 0;
1681
        for(j = 0; j < 8; j++) {
1682
            v |= ((i >> j) & 1) << (j * 4);
1683
        }
1684
        expand4[i] = v;
1685

    
1686
        v = 0;
1687
        for(j = 0; j < 4; j++) {
1688
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1689
        }
1690
        expand2[i] = v;
1691
    }
1692
    for(i = 0; i < 16; i++) {
1693
        v = 0;
1694
        for(j = 0; j < 4; j++) {
1695
            b = ((i >> j) & 1);
1696
            v |= b << (2 * j);
1697
            v |= b << (2 * j + 1);
1698
        }
1699
        expand4to8[i] = v;
1700
    }
1701

    
1702
    vga_reset(s);
1703

    
1704
    s->vram_ptr = vga_ram_base;
1705
    s->vram_offset = vga_ram_offset;
1706
    s->vram_size = vga_ram_size;
1707
    s->ds = ds;
1708

    
1709
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1710

    
1711
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1712

    
1713
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1714
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1715
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1716
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1717

    
1718
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1719

    
1720
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1721
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1722
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1723
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1724
    s->bank_offset = -0xa0000;
1725

    
1726
#ifdef CONFIG_BOCHS_VBE
1727
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1728
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1729
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read, s);
1730
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read, s);
1731

    
1732
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write, s);
1733
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write, s);
1734
#endif
1735

    
1736
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1737
#if defined (TARGET_I386)
1738
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1739
#ifdef CONFIG_BOCHS_VBE
1740
    /* XXX: use optimized standard vga accesses */
1741
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1742
                                 vga_ram_size, vga_ram_offset);
1743
#endif
1744
#elif defined (TARGET_PPC)
1745
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1746
#endif
1747
    return 0;
1748
}
1749

    
1750
/********************************************************/
1751
/* vga screen dump */
1752

    
1753
static int vga_save_w, vga_save_h;
1754

    
1755
static void vga_save_dpy_update(DisplayState *s, 
1756
                                int x, int y, int w, int h)
1757
{
1758
}
1759

    
1760
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1761
{
1762
    s->linesize = w * 4;
1763
    s->data = qemu_malloc(h * s->linesize);
1764
    vga_save_w = w;
1765
    vga_save_h = h;
1766
}
1767

    
1768
static void vga_save_dpy_refresh(DisplayState *s)
1769
{
1770
}
1771

    
1772
static int ppm_save(const char *filename, uint8_t *data, 
1773
                    int w, int h, int linesize)
1774
{
1775
    FILE *f;
1776
    uint8_t *d, *d1;
1777
    unsigned int v;
1778
    int y, x;
1779

    
1780
    f = fopen(filename, "wb");
1781
    if (!f)
1782
        return -1;
1783
    fprintf(f, "P6\n%d %d\n%d\n",
1784
            w, h, 255);
1785
    d1 = data;
1786
    for(y = 0; y < h; y++) {
1787
        d = d1;
1788
        for(x = 0; x < w; x++) {
1789
            v = *(uint32_t *)d;
1790
            fputc((v >> 16) & 0xff, f);
1791
            fputc((v >> 8) & 0xff, f);
1792
            fputc((v) & 0xff, f);
1793
            d += 4;
1794
        }
1795
        d1 += linesize;
1796
    }
1797
    fclose(f);
1798
    return 0;
1799
}
1800

    
1801
/* save the vga display in a PPM image even if no display is
1802
   available */
1803
void vga_screen_dump(const char *filename)
1804
{
1805
    VGAState *s = &vga_state;
1806
    DisplayState *saved_ds, ds1, *ds = &ds1;
1807
    
1808
    /* XXX: this is a little hackish */
1809
    s->last_width = -1;
1810
    s->last_height = -1;
1811
    saved_ds = s->ds;
1812

    
1813
    memset(ds, 0, sizeof(DisplayState));
1814
    ds->dpy_update = vga_save_dpy_update;
1815
    ds->dpy_resize = vga_save_dpy_resize;
1816
    ds->dpy_refresh = vga_save_dpy_refresh;
1817
    ds->depth = 32;
1818

    
1819
    s->ds = ds;
1820
    s->graphic_mode = -1;
1821
    vga_update_display();
1822
    
1823
    if (ds->data) {
1824
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1825
                 s->ds->linesize);
1826
        qemu_free(ds->data);
1827
    }
1828
    s->ds = saved_ds;
1829
}