Statistics
| Branch: | Revision:

root / hw / vga.c @ 4fa0f5d2

History | View | Annotate | Download (45 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
#define NO_THUNK_TYPE_SIZE
44
#include "thunk.h"
45

    
46
#include "cpu.h"
47
#include "exec-all.h"
48

    
49
#include "vl.h"
50

    
51
//#define DEBUG_VGA
52
//#define DEBUG_VGA_MEM
53
//#define DEBUG_VGA_REG
54

    
55
//#define DEBUG_S3
56
//#define DEBUG_BOCHS_VBE
57

    
58
#define CONFIG_S3VGA
59

    
60
#define MSR_COLOR_EMULATION 0x01
61
#define MSR_PAGE_SELECT     0x20
62

    
63
#define ST01_V_RETRACE      0x08
64
#define ST01_DISP_ENABLE    0x01
65

    
66
/* bochs VBE support */
67
#define CONFIG_BOCHS_VBE
68

    
69
#define VBE_DISPI_MAX_XRES              1024
70
#define VBE_DISPI_MAX_YRES              768
71

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

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

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

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

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

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

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

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

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

    
220
#undef PAT
221

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

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

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

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

    
258
VGAState vga_state;
259
int vga_io_memory;
260

    
261
static uint32_t vga_ioport_read(CPUState *env, uint32_t addr)
262
{
263
    VGAState *s = &vga_state;
264
    int val, index;
265

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

    
357
static void vga_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
358
{
359
    VGAState *s = &vga_state;
360
    int index, v;
361

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

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

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

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

    
506
#ifdef CONFIG_BOCHS_VBE
507
static uint32_t vbe_ioport_read(CPUState *env, uint32_t addr)
508
{
509
    VGAState *s = &vga_state;
510
    uint32_t val;
511

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

    
527
static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
528
{
529
    VGAState *s = &vga_state;
530

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

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

    
622
/* called for accesses between 0xa0000 and 0xc0000 */
623
static uint32_t vga_mem_readb(uint32_t addr)
624
{
625
    VGAState *s = &vga_state;
626
    int memory_map_mode, plane;
627
    uint32_t ret;
628
    
629
    /* convert to VGA memory offset */
630
    memory_map_mode = (s->gr[6] >> 2) & 3;
631
    switch(memory_map_mode) {
632
    case 0:
633
        addr -= 0xa0000;
634
        break;
635
    case 1:
636
        addr -= 0xa0000;
637
        if (addr >= 0x10000)
638
            return 0xff;
639
        break;
640
    case 2:
641
        addr -= 0xb0000;
642
        if (addr >= 0x8000)
643
            return 0xff;
644
        break;
645
    default:
646
    case 3:
647
        addr -= 0xb8000;
648
        if (addr >= 0x8000)
649
            return 0xff;
650
        break;
651
    }
652
    
653
    if (s->sr[4] & 0x08) {
654
        /* chain 4 mode : simplest access */
655
        ret = s->vram_ptr[addr];
656
    } else if (s->gr[5] & 0x10) {
657
        /* odd/even mode (aka text mode mapping) */
658
        plane = (s->gr[4] & 2) | (addr & 1);
659
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
660
    } else {
661
        /* standard VGA latched access */
662
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
663

    
664
        if (!(s->gr[5] & 0x08)) {
665
            /* read mode 0 */
666
            plane = s->gr[4];
667
            ret = GET_PLANE(s->latch, plane);
668
        } else {
669
            /* read mode 1 */
670
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
671
            ret |= ret >> 16;
672
            ret |= ret >> 8;
673
            ret = (~ret) & 0xff;
674
        }
675
    }
676
    return ret;
677
}
678

    
679
static uint32_t vga_mem_readw(uint32_t addr)
680
{
681
    uint32_t v;
682
    v = vga_mem_readb(addr);
683
    v |= vga_mem_readb(addr + 1) << 8;
684
    return v;
685
}
686

    
687
static uint32_t vga_mem_readl(uint32_t addr)
688
{
689
    uint32_t v;
690
    v = vga_mem_readb(addr);
691
    v |= vga_mem_readb(addr + 1) << 8;
692
    v |= vga_mem_readb(addr + 2) << 16;
693
    v |= vga_mem_readb(addr + 3) << 24;
694
    return v;
695
}
696

    
697
/* called for accesses between 0xa0000 and 0xc0000 */
698
void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
699
{
700
    VGAState *s = &vga_state;
701
    int memory_map_mode, plane, write_mode, b, func_select;
702
    uint32_t write_mask, bit_mask, set_mask;
703

    
704
#ifdef DEBUG_VGA_MEM
705
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
706
#endif
707
    /* convert to VGA memory offset */
708
    memory_map_mode = (s->gr[6] >> 2) & 3;
709
    switch(memory_map_mode) {
710
    case 0:
711
        addr -= 0xa0000;
712
        break;
713
    case 1:
714
        addr -= 0xa0000;
715
        if (addr >= 0x10000)
716
            return;
717
        break;
718
    case 2:
719
        addr -= 0xb0000;
720
        if (addr >= 0x8000)
721
            return;
722
        break;
723
    default:
724
    case 3:
725
        addr -= 0xb8000;
726
        if (addr >= 0x8000)
727
            return;
728
        break;
729
    }
730
    
731
    if (s->sr[4] & 0x08) {
732
        /* chain 4 mode : simplest access */
733
        plane = addr & 3;
734
        if (s->sr[2] & (1 << plane)) {
735
            s->vram_ptr[addr] = val;
736
#ifdef DEBUG_VGA_MEM
737
            printf("vga: chain4: [0x%x]\n", addr);
738
#endif
739
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
740
        }
741
    } else if (s->gr[5] & 0x10) {
742
        /* odd/even mode (aka text mode mapping) */
743
        plane = (s->gr[4] & 2) | (addr & 1);
744
        if (s->sr[2] & (1 << plane)) {
745
            addr = ((addr & ~1) << 1) | plane;
746
            s->vram_ptr[addr] = val;
747
#ifdef DEBUG_VGA_MEM
748
            printf("vga: odd/even: [0x%x]\n", addr);
749
#endif
750
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
751
        }
752
    } else {
753
        /* standard VGA latched access */
754
        write_mode = s->gr[5] & 3;
755
        switch(write_mode) {
756
        default:
757
        case 0:
758
            /* rotate */
759
            b = s->gr[3] & 7;
760
            val = ((val >> b) | (val << (8 - b))) & 0xff;
761
            val |= val << 8;
762
            val |= val << 16;
763

    
764
            /* apply set/reset mask */
765
            set_mask = mask16[s->gr[1]];
766
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
767
            bit_mask = s->gr[8];
768
            break;
769
        case 1:
770
            val = s->latch;
771
            goto do_write;
772
        case 2:
773
            val = mask16[val & 0x0f];
774
            bit_mask = s->gr[8];
775
            break;
776
        case 3:
777
            /* rotate */
778
            b = s->gr[3] & 7;
779
            val = (val >> b) | (val << (8 - b));
780

    
781
            bit_mask = s->gr[8] & val;
782
            val = mask16[s->gr[0]];
783
            break;
784
        }
785

    
786
        /* apply logical operation */
787
        func_select = s->gr[3] >> 3;
788
        switch(func_select) {
789
        case 0:
790
        default:
791
            /* nothing to do */
792
            break;
793
        case 1:
794
            /* and */
795
            val &= s->latch;
796
            break;
797
        case 2:
798
            /* or */
799
            val |= s->latch;
800
            break;
801
        case 3:
802
            /* xor */
803
            val ^= s->latch;
804
            break;
805
        }
806

    
807
        /* apply bit mask */
808
        bit_mask |= bit_mask << 8;
809
        bit_mask |= bit_mask << 16;
810
        val = (val & bit_mask) | (s->latch & ~bit_mask);
811

    
812
    do_write:
813
        /* mask data according to sr[2] */
814
        write_mask = mask16[s->sr[2]];
815
        ((uint32_t *)s->vram_ptr)[addr] = 
816
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
817
            (val & write_mask);
818
#ifdef DEBUG_VGA_MEM
819
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
820
                   addr * 4, write_mask, val);
821
#endif
822
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
823
    }
824
}
825

    
826
void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
827
{
828
    vga_mem_writeb(addr, val & 0xff, vaddr);
829
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
830
}
831

    
832
void vga_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
833
{
834
    vga_mem_writeb(addr, val & 0xff, vaddr);
835
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
836
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff, vaddr);
837
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff, vaddr);
838
}
839

    
840
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
841
                             const uint8_t *font_ptr, int h,
842
                             uint32_t fgcol, uint32_t bgcol);
843
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
844
                                  const uint8_t *font_ptr, int h, 
845
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
846
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
847
                                const uint8_t *s, int width);
848

    
849
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
850
{
851
    /* XXX: TODO */
852
    return 0;
853
}
854

    
855
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
856
{
857
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
858
}
859

    
860
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
861
{
862
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
863
}
864

    
865
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
866
{
867
    return (r << 16) | (g << 8) | b;
868
}
869

    
870
#define DEPTH 8
871
#include "vga_template.h"
872

    
873
#define DEPTH 15
874
#include "vga_template.h"
875

    
876
#define DEPTH 16
877
#include "vga_template.h"
878

    
879
#define DEPTH 32
880
#include "vga_template.h"
881

    
882
static inline int c6_to_8(int v)
883
{
884
    int b;
885
    v &= 0x3f;
886
    b = v & 1;
887
    return (v << 2) | (b << 1) | b;
888
}
889

    
890
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
891
{
892
    unsigned int col;
893
    col = rgb_to_pixel8(r, g, b);
894
    col |= col << 8;
895
    col |= col << 16;
896
    return col;
897
}
898

    
899
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
900
{
901
    unsigned int col;
902
    col = rgb_to_pixel15(r, g, b);
903
    col |= col << 16;
904
    return col;
905
}
906

    
907
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
908
{
909
    unsigned int col;
910
    col = rgb_to_pixel16(r, g, b);
911
    col |= col << 16;
912
    return col;
913
}
914

    
915
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
916
{
917
    unsigned int col;
918
    col = rgb_to_pixel32(r, g, b);
919
    return col;
920
}
921

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

    
928
    full_update = 0;
929
    palette = s->last_palette;
930
    for(i = 0; i < 16; i++) {
931
        v = s->ar[i];
932
        if (s->ar[0x10] & 0x80)
933
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
934
        else
935
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
936
        v = v * 3;
937
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
938
                              c6_to_8(s->palette[v + 1]), 
939
                              c6_to_8(s->palette[v + 2]));
940
        if (col != palette[i]) {
941
            full_update = 1;
942
            palette[i] = col;
943
        }
944
    }
945
    return full_update;
946
}
947

    
948
/* return true if the palette was modified */
949
static int update_palette256(VGAState *s)
950
{
951
    int full_update, i;
952
    uint32_t v, col, *palette;
953

    
954
    full_update = 0;
955
    palette = s->last_palette;
956
    v = 0;
957
    for(i = 0; i < 256; i++) {
958
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
959
                              c6_to_8(s->palette[v + 1]), 
960
                              c6_to_8(s->palette[v + 2]));
961
        if (col != palette[i]) {
962
            full_update = 1;
963
            palette[i] = col;
964
        }
965
        v += 3;
966
    }
967
    return full_update;
968
}
969

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

    
978
#ifdef CONFIG_BOCHS_VBE
979
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
980
        line_offset = s->vbe_line_offset;
981
        start_addr = s->vbe_start_addr;
982
    } else
983
#endif
984
    {  
985
        /* compute line_offset in bytes */
986
        line_offset = s->cr[0x13];
987
#ifdef CONFIG_S3VGA
988
        v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
989
        if (v == 0)
990
            v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
991
        line_offset |= (v << 8);
992
#endif
993
        line_offset <<= 3;
994
        
995
        /* starting address */
996
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
997
#ifdef CONFIG_S3VGA
998
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
999
#endif
1000
    }
1001
    
1002
    /* line compare */
1003
    line_compare = s->cr[0x18] | 
1004
        ((s->cr[0x07] & 0x10) << 4) |
1005
        ((s->cr[0x09] & 0x40) << 3);
1006

    
1007
    if (line_offset != s->line_offset ||
1008
        start_addr != s->start_addr ||
1009
        line_compare != s->line_compare) {
1010
        s->line_offset = line_offset;
1011
        s->start_addr = start_addr;
1012
        s->line_compare = line_compare;
1013
        full_update = 1;
1014
    }
1015
    return full_update;
1016
}
1017

    
1018
static inline int get_depth_index(int depth)
1019
{
1020
    switch(depth) {
1021
    default:
1022
    case 8:
1023
        return 0;
1024
    case 15:
1025
        return 1;
1026
    case 16:
1027
        return 2;
1028
    case 32:
1029
        return 3;
1030
    }
1031
}
1032

    
1033
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1034
    vga_draw_glyph8_8,
1035
    vga_draw_glyph8_16,
1036
    vga_draw_glyph8_16,
1037
    vga_draw_glyph8_32,
1038
};
1039

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

    
1047
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1048
    vga_draw_glyph9_8,
1049
    vga_draw_glyph9_16,
1050
    vga_draw_glyph9_16,
1051
    vga_draw_glyph9_32,
1052
};
1053
    
1054
static const uint8_t cursor_glyph[32 * 4] = {
1055
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1056
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1057
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1058
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1059
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1060
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1061
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1062
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1063
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1064
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1065
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1066
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1067
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1068
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1069
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1070
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1071
};    
1072

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

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

    
1106
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1107
    font_base[1] = s->vram_ptr + offset;
1108
    if (offset != s->font_offsets[1]) {
1109
        s->font_offsets[1] = offset;
1110
        full_update = 1;
1111
    }
1112

    
1113
    full_update |= update_basic_params(s);
1114

    
1115
    line_offset = s->line_offset;
1116
    s1 = s->vram_ptr + (s->start_addr * 4);
1117

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

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

    
1254
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1255
    vga_draw_line2_8,
1256
    vga_draw_line2_16,
1257
    vga_draw_line2_16,
1258
    vga_draw_line2_32,
1259

    
1260
    vga_draw_line2d2_8,
1261
    vga_draw_line2d2_16,
1262
    vga_draw_line2d2_16,
1263
    vga_draw_line2d2_32,
1264

    
1265
    vga_draw_line4_8,
1266
    vga_draw_line4_16,
1267
    vga_draw_line4_16,
1268
    vga_draw_line4_32,
1269

    
1270
    vga_draw_line4d2_8,
1271
    vga_draw_line4d2_16,
1272
    vga_draw_line4d2_16,
1273
    vga_draw_line4d2_32,
1274

    
1275
    vga_draw_line8d2_8,
1276
    vga_draw_line8d2_16,
1277
    vga_draw_line8d2_16,
1278
    vga_draw_line8d2_32,
1279

    
1280
    vga_draw_line8_8,
1281
    vga_draw_line8_16,
1282
    vga_draw_line8_16,
1283
    vga_draw_line8_32,
1284

    
1285
    vga_draw_line15_8,
1286
    vga_draw_line15_15,
1287
    vga_draw_line15_16,
1288
    vga_draw_line15_32,
1289

    
1290
    vga_draw_line16_8,
1291
    vga_draw_line16_15,
1292
    vga_draw_line16_16,
1293
    vga_draw_line16_32,
1294

    
1295
    vga_draw_line24_8,
1296
    vga_draw_line24_15,
1297
    vga_draw_line24_16,
1298
    vga_draw_line24_32,
1299

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

    
1306
/* 
1307
 * graphic modes
1308
 * Missing:
1309
 * - double scan
1310
 * - double width 
1311
 */
1312
static void vga_draw_graphic(VGAState *s, int full_update)
1313
{
1314
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1315
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1316
    int disp_width, multi_scan, multi_run;
1317
    uint8_t *d;
1318
    uint32_t v, addr1, addr;
1319
    vga_draw_line_func *vga_draw_line;
1320
    
1321
    full_update |= update_basic_params(s);
1322

    
1323
    width = (s->cr[0x01] + 1) * 8;
1324
    height = s->cr[0x12] | 
1325
        ((s->cr[0x07] & 0x02) << 7) | 
1326
        ((s->cr[0x07] & 0x40) << 3);
1327
    height = (height + 1);
1328
    disp_width = width;
1329
    
1330
    shift_control = (s->gr[0x05] >> 5) & 3;
1331
    double_scan = (s->cr[0x09] & 0x80);
1332
    if (shift_control > 1) {
1333
        multi_scan = (s->cr[0x09] & 0x1f);
1334
    } else {
1335
        multi_scan = 0;
1336
    }
1337
    multi_run = multi_scan;
1338
    if (shift_control != s->shift_control ||
1339
        double_scan != s->double_scan) {
1340
        full_update = 1;
1341
        s->shift_control = shift_control;
1342
        s->double_scan = double_scan;
1343
    }
1344
    
1345
    if (shift_control == 0) {
1346
        full_update |= update_palette16(s);
1347
        if (s->sr[0x01] & 8) {
1348
            v = VGA_DRAW_LINE4D2;
1349
            disp_width <<= 1;
1350
        } else {
1351
            v = VGA_DRAW_LINE4;
1352
        }
1353
    } else if (shift_control == 1) {
1354
        full_update |= update_palette16(s);
1355
        if (s->sr[0x01] & 8) {
1356
            v = VGA_DRAW_LINE2D2;
1357
            disp_width <<= 1;
1358
        } else {
1359
            v = VGA_DRAW_LINE2;
1360
        }
1361
    } else {
1362
#ifdef CONFIG_BOCHS_VBE
1363
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1364
            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
1365
            default:
1366
            case 8:
1367
                full_update |= update_palette256(s);
1368
                v = VGA_DRAW_LINE8;
1369
                break;
1370
            case 15:
1371
                v = VGA_DRAW_LINE15;
1372
                break;
1373
            case 16:
1374
                v = VGA_DRAW_LINE16;
1375
                break;
1376
            case 24:
1377
                v = VGA_DRAW_LINE24;
1378
                break;
1379
            case 32:
1380
                v = VGA_DRAW_LINE32;
1381
                break;
1382
            }
1383
        } else 
1384
#endif
1385
        {
1386
            full_update |= update_palette256(s);
1387
            v = VGA_DRAW_LINE8D2;
1388
        }
1389
    }
1390
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1391

    
1392
    if (disp_width != s->last_width ||
1393
        height != s->last_height) {
1394
        dpy_resize(s->ds, disp_width, height);
1395
        s->last_width = disp_width;
1396
        s->last_height = height;
1397
        full_update = 1;
1398
    }
1399

    
1400
    line_offset = s->line_offset;
1401
#if 0
1402
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1403
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1404
#endif
1405
    addr1 = (s->start_addr * 4);
1406
    bwidth = width * 4;
1407
    y_start = -1;
1408
    page_min = 0x7fffffff;
1409
    page_max = -1;
1410
    d = s->ds->data;
1411
    linesize = s->ds->linesize;
1412
    y1 = 0;
1413
    for(y = 0; y < height; y++) {
1414
        addr = addr1;
1415
        if (!(s->cr[0x17] & 1)) {
1416
            int shift;
1417
            /* CGA compatibility handling */
1418
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1419
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1420
        }
1421
        if (!(s->cr[0x17] & 2)) {
1422
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1423
        }
1424
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1425
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1426
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1427
            cpu_physical_memory_is_dirty(page1);
1428
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1429
            /* if wide line, can use another page */
1430
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1431
        }
1432
        if (update) {
1433
            if (y_start < 0)
1434
                y_start = y;
1435
            if (page0 < page_min)
1436
                page_min = page0;
1437
            if (page1 > page_max)
1438
                page_max = page1;
1439
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1440
        } else {
1441
            if (y_start >= 0) {
1442
                /* flush to display */
1443
                dpy_update(s->ds, 0, y_start, 
1444
                           disp_width, y - y_start);
1445
                y_start = -1;
1446
            }
1447
        }
1448
        if (!multi_run) {
1449
            if (!double_scan || (y & 1) != 0) {
1450
                if (y1 == s->line_compare) {
1451
                    addr1 = 0;
1452
                } else {
1453
                    mask = (s->cr[0x17] & 3) ^ 3;
1454
                    if ((y1 & mask) == mask)
1455
                        addr1 += line_offset;
1456
                }
1457
                y1++;
1458
            }
1459
            multi_run = multi_scan;
1460
        } else {
1461
            multi_run--;
1462
            y1++;
1463
        }
1464
        d += linesize;
1465
    }
1466
    if (y_start >= 0) {
1467
        /* flush to display */
1468
        dpy_update(s->ds, 0, y_start, 
1469
                   disp_width, y - y_start);
1470
    }
1471
    /* reset modified pages */
1472
    if (page_max != -1) {
1473
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1474
    }
1475
}
1476

    
1477
/* draw text terminal (very limited, just for simple boot debug
1478
   messages) */
1479
static int last_cursor_pos;
1480

    
1481
void vga_draw_dumb(VGAState *s)
1482
{
1483
    int c, i, cursor_pos, eol;
1484

    
1485
    cursor_pos = s->cr[0x0f] | (s->cr[0x0e] << 8);
1486
    eol = 0;
1487
    for(i = last_cursor_pos; i < cursor_pos; i++) {
1488
        /* XXX: should use vga RAM */
1489
        c = phys_ram_base[0xb8000 + (i) * 2];
1490
        if (c >= ' ') {
1491
            putchar(c);
1492
            eol = 0;
1493
        } else {
1494
            if (!eol)
1495
                putchar('\n');
1496
            eol = 1;
1497
        }
1498
    }
1499
    fflush(stdout);
1500
    last_cursor_pos = cursor_pos;
1501
}
1502

    
1503
void vga_update_display(void)
1504
{
1505
    VGAState *s = &vga_state;
1506
    int full_update, graphic_mode;
1507

    
1508
    if (s->ds->depth == 0) {
1509
        vga_draw_dumb(s);
1510
    } else {
1511
        full_update = 0;
1512
        graphic_mode = s->gr[6] & 1;
1513
        if (graphic_mode != s->graphic_mode) {
1514
            s->graphic_mode = graphic_mode;
1515
            full_update = 1;
1516
        }
1517
        if (graphic_mode)
1518
            vga_draw_graphic(s, full_update);
1519
        else
1520
            vga_draw_text(s, full_update);
1521
    }
1522
}
1523

    
1524
void vga_reset(VGAState *s)
1525
{
1526
    memset(s, 0, sizeof(VGAState));
1527
#ifdef CONFIG_S3VGA
1528
    /* chip ID for 8c968 */
1529
    s->cr[0x2d] = 0x88;
1530
    s->cr[0x2e] = 0xb0;
1531
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1532
    s->cr[0x30] = 0xe1;
1533
#endif
1534
    s->graphic_mode = -1; /* force full update */
1535
}
1536

    
1537
CPUReadMemoryFunc *vga_mem_read[3] = {
1538
    vga_mem_readb,
1539
    vga_mem_readw,
1540
    vga_mem_readl,
1541
};
1542

    
1543
CPUWriteMemoryFunc *vga_mem_write[3] = {
1544
    vga_mem_writeb,
1545
    vga_mem_writew,
1546
    vga_mem_writel,
1547
};
1548

    
1549
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1550
                   unsigned long vga_ram_offset, int vga_ram_size)
1551
{
1552
    VGAState *s = &vga_state;
1553
    int i, j, v, b;
1554

    
1555
    for(i = 0;i < 256; i++) {
1556
        v = 0;
1557
        for(j = 0; j < 8; j++) {
1558
            v |= ((i >> j) & 1) << (j * 4);
1559
        }
1560
        expand4[i] = v;
1561

    
1562
        v = 0;
1563
        for(j = 0; j < 4; j++) {
1564
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1565
        }
1566
        expand2[i] = v;
1567
    }
1568
    for(i = 0; i < 16; i++) {
1569
        v = 0;
1570
        for(j = 0; j < 4; j++) {
1571
            b = ((i >> j) & 1);
1572
            v |= b << (2 * j);
1573
            v |= b << (2 * j + 1);
1574
        }
1575
        expand4to8[i] = v;
1576
    }
1577

    
1578
    vga_reset(s);
1579

    
1580
    switch(ds->depth) {
1581
    case 8:
1582
        s->rgb_to_pixel = rgb_to_pixel8_dup;
1583
        break;
1584
    case 15:
1585
        s->rgb_to_pixel = rgb_to_pixel15_dup;
1586
        break;
1587
    default:
1588
    case 16:
1589
        s->rgb_to_pixel = rgb_to_pixel16_dup;
1590
        break;
1591
    case 32:
1592
        s->rgb_to_pixel = rgb_to_pixel32_dup;
1593
        break;
1594
    }
1595

    
1596
    s->vram_ptr = vga_ram_base;
1597
    s->vram_offset = vga_ram_offset;
1598
    s->vram_size = vga_ram_size;
1599
    s->ds = ds;
1600

    
1601
    register_ioport_write(0x3c0, 16, vga_ioport_write, 1);
1602

    
1603
    register_ioport_write(0x3b4, 2, vga_ioport_write, 1);
1604
    register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
1605
    register_ioport_write(0x3ba, 1, vga_ioport_write, 1);
1606
    register_ioport_write(0x3da, 1, vga_ioport_write, 1);
1607

    
1608
    register_ioport_read(0x3c0, 16, vga_ioport_read, 1);
1609

    
1610
    register_ioport_read(0x3b4, 2, vga_ioport_read, 1);
1611
    register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
1612
    register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
1613
    register_ioport_read(0x3da, 1, vga_ioport_read, 1);
1614

    
1615
#ifdef CONFIG_BOCHS_VBE
1616
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1617
    register_ioport_read(0x1ce, 1, vbe_ioport_read, 2);
1618
    register_ioport_read(0x1cf, 1, vbe_ioport_read, 2);
1619

    
1620
    register_ioport_write(0x1ce, 1, vbe_ioport_write, 2);
1621
    register_ioport_write(0x1cf, 1, vbe_ioport_write, 2);
1622
#endif
1623

    
1624
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1625
#if defined (TARGET_I386)
1626
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1627
#ifdef CONFIG_BOCHS_VBE
1628
    /* XXX: use optimized standard vga accesses */
1629
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1630
                                 vga_ram_size, vga_ram_offset);
1631
#endif
1632
#elif defined (TARGET_PPC)
1633
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1634
#endif
1635
    return 0;
1636
}