Statistics
| Branch: | Revision:

root / hw / vga.c @ c92b2e84

History | View | Annotate | Download (38.2 kB)

1
/*
2
 * QEMU VGA Emulator. An S3 86c968 is emulated
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 CONFIG_S3VGA
57

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

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

    
64
typedef struct VGAState {
65
    uint8_t *vram_ptr;
66
    unsigned long vram_offset;
67
    unsigned int vram_size;
68
    uint32_t latch;
69
    uint8_t sr_index;
70
    uint8_t sr[8];
71
    uint8_t gr_index;
72
    uint8_t gr[16];
73
    uint8_t ar_index;
74
    uint8_t ar[21];
75
    int ar_flip_flop;
76
    uint8_t cr_index;
77
    uint8_t cr[256]; /* CRT registers */
78
    uint8_t msr; /* Misc Output Register */
79
    uint8_t fcr; /* Feature Control Register */
80
    uint8_t st00; /* status 0 */
81
    uint8_t st01; /* status 1 */
82
    uint8_t dac_state;
83
    uint8_t dac_sub_index;
84
    uint8_t dac_read_index;
85
    uint8_t dac_write_index;
86
    uint8_t dac_cache[3]; /* used when writing */
87
    uint8_t palette[768];
88

    
89
    /* display refresh support */
90
    DisplayState *ds;
91
    uint32_t font_offsets[2];
92
    int graphic_mode;
93
    uint8_t shift_control;
94
    uint8_t double_scan;
95
    uint32_t line_offset;
96
    uint32_t line_compare;
97
    uint32_t start_addr;
98
    uint8_t last_cw, last_ch;
99
    uint32_t last_width, last_height;
100
    uint8_t cursor_start, cursor_end;
101
    uint32_t cursor_offset;
102
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
103
    /* tell for each page if it has been updated since the last time */
104
    uint8_t vram_updated[VGA_RAM_SIZE / 4096];
105
    uint32_t last_palette[256];
106
#define CH_ATTR_SIZE (160 * 100)
107
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
108
} VGAState;
109

    
110
/* force some bits to zero */
111
static const uint8_t sr_mask[8] = {
112
    (uint8_t)~0xfc,
113
    (uint8_t)~0xc2,
114
    (uint8_t)~0xf0,
115
    (uint8_t)~0xc0,
116
    (uint8_t)~0xf1,
117
    (uint8_t)~0xff,
118
    (uint8_t)~0xff,
119
    (uint8_t)~0x00,
120
};
121

    
122
static const uint8_t gr_mask[16] = {
123
    (uint8_t)~0xf0, /* 0x00 */
124
    (uint8_t)~0xf0, /* 0x01 */
125
    (uint8_t)~0xf0, /* 0x02 */
126
    (uint8_t)~0xe0, /* 0x03 */
127
    (uint8_t)~0xfc, /* 0x04 */
128
    (uint8_t)~0x84, /* 0x05 */
129
    (uint8_t)~0xf0, /* 0x06 */
130
    (uint8_t)~0xf0, /* 0x07 */
131
    (uint8_t)~0x00, /* 0x08 */
132
    (uint8_t)~0xff, /* 0x09 */
133
    (uint8_t)~0xff, /* 0x0a */
134
    (uint8_t)~0xff, /* 0x0b */
135
    (uint8_t)~0xff, /* 0x0c */
136
    (uint8_t)~0xff, /* 0x0d */
137
    (uint8_t)~0xff, /* 0x0e */
138
    (uint8_t)~0xff, /* 0x0f */
139
};
140

    
141
#define cbswap_32(__x) \
142
((uint32_t)( \
143
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
144
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
145
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
146
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
147

    
148
#ifdef WORDS_BIGENDIAN
149
#define PAT(x) cbswap_32(x)
150
#else
151
#define PAT(x) (x)
152
#endif
153

    
154
#ifdef WORDS_BIGENDIAN
155
#define BIG 1
156
#else
157
#define BIG 0
158
#endif
159

    
160
#ifdef WORDS_BIGENDIAN
161
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
162
#else
163
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
164
#endif
165

    
166
static const uint32_t mask16[16] = {
167
    PAT(0x00000000),
168
    PAT(0x000000ff),
169
    PAT(0x0000ff00),
170
    PAT(0x0000ffff),
171
    PAT(0x00ff0000),
172
    PAT(0x00ff00ff),
173
    PAT(0x00ffff00),
174
    PAT(0x00ffffff),
175
    PAT(0xff000000),
176
    PAT(0xff0000ff),
177
    PAT(0xff00ff00),
178
    PAT(0xff00ffff),
179
    PAT(0xffff0000),
180
    PAT(0xffff00ff),
181
    PAT(0xffffff00),
182
    PAT(0xffffffff),
183
};
184

    
185
#undef PAT
186

    
187
#ifdef WORDS_BIGENDIAN
188
#define PAT(x) (x)
189
#else
190
#define PAT(x) cbswap_32(x)
191
#endif
192

    
193
static const uint32_t dmask16[16] = {
194
    PAT(0x00000000),
195
    PAT(0x000000ff),
196
    PAT(0x0000ff00),
197
    PAT(0x0000ffff),
198
    PAT(0x00ff0000),
199
    PAT(0x00ff00ff),
200
    PAT(0x00ffff00),
201
    PAT(0x00ffffff),
202
    PAT(0xff000000),
203
    PAT(0xff0000ff),
204
    PAT(0xff00ff00),
205
    PAT(0xff00ffff),
206
    PAT(0xffff0000),
207
    PAT(0xffff00ff),
208
    PAT(0xffffff00),
209
    PAT(0xffffffff),
210
};
211

    
212
static const uint32_t dmask4[4] = {
213
    PAT(0x00000000),
214
    PAT(0x0000ffff),
215
    PAT(0xffff0000),
216
    PAT(0xffffffff),
217
};
218

    
219
static uint32_t expand4[256];
220
static uint16_t expand2[256];
221
static uint8_t expand4to8[16];
222

    
223
VGAState vga_state;
224
int vga_io_memory;
225

    
226
static uint32_t vga_ioport_read(CPUState *env, uint32_t addr)
227
{
228
    VGAState *s = &vga_state;
229
    int val, index;
230

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

    
322
static void vga_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
323
{
324
    VGAState *s = &vga_state;
325
    int index, v;
326

    
327
    /* check port range access depending on color/monochrome mode */
328
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
329
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
330
        return;
331

    
332
#ifdef DEBUG_VGA
333
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
334
#endif
335

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

    
433
#ifdef CONFIG_S3VGA
434
            /* S3 registers */
435
        case 0x2d:
436
        case 0x2e:
437
        case 0x2f:
438
        case 0x30:
439
            /* chip ID, cannot write */
440
            break;
441
        case 0x31:
442
            /* update start address */
443
            s->cr[s->cr_index] = val;
444
            v = (val >> 4) & 3;
445
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
446
            break;
447
        case 0x51:
448
            /* update start address */
449
            s->cr[s->cr_index] = val;
450
            v = val & 3;
451
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
452
            break;
453
#endif
454
        default:
455
            s->cr[s->cr_index] = val;
456
            break;
457
        }
458
#ifdef DEBUG_S3
459
        if (s->cr_index >= 0x20)
460
            printf("S3: CR write index=0x%x val=0x%x\n",
461
                   s->cr_index, val);
462
#endif
463
        break;
464
    case 0x3ba:
465
    case 0x3da:
466
        s->fcr = val & 0x10;
467
        break;
468
    }
469
}
470

    
471
/* called for accesses between 0xa0000 and 0xc0000 */
472
static uint32_t vga_mem_readb(uint32_t addr)
473
{
474
    VGAState *s = &vga_state;
475
    int memory_map_mode, plane;
476
    uint32_t ret;
477
    
478
    /* convert to VGA memory offset */
479
    memory_map_mode = (s->gr[6] >> 2) & 3;
480
    switch(memory_map_mode) {
481
    case 0:
482
        addr -= 0xa0000;
483
        break;
484
    case 1:
485
        addr -= 0xa0000;
486
        if (addr >= 0x10000)
487
            return 0xff;
488
        break;
489
    case 2:
490
        addr -= 0xb0000;
491
        if (addr >= 0x8000)
492
            return 0xff;
493
        break;
494
    default:
495
    case 3:
496
        addr -= 0xb8000;
497
        if (addr >= 0x8000)
498
            return 0xff;
499
        break;
500
    }
501
    
502
    if (s->sr[4] & 0x08) {
503
        /* chain 4 mode : simplest access */
504
        ret = s->vram_ptr[addr];
505
    } else if (s->gr[5] & 0x10) {
506
        /* odd/even mode (aka text mode mapping) */
507
        plane = (s->gr[4] & 2) | (addr & 1);
508
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
509
    } else {
510
        /* standard VGA latched access */
511
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
512

    
513
        if (!(s->gr[5] & 0x08)) {
514
            /* read mode 0 */
515
            plane = s->gr[4];
516
            ret = GET_PLANE(s->latch, plane);
517
        } else {
518
            /* read mode 1 */
519
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
520
            ret |= ret >> 16;
521
            ret |= ret >> 8;
522
            ret = (~ret) & 0xff;
523
        }
524
    }
525
    return ret;
526
}
527

    
528
static uint32_t vga_mem_readw(uint32_t addr)
529
{
530
    uint32_t v;
531
    v = vga_mem_readb(addr);
532
    v |= vga_mem_readb(addr + 1) << 8;
533
    return v;
534
}
535

    
536
static uint32_t vga_mem_readl(uint32_t addr)
537
{
538
    uint32_t v;
539
    v = vga_mem_readb(addr);
540
    v |= vga_mem_readb(addr + 1) << 8;
541
    v |= vga_mem_readb(addr + 2) << 16;
542
    v |= vga_mem_readb(addr + 3) << 24;
543
    return v;
544
}
545

    
546
/* called for accesses between 0xa0000 and 0xc0000 */
547
void vga_mem_writeb(uint32_t addr, uint32_t val)
548
{
549
    VGAState *s = &vga_state;
550
    int memory_map_mode, plane, write_mode, b, func_select;
551
    uint32_t write_mask, bit_mask, set_mask;
552

    
553
#ifdef DEBUG_VGA_MEM
554
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
555
#endif
556
    /* convert to VGA memory offset */
557
    memory_map_mode = (s->gr[6] >> 2) & 3;
558
    switch(memory_map_mode) {
559
    case 0:
560
        addr -= 0xa0000;
561
        break;
562
    case 1:
563
        addr -= 0xa0000;
564
        if (addr >= 0x10000)
565
            return;
566
        break;
567
    case 2:
568
        addr -= 0xb0000;
569
        if (addr >= 0x8000)
570
            return;
571
        break;
572
    default:
573
    case 3:
574
        addr -= 0xb8000;
575
        if (addr >= 0x8000)
576
            return;
577
        break;
578
    }
579
    
580
    if (s->sr[4] & 0x08) {
581
        /* chain 4 mode : simplest access */
582
        plane = addr & 3;
583
        if (s->sr[2] & (1 << plane)) {
584
            s->vram_ptr[addr] = val;
585
#ifdef DEBUG_VGA_MEM
586
            printf("vga: chain4: [0x%x]\n", addr);
587
#endif
588
            s->vram_updated[addr >> 12] = 1;
589
        }
590
    } else if (s->gr[5] & 0x10) {
591
        /* odd/even mode (aka text mode mapping) */
592
        plane = (s->gr[4] & 2) | (addr & 1);
593
        if (s->sr[2] & (1 << plane)) {
594
            addr = ((addr & ~1) << 1) | plane;
595
            s->vram_ptr[addr] = val;
596
#ifdef DEBUG_VGA_MEM
597
            printf("vga: odd/even: [0x%x]\n", addr);
598
#endif
599
            s->vram_updated[addr >> 12] = 1;
600
        }
601
    } else {
602
        /* standard VGA latched access */
603
        write_mode = s->gr[5] & 3;
604
        switch(write_mode) {
605
        default:
606
        case 0:
607
            /* rotate */
608
            b = s->gr[3] & 7;
609
            val = ((val >> b) | (val << (8 - b))) & 0xff;
610
            val |= val << 8;
611
            val |= val << 16;
612

    
613
            /* apply set/reset mask */
614
            set_mask = mask16[s->gr[1]];
615
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
616
            bit_mask = s->gr[8];
617
            break;
618
        case 1:
619
            val = s->latch;
620
            goto do_write;
621
        case 2:
622
            val = mask16[val & 0x0f];
623
            bit_mask = s->gr[8];
624
            break;
625
        case 3:
626
            /* rotate */
627
            b = s->gr[3] & 7;
628
            val = (val >> b) | (val << (8 - b));
629

    
630
            bit_mask = s->gr[8] & val;
631
            val = mask16[s->gr[0]];
632
            break;
633
        }
634

    
635
        /* apply logical operation */
636
        func_select = s->gr[3] >> 3;
637
        switch(func_select) {
638
        case 0:
639
        default:
640
            /* nothing to do */
641
            break;
642
        case 1:
643
            /* and */
644
            val &= s->latch;
645
            break;
646
        case 2:
647
            /* or */
648
            val |= s->latch;
649
            break;
650
        case 3:
651
            /* xor */
652
            val ^= s->latch;
653
            break;
654
        }
655

    
656
        /* apply bit mask */
657
        bit_mask |= bit_mask << 8;
658
        bit_mask |= bit_mask << 16;
659
        val = (val & bit_mask) | (s->latch & ~bit_mask);
660

    
661
    do_write:
662
        /* mask data according to sr[2] */
663
        write_mask = mask16[s->sr[2]];
664
        ((uint32_t *)s->vram_ptr)[addr] = 
665
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
666
            (val & write_mask);
667
#ifdef DEBUG_VGA_MEM
668
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
669
                   addr * 4, write_mask, val);
670
#endif
671
        s->vram_updated[addr >> 10] = 1;
672
    }
673
}
674

    
675
void vga_mem_writew(uint32_t addr, uint32_t val)
676
{
677
    vga_mem_writeb(addr, val & 0xff);
678
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
679
}
680

    
681
void vga_mem_writel(uint32_t addr, uint32_t val)
682
{
683
    vga_mem_writeb(addr, val & 0xff);
684
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
685
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff);
686
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff);
687
}
688

    
689
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
690
                             const uint8_t *font_ptr, int h,
691
                             uint32_t fgcol, uint32_t bgcol);
692
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
693
                                  const uint8_t *font_ptr, int h, 
694
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
695
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
696
                                const uint8_t *s, int width);
697

    
698
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
699
{
700
    /* XXX: TODO */
701
    return 0;
702
}
703

    
704
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
705
{
706
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
707
}
708

    
709
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
710
{
711
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
712
}
713

    
714
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
715
{
716
    return (r << 16) | (g << 8) | b;
717
}
718

    
719
#define DEPTH 8
720
#include "vga_template.h"
721

    
722
#define DEPTH 15
723
#include "vga_template.h"
724

    
725
#define DEPTH 16
726
#include "vga_template.h"
727

    
728
#define DEPTH 32
729
#include "vga_template.h"
730

    
731
static inline int c6_to_8(int v)
732
{
733
    int b;
734
    v &= 0x3f;
735
    b = v & 1;
736
    return (v << 2) | (b << 1) | b;
737
}
738

    
739
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
740
{
741
    unsigned int col;
742
    col = rgb_to_pixel8(r, g, b);
743
    col |= col << 8;
744
    col |= col << 16;
745
    return col;
746
}
747

    
748
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
749
{
750
    unsigned int col;
751
    col = rgb_to_pixel15(r, g, b);
752
    col |= col << 16;
753
    return col;
754
}
755

    
756
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
757
{
758
    unsigned int col;
759
    col = rgb_to_pixel16(r, g, b);
760
    col |= col << 16;
761
    return col;
762
}
763

    
764
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
765
{
766
    unsigned int col;
767
    col = rgb_to_pixel32(r, g, b);
768
    return col;
769
}
770

    
771
/* return true if the palette was modified */
772
static int update_palette16(VGAState *s)
773
{
774
    int full_update, i;
775
    uint32_t v, col, *palette;
776

    
777
    full_update = 0;
778
    palette = s->last_palette;
779
    for(i = 0; i < 16; i++) {
780
        v = s->ar[i];
781
        if (s->ar[0x10] & 0x80)
782
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
783
        else
784
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
785
        v = v * 3;
786
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
787
                              c6_to_8(s->palette[v + 1]), 
788
                              c6_to_8(s->palette[v + 2]));
789
        if (col != palette[i]) {
790
            full_update = 1;
791
            palette[i] = col;
792
        }
793
    }
794
    return full_update;
795
}
796

    
797
/* return true if the palette was modified */
798
static int update_palette256(VGAState *s)
799
{
800
    int full_update, i;
801
    uint32_t v, col, *palette;
802

    
803
    full_update = 0;
804
    palette = s->last_palette;
805
    v = 0;
806
    for(i = 0; i < 256; i++) {
807
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
808
                              c6_to_8(s->palette[v + 1]), 
809
                              c6_to_8(s->palette[v + 2]));
810
        if (col != palette[i]) {
811
            full_update = 1;
812
            palette[i] = col;
813
        }
814
        v += 3;
815
    }
816
    return full_update;
817
}
818

    
819
/* update start_addr and line_offset. Return TRUE if modified */
820
static int update_basic_params(VGAState *s)
821
{
822
    int full_update;
823
    uint32_t start_addr, line_offset, line_compare, v;
824
    
825
    full_update = 0;
826
    /* compute line_offset in bytes */
827
    line_offset = s->cr[0x13];
828
#ifdef CONFIG_S3VGA
829
    v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
830
    if (v == 0)
831
        v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
832
    line_offset |= (v << 8);
833
#endif
834
    line_offset <<= 3;
835

    
836
    /* starting address */
837
    start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
838
#ifdef CONFIG_S3VGA
839
    start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
840
#endif
841

    
842
    /* line compare */
843
    line_compare = s->cr[0x18] | 
844
        ((s->cr[0x07] & 0x10) << 4) |
845
        ((s->cr[0x09] & 0x40) << 3);
846

    
847
    if (line_offset != s->line_offset ||
848
        start_addr != s->start_addr ||
849
        line_compare != s->line_compare) {
850
        s->line_offset = line_offset;
851
        s->start_addr = start_addr;
852
        s->line_compare = line_compare;
853
        full_update = 1;
854
    }
855
    return full_update;
856
}
857

    
858
static inline int get_depth_index(int depth)
859
{
860
    switch(depth) {
861
    default:
862
    case 8:
863
        return 0;
864
    case 15:
865
        return 1;
866
    case 16:
867
        return 2;
868
    case 32:
869
        return 3;
870
    }
871
}
872

    
873
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
874
    vga_draw_glyph8_8,
875
    vga_draw_glyph8_16,
876
    vga_draw_glyph8_16,
877
    vga_draw_glyph8_32,
878
};
879

    
880
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
881
    vga_draw_glyph16_8,
882
    vga_draw_glyph16_16,
883
    vga_draw_glyph16_16,
884
    vga_draw_glyph16_32,
885
};
886

    
887
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
888
    vga_draw_glyph9_8,
889
    vga_draw_glyph9_16,
890
    vga_draw_glyph9_16,
891
    vga_draw_glyph9_32,
892
};
893
    
894
static const uint8_t cursor_glyph[32 * 4] = {
895
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
896
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
897
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
898
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
899
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
900
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
901
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
902
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
903
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
904
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
905
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
906
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
907
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
908
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
909
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
910
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
911
};    
912

    
913
/* 
914
 * Text mode update 
915
 * Missing:
916
 * - double scan
917
 * - double width 
918
 * - underline
919
 * - flashing
920
 */
921
static void vga_draw_text(VGAState *s, int full_update)
922
{
923
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
924
    int cx_min, cx_max, linesize, x_incr;
925
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
926
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
927
    const uint8_t *font_ptr, *font_base[2];
928
    int dup9, line_offset, depth_index;
929
    uint32_t *palette;
930
    uint32_t *ch_attr_ptr;
931
    vga_draw_glyph8_func *vga_draw_glyph8;
932
    vga_draw_glyph9_func *vga_draw_glyph9;
933

    
934
    full_update |= update_palette16(s);
935
    palette = s->last_palette;
936
    
937
    /* compute font data address (in plane 2) */
938
    v = s->sr[3];
939
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
940
    if (offset != s->font_offsets[0]) {
941
        s->font_offsets[0] = offset;
942
        full_update = 1;
943
    }
944
    font_base[0] = s->vram_ptr + offset;
945

    
946
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
947
    font_base[1] = s->vram_ptr + offset;
948
    if (offset != s->font_offsets[1]) {
949
        s->font_offsets[1] = offset;
950
        full_update = 1;
951
    }
952

    
953
    full_update |= update_basic_params(s);
954

    
955
    line_offset = s->line_offset;
956
    s1 = s->vram_ptr + (s->start_addr * 4);
957

    
958
    /* total width & height */
959
    cheight = (s->cr[9] & 0x1f) + 1;
960
    cw = 8;
961
    if (s->sr[1] & 0x01)
962
        cw = 9;
963
    if (s->sr[1] & 0x08)
964
        cw = 16; /* NOTE: no 18 pixel wide */
965
    x_incr = cw * ((s->ds->depth + 7) >> 3);
966
    width = (s->cr[0x01] + 1);
967
    if (s->cr[0x06] == 100) {
968
        /* ugly hack for CGA 160x100x16 - explain me the logic */
969
        height = 100;
970
    } else {
971
        height = s->cr[0x12] | 
972
            ((s->cr[0x07] & 0x02) << 7) | 
973
            ((s->cr[0x07] & 0x40) << 3);
974
        height = (height + 1) / cheight;
975
    }
976
    if (width != s->last_width || height != s->last_height ||
977
        cw != s->last_cw || cw != s->last_cw) {
978
        dpy_resize(s->ds, width * cw, height * cheight);
979
        s->last_width = width;
980
        s->last_height = height;
981
        s->last_ch = cheight;
982
        s->last_cw = cw;
983
        full_update = 1;
984
    }
985
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
986
    if (cursor_offset != s->cursor_offset ||
987
        s->cr[0xa] != s->cursor_start ||
988
        s->cr[0xb] != s->cursor_end) {
989
      /* if the cursor position changed, we update the old and new
990
         chars */
991
        if (s->cursor_offset < CH_ATTR_SIZE)
992
            s->last_ch_attr[s->cursor_offset] = -1;
993
        if (cursor_offset < CH_ATTR_SIZE)
994
            s->last_ch_attr[cursor_offset] = -1;
995
        s->cursor_offset = cursor_offset;
996
        s->cursor_start = s->cr[0xa];
997
        s->cursor_end = s->cr[0xb];
998
    }
999
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1000
    
1001
    depth_index = get_depth_index(s->ds->depth);
1002
    if (cw == 16)
1003
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1004
    else
1005
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1006
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1007
    
1008
    dest = s->ds->data;
1009
    linesize = s->ds->linesize;
1010
    ch_attr_ptr = s->last_ch_attr;
1011
    for(cy = 0; cy < height; cy++) {
1012
        d1 = dest;
1013
        src = s1;
1014
        cx_min = width;
1015
        cx_max = -1;
1016
        for(cx = 0; cx < width; cx++) {
1017
            ch_attr = *(uint16_t *)src;
1018
            if (full_update || ch_attr != *ch_attr_ptr) {
1019
                if (cx < cx_min)
1020
                    cx_min = cx;
1021
                if (cx > cx_max)
1022
                    cx_max = cx;
1023
                *ch_attr_ptr = ch_attr;
1024
#ifdef WORDS_BIGENDIAN
1025
                ch = ch_attr >> 8;
1026
                cattr = ch_attr & 0xff;
1027
#else
1028
                ch = ch_attr & 0xff;
1029
                cattr = ch_attr >> 8;
1030
#endif
1031
                font_ptr = font_base[(cattr >> 3) & 1];
1032
                font_ptr += 32 * 4 * ch;
1033
                bgcol = palette[cattr >> 4];
1034
                fgcol = palette[cattr & 0x0f];
1035
                if (cw != 9) {
1036
                    vga_draw_glyph8(d1, linesize, 
1037
                                    font_ptr, cheight, fgcol, bgcol);
1038
                } else {
1039
                    dup9 = 0;
1040
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1041
                        dup9 = 1;
1042
                    vga_draw_glyph9(d1, linesize, 
1043
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1044
                }
1045
                if (src == cursor_ptr &&
1046
                    !(s->cr[0x0a] & 0x20)) {
1047
                    int line_start, line_last, h;
1048
                    /* draw the cursor */
1049
                    line_start = s->cr[0x0a] & 0x1f;
1050
                    line_last = s->cr[0x0b] & 0x1f;
1051
                    /* XXX: check that */
1052
                    if (line_last > cheight - 1)
1053
                        line_last = cheight - 1;
1054
                    if (line_last >= line_start && line_start < cheight) {
1055
                        h = line_last - line_start + 1;
1056
                        d = d1 + linesize * line_start;
1057
                        if (cw != 9) {
1058
                            vga_draw_glyph8(d, linesize, 
1059
                                            cursor_glyph, h, fgcol, bgcol);
1060
                        } else {
1061
                            vga_draw_glyph9(d, linesize, 
1062
                                            cursor_glyph, h, fgcol, bgcol, 1);
1063
                        }
1064
                    }
1065
                }
1066
            }
1067
            d1 += x_incr;
1068
            src += 4;
1069
            ch_attr_ptr++;
1070
        }
1071
        if (cx_max != -1) {
1072
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1073
                       (cx_max - cx_min + 1) * cw, cheight);
1074
        }
1075
        dest += linesize * cheight;
1076
        s1 += line_offset;
1077
    }
1078
}
1079

    
1080
enum {
1081
    VGA_DRAW_LINE2,
1082
    VGA_DRAW_LINE2D2,
1083
    VGA_DRAW_LINE4,
1084
    VGA_DRAW_LINE4D2,
1085
    VGA_DRAW_LINE8D2,
1086
    VGA_DRAW_LINE8,
1087
    VGA_DRAW_LINE15,
1088
    VGA_DRAW_LINE16,
1089
    VGA_DRAW_LINE32,
1090
    VGA_DRAW_LINE_NB,
1091
};
1092

    
1093
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1094
    vga_draw_line2_8,
1095
    vga_draw_line2_16,
1096
    vga_draw_line2_16,
1097
    vga_draw_line2_32,
1098

    
1099
    vga_draw_line2d2_8,
1100
    vga_draw_line2d2_16,
1101
    vga_draw_line2d2_16,
1102
    vga_draw_line2d2_32,
1103

    
1104
    vga_draw_line4_8,
1105
    vga_draw_line4_16,
1106
    vga_draw_line4_16,
1107
    vga_draw_line4_32,
1108

    
1109
    vga_draw_line4d2_8,
1110
    vga_draw_line4d2_16,
1111
    vga_draw_line4d2_16,
1112
    vga_draw_line4d2_32,
1113

    
1114
    vga_draw_line8d2_8,
1115
    vga_draw_line8d2_16,
1116
    vga_draw_line8d2_16,
1117
    vga_draw_line8d2_32,
1118

    
1119
    vga_draw_line8_8,
1120
    vga_draw_line8_16,
1121
    vga_draw_line8_16,
1122
    vga_draw_line8_32,
1123

    
1124
    vga_draw_line15_8,
1125
    vga_draw_line15_15,
1126
    vga_draw_line15_16,
1127
    vga_draw_line15_32,
1128

    
1129
    vga_draw_line16_8,
1130
    vga_draw_line16_15,
1131
    vga_draw_line16_16,
1132
    vga_draw_line16_32,
1133

    
1134
    vga_draw_line32_8,
1135
    vga_draw_line32_15,
1136
    vga_draw_line32_16,
1137
    vga_draw_line32_32,
1138
};
1139

    
1140
/* 
1141
 * graphic modes
1142
 * Missing:
1143
 * - double scan
1144
 * - double width 
1145
 */
1146
static void vga_draw_graphic(VGAState *s, int full_update)
1147
{
1148
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1149
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1150
    int disp_width, multi_scan, multi_run;
1151
    uint8_t *d;
1152
    uint32_t v, addr1, addr;
1153
    vga_draw_line_func *vga_draw_line;
1154
    
1155
    full_update |= update_basic_params(s);
1156

    
1157
    width = (s->cr[0x01] + 1) * 8;
1158
    height = s->cr[0x12] | 
1159
        ((s->cr[0x07] & 0x02) << 7) | 
1160
        ((s->cr[0x07] & 0x40) << 3);
1161
    height = (height + 1);
1162
    disp_width = width;
1163
    
1164
    shift_control = (s->gr[0x05] >> 5) & 3;
1165
    double_scan = (s->cr[0x09] & 0x80);
1166
    if (shift_control > 1) {
1167
        multi_scan = (s->cr[0x09] & 0x1f);
1168
    } else {
1169
        multi_scan = 0;
1170
    }
1171
    multi_run = multi_scan;
1172
    if (shift_control != s->shift_control ||
1173
        double_scan != s->double_scan) {
1174
        full_update = 1;
1175
        s->shift_control = shift_control;
1176
        s->double_scan = double_scan;
1177
    }
1178
    
1179
    if (shift_control == 0) {
1180
        full_update |= update_palette16(s);
1181
        if (s->sr[0x01] & 8) {
1182
            v = VGA_DRAW_LINE4D2;
1183
            disp_width <<= 1;
1184
        } else {
1185
            v = VGA_DRAW_LINE4;
1186
        }
1187
    } else if (shift_control == 1) {
1188
        full_update |= update_palette16(s);
1189
        if (s->sr[0x01] & 8) {
1190
            v = VGA_DRAW_LINE2D2;
1191
            disp_width <<= 1;
1192
        } else {
1193
            v = VGA_DRAW_LINE2;
1194
        }
1195
    } else {
1196
        full_update |= update_palette256(s);
1197
        v = VGA_DRAW_LINE8D2;
1198
    }
1199
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1200

    
1201
    if (disp_width != s->last_width ||
1202
        height != s->last_height) {
1203
        dpy_resize(s->ds, disp_width, height);
1204
        s->last_width = disp_width;
1205
        s->last_height = height;
1206
        full_update = 1;
1207
    }
1208

    
1209
    line_offset = s->line_offset;
1210
#if 0
1211
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1212
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1213
#endif
1214
    addr1 = (s->start_addr * 4);
1215
    bwidth = width * 4;
1216
    y_start = -1;
1217
    page_min = 0x7fffffff;
1218
    page_max = -1;
1219
    d = s->ds->data;
1220
    linesize = s->ds->linesize;
1221
    y1 = 0;
1222
    for(y = 0; y < height; y++) {
1223
        addr = addr1;
1224
        if (!(s->cr[0x17] & 1)) {
1225
            int shift;
1226
            /* CGA compatibility handling */
1227
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1228
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1229
        }
1230
        if (!(s->cr[0x17] & 2)) {
1231
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1232
        }
1233
        page0 = addr >> 12;
1234
        page1 = (addr + bwidth - 1) >> 12;
1235
        update = full_update | s->vram_updated[page0] | s->vram_updated[page1];
1236
        if ((page1 - page0) > 1) {
1237
            /* if wide line, can use another page */
1238
            update |= s->vram_updated[page0 + 1];
1239
        }
1240
        if (update) {
1241
            if (y_start < 0)
1242
                y_start = y;
1243
            if (page0 < page_min)
1244
                page_min = page0;
1245
            if (page1 > page_max)
1246
                page_max = page1;
1247
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1248
        } else {
1249
            if (y_start >= 0) {
1250
                /* flush to display */
1251
                dpy_update(s->ds, 0, y_start, 
1252
                           disp_width, y - y_start);
1253
                y_start = -1;
1254
            }
1255
        }
1256
        if (!multi_run) {
1257
            if (!double_scan || (y & 1) != 0) {
1258
                if (y1 == s->line_compare) {
1259
                    addr1 = 0;
1260
                } else {
1261
                    mask = (s->cr[0x17] & 3) ^ 3;
1262
                    if ((y1 & mask) == mask)
1263
                        addr1 += line_offset;
1264
                }
1265
                y1++;
1266
            }
1267
            multi_run = multi_scan;
1268
        } else {
1269
            multi_run--;
1270
            y1++;
1271
        }
1272
        d += linesize;
1273
    }
1274
    if (y_start >= 0) {
1275
        /* flush to display */
1276
        dpy_update(s->ds, 0, y_start, 
1277
                   disp_width, y - y_start);
1278
    }
1279
    /* reset modified pages */
1280
    if (page_max != -1) {
1281
        memset(s->vram_updated + page_min, 0, page_max - page_min + 1);
1282
    }
1283
}
1284

    
1285
/* draw text terminal (very limited, just for simple boot debug
1286
   messages) */
1287
static int last_cursor_pos;
1288

    
1289
void vga_draw_dumb(VGAState *s)
1290
{
1291
    int c, i, cursor_pos, eol;
1292

    
1293
    cursor_pos = s->cr[0x0f] | (s->cr[0x0e] << 8);
1294
    eol = 0;
1295
    for(i = last_cursor_pos; i < cursor_pos; i++) {
1296
        /* XXX: should use vga RAM */
1297
        c = phys_ram_base[0xb8000 + (i) * 2];
1298
        if (c >= ' ') {
1299
            putchar(c);
1300
            eol = 0;
1301
        } else {
1302
            if (!eol)
1303
                putchar('\n');
1304
            eol = 1;
1305
        }
1306
    }
1307
    fflush(stdout);
1308
    last_cursor_pos = cursor_pos;
1309
}
1310

    
1311
void vga_update_display(void)
1312
{
1313
    VGAState *s = &vga_state;
1314
    int full_update, graphic_mode;
1315

    
1316
    if (s->ds->depth == 0) {
1317
        vga_draw_dumb(s);
1318
    } else {
1319
        full_update = 0;
1320
        graphic_mode = s->gr[6] & 1;
1321
        if (graphic_mode != s->graphic_mode) {
1322
            s->graphic_mode = graphic_mode;
1323
            full_update = 1;
1324
        }
1325
        if (graphic_mode)
1326
            vga_draw_graphic(s, full_update);
1327
        else
1328
            vga_draw_text(s, full_update);
1329
    }
1330
}
1331

    
1332
void vga_reset(VGAState *s)
1333
{
1334
    memset(s, 0, sizeof(VGAState));
1335
#ifdef CONFIG_S3VGA
1336
    /* chip ID for 8c968 */
1337
    s->cr[0x2d] = 0x88;
1338
    s->cr[0x2e] = 0xb0;
1339
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1340
    s->cr[0x30] = 0xe1;
1341
#endif
1342
    s->graphic_mode = -1; /* force full update */
1343
}
1344

    
1345
CPUReadMemoryFunc *vga_mem_read[3] = {
1346
    vga_mem_readb,
1347
    vga_mem_readw,
1348
    vga_mem_readl,
1349
};
1350

    
1351
CPUWriteMemoryFunc *vga_mem_write[3] = {
1352
    vga_mem_writeb,
1353
    vga_mem_writew,
1354
    vga_mem_writel,
1355
};
1356

    
1357
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1358
                   unsigned long vga_ram_offset, int vga_ram_size)
1359
{
1360
    VGAState *s = &vga_state;
1361
    int i, j, v, b;
1362

    
1363
    for(i = 0;i < 256; i++) {
1364
        v = 0;
1365
        for(j = 0; j < 8; j++) {
1366
            v |= ((i >> j) & 1) << (j * 4);
1367
        }
1368
        expand4[i] = v;
1369

    
1370
        v = 0;
1371
        for(j = 0; j < 4; j++) {
1372
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1373
        }
1374
        expand2[i] = v;
1375
    }
1376
    for(i = 0; i < 16; i++) {
1377
        v = 0;
1378
        for(j = 0; j < 4; j++) {
1379
            b = ((i >> j) & 1);
1380
            v |= b << (2 * j);
1381
            v |= b << (2 * j + 1);
1382
        }
1383
        expand4to8[i] = v;
1384
    }
1385

    
1386
    vga_reset(s);
1387

    
1388
    switch(ds->depth) {
1389
    case 8:
1390
        s->rgb_to_pixel = rgb_to_pixel8_dup;
1391
        break;
1392
    case 15:
1393
        s->rgb_to_pixel = rgb_to_pixel15_dup;
1394
        break;
1395
    default:
1396
    case 16:
1397
        s->rgb_to_pixel = rgb_to_pixel16_dup;
1398
        break;
1399
    case 32:
1400
        s->rgb_to_pixel = rgb_to_pixel32_dup;
1401
        break;
1402
    }
1403

    
1404
    s->vram_ptr = vga_ram_base;
1405
    s->vram_offset = vga_ram_offset;
1406
    s->vram_size = vga_ram_size;
1407
    s->ds = ds;
1408

    
1409
    register_ioport_write(0x3c0, 16, vga_ioport_write, 1);
1410

    
1411
    register_ioport_write(0x3b4, 2, vga_ioport_write, 1);
1412
    register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
1413
    register_ioport_write(0x3ba, 1, vga_ioport_write, 1);
1414
    register_ioport_write(0x3da, 1, vga_ioport_write, 1);
1415

    
1416
    register_ioport_read(0x3c0, 16, vga_ioport_read, 1);
1417

    
1418
    register_ioport_read(0x3b4, 2, vga_ioport_read, 1);
1419
    register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
1420
    register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
1421
    register_ioport_read(0x3da, 1, vga_ioport_read, 1);
1422

    
1423
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1424
#if defined (TARGET_I386)
1425
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1426
#elif defined (TARGET_PPC)
1427
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1428
#endif
1429
    return 0;
1430
}