Statistics
| Branch: | Revision:

root / hw / vga.c @ 99a0949b

History | View | Annotate | Download (67.6 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 "hw.h"
25
#include "console.h"
26
#include "pc.h"
27
#include "pci.h"
28
#include "vga_int.h"
29
#include "pixel_ops.h"
30
#include "qemu-timer.h"
31

    
32
//#define DEBUG_VGA
33
//#define DEBUG_VGA_MEM
34
//#define DEBUG_VGA_REG
35

    
36
//#define DEBUG_BOCHS_VBE
37

    
38
/* force some bits to zero */
39
const uint8_t sr_mask[8] = {
40
    0x03,
41
    0x3d,
42
    0x0f,
43
    0x3f,
44
    0x0e,
45
    0x00,
46
    0x00,
47
    0xff,
48
};
49

    
50
const uint8_t gr_mask[16] = {
51
    0x0f, /* 0x00 */
52
    0x0f, /* 0x01 */
53
    0x0f, /* 0x02 */
54
    0x1f, /* 0x03 */
55
    0x03, /* 0x04 */
56
    0x7b, /* 0x05 */
57
    0x0f, /* 0x06 */
58
    0x0f, /* 0x07 */
59
    0xff, /* 0x08 */
60
    0x00, /* 0x09 */
61
    0x00, /* 0x0a */
62
    0x00, /* 0x0b */
63
    0x00, /* 0x0c */
64
    0x00, /* 0x0d */
65
    0x00, /* 0x0e */
66
    0x00, /* 0x0f */
67
};
68

    
69
#define cbswap_32(__x) \
70
((uint32_t)( \
71
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
72
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
73
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
74
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
75

    
76
#ifdef HOST_WORDS_BIGENDIAN
77
#define PAT(x) cbswap_32(x)
78
#else
79
#define PAT(x) (x)
80
#endif
81

    
82
#ifdef HOST_WORDS_BIGENDIAN
83
#define BIG 1
84
#else
85
#define BIG 0
86
#endif
87

    
88
#ifdef HOST_WORDS_BIGENDIAN
89
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
90
#else
91
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
92
#endif
93

    
94
static const uint32_t mask16[16] = {
95
    PAT(0x00000000),
96
    PAT(0x000000ff),
97
    PAT(0x0000ff00),
98
    PAT(0x0000ffff),
99
    PAT(0x00ff0000),
100
    PAT(0x00ff00ff),
101
    PAT(0x00ffff00),
102
    PAT(0x00ffffff),
103
    PAT(0xff000000),
104
    PAT(0xff0000ff),
105
    PAT(0xff00ff00),
106
    PAT(0xff00ffff),
107
    PAT(0xffff0000),
108
    PAT(0xffff00ff),
109
    PAT(0xffffff00),
110
    PAT(0xffffffff),
111
};
112

    
113
#undef PAT
114

    
115
#ifdef HOST_WORDS_BIGENDIAN
116
#define PAT(x) (x)
117
#else
118
#define PAT(x) cbswap_32(x)
119
#endif
120

    
121
static const uint32_t dmask16[16] = {
122
    PAT(0x00000000),
123
    PAT(0x000000ff),
124
    PAT(0x0000ff00),
125
    PAT(0x0000ffff),
126
    PAT(0x00ff0000),
127
    PAT(0x00ff00ff),
128
    PAT(0x00ffff00),
129
    PAT(0x00ffffff),
130
    PAT(0xff000000),
131
    PAT(0xff0000ff),
132
    PAT(0xff00ff00),
133
    PAT(0xff00ffff),
134
    PAT(0xffff0000),
135
    PAT(0xffff00ff),
136
    PAT(0xffffff00),
137
    PAT(0xffffffff),
138
};
139

    
140
static const uint32_t dmask4[4] = {
141
    PAT(0x00000000),
142
    PAT(0x0000ffff),
143
    PAT(0xffff0000),
144
    PAT(0xffffffff),
145
};
146

    
147
static uint32_t expand4[256];
148
static uint16_t expand2[256];
149
static uint8_t expand4to8[16];
150

    
151
static void vga_screen_dump(void *opaque, const char *filename);
152
static char *screen_dump_filename;
153
static DisplayChangeListener *screen_dump_dcl;
154

    
155
static void vga_dumb_update_retrace_info(VGACommonState *s)
156
{
157
    (void) s;
158
}
159

    
160
static void vga_precise_update_retrace_info(VGACommonState *s)
161
{
162
    int htotal_chars;
163
    int hretr_start_char;
164
    int hretr_skew_chars;
165
    int hretr_end_char;
166

    
167
    int vtotal_lines;
168
    int vretr_start_line;
169
    int vretr_end_line;
170

    
171
    int div2, sldiv2, dots;
172
    int clocking_mode;
173
    int clock_sel;
174
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
175
    int64_t chars_per_sec;
176
    struct vga_precise_retrace *r = &s->retrace_info.precise;
177

    
178
    htotal_chars = s->cr[0x00] + 5;
179
    hretr_start_char = s->cr[0x04];
180
    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
181
    hretr_end_char = s->cr[0x05] & 0x1f;
182

    
183
    vtotal_lines = (s->cr[0x06]
184
                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
185
        ;
186
    vretr_start_line = s->cr[0x10]
187
        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
188
        ;
189
    vretr_end_line = s->cr[0x11] & 0xf;
190

    
191

    
192
    div2 = (s->cr[0x17] >> 2) & 1;
193
    sldiv2 = (s->cr[0x17] >> 3) & 1;
194

    
195
    clocking_mode = (s->sr[0x01] >> 3) & 1;
196
    clock_sel = (s->msr >> 2) & 3;
197
    dots = (s->msr & 1) ? 8 : 9;
198

    
199
    chars_per_sec = clk_hz[clock_sel] / dots;
200

    
201
    htotal_chars <<= clocking_mode;
202

    
203
    r->total_chars = vtotal_lines * htotal_chars;
204
    if (r->freq) {
205
        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
206
    } else {
207
        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
208
    }
209

    
210
    r->vstart = vretr_start_line;
211
    r->vend = r->vstart + vretr_end_line + 1;
212

    
213
    r->hstart = hretr_start_char + hretr_skew_chars;
214
    r->hend = r->hstart + hretr_end_char + 1;
215
    r->htotal = htotal_chars;
216

    
217
#if 0
218
    printf (
219
        "hz=%f\n"
220
        "htotal = %d\n"
221
        "hretr_start = %d\n"
222
        "hretr_skew = %d\n"
223
        "hretr_end = %d\n"
224
        "vtotal = %d\n"
225
        "vretr_start = %d\n"
226
        "vretr_end = %d\n"
227
        "div2 = %d sldiv2 = %d\n"
228
        "clocking_mode = %d\n"
229
        "clock_sel = %d %d\n"
230
        "dots = %d\n"
231
        "ticks/char = %lld\n"
232
        "\n",
233
        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
234
        htotal_chars,
235
        hretr_start_char,
236
        hretr_skew_chars,
237
        hretr_end_char,
238
        vtotal_lines,
239
        vretr_start_line,
240
        vretr_end_line,
241
        div2, sldiv2,
242
        clocking_mode,
243
        clock_sel,
244
        clk_hz[clock_sel],
245
        dots,
246
        r->ticks_per_char
247
        );
248
#endif
249
}
250

    
251
static uint8_t vga_precise_retrace(VGACommonState *s)
252
{
253
    struct vga_precise_retrace *r = &s->retrace_info.precise;
254
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
255

    
256
    if (r->total_chars) {
257
        int cur_line, cur_line_char, cur_char;
258
        int64_t cur_tick;
259

    
260
        cur_tick = qemu_get_clock(vm_clock);
261

    
262
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
263
        cur_line = cur_char / r->htotal;
264

    
265
        if (cur_line >= r->vstart && cur_line <= r->vend) {
266
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
267
        } else {
268
            cur_line_char = cur_char % r->htotal;
269
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
270
                val |= ST01_DISP_ENABLE;
271
            }
272
        }
273

    
274
        return val;
275
    } else {
276
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
277
    }
278
}
279

    
280
static uint8_t vga_dumb_retrace(VGACommonState *s)
281
{
282
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
283
}
284

    
285
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
286
{
287
    if (s->msr & MSR_COLOR_EMULATION) {
288
        /* Color */
289
        return (addr >= 0x3b0 && addr <= 0x3bf);
290
    } else {
291
        /* Monochrome */
292
        return (addr >= 0x3d0 && addr <= 0x3df);
293
    }
294
}
295

    
296
uint32_t vga_ioport_read(void *opaque, uint32_t addr)
297
{
298
    VGACommonState *s = opaque;
299
    int val, index;
300

    
301
    if (vga_ioport_invalid(s, addr)) {
302
        val = 0xff;
303
    } else {
304
        switch(addr) {
305
        case 0x3c0:
306
            if (s->ar_flip_flop == 0) {
307
                val = s->ar_index;
308
            } else {
309
                val = 0;
310
            }
311
            break;
312
        case 0x3c1:
313
            index = s->ar_index & 0x1f;
314
            if (index < 21)
315
                val = s->ar[index];
316
            else
317
                val = 0;
318
            break;
319
        case 0x3c2:
320
            val = s->st00;
321
            break;
322
        case 0x3c4:
323
            val = s->sr_index;
324
            break;
325
        case 0x3c5:
326
            val = s->sr[s->sr_index];
327
#ifdef DEBUG_VGA_REG
328
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
329
#endif
330
            break;
331
        case 0x3c7:
332
            val = s->dac_state;
333
            break;
334
        case 0x3c8:
335
            val = s->dac_write_index;
336
            break;
337
        case 0x3c9:
338
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
339
            if (++s->dac_sub_index == 3) {
340
                s->dac_sub_index = 0;
341
                s->dac_read_index++;
342
            }
343
            break;
344
        case 0x3ca:
345
            val = s->fcr;
346
            break;
347
        case 0x3cc:
348
            val = s->msr;
349
            break;
350
        case 0x3ce:
351
            val = s->gr_index;
352
            break;
353
        case 0x3cf:
354
            val = s->gr[s->gr_index];
355
#ifdef DEBUG_VGA_REG
356
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
357
#endif
358
            break;
359
        case 0x3b4:
360
        case 0x3d4:
361
            val = s->cr_index;
362
            break;
363
        case 0x3b5:
364
        case 0x3d5:
365
            val = s->cr[s->cr_index];
366
#ifdef DEBUG_VGA_REG
367
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
368
#endif
369
            break;
370
        case 0x3ba:
371
        case 0x3da:
372
            /* just toggle to fool polling */
373
            val = s->st01 = s->retrace(s);
374
            s->ar_flip_flop = 0;
375
            break;
376
        default:
377
            val = 0x00;
378
            break;
379
        }
380
    }
381
#if defined(DEBUG_VGA)
382
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
383
#endif
384
    return val;
385
}
386

    
387
void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
388
{
389
    VGACommonState *s = opaque;
390
    int index;
391

    
392
    /* check port range access depending on color/monochrome mode */
393
    if (vga_ioport_invalid(s, addr)) {
394
        return;
395
    }
396
#ifdef DEBUG_VGA
397
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
398
#endif
399

    
400
    switch(addr) {
401
    case 0x3c0:
402
        if (s->ar_flip_flop == 0) {
403
            val &= 0x3f;
404
            s->ar_index = val;
405
        } else {
406
            index = s->ar_index & 0x1f;
407
            switch(index) {
408
            case 0x00 ... 0x0f:
409
                s->ar[index] = val & 0x3f;
410
                break;
411
            case 0x10:
412
                s->ar[index] = val & ~0x10;
413
                break;
414
            case 0x11:
415
                s->ar[index] = val;
416
                break;
417
            case 0x12:
418
                s->ar[index] = val & ~0xc0;
419
                break;
420
            case 0x13:
421
                s->ar[index] = val & ~0xf0;
422
                break;
423
            case 0x14:
424
                s->ar[index] = val & ~0xf0;
425
                break;
426
            default:
427
                break;
428
            }
429
        }
430
        s->ar_flip_flop ^= 1;
431
        break;
432
    case 0x3c2:
433
        s->msr = val & ~0x10;
434
        s->update_retrace_info(s);
435
        break;
436
    case 0x3c4:
437
        s->sr_index = val & 7;
438
        break;
439
    case 0x3c5:
440
#ifdef DEBUG_VGA_REG
441
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
442
#endif
443
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
444
        if (s->sr_index == 1) s->update_retrace_info(s);
445
        break;
446
    case 0x3c7:
447
        s->dac_read_index = val;
448
        s->dac_sub_index = 0;
449
        s->dac_state = 3;
450
        break;
451
    case 0x3c8:
452
        s->dac_write_index = val;
453
        s->dac_sub_index = 0;
454
        s->dac_state = 0;
455
        break;
456
    case 0x3c9:
457
        s->dac_cache[s->dac_sub_index] = val;
458
        if (++s->dac_sub_index == 3) {
459
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
460
            s->dac_sub_index = 0;
461
            s->dac_write_index++;
462
        }
463
        break;
464
    case 0x3ce:
465
        s->gr_index = val & 0x0f;
466
        break;
467
    case 0x3cf:
468
#ifdef DEBUG_VGA_REG
469
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
470
#endif
471
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
472
        break;
473
    case 0x3b4:
474
    case 0x3d4:
475
        s->cr_index = val;
476
        break;
477
    case 0x3b5:
478
    case 0x3d5:
479
#ifdef DEBUG_VGA_REG
480
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
481
#endif
482
        /* handle CR0-7 protection */
483
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
484
            /* can always write bit 4 of CR7 */
485
            if (s->cr_index == 7)
486
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
487
            return;
488
        }
489
        s->cr[s->cr_index] = val;
490

    
491
        switch(s->cr_index) {
492
        case 0x00:
493
        case 0x04:
494
        case 0x05:
495
        case 0x06:
496
        case 0x07:
497
        case 0x11:
498
        case 0x17:
499
            s->update_retrace_info(s);
500
            break;
501
        }
502
        break;
503
    case 0x3ba:
504
    case 0x3da:
505
        s->fcr = val & 0x10;
506
        break;
507
    }
508
}
509

    
510
#ifdef CONFIG_BOCHS_VBE
511
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
512
{
513
    VGACommonState *s = opaque;
514
    uint32_t val;
515
    val = s->vbe_index;
516
    return val;
517
}
518

    
519
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
520
{
521
    VGACommonState *s = opaque;
522
    uint32_t val;
523

    
524
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
525
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
526
            switch(s->vbe_index) {
527
                /* XXX: do not hardcode ? */
528
            case VBE_DISPI_INDEX_XRES:
529
                val = VBE_DISPI_MAX_XRES;
530
                break;
531
            case VBE_DISPI_INDEX_YRES:
532
                val = VBE_DISPI_MAX_YRES;
533
                break;
534
            case VBE_DISPI_INDEX_BPP:
535
                val = VBE_DISPI_MAX_BPP;
536
                break;
537
            default:
538
                val = s->vbe_regs[s->vbe_index];
539
                break;
540
            }
541
        } else {
542
            val = s->vbe_regs[s->vbe_index];
543
        }
544
    } else {
545
        val = 0;
546
    }
547
#ifdef DEBUG_BOCHS_VBE
548
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
549
#endif
550
    return val;
551
}
552

    
553
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
554
{
555
    VGACommonState *s = opaque;
556
    s->vbe_index = val;
557
}
558

    
559
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
560
{
561
    VGACommonState *s = opaque;
562

    
563
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
564
#ifdef DEBUG_BOCHS_VBE
565
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
566
#endif
567
        switch(s->vbe_index) {
568
        case VBE_DISPI_INDEX_ID:
569
            if (val == VBE_DISPI_ID0 ||
570
                val == VBE_DISPI_ID1 ||
571
                val == VBE_DISPI_ID2 ||
572
                val == VBE_DISPI_ID3 ||
573
                val == VBE_DISPI_ID4) {
574
                s->vbe_regs[s->vbe_index] = val;
575
            }
576
            break;
577
        case VBE_DISPI_INDEX_XRES:
578
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
579
                s->vbe_regs[s->vbe_index] = val;
580
            }
581
            break;
582
        case VBE_DISPI_INDEX_YRES:
583
            if (val <= VBE_DISPI_MAX_YRES) {
584
                s->vbe_regs[s->vbe_index] = val;
585
            }
586
            break;
587
        case VBE_DISPI_INDEX_BPP:
588
            if (val == 0)
589
                val = 8;
590
            if (val == 4 || val == 8 || val == 15 ||
591
                val == 16 || val == 24 || val == 32) {
592
                s->vbe_regs[s->vbe_index] = val;
593
            }
594
            break;
595
        case VBE_DISPI_INDEX_BANK:
596
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
597
              val &= (s->vbe_bank_mask >> 2);
598
            } else {
599
              val &= s->vbe_bank_mask;
600
            }
601
            s->vbe_regs[s->vbe_index] = val;
602
            s->bank_offset = (val << 16);
603
            break;
604
        case VBE_DISPI_INDEX_ENABLE:
605
            if ((val & VBE_DISPI_ENABLED) &&
606
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
607
                int h, shift_control;
608

    
609
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
610
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
611
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
612
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
613
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
614
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
615

    
616
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
617
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
618
                else
619
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
620
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
621
                s->vbe_start_addr = 0;
622

    
623
                /* clear the screen (should be done in BIOS) */
624
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
625
                    memset(s->vram_ptr, 0,
626
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
627
                }
628

    
629
                /* we initialize the VGA graphic mode (should be done
630
                   in BIOS) */
631
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
632
                s->cr[0x17] |= 3; /* no CGA modes */
633
                s->cr[0x13] = s->vbe_line_offset >> 3;
634
                /* width */
635
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
636
                /* height (only meaningful if < 1024) */
637
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
638
                s->cr[0x12] = h;
639
                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
640
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
641
                /* line compare to 1023 */
642
                s->cr[0x18] = 0xff;
643
                s->cr[0x07] |= 0x10;
644
                s->cr[0x09] |= 0x40;
645

    
646
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
647
                    shift_control = 0;
648
                    s->sr[0x01] &= ~8; /* no double line */
649
                } else {
650
                    shift_control = 2;
651
                    s->sr[4] |= 0x08; /* set chain 4 mode */
652
                    s->sr[2] |= 0x0f; /* activate all planes */
653
                }
654
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
655
                s->cr[0x09] &= ~0x9f; /* no double scan */
656
            } else {
657
                /* XXX: the bios should do that */
658
                s->bank_offset = 0;
659
            }
660
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
661
            s->vbe_regs[s->vbe_index] = val;
662
            break;
663
        case VBE_DISPI_INDEX_VIRT_WIDTH:
664
            {
665
                int w, h, line_offset;
666

    
667
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
668
                    return;
669
                w = val;
670
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
671
                    line_offset = w >> 1;
672
                else
673
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
674
                h = s->vram_size / line_offset;
675
                /* XXX: support weird bochs semantics ? */
676
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
677
                    return;
678
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
679
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
680
                s->vbe_line_offset = line_offset;
681
            }
682
            break;
683
        case VBE_DISPI_INDEX_X_OFFSET:
684
        case VBE_DISPI_INDEX_Y_OFFSET:
685
            {
686
                int x;
687
                s->vbe_regs[s->vbe_index] = val;
688
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
689
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
690
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
691
                    s->vbe_start_addr += x >> 1;
692
                else
693
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
694
                s->vbe_start_addr >>= 2;
695
            }
696
            break;
697
        default:
698
            break;
699
        }
700
    }
701
}
702
#endif
703

    
704
/* called for accesses between 0xa0000 and 0xc0000 */
705
uint32_t vga_mem_readb(void *opaque, a_target_phys_addr addr)
706
{
707
    VGACommonState *s = opaque;
708
    int memory_map_mode, plane;
709
    uint32_t ret;
710

    
711
    /* convert to VGA memory offset */
712
    memory_map_mode = (s->gr[6] >> 2) & 3;
713
    addr &= 0x1ffff;
714
    switch(memory_map_mode) {
715
    case 0:
716
        break;
717
    case 1:
718
        if (addr >= 0x10000)
719
            return 0xff;
720
        addr += s->bank_offset;
721
        break;
722
    case 2:
723
        addr -= 0x10000;
724
        if (addr >= 0x8000)
725
            return 0xff;
726
        break;
727
    default:
728
    case 3:
729
        addr -= 0x18000;
730
        if (addr >= 0x8000)
731
            return 0xff;
732
        break;
733
    }
734

    
735
    if (s->sr[4] & 0x08) {
736
        /* chain 4 mode : simplest access */
737
        ret = s->vram_ptr[addr];
738
    } else if (s->gr[5] & 0x10) {
739
        /* odd/even mode (aka text mode mapping) */
740
        plane = (s->gr[4] & 2) | (addr & 1);
741
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
742
    } else {
743
        /* standard VGA latched access */
744
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
745

    
746
        if (!(s->gr[5] & 0x08)) {
747
            /* read mode 0 */
748
            plane = s->gr[4];
749
            ret = GET_PLANE(s->latch, plane);
750
        } else {
751
            /* read mode 1 */
752
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
753
            ret |= ret >> 16;
754
            ret |= ret >> 8;
755
            ret = (~ret) & 0xff;
756
        }
757
    }
758
    return ret;
759
}
760

    
761
static uint32_t vga_mem_readw(void *opaque, a_target_phys_addr addr)
762
{
763
    uint32_t v;
764
#ifdef TARGET_WORDS_BIGENDIAN
765
    v = vga_mem_readb(opaque, addr) << 8;
766
    v |= vga_mem_readb(opaque, addr + 1);
767
#else
768
    v = vga_mem_readb(opaque, addr);
769
    v |= vga_mem_readb(opaque, addr + 1) << 8;
770
#endif
771
    return v;
772
}
773

    
774
static uint32_t vga_mem_readl(void *opaque, a_target_phys_addr addr)
775
{
776
    uint32_t v;
777
#ifdef TARGET_WORDS_BIGENDIAN
778
    v = vga_mem_readb(opaque, addr) << 24;
779
    v |= vga_mem_readb(opaque, addr + 1) << 16;
780
    v |= vga_mem_readb(opaque, addr + 2) << 8;
781
    v |= vga_mem_readb(opaque, addr + 3);
782
#else
783
    v = vga_mem_readb(opaque, addr);
784
    v |= vga_mem_readb(opaque, addr + 1) << 8;
785
    v |= vga_mem_readb(opaque, addr + 2) << 16;
786
    v |= vga_mem_readb(opaque, addr + 3) << 24;
787
#endif
788
    return v;
789
}
790

    
791
/* called for accesses between 0xa0000 and 0xc0000 */
792
void vga_mem_writeb(void *opaque, a_target_phys_addr addr, uint32_t val)
793
{
794
    VGACommonState *s = opaque;
795
    int memory_map_mode, plane, write_mode, b, func_select, mask;
796
    uint32_t write_mask, bit_mask, set_mask;
797

    
798
#ifdef DEBUG_VGA_MEM
799
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
800
#endif
801
    /* convert to VGA memory offset */
802
    memory_map_mode = (s->gr[6] >> 2) & 3;
803
    addr &= 0x1ffff;
804
    switch(memory_map_mode) {
805
    case 0:
806
        break;
807
    case 1:
808
        if (addr >= 0x10000)
809
            return;
810
        addr += s->bank_offset;
811
        break;
812
    case 2:
813
        addr -= 0x10000;
814
        if (addr >= 0x8000)
815
            return;
816
        break;
817
    default:
818
    case 3:
819
        addr -= 0x18000;
820
        if (addr >= 0x8000)
821
            return;
822
        break;
823
    }
824

    
825
    if (s->sr[4] & 0x08) {
826
        /* chain 4 mode : simplest access */
827
        plane = addr & 3;
828
        mask = (1 << plane);
829
        if (s->sr[2] & mask) {
830
            s->vram_ptr[addr] = val;
831
#ifdef DEBUG_VGA_MEM
832
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
833
#endif
834
            s->plane_updated |= mask; /* only used to detect font change */
835
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
836
        }
837
    } else if (s->gr[5] & 0x10) {
838
        /* odd/even mode (aka text mode mapping) */
839
        plane = (s->gr[4] & 2) | (addr & 1);
840
        mask = (1 << plane);
841
        if (s->sr[2] & mask) {
842
            addr = ((addr & ~1) << 1) | plane;
843
            s->vram_ptr[addr] = val;
844
#ifdef DEBUG_VGA_MEM
845
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
846
#endif
847
            s->plane_updated |= mask; /* only used to detect font change */
848
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
849
        }
850
    } else {
851
        /* standard VGA latched access */
852
        write_mode = s->gr[5] & 3;
853
        switch(write_mode) {
854
        default:
855
        case 0:
856
            /* rotate */
857
            b = s->gr[3] & 7;
858
            val = ((val >> b) | (val << (8 - b))) & 0xff;
859
            val |= val << 8;
860
            val |= val << 16;
861

    
862
            /* apply set/reset mask */
863
            set_mask = mask16[s->gr[1]];
864
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
865
            bit_mask = s->gr[8];
866
            break;
867
        case 1:
868
            val = s->latch;
869
            goto do_write;
870
        case 2:
871
            val = mask16[val & 0x0f];
872
            bit_mask = s->gr[8];
873
            break;
874
        case 3:
875
            /* rotate */
876
            b = s->gr[3] & 7;
877
            val = (val >> b) | (val << (8 - b));
878

    
879
            bit_mask = s->gr[8] & val;
880
            val = mask16[s->gr[0]];
881
            break;
882
        }
883

    
884
        /* apply logical operation */
885
        func_select = s->gr[3] >> 3;
886
        switch(func_select) {
887
        case 0:
888
        default:
889
            /* nothing to do */
890
            break;
891
        case 1:
892
            /* and */
893
            val &= s->latch;
894
            break;
895
        case 2:
896
            /* or */
897
            val |= s->latch;
898
            break;
899
        case 3:
900
            /* xor */
901
            val ^= s->latch;
902
            break;
903
        }
904

    
905
        /* apply bit mask */
906
        bit_mask |= bit_mask << 8;
907
        bit_mask |= bit_mask << 16;
908
        val = (val & bit_mask) | (s->latch & ~bit_mask);
909

    
910
    do_write:
911
        /* mask data according to sr[2] */
912
        mask = s->sr[2];
913
        s->plane_updated |= mask; /* only used to detect font change */
914
        write_mask = mask16[mask];
915
        ((uint32_t *)s->vram_ptr)[addr] =
916
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
917
            (val & write_mask);
918
#ifdef DEBUG_VGA_MEM
919
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
920
               addr * 4, write_mask, val);
921
#endif
922
        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
923
    }
924
}
925

    
926
static void vga_mem_writew(void *opaque, a_target_phys_addr addr, uint32_t val)
927
{
928
#ifdef TARGET_WORDS_BIGENDIAN
929
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
930
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
931
#else
932
    vga_mem_writeb(opaque, addr, val & 0xff);
933
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
934
#endif
935
}
936

    
937
static void vga_mem_writel(void *opaque, a_target_phys_addr addr, uint32_t val)
938
{
939
#ifdef TARGET_WORDS_BIGENDIAN
940
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
941
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
942
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
943
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
944
#else
945
    vga_mem_writeb(opaque, addr, val & 0xff);
946
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
947
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
948
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
949
#endif
950
}
951

    
952
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
953
                             const uint8_t *font_ptr, int h,
954
                             uint32_t fgcol, uint32_t bgcol);
955
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
956
                                  const uint8_t *font_ptr, int h,
957
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
958
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
959
                                const uint8_t *s, int width);
960

    
961
#define DEPTH 8
962
#include "vga_template.h"
963

    
964
#define DEPTH 15
965
#include "vga_template.h"
966

    
967
#define BGR_FORMAT
968
#define DEPTH 15
969
#include "vga_template.h"
970

    
971
#define DEPTH 16
972
#include "vga_template.h"
973

    
974
#define BGR_FORMAT
975
#define DEPTH 16
976
#include "vga_template.h"
977

    
978
#define DEPTH 32
979
#include "vga_template.h"
980

    
981
#define BGR_FORMAT
982
#define DEPTH 32
983
#include "vga_template.h"
984

    
985
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
986
{
987
    unsigned int col;
988
    col = rgb_to_pixel8(r, g, b);
989
    col |= col << 8;
990
    col |= col << 16;
991
    return col;
992
}
993

    
994
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
995
{
996
    unsigned int col;
997
    col = rgb_to_pixel15(r, g, b);
998
    col |= col << 16;
999
    return col;
1000
}
1001

    
1002
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1003
                                          unsigned int b)
1004
{
1005
    unsigned int col;
1006
    col = rgb_to_pixel15bgr(r, g, b);
1007
    col |= col << 16;
1008
    return col;
1009
}
1010

    
1011
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1012
{
1013
    unsigned int col;
1014
    col = rgb_to_pixel16(r, g, b);
1015
    col |= col << 16;
1016
    return col;
1017
}
1018

    
1019
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1020
                                          unsigned int b)
1021
{
1022
    unsigned int col;
1023
    col = rgb_to_pixel16bgr(r, g, b);
1024
    col |= col << 16;
1025
    return col;
1026
}
1027

    
1028
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1029
{
1030
    unsigned int col;
1031
    col = rgb_to_pixel32(r, g, b);
1032
    return col;
1033
}
1034

    
1035
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1036
{
1037
    unsigned int col;
1038
    col = rgb_to_pixel32bgr(r, g, b);
1039
    return col;
1040
}
1041

    
1042
/* return true if the palette was modified */
1043
static int update_palette16(VGACommonState *s)
1044
{
1045
    int full_update, i;
1046
    uint32_t v, col, *palette;
1047

    
1048
    full_update = 0;
1049
    palette = s->last_palette;
1050
    for(i = 0; i < 16; i++) {
1051
        v = s->ar[i];
1052
        if (s->ar[0x10] & 0x80)
1053
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1054
        else
1055
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1056
        v = v * 3;
1057
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1058
                              c6_to_8(s->palette[v + 1]),
1059
                              c6_to_8(s->palette[v + 2]));
1060
        if (col != palette[i]) {
1061
            full_update = 1;
1062
            palette[i] = col;
1063
        }
1064
    }
1065
    return full_update;
1066
}
1067

    
1068
/* return true if the palette was modified */
1069
static int update_palette256(VGACommonState *s)
1070
{
1071
    int full_update, i;
1072
    uint32_t v, col, *palette;
1073

    
1074
    full_update = 0;
1075
    palette = s->last_palette;
1076
    v = 0;
1077
    for(i = 0; i < 256; i++) {
1078
        if (s->dac_8bit) {
1079
          col = s->rgb_to_pixel(s->palette[v],
1080
                                s->palette[v + 1],
1081
                                s->palette[v + 2]);
1082
        } else {
1083
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1084
                                c6_to_8(s->palette[v + 1]),
1085
                                c6_to_8(s->palette[v + 2]));
1086
        }
1087
        if (col != palette[i]) {
1088
            full_update = 1;
1089
            palette[i] = col;
1090
        }
1091
        v += 3;
1092
    }
1093
    return full_update;
1094
}
1095

    
1096
static void vga_get_offsets(VGACommonState *s,
1097
                            uint32_t *pline_offset,
1098
                            uint32_t *pstart_addr,
1099
                            uint32_t *pline_compare)
1100
{
1101
    uint32_t start_addr, line_offset, line_compare;
1102
#ifdef CONFIG_BOCHS_VBE
1103
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1104
        line_offset = s->vbe_line_offset;
1105
        start_addr = s->vbe_start_addr;
1106
        line_compare = 65535;
1107
    } else
1108
#endif
1109
    {
1110
        /* compute line_offset in bytes */
1111
        line_offset = s->cr[0x13];
1112
        line_offset <<= 3;
1113

    
1114
        /* starting address */
1115
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1116

    
1117
        /* line compare */
1118
        line_compare = s->cr[0x18] |
1119
            ((s->cr[0x07] & 0x10) << 4) |
1120
            ((s->cr[0x09] & 0x40) << 3);
1121
    }
1122
    *pline_offset = line_offset;
1123
    *pstart_addr = start_addr;
1124
    *pline_compare = line_compare;
1125
}
1126

    
1127
/* update start_addr and line_offset. Return TRUE if modified */
1128
static int update_basic_params(VGACommonState *s)
1129
{
1130
    int full_update;
1131
    uint32_t start_addr, line_offset, line_compare;
1132

    
1133
    full_update = 0;
1134

    
1135
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1136

    
1137
    if (line_offset != s->line_offset ||
1138
        start_addr != s->start_addr ||
1139
        line_compare != s->line_compare) {
1140
        s->line_offset = line_offset;
1141
        s->start_addr = start_addr;
1142
        s->line_compare = line_compare;
1143
        full_update = 1;
1144
    }
1145
    return full_update;
1146
}
1147

    
1148
#define NB_DEPTHS 7
1149

    
1150
static inline int get_depth_index(DisplayState *s)
1151
{
1152
    switch(ds_get_bits_per_pixel(s)) {
1153
    default:
1154
    case 8:
1155
        return 0;
1156
    case 15:
1157
        return 1;
1158
    case 16:
1159
        return 2;
1160
    case 32:
1161
        if (is_surface_bgr(s->surface))
1162
            return 4;
1163
        else
1164
            return 3;
1165
    }
1166
}
1167

    
1168
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1169
    vga_draw_glyph8_8,
1170
    vga_draw_glyph8_16,
1171
    vga_draw_glyph8_16,
1172
    vga_draw_glyph8_32,
1173
    vga_draw_glyph8_32,
1174
    vga_draw_glyph8_16,
1175
    vga_draw_glyph8_16,
1176
};
1177

    
1178
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1179
    vga_draw_glyph16_8,
1180
    vga_draw_glyph16_16,
1181
    vga_draw_glyph16_16,
1182
    vga_draw_glyph16_32,
1183
    vga_draw_glyph16_32,
1184
    vga_draw_glyph16_16,
1185
    vga_draw_glyph16_16,
1186
};
1187

    
1188
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1189
    vga_draw_glyph9_8,
1190
    vga_draw_glyph9_16,
1191
    vga_draw_glyph9_16,
1192
    vga_draw_glyph9_32,
1193
    vga_draw_glyph9_32,
1194
    vga_draw_glyph9_16,
1195
    vga_draw_glyph9_16,
1196
};
1197

    
1198
static const uint8_t cursor_glyph[32 * 4] = {
1199
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1200
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1201
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1202
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1203
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1204
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1205
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215
};
1216

    
1217
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1218
                                    int *pcwidth, int *pcheight)
1219
{
1220
    int width, cwidth, height, cheight;
1221

    
1222
    /* total width & height */
1223
    cheight = (s->cr[9] & 0x1f) + 1;
1224
    cwidth = 8;
1225
    if (!(s->sr[1] & 0x01))
1226
        cwidth = 9;
1227
    if (s->sr[1] & 0x08)
1228
        cwidth = 16; /* NOTE: no 18 pixel wide */
1229
    width = (s->cr[0x01] + 1);
1230
    if (s->cr[0x06] == 100) {
1231
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1232
        height = 100;
1233
    } else {
1234
        height = s->cr[0x12] |
1235
            ((s->cr[0x07] & 0x02) << 7) |
1236
            ((s->cr[0x07] & 0x40) << 3);
1237
        height = (height + 1) / cheight;
1238
    }
1239

    
1240
    *pwidth = width;
1241
    *pheight = height;
1242
    *pcwidth = cwidth;
1243
    *pcheight = cheight;
1244
}
1245

    
1246
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1247

    
1248
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1249
    rgb_to_pixel8_dup,
1250
    rgb_to_pixel15_dup,
1251
    rgb_to_pixel16_dup,
1252
    rgb_to_pixel32_dup,
1253
    rgb_to_pixel32bgr_dup,
1254
    rgb_to_pixel15bgr_dup,
1255
    rgb_to_pixel16bgr_dup,
1256
};
1257

    
1258
/*
1259
 * Text mode update
1260
 * Missing:
1261
 * - double scan
1262
 * - double width
1263
 * - underline
1264
 * - flashing
1265
 */
1266
static void vga_draw_text(VGACommonState *s, int full_update)
1267
{
1268
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1269
    int cx_min, cx_max, linesize, x_incr;
1270
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1271
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1272
    const uint8_t *font_ptr, *font_base[2];
1273
    int dup9, line_offset, depth_index;
1274
    uint32_t *palette;
1275
    uint32_t *ch_attr_ptr;
1276
    vga_draw_glyph8_func *vga_draw_glyph8;
1277
    vga_draw_glyph9_func *vga_draw_glyph9;
1278

    
1279
    /* compute font data address (in plane 2) */
1280
    v = s->sr[3];
1281
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1282
    if (offset != s->font_offsets[0]) {
1283
        s->font_offsets[0] = offset;
1284
        full_update = 1;
1285
    }
1286
    font_base[0] = s->vram_ptr + offset;
1287

    
1288
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1289
    font_base[1] = s->vram_ptr + offset;
1290
    if (offset != s->font_offsets[1]) {
1291
        s->font_offsets[1] = offset;
1292
        full_update = 1;
1293
    }
1294
    if (s->plane_updated & (1 << 2)) {
1295
        /* if the plane 2 was modified since the last display, it
1296
           indicates the font may have been modified */
1297
        s->plane_updated = 0;
1298
        full_update = 1;
1299
    }
1300
    full_update |= update_basic_params(s);
1301

    
1302
    line_offset = s->line_offset;
1303
    s1 = s->vram_ptr + (s->start_addr * 4);
1304

    
1305
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1306
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1307
    if ((height * width) > CH_ATTR_SIZE) {
1308
        /* better than nothing: exit if transient size is too big */
1309
        return;
1310
    }
1311

    
1312
    if (width != s->last_width || height != s->last_height ||
1313
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1314
        s->last_scr_width = width * cw;
1315
        s->last_scr_height = height * cheight;
1316
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1317
        s->last_depth = 0;
1318
        s->last_width = width;
1319
        s->last_height = height;
1320
        s->last_ch = cheight;
1321
        s->last_cw = cw;
1322
        full_update = 1;
1323
    }
1324
    s->rgb_to_pixel =
1325
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1326
    full_update |= update_palette16(s);
1327
    palette = s->last_palette;
1328
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1329

    
1330
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1331
    if (cursor_offset != s->cursor_offset ||
1332
        s->cr[0xa] != s->cursor_start ||
1333
        s->cr[0xb] != s->cursor_end) {
1334
      /* if the cursor position changed, we update the old and new
1335
         chars */
1336
        if (s->cursor_offset < CH_ATTR_SIZE)
1337
            s->last_ch_attr[s->cursor_offset] = -1;
1338
        if (cursor_offset < CH_ATTR_SIZE)
1339
            s->last_ch_attr[cursor_offset] = -1;
1340
        s->cursor_offset = cursor_offset;
1341
        s->cursor_start = s->cr[0xa];
1342
        s->cursor_end = s->cr[0xb];
1343
    }
1344
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1345

    
1346
    depth_index = get_depth_index(s->ds);
1347
    if (cw == 16)
1348
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1349
    else
1350
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1351
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1352

    
1353
    dest = ds_get_data(s->ds);
1354
    linesize = ds_get_linesize(s->ds);
1355
    ch_attr_ptr = s->last_ch_attr;
1356
    for(cy = 0; cy < height; cy++) {
1357
        d1 = dest;
1358
        src = s1;
1359
        cx_min = width;
1360
        cx_max = -1;
1361
        for(cx = 0; cx < width; cx++) {
1362
            ch_attr = *(uint16_t *)src;
1363
            if (full_update || ch_attr != *ch_attr_ptr) {
1364
                if (cx < cx_min)
1365
                    cx_min = cx;
1366
                if (cx > cx_max)
1367
                    cx_max = cx;
1368
                *ch_attr_ptr = ch_attr;
1369
#ifdef HOST_WORDS_BIGENDIAN
1370
                ch = ch_attr >> 8;
1371
                cattr = ch_attr & 0xff;
1372
#else
1373
                ch = ch_attr & 0xff;
1374
                cattr = ch_attr >> 8;
1375
#endif
1376
                font_ptr = font_base[(cattr >> 3) & 1];
1377
                font_ptr += 32 * 4 * ch;
1378
                bgcol = palette[cattr >> 4];
1379
                fgcol = palette[cattr & 0x0f];
1380
                if (cw != 9) {
1381
                    vga_draw_glyph8(d1, linesize,
1382
                                    font_ptr, cheight, fgcol, bgcol);
1383
                } else {
1384
                    dup9 = 0;
1385
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1386
                        dup9 = 1;
1387
                    vga_draw_glyph9(d1, linesize,
1388
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1389
                }
1390
                if (src == cursor_ptr &&
1391
                    !(s->cr[0x0a] & 0x20)) {
1392
                    int line_start, line_last, h;
1393
                    /* draw the cursor */
1394
                    line_start = s->cr[0x0a] & 0x1f;
1395
                    line_last = s->cr[0x0b] & 0x1f;
1396
                    /* XXX: check that */
1397
                    if (line_last > cheight - 1)
1398
                        line_last = cheight - 1;
1399
                    if (line_last >= line_start && line_start < cheight) {
1400
                        h = line_last - line_start + 1;
1401
                        d = d1 + linesize * line_start;
1402
                        if (cw != 9) {
1403
                            vga_draw_glyph8(d, linesize,
1404
                                            cursor_glyph, h, fgcol, bgcol);
1405
                        } else {
1406
                            vga_draw_glyph9(d, linesize,
1407
                                            cursor_glyph, h, fgcol, bgcol, 1);
1408
                        }
1409
                    }
1410
                }
1411
            }
1412
            d1 += x_incr;
1413
            src += 4;
1414
            ch_attr_ptr++;
1415
        }
1416
        if (cx_max != -1) {
1417
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1418
                       (cx_max - cx_min + 1) * cw, cheight);
1419
        }
1420
        dest += linesize * cheight;
1421
        s1 += line_offset;
1422
    }
1423
}
1424

    
1425
enum {
1426
    VGA_DRAW_LINE2,
1427
    VGA_DRAW_LINE2D2,
1428
    VGA_DRAW_LINE4,
1429
    VGA_DRAW_LINE4D2,
1430
    VGA_DRAW_LINE8D2,
1431
    VGA_DRAW_LINE8,
1432
    VGA_DRAW_LINE15,
1433
    VGA_DRAW_LINE16,
1434
    VGA_DRAW_LINE24,
1435
    VGA_DRAW_LINE32,
1436
    VGA_DRAW_LINE_NB,
1437
};
1438

    
1439
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1440
    vga_draw_line2_8,
1441
    vga_draw_line2_16,
1442
    vga_draw_line2_16,
1443
    vga_draw_line2_32,
1444
    vga_draw_line2_32,
1445
    vga_draw_line2_16,
1446
    vga_draw_line2_16,
1447

    
1448
    vga_draw_line2d2_8,
1449
    vga_draw_line2d2_16,
1450
    vga_draw_line2d2_16,
1451
    vga_draw_line2d2_32,
1452
    vga_draw_line2d2_32,
1453
    vga_draw_line2d2_16,
1454
    vga_draw_line2d2_16,
1455

    
1456
    vga_draw_line4_8,
1457
    vga_draw_line4_16,
1458
    vga_draw_line4_16,
1459
    vga_draw_line4_32,
1460
    vga_draw_line4_32,
1461
    vga_draw_line4_16,
1462
    vga_draw_line4_16,
1463

    
1464
    vga_draw_line4d2_8,
1465
    vga_draw_line4d2_16,
1466
    vga_draw_line4d2_16,
1467
    vga_draw_line4d2_32,
1468
    vga_draw_line4d2_32,
1469
    vga_draw_line4d2_16,
1470
    vga_draw_line4d2_16,
1471

    
1472
    vga_draw_line8d2_8,
1473
    vga_draw_line8d2_16,
1474
    vga_draw_line8d2_16,
1475
    vga_draw_line8d2_32,
1476
    vga_draw_line8d2_32,
1477
    vga_draw_line8d2_16,
1478
    vga_draw_line8d2_16,
1479

    
1480
    vga_draw_line8_8,
1481
    vga_draw_line8_16,
1482
    vga_draw_line8_16,
1483
    vga_draw_line8_32,
1484
    vga_draw_line8_32,
1485
    vga_draw_line8_16,
1486
    vga_draw_line8_16,
1487

    
1488
    vga_draw_line15_8,
1489
    vga_draw_line15_15,
1490
    vga_draw_line15_16,
1491
    vga_draw_line15_32,
1492
    vga_draw_line15_32bgr,
1493
    vga_draw_line15_15bgr,
1494
    vga_draw_line15_16bgr,
1495

    
1496
    vga_draw_line16_8,
1497
    vga_draw_line16_15,
1498
    vga_draw_line16_16,
1499
    vga_draw_line16_32,
1500
    vga_draw_line16_32bgr,
1501
    vga_draw_line16_15bgr,
1502
    vga_draw_line16_16bgr,
1503

    
1504
    vga_draw_line24_8,
1505
    vga_draw_line24_15,
1506
    vga_draw_line24_16,
1507
    vga_draw_line24_32,
1508
    vga_draw_line24_32bgr,
1509
    vga_draw_line24_15bgr,
1510
    vga_draw_line24_16bgr,
1511

    
1512
    vga_draw_line32_8,
1513
    vga_draw_line32_15,
1514
    vga_draw_line32_16,
1515
    vga_draw_line32_32,
1516
    vga_draw_line32_32bgr,
1517
    vga_draw_line32_15bgr,
1518
    vga_draw_line32_16bgr,
1519
};
1520

    
1521
static int vga_get_bpp(VGACommonState *s)
1522
{
1523
    int ret;
1524
#ifdef CONFIG_BOCHS_VBE
1525
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1526
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1527
    } else
1528
#endif
1529
    {
1530
        ret = 0;
1531
    }
1532
    return ret;
1533
}
1534

    
1535
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1536
{
1537
    int width, height;
1538

    
1539
#ifdef CONFIG_BOCHS_VBE
1540
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1541
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1542
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1543
    } else
1544
#endif
1545
    {
1546
        width = (s->cr[0x01] + 1) * 8;
1547
        height = s->cr[0x12] |
1548
            ((s->cr[0x07] & 0x02) << 7) |
1549
            ((s->cr[0x07] & 0x40) << 3);
1550
        height = (height + 1);
1551
    }
1552
    *pwidth = width;
1553
    *pheight = height;
1554
}
1555

    
1556
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1557
{
1558
    int y;
1559
    if (y1 >= VGA_MAX_HEIGHT)
1560
        return;
1561
    if (y2 >= VGA_MAX_HEIGHT)
1562
        y2 = VGA_MAX_HEIGHT;
1563
    for(y = y1; y < y2; y++) {
1564
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1565
    }
1566
}
1567

    
1568
static void vga_sync_dirty_bitmap(VGACommonState *s)
1569
{
1570
    if (s->map_addr)
1571
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1572

    
1573
    if (s->lfb_vram_mapped) {
1574
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1575
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1576
    }
1577
}
1578

    
1579
/*
1580
 * graphic modes
1581
 */
1582
static void vga_draw_graphic(VGACommonState *s, int full_update)
1583
{
1584
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1585
    int width, height, shift_control, line_offset, bwidth, bits;
1586
    a_ram_addr page0, page1, page_min, page_max;
1587
    int disp_width, multi_scan, multi_run;
1588
    uint8_t *d;
1589
    uint32_t v, addr1, addr;
1590
    vga_draw_line_func *vga_draw_line;
1591

    
1592
    full_update |= update_basic_params(s);
1593

    
1594
    if (!full_update)
1595
        vga_sync_dirty_bitmap(s);
1596

    
1597
    s->get_resolution(s, &width, &height);
1598
    disp_width = width;
1599

    
1600
    shift_control = (s->gr[0x05] >> 5) & 3;
1601
    double_scan = (s->cr[0x09] >> 7);
1602
    if (shift_control != 1) {
1603
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1604
    } else {
1605
        /* in CGA modes, multi_scan is ignored */
1606
        /* XXX: is it correct ? */
1607
        multi_scan = double_scan;
1608
    }
1609
    multi_run = multi_scan;
1610
    if (shift_control != s->shift_control ||
1611
        double_scan != s->double_scan) {
1612
        full_update = 1;
1613
        s->shift_control = shift_control;
1614
        s->double_scan = double_scan;
1615
    }
1616

    
1617
    if (shift_control == 0) {
1618
        if (s->sr[0x01] & 8) {
1619
            disp_width <<= 1;
1620
        }
1621
    } else if (shift_control == 1) {
1622
        if (s->sr[0x01] & 8) {
1623
            disp_width <<= 1;
1624
        }
1625
    }
1626

    
1627
    depth = s->get_bpp(s);
1628
    if (s->line_offset != s->last_line_offset ||
1629
        disp_width != s->last_width ||
1630
        height != s->last_height ||
1631
        s->last_depth != depth) {
1632
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1633
        if (depth == 16 || depth == 32) {
1634
#else
1635
        if (depth == 32) {
1636
#endif
1637
            qemu_free_displaysurface(s->ds);
1638
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1639
                    s->line_offset,
1640
                    s->vram_ptr + (s->start_addr * 4));
1641
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1642
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1643
#endif
1644
            dpy_resize(s->ds);
1645
        } else {
1646
            qemu_console_resize(s->ds, disp_width, height);
1647
        }
1648
        s->last_scr_width = disp_width;
1649
        s->last_scr_height = height;
1650
        s->last_width = disp_width;
1651
        s->last_height = height;
1652
        s->last_line_offset = s->line_offset;
1653
        s->last_depth = depth;
1654
        full_update = 1;
1655
    } else if (is_buffer_shared(s->ds->surface) &&
1656
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1657
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1658
        dpy_setdata(s->ds);
1659
    }
1660

    
1661
    s->rgb_to_pixel =
1662
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1663

    
1664
    if (shift_control == 0) {
1665
        full_update |= update_palette16(s);
1666
        if (s->sr[0x01] & 8) {
1667
            v = VGA_DRAW_LINE4D2;
1668
        } else {
1669
            v = VGA_DRAW_LINE4;
1670
        }
1671
        bits = 4;
1672
    } else if (shift_control == 1) {
1673
        full_update |= update_palette16(s);
1674
        if (s->sr[0x01] & 8) {
1675
            v = VGA_DRAW_LINE2D2;
1676
        } else {
1677
            v = VGA_DRAW_LINE2;
1678
        }
1679
        bits = 4;
1680
    } else {
1681
        switch(s->get_bpp(s)) {
1682
        default:
1683
        case 0:
1684
            full_update |= update_palette256(s);
1685
            v = VGA_DRAW_LINE8D2;
1686
            bits = 4;
1687
            break;
1688
        case 8:
1689
            full_update |= update_palette256(s);
1690
            v = VGA_DRAW_LINE8;
1691
            bits = 8;
1692
            break;
1693
        case 15:
1694
            v = VGA_DRAW_LINE15;
1695
            bits = 16;
1696
            break;
1697
        case 16:
1698
            v = VGA_DRAW_LINE16;
1699
            bits = 16;
1700
            break;
1701
        case 24:
1702
            v = VGA_DRAW_LINE24;
1703
            bits = 24;
1704
            break;
1705
        case 32:
1706
            v = VGA_DRAW_LINE32;
1707
            bits = 32;
1708
            break;
1709
        }
1710
    }
1711
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1712

    
1713
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1714
        s->cursor_invalidate(s);
1715

    
1716
    line_offset = s->line_offset;
1717
#if 0
1718
    printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1719
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1720
#endif
1721
    addr1 = (s->start_addr * 4);
1722
    bwidth = (width * bits + 7) / 8;
1723
    y_start = -1;
1724
    page_min = -1;
1725
    page_max = 0;
1726
    d = ds_get_data(s->ds);
1727
    linesize = ds_get_linesize(s->ds);
1728
    y1 = 0;
1729
    for(y = 0; y < height; y++) {
1730
        addr = addr1;
1731
        if (!(s->cr[0x17] & 1)) {
1732
            int shift;
1733
            /* CGA compatibility handling */
1734
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1735
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1736
        }
1737
        if (!(s->cr[0x17] & 2)) {
1738
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1739
        }
1740
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1741
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1742
        update = full_update |
1743
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1744
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1745
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1746
            /* if wide line, can use another page */
1747
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1748
                                                    VGA_DIRTY_FLAG);
1749
        }
1750
        /* explicit invalidation for the hardware cursor */
1751
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1752
        if (update) {
1753
            if (y_start < 0)
1754
                y_start = y;
1755
            if (page0 < page_min)
1756
                page_min = page0;
1757
            if (page1 > page_max)
1758
                page_max = page1;
1759
            if (!(is_buffer_shared(s->ds->surface))) {
1760
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1761
                if (s->cursor_draw_line)
1762
                    s->cursor_draw_line(s, d, y);
1763
            }
1764
        } else {
1765
            if (y_start >= 0) {
1766
                /* flush to display */
1767
                dpy_update(s->ds, 0, y_start,
1768
                           disp_width, y - y_start);
1769
                y_start = -1;
1770
            }
1771
        }
1772
        if (!multi_run) {
1773
            mask = (s->cr[0x17] & 3) ^ 3;
1774
            if ((y1 & mask) == mask)
1775
                addr1 += line_offset;
1776
            y1++;
1777
            multi_run = multi_scan;
1778
        } else {
1779
            multi_run--;
1780
        }
1781
        /* line compare acts on the displayed lines */
1782
        if (y == s->line_compare)
1783
            addr1 = 0;
1784
        d += linesize;
1785
    }
1786
    if (y_start >= 0) {
1787
        /* flush to display */
1788
        dpy_update(s->ds, 0, y_start,
1789
                   disp_width, y - y_start);
1790
    }
1791
    /* reset modified pages */
1792
    if (page_max >= page_min) {
1793
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1794
                                        VGA_DIRTY_FLAG);
1795
    }
1796
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1797
}
1798

    
1799
static void vga_draw_blank(VGACommonState *s, int full_update)
1800
{
1801
    int i, w, val;
1802
    uint8_t *d;
1803

    
1804
    if (!full_update)
1805
        return;
1806
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1807
        return;
1808

    
1809
    s->rgb_to_pixel =
1810
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1811
    if (ds_get_bits_per_pixel(s->ds) == 8)
1812
        val = s->rgb_to_pixel(0, 0, 0);
1813
    else
1814
        val = 0;
1815
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1816
    d = ds_get_data(s->ds);
1817
    for(i = 0; i < s->last_scr_height; i++) {
1818
        memset(d, val, w);
1819
        d += ds_get_linesize(s->ds);
1820
    }
1821
    dpy_update(s->ds, 0, 0,
1822
               s->last_scr_width, s->last_scr_height);
1823
}
1824

    
1825
#define GMODE_TEXT     0
1826
#define GMODE_GRAPH    1
1827
#define GMODE_BLANK 2
1828

    
1829
static void vga_update_display(void *opaque)
1830
{
1831
    VGACommonState *s = opaque;
1832
    int full_update, graphic_mode;
1833

    
1834
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1835
        /* nothing to do */
1836
    } else {
1837
        full_update = s->full_update;
1838
        s->full_update = 0;
1839
        if (!(s->ar_index & 0x20)) {
1840
            graphic_mode = GMODE_BLANK;
1841
        } else {
1842
            graphic_mode = s->gr[6] & 1;
1843
        }
1844
        if (graphic_mode != s->graphic_mode) {
1845
            s->graphic_mode = graphic_mode;
1846
            full_update = 1;
1847
        }
1848
        switch(graphic_mode) {
1849
        case GMODE_TEXT:
1850
            vga_draw_text(s, full_update);
1851
            break;
1852
        case GMODE_GRAPH:
1853
            vga_draw_graphic(s, full_update);
1854
            break;
1855
        case GMODE_BLANK:
1856
        default:
1857
            vga_draw_blank(s, full_update);
1858
            break;
1859
        }
1860
    }
1861
}
1862

    
1863
/* force a full display refresh */
1864
static void vga_invalidate_display(void *opaque)
1865
{
1866
    VGACommonState *s = opaque;
1867

    
1868
    s->full_update = 1;
1869
}
1870

    
1871
void vga_common_reset(VGACommonState *s)
1872
{
1873
    s->lfb_addr = 0;
1874
    s->lfb_end = 0;
1875
    s->map_addr = 0;
1876
    s->map_end = 0;
1877
    s->lfb_vram_mapped = 0;
1878
    s->bios_offset = 0;
1879
    s->bios_size = 0;
1880
    s->sr_index = 0;
1881
    memset(s->sr, '\0', sizeof(s->sr));
1882
    s->gr_index = 0;
1883
    memset(s->gr, '\0', sizeof(s->gr));
1884
    s->ar_index = 0;
1885
    memset(s->ar, '\0', sizeof(s->ar));
1886
    s->ar_flip_flop = 0;
1887
    s->cr_index = 0;
1888
    memset(s->cr, '\0', sizeof(s->cr));
1889
    s->msr = 0;
1890
    s->fcr = 0;
1891
    s->st00 = 0;
1892
    s->st01 = 0;
1893
    s->dac_state = 0;
1894
    s->dac_sub_index = 0;
1895
    s->dac_read_index = 0;
1896
    s->dac_write_index = 0;
1897
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1898
    s->dac_8bit = 0;
1899
    memset(s->palette, '\0', sizeof(s->palette));
1900
    s->bank_offset = 0;
1901
#ifdef CONFIG_BOCHS_VBE
1902
    s->vbe_index = 0;
1903
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1904
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1905
    s->vbe_start_addr = 0;
1906
    s->vbe_line_offset = 0;
1907
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1908
#endif
1909
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1910
    s->graphic_mode = -1; /* force full update */
1911
    s->shift_control = 0;
1912
    s->double_scan = 0;
1913
    s->line_offset = 0;
1914
    s->line_compare = 0;
1915
    s->start_addr = 0;
1916
    s->plane_updated = 0;
1917
    s->last_cw = 0;
1918
    s->last_ch = 0;
1919
    s->last_width = 0;
1920
    s->last_height = 0;
1921
    s->last_scr_width = 0;
1922
    s->last_scr_height = 0;
1923
    s->cursor_start = 0;
1924
    s->cursor_end = 0;
1925
    s->cursor_offset = 0;
1926
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1927
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1928
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1929
    switch (vga_retrace_method) {
1930
    case VGA_RETRACE_DUMB:
1931
        break;
1932
    case VGA_RETRACE_PRECISE:
1933
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1934
        break;
1935
    }
1936
}
1937

    
1938
static void vga_reset(void *opaque)
1939
{
1940
    VGACommonState *s =  opaque;
1941
    vga_common_reset(s);
1942
}
1943

    
1944
#define TEXTMODE_X(x)        ((x) % width)
1945
#define TEXTMODE_Y(x)        ((x) / width)
1946
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1947
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1948
/* relay text rendering to the display driver
1949
 * instead of doing a full vga_update_display() */
1950
static void vga_update_text(void *opaque, a_console_ch *chardata)
1951
{
1952
    VGACommonState *s =  opaque;
1953
    int graphic_mode, i, cursor_offset, cursor_visible;
1954
    int cw, cheight, width, height, size, c_min, c_max;
1955
    uint32_t *src;
1956
    a_console_ch *dst, val;
1957
    char msg_buffer[80];
1958
    int full_update = 0;
1959

    
1960
    if (!(s->ar_index & 0x20)) {
1961
        graphic_mode = GMODE_BLANK;
1962
    } else {
1963
        graphic_mode = s->gr[6] & 1;
1964
    }
1965
    if (graphic_mode != s->graphic_mode) {
1966
        s->graphic_mode = graphic_mode;
1967
        full_update = 1;
1968
    }
1969
    if (s->last_width == -1) {
1970
        s->last_width = 0;
1971
        full_update = 1;
1972
    }
1973

    
1974
    switch (graphic_mode) {
1975
    case GMODE_TEXT:
1976
        /* TODO: update palette */
1977
        full_update |= update_basic_params(s);
1978

    
1979
        /* total width & height */
1980
        cheight = (s->cr[9] & 0x1f) + 1;
1981
        cw = 8;
1982
        if (!(s->sr[1] & 0x01))
1983
            cw = 9;
1984
        if (s->sr[1] & 0x08)
1985
            cw = 16; /* NOTE: no 18 pixel wide */
1986
        width = (s->cr[0x01] + 1);
1987
        if (s->cr[0x06] == 100) {
1988
            /* ugly hack for CGA 160x100x16 - explain me the logic */
1989
            height = 100;
1990
        } else {
1991
            height = s->cr[0x12] | 
1992
                ((s->cr[0x07] & 0x02) << 7) | 
1993
                ((s->cr[0x07] & 0x40) << 3);
1994
            height = (height + 1) / cheight;
1995
        }
1996

    
1997
        size = (height * width);
1998
        if (size > CH_ATTR_SIZE) {
1999
            if (!full_update)
2000
                return;
2001

    
2002
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2003
                     width, height);
2004
            break;
2005
        }
2006

    
2007
        if (width != s->last_width || height != s->last_height ||
2008
            cw != s->last_cw || cheight != s->last_ch) {
2009
            s->last_scr_width = width * cw;
2010
            s->last_scr_height = height * cheight;
2011
            s->ds->surface->width = width;
2012
            s->ds->surface->height = height;
2013
            dpy_resize(s->ds);
2014
            s->last_width = width;
2015
            s->last_height = height;
2016
            s->last_ch = cheight;
2017
            s->last_cw = cw;
2018
            full_update = 1;
2019
        }
2020

    
2021
        /* Update "hardware" cursor */
2022
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2023
        if (cursor_offset != s->cursor_offset ||
2024
            s->cr[0xa] != s->cursor_start ||
2025
            s->cr[0xb] != s->cursor_end || full_update) {
2026
            cursor_visible = !(s->cr[0xa] & 0x20);
2027
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2028
                dpy_cursor(s->ds,
2029
                           TEXTMODE_X(cursor_offset),
2030
                           TEXTMODE_Y(cursor_offset));
2031
            else
2032
                dpy_cursor(s->ds, -1, -1);
2033
            s->cursor_offset = cursor_offset;
2034
            s->cursor_start = s->cr[0xa];
2035
            s->cursor_end = s->cr[0xb];
2036
        }
2037

    
2038
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2039
        dst = chardata;
2040

    
2041
        if (full_update) {
2042
            for (i = 0; i < size; src ++, dst ++, i ++)
2043
                console_write_ch(dst, VMEM2CHTYPE(*src));
2044

    
2045
            dpy_update(s->ds, 0, 0, width, height);
2046
        } else {
2047
            c_max = 0;
2048

    
2049
            for (i = 0; i < size; src ++, dst ++, i ++) {
2050
                console_write_ch(&val, VMEM2CHTYPE(*src));
2051
                if (*dst != val) {
2052
                    *dst = val;
2053
                    c_max = i;
2054
                    break;
2055
                }
2056
            }
2057
            c_min = i;
2058
            for (; i < size; src ++, dst ++, i ++) {
2059
                console_write_ch(&val, VMEM2CHTYPE(*src));
2060
                if (*dst != val) {
2061
                    *dst = val;
2062
                    c_max = i;
2063
                }
2064
            }
2065

    
2066
            if (c_min <= c_max) {
2067
                i = TEXTMODE_Y(c_min);
2068
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2069
            }
2070
        }
2071

    
2072
        return;
2073
    case GMODE_GRAPH:
2074
        if (!full_update)
2075
            return;
2076

    
2077
        s->get_resolution(s, &width, &height);
2078
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2079
                 width, height);
2080
        break;
2081
    case GMODE_BLANK:
2082
    default:
2083
        if (!full_update)
2084
            return;
2085

    
2086
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2087
        break;
2088
    }
2089

    
2090
    /* Display a message */
2091
    s->last_width = 60;
2092
    s->last_height = height = 3;
2093
    dpy_cursor(s->ds, -1, -1);
2094
    s->ds->surface->width = s->last_width;
2095
    s->ds->surface->height = height;
2096
    dpy_resize(s->ds);
2097

    
2098
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2099
        console_write_ch(dst ++, ' ');
2100

    
2101
    size = strlen(msg_buffer);
2102
    width = (s->last_width - size) / 2;
2103
    dst = chardata + s->last_width + width;
2104
    for (i = 0; i < size; i ++)
2105
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2106

    
2107
    dpy_update(s->ds, 0, 0, s->last_width, height);
2108
}
2109

    
2110
CPUReadMemoryFunc * const vga_mem_read[3] = {
2111
    vga_mem_readb,
2112
    vga_mem_readw,
2113
    vga_mem_readl,
2114
};
2115

    
2116
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2117
    vga_mem_writeb,
2118
    vga_mem_writew,
2119
    vga_mem_writel,
2120
};
2121

    
2122
void vga_common_save(QEMUFile *f, void *opaque)
2123
{
2124
    VGACommonState *s = opaque;
2125
    int i;
2126

    
2127
    qemu_put_be32s(f, &s->latch);
2128
    qemu_put_8s(f, &s->sr_index);
2129
    qemu_put_buffer(f, s->sr, 8);
2130
    qemu_put_8s(f, &s->gr_index);
2131
    qemu_put_buffer(f, s->gr, 16);
2132
    qemu_put_8s(f, &s->ar_index);
2133
    qemu_put_buffer(f, s->ar, 21);
2134
    qemu_put_be32(f, s->ar_flip_flop);
2135
    qemu_put_8s(f, &s->cr_index);
2136
    qemu_put_buffer(f, s->cr, 256);
2137
    qemu_put_8s(f, &s->msr);
2138
    qemu_put_8s(f, &s->fcr);
2139
    qemu_put_byte(f, s->st00);
2140
    qemu_put_8s(f, &s->st01);
2141

    
2142
    qemu_put_8s(f, &s->dac_state);
2143
    qemu_put_8s(f, &s->dac_sub_index);
2144
    qemu_put_8s(f, &s->dac_read_index);
2145
    qemu_put_8s(f, &s->dac_write_index);
2146
    qemu_put_buffer(f, s->dac_cache, 3);
2147
    qemu_put_buffer(f, s->palette, 768);
2148

    
2149
    qemu_put_be32(f, s->bank_offset);
2150
#ifdef CONFIG_BOCHS_VBE
2151
    qemu_put_byte(f, 1);
2152
    qemu_put_be16s(f, &s->vbe_index);
2153
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2154
        qemu_put_be16s(f, &s->vbe_regs[i]);
2155
    qemu_put_be32s(f, &s->vbe_start_addr);
2156
    qemu_put_be32s(f, &s->vbe_line_offset);
2157
    qemu_put_be32s(f, &s->vbe_bank_mask);
2158
#else
2159
    qemu_put_byte(f, 0);
2160
#endif
2161
}
2162

    
2163
int vga_common_load(QEMUFile *f, void *opaque, int version_id)
2164
{
2165
    VGACommonState *s = opaque;
2166
    int is_vbe, i;
2167

    
2168
    if (version_id > 2)
2169
        return -EINVAL;
2170

    
2171
    qemu_get_be32s(f, &s->latch);
2172
    qemu_get_8s(f, &s->sr_index);
2173
    qemu_get_buffer(f, s->sr, 8);
2174
    qemu_get_8s(f, &s->gr_index);
2175
    qemu_get_buffer(f, s->gr, 16);
2176
    qemu_get_8s(f, &s->ar_index);
2177
    qemu_get_buffer(f, s->ar, 21);
2178
    s->ar_flip_flop=qemu_get_be32(f);
2179
    qemu_get_8s(f, &s->cr_index);
2180
    qemu_get_buffer(f, s->cr, 256);
2181
    qemu_get_8s(f, &s->msr);
2182
    qemu_get_8s(f, &s->fcr);
2183
    qemu_get_8s(f, &s->st00);
2184
    qemu_get_8s(f, &s->st01);
2185

    
2186
    qemu_get_8s(f, &s->dac_state);
2187
    qemu_get_8s(f, &s->dac_sub_index);
2188
    qemu_get_8s(f, &s->dac_read_index);
2189
    qemu_get_8s(f, &s->dac_write_index);
2190
    qemu_get_buffer(f, s->dac_cache, 3);
2191
    qemu_get_buffer(f, s->palette, 768);
2192

    
2193
    s->bank_offset=qemu_get_be32(f);
2194
    is_vbe = qemu_get_byte(f);
2195
#ifdef CONFIG_BOCHS_VBE
2196
    if (!is_vbe)
2197
        return -EINVAL;
2198
    qemu_get_be16s(f, &s->vbe_index);
2199
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2200
        qemu_get_be16s(f, &s->vbe_regs[i]);
2201
    qemu_get_be32s(f, &s->vbe_start_addr);
2202
    qemu_get_be32s(f, &s->vbe_line_offset);
2203
    qemu_get_be32s(f, &s->vbe_bank_mask);
2204
#else
2205
    if (is_vbe)
2206
        return -EINVAL;
2207
#endif
2208

    
2209
    /* force refresh */
2210
    s->graphic_mode = -1;
2211
    return 0;
2212
}
2213

    
2214
void vga_common_init(VGACommonState *s, int vga_ram_size)
2215
{
2216
    int i, j, v, b;
2217

    
2218
    for(i = 0;i < 256; i++) {
2219
        v = 0;
2220
        for(j = 0; j < 8; j++) {
2221
            v |= ((i >> j) & 1) << (j * 4);
2222
        }
2223
        expand4[i] = v;
2224

    
2225
        v = 0;
2226
        for(j = 0; j < 4; j++) {
2227
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2228
        }
2229
        expand2[i] = v;
2230
    }
2231
    for(i = 0; i < 16; i++) {
2232
        v = 0;
2233
        for(j = 0; j < 4; j++) {
2234
            b = ((i >> j) & 1);
2235
            v |= b << (2 * j);
2236
            v |= b << (2 * j + 1);
2237
        }
2238
        expand4to8[i] = v;
2239
    }
2240

    
2241
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2242
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2243
    s->vram_size = vga_ram_size;
2244
    s->get_bpp = vga_get_bpp;
2245
    s->get_offsets = vga_get_offsets;
2246
    s->get_resolution = vga_get_resolution;
2247
    s->update = vga_update_display;
2248
    s->invalidate = vga_invalidate_display;
2249
    s->screen_dump = vga_screen_dump;
2250
    s->text_update = vga_update_text;
2251
    switch (vga_retrace_method) {
2252
    case VGA_RETRACE_DUMB:
2253
        s->retrace = vga_dumb_retrace;
2254
        s->update_retrace_info = vga_dumb_update_retrace_info;
2255
        break;
2256

    
2257
    case VGA_RETRACE_PRECISE:
2258
        s->retrace = vga_precise_retrace;
2259
        s->update_retrace_info = vga_precise_update_retrace_info;
2260
        break;
2261
    }
2262
    vga_reset(s);
2263
}
2264

    
2265
/* used by both ISA and PCI */
2266
void vga_init(VGACommonState *s)
2267
{
2268
    int vga_io_memory;
2269

    
2270
    qemu_register_reset(vga_reset, s);
2271

    
2272
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2273

    
2274
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2275
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2276
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2277
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2278

    
2279
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2280

    
2281
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2282
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2283
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2284
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2285
    s->bank_offset = 0;
2286

    
2287
#ifdef CONFIG_BOCHS_VBE
2288
#if defined (TARGET_I386)
2289
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2290
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2291

    
2292
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2293
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2294

    
2295
    /* old Bochs IO ports */
2296
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2297
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2298

    
2299
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2300
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2301
#else
2302
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2303
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2304

    
2305
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2306
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2307
#endif
2308
#endif /* CONFIG_BOCHS_VBE */
2309

    
2310
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2311
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2312
                                 vga_io_memory);
2313
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2314
}
2315

    
2316
/********************************************************/
2317
/* vga screen dump */
2318

    
2319
static void vga_save_dpy_update(DisplayState *ds,
2320
                                int x, int y, int w, int h)
2321
{
2322
    if (screen_dump_filename) {
2323
        ppm_save(screen_dump_filename, ds->surface);
2324
        screen_dump_filename = NULL;
2325
    }
2326
}
2327

    
2328
static void vga_save_dpy_resize(DisplayState *s)
2329
{
2330
}
2331

    
2332
static void vga_save_dpy_refresh(DisplayState *s)
2333
{
2334
}
2335

    
2336
int ppm_save(const char *filename, struct DisplaySurface *ds)
2337
{
2338
    FILE *f;
2339
    uint8_t *d, *d1;
2340
    uint32_t v;
2341
    int y, x;
2342
    uint8_t r, g, b;
2343

    
2344
    f = fopen(filename, "wb");
2345
    if (!f)
2346
        return -1;
2347
    fprintf(f, "P6\n%d %d\n%d\n",
2348
            ds->width, ds->height, 255);
2349
    d1 = ds->data;
2350
    for(y = 0; y < ds->height; y++) {
2351
        d = d1;
2352
        for(x = 0; x < ds->width; x++) {
2353
            if (ds->pf.bits_per_pixel == 32)
2354
                v = *(uint32_t *)d;
2355
            else
2356
                v = (uint32_t) (*(uint16_t *)d);
2357
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2358
                (ds->pf.rmax + 1);
2359
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2360
                (ds->pf.gmax + 1);
2361
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2362
                (ds->pf.bmax + 1);
2363
            fputc(r, f);
2364
            fputc(g, f);
2365
            fputc(b, f);
2366
            d += ds->pf.bytes_per_pixel;
2367
        }
2368
        d1 += ds->linesize;
2369
    }
2370
    fclose(f);
2371
    return 0;
2372
}
2373

    
2374
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2375
{
2376
    DisplayChangeListener *dcl;
2377

    
2378
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2379
    dcl->dpy_update = vga_save_dpy_update;
2380
    dcl->dpy_resize = vga_save_dpy_resize;
2381
    dcl->dpy_refresh = vga_save_dpy_refresh;
2382
    register_displaychangelistener(ds, dcl);
2383
    return dcl;
2384
}
2385

    
2386
/* save the vga display in a PPM image even if no display is
2387
   available */
2388
static void vga_screen_dump(void *opaque, const char *filename)
2389
{
2390
    VGACommonState *s = opaque;
2391

    
2392
    if (!screen_dump_dcl)
2393
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2394

    
2395
    screen_dump_filename = (char *)filename;
2396
    vga_invalidate_display(s);
2397
    vga_hw_update();
2398
}
2399