Statistics
| Branch: | Revision:

root / hw / vga.c @ cae61cef

History | View | Annotate | Download (47 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
    uint32_t bank_offset;
120
#ifdef CONFIG_BOCHS_VBE
121
    uint16_t vbe_index;
122
    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
123
    uint32_t vbe_start_addr;
124
    uint32_t vbe_line_offset;
125
    uint32_t vbe_bank_mask;
126
#endif
127
    /* display refresh support */
128
    DisplayState *ds;
129
    uint32_t font_offsets[2];
130
    int graphic_mode;
131
    uint8_t shift_control;
132
    uint8_t double_scan;
133
    uint32_t line_offset;
134
    uint32_t line_compare;
135
    uint32_t start_addr;
136
    uint8_t last_cw, last_ch;
137
    uint32_t last_width, last_height;
138
    uint8_t cursor_start, cursor_end;
139
    uint32_t cursor_offset;
140
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
141
    /* tell for each page if it has been updated since the last time */
142
    uint32_t last_palette[256];
143
#define CH_ATTR_SIZE (160 * 100)
144
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
145
} VGAState;
146

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

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

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

    
185
#ifdef WORDS_BIGENDIAN
186
#define PAT(x) cbswap_32(x)
187
#else
188
#define PAT(x) (x)
189
#endif
190

    
191
#ifdef WORDS_BIGENDIAN
192
#define BIG 1
193
#else
194
#define BIG 0
195
#endif
196

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

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

    
222
#undef PAT
223

    
224
#ifdef WORDS_BIGENDIAN
225
#define PAT(x) (x)
226
#else
227
#define PAT(x) cbswap_32(x)
228
#endif
229

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

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

    
256
static uint32_t expand4[256];
257
static uint16_t expand2[256];
258
static uint8_t expand4to8[16];
259

    
260
VGAState vga_state;
261
int vga_io_memory;
262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
724
static uint32_t vga_mem_readw(uint32_t addr)
725
{
726
    uint32_t v;
727
    v = vga_mem_readb(addr);
728
    v |= vga_mem_readb(addr + 1) << 8;
729
    return v;
730
}
731

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

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

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

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

    
826
            bit_mask = s->gr[8] & val;
827
            val = mask16[s->gr[0]];
828
            break;
829
        }
830

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

    
852
        /* apply bit mask */
853
        bit_mask |= bit_mask << 8;
854
        bit_mask |= bit_mask << 16;
855
        val = (val & bit_mask) | (s->latch & ~bit_mask);
856

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

    
871
void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
872
{
873
    vga_mem_writeb(addr, val & 0xff, vaddr);
874
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
875
}
876

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

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

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

    
900
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
901
{
902
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
903
}
904

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

    
910
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
911
{
912
    return (r << 16) | (g << 8) | b;
913
}
914

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

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

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

    
924
#define DEPTH 32
925
#include "vga_template.h"
926

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

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

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

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

    
960
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
961
{
962
    unsigned int col;
963
    col = rgb_to_pixel32(r, g, b);
964
    return col;
965
}
966

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

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

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

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

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

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

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

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

    
1078
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1079
    vga_draw_glyph8_8,
1080
    vga_draw_glyph8_16,
1081
    vga_draw_glyph8_16,
1082
    vga_draw_glyph8_32,
1083
};
1084

    
1085
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1086
    vga_draw_glyph16_8,
1087
    vga_draw_glyph16_16,
1088
    vga_draw_glyph16_16,
1089
    vga_draw_glyph16_32,
1090
};
1091

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

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

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

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

    
1158
    full_update |= update_basic_params(s);
1159

    
1160
    line_offset = s->line_offset;
1161
    s1 = s->vram_ptr + (s->start_addr * 4);
1162

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

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

    
1299
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1300
    vga_draw_line2_8,
1301
    vga_draw_line2_16,
1302
    vga_draw_line2_16,
1303
    vga_draw_line2_32,
1304

    
1305
    vga_draw_line2d2_8,
1306
    vga_draw_line2d2_16,
1307
    vga_draw_line2d2_16,
1308
    vga_draw_line2d2_32,
1309

    
1310
    vga_draw_line4_8,
1311
    vga_draw_line4_16,
1312
    vga_draw_line4_16,
1313
    vga_draw_line4_32,
1314

    
1315
    vga_draw_line4d2_8,
1316
    vga_draw_line4d2_16,
1317
    vga_draw_line4d2_16,
1318
    vga_draw_line4d2_32,
1319

    
1320
    vga_draw_line8d2_8,
1321
    vga_draw_line8d2_16,
1322
    vga_draw_line8d2_16,
1323
    vga_draw_line8d2_32,
1324

    
1325
    vga_draw_line8_8,
1326
    vga_draw_line8_16,
1327
    vga_draw_line8_16,
1328
    vga_draw_line8_32,
1329

    
1330
    vga_draw_line15_8,
1331
    vga_draw_line15_15,
1332
    vga_draw_line15_16,
1333
    vga_draw_line15_32,
1334

    
1335
    vga_draw_line16_8,
1336
    vga_draw_line16_15,
1337
    vga_draw_line16_16,
1338
    vga_draw_line16_32,
1339

    
1340
    vga_draw_line24_8,
1341
    vga_draw_line24_15,
1342
    vga_draw_line24_16,
1343
    vga_draw_line24_32,
1344

    
1345
    vga_draw_line32_8,
1346
    vga_draw_line32_15,
1347
    vga_draw_line32_16,
1348
    vga_draw_line32_32,
1349
};
1350

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

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

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

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

    
1522
/* draw text terminal (very limited, just for simple boot debug
1523
   messages) */
1524
static int last_cursor_pos;
1525

    
1526
void vga_draw_dumb(VGAState *s)
1527
{
1528
    int c, i, cursor_pos, eol;
1529

    
1530
    cursor_pos = s->cr[0x0f] | (s->cr[0x0e] << 8);
1531
    eol = 0;
1532
    for(i = last_cursor_pos; i < cursor_pos; i++) {
1533
        /* XXX: should use vga RAM */
1534
        c = phys_ram_base[0xb8000 + (i) * 2];
1535
        if (c >= ' ') {
1536
            putchar(c);
1537
            eol = 0;
1538
        } else {
1539
            if (!eol)
1540
                putchar('\n');
1541
            eol = 1;
1542
        }
1543
    }
1544
    fflush(stdout);
1545
    last_cursor_pos = cursor_pos;
1546
}
1547

    
1548
void vga_update_display(void)
1549
{
1550
    VGAState *s = &vga_state;
1551
    int full_update, graphic_mode;
1552

    
1553
    if (s->ds->depth == 0) {
1554
        vga_draw_dumb(s);
1555
    } else {
1556
        full_update = 0;
1557
        graphic_mode = s->gr[6] & 1;
1558
        if (graphic_mode != s->graphic_mode) {
1559
            s->graphic_mode = graphic_mode;
1560
            full_update = 1;
1561
        }
1562
        if (graphic_mode)
1563
            vga_draw_graphic(s, full_update);
1564
        else
1565
            vga_draw_text(s, full_update);
1566
    }
1567
}
1568

    
1569
void vga_reset(VGAState *s)
1570
{
1571
    memset(s, 0, sizeof(VGAState));
1572
#ifdef CONFIG_S3VGA
1573
    /* chip ID for 8c968 */
1574
    s->cr[0x2d] = 0x88;
1575
    s->cr[0x2e] = 0xb0;
1576
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1577
    s->cr[0x30] = 0xe1;
1578
#endif
1579
    s->graphic_mode = -1; /* force full update */
1580
}
1581

    
1582
CPUReadMemoryFunc *vga_mem_read[3] = {
1583
    vga_mem_readb,
1584
    vga_mem_readw,
1585
    vga_mem_readl,
1586
};
1587

    
1588
CPUWriteMemoryFunc *vga_mem_write[3] = {
1589
    vga_mem_writeb,
1590
    vga_mem_writew,
1591
    vga_mem_writel,
1592
};
1593

    
1594
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1595
                   unsigned long vga_ram_offset, int vga_ram_size)
1596
{
1597
    VGAState *s = &vga_state;
1598
    int i, j, v, b;
1599

    
1600
    for(i = 0;i < 256; i++) {
1601
        v = 0;
1602
        for(j = 0; j < 8; j++) {
1603
            v |= ((i >> j) & 1) << (j * 4);
1604
        }
1605
        expand4[i] = v;
1606

    
1607
        v = 0;
1608
        for(j = 0; j < 4; j++) {
1609
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1610
        }
1611
        expand2[i] = v;
1612
    }
1613
    for(i = 0; i < 16; i++) {
1614
        v = 0;
1615
        for(j = 0; j < 4; j++) {
1616
            b = ((i >> j) & 1);
1617
            v |= b << (2 * j);
1618
            v |= b << (2 * j + 1);
1619
        }
1620
        expand4to8[i] = v;
1621
    }
1622

    
1623
    vga_reset(s);
1624

    
1625
    switch(ds->depth) {
1626
    case 8:
1627
        s->rgb_to_pixel = rgb_to_pixel8_dup;
1628
        break;
1629
    case 15:
1630
        s->rgb_to_pixel = rgb_to_pixel15_dup;
1631
        break;
1632
    default:
1633
    case 16:
1634
        s->rgb_to_pixel = rgb_to_pixel16_dup;
1635
        break;
1636
    case 32:
1637
        s->rgb_to_pixel = rgb_to_pixel32_dup;
1638
        break;
1639
    }
1640

    
1641
    s->vram_ptr = vga_ram_base;
1642
    s->vram_offset = vga_ram_offset;
1643
    s->vram_size = vga_ram_size;
1644
    s->ds = ds;
1645

    
1646
    register_ioport_write(0x3c0, 16, vga_ioport_write, 1);
1647

    
1648
    register_ioport_write(0x3b4, 2, vga_ioport_write, 1);
1649
    register_ioport_write(0x3d4, 2, vga_ioport_write, 1);
1650
    register_ioport_write(0x3ba, 1, vga_ioport_write, 1);
1651
    register_ioport_write(0x3da, 1, vga_ioport_write, 1);
1652

    
1653
    register_ioport_read(0x3c0, 16, vga_ioport_read, 1);
1654

    
1655
    register_ioport_read(0x3b4, 2, vga_ioport_read, 1);
1656
    register_ioport_read(0x3d4, 2, vga_ioport_read, 1);
1657
    register_ioport_read(0x3ba, 1, vga_ioport_read, 1);
1658
    register_ioport_read(0x3da, 1, vga_ioport_read, 1);
1659
    s->bank_offset = -0xa0000;
1660

    
1661
#ifdef CONFIG_BOCHS_VBE
1662
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1663
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1664
    register_ioport_read(0x1ce, 1, vbe_ioport_read, 2);
1665
    register_ioport_read(0x1cf, 1, vbe_ioport_read, 2);
1666

    
1667
    register_ioport_write(0x1ce, 1, vbe_ioport_write, 2);
1668
    register_ioport_write(0x1cf, 1, vbe_ioport_write, 2);
1669
#endif
1670

    
1671
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1672
#if defined (TARGET_I386)
1673
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1674
#ifdef CONFIG_BOCHS_VBE
1675
    /* XXX: use optimized standard vga accesses */
1676
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1677
                                 vga_ram_size, vga_ram_offset);
1678
#endif
1679
#elif defined (TARGET_PPC)
1680
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1681
#endif
1682
    return 0;
1683
}