Statistics
| Branch: | Revision:

root / hw / vga.c @ a46007a0

History | View | Annotate | Download (67.5 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
typedef VGACommonState VGAState;
152

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

    
157
static void vga_dumb_update_retrace_info(VGAState *s)
158
{
159
    (void) s;
160
}
161

    
162
static void vga_precise_update_retrace_info(VGAState *s)
163
{
164
    int htotal_chars;
165
    int hretr_start_char;
166
    int hretr_skew_chars;
167
    int hretr_end_char;
168

    
169
    int vtotal_lines;
170
    int vretr_start_line;
171
    int vretr_end_line;
172

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

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

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

    
193

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

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

    
201
    chars_per_sec = clk_hz[clock_sel] / dots;
202

    
203
    htotal_chars <<= clocking_mode;
204

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

    
212
    r->vstart = vretr_start_line;
213
    r->vend = r->vstart + vretr_end_line + 1;
214

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

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

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

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

    
262
        cur_tick = qemu_get_clock(vm_clock);
263

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

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

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

    
282
static uint8_t vga_dumb_retrace(VGAState *s)
283
{
284
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
285
}
286

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

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

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

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

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

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

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

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

    
521
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
522
{
523
    VGAState *s = opaque;
524
    uint32_t val;
525

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

    
555
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
556
{
557
    VGAState *s = opaque;
558
    s->vbe_index = val;
559
}
560

    
561
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
562
{
563
    VGAState *s = opaque;
564

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

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

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

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

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

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

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

    
706
/* called for accesses between 0xa0000 and 0xc0000 */
707
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
708
{
709
    VGAState *s = opaque;
710
    int memory_map_mode, plane;
711
    uint32_t ret;
712

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
963
#define DEPTH 8
964
#include "vga_template.h"
965

    
966
#define DEPTH 15
967
#include "vga_template.h"
968

    
969
#define BGR_FORMAT
970
#define DEPTH 15
971
#include "vga_template.h"
972

    
973
#define DEPTH 16
974
#include "vga_template.h"
975

    
976
#define BGR_FORMAT
977
#define DEPTH 16
978
#include "vga_template.h"
979

    
980
#define DEPTH 32
981
#include "vga_template.h"
982

    
983
#define BGR_FORMAT
984
#define DEPTH 32
985
#include "vga_template.h"
986

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1135
    full_update = 0;
1136

    
1137
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1138

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

    
1150
#define NB_DEPTHS 7
1151

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

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

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

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

    
1200
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217
};
1218

    
1219
static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1220
                                    int *pcwidth, int *pcheight)
1221
{
1222
    int width, cwidth, height, cheight;
1223

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

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

    
1248
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1249

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

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

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

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

    
1304
    line_offset = s->line_offset;
1305
    s1 = s->vram_ptr + (s->start_addr * 4);
1306

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

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

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

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

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

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

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

    
1450
    vga_draw_line2d2_8,
1451
    vga_draw_line2d2_16,
1452
    vga_draw_line2d2_16,
1453
    vga_draw_line2d2_32,
1454
    vga_draw_line2d2_32,
1455
    vga_draw_line2d2_16,
1456
    vga_draw_line2d2_16,
1457

    
1458
    vga_draw_line4_8,
1459
    vga_draw_line4_16,
1460
    vga_draw_line4_16,
1461
    vga_draw_line4_32,
1462
    vga_draw_line4_32,
1463
    vga_draw_line4_16,
1464
    vga_draw_line4_16,
1465

    
1466
    vga_draw_line4d2_8,
1467
    vga_draw_line4d2_16,
1468
    vga_draw_line4d2_16,
1469
    vga_draw_line4d2_32,
1470
    vga_draw_line4d2_32,
1471
    vga_draw_line4d2_16,
1472
    vga_draw_line4d2_16,
1473

    
1474
    vga_draw_line8d2_8,
1475
    vga_draw_line8d2_16,
1476
    vga_draw_line8d2_16,
1477
    vga_draw_line8d2_32,
1478
    vga_draw_line8d2_32,
1479
    vga_draw_line8d2_16,
1480
    vga_draw_line8d2_16,
1481

    
1482
    vga_draw_line8_8,
1483
    vga_draw_line8_16,
1484
    vga_draw_line8_16,
1485
    vga_draw_line8_32,
1486
    vga_draw_line8_32,
1487
    vga_draw_line8_16,
1488
    vga_draw_line8_16,
1489

    
1490
    vga_draw_line15_8,
1491
    vga_draw_line15_15,
1492
    vga_draw_line15_16,
1493
    vga_draw_line15_32,
1494
    vga_draw_line15_32bgr,
1495
    vga_draw_line15_15bgr,
1496
    vga_draw_line15_16bgr,
1497

    
1498
    vga_draw_line16_8,
1499
    vga_draw_line16_15,
1500
    vga_draw_line16_16,
1501
    vga_draw_line16_32,
1502
    vga_draw_line16_32bgr,
1503
    vga_draw_line16_15bgr,
1504
    vga_draw_line16_16bgr,
1505

    
1506
    vga_draw_line24_8,
1507
    vga_draw_line24_15,
1508
    vga_draw_line24_16,
1509
    vga_draw_line24_32,
1510
    vga_draw_line24_32bgr,
1511
    vga_draw_line24_15bgr,
1512
    vga_draw_line24_16bgr,
1513

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

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

    
1537
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1538
{
1539
    int width, height;
1540

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

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

    
1570
static void vga_sync_dirty_bitmap(VGAState *s)
1571
{
1572
    if (s->map_addr)
1573
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1574

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

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

    
1594
    full_update |= update_basic_params(s);
1595

    
1596
    if (!full_update)
1597
        vga_sync_dirty_bitmap(s);
1598

    
1599
    s->get_resolution(s, &width, &height);
1600
    disp_width = width;
1601

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

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

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

    
1663
    s->rgb_to_pixel =
1664
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1665

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

    
1715
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1716
        s->cursor_invalidate(s);
1717

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

    
1801
static void vga_draw_blank(VGAState *s, int full_update)
1802
{
1803
    int i, w, val;
1804
    uint8_t *d;
1805

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

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

    
1827
#define GMODE_TEXT     0
1828
#define GMODE_GRAPH    1
1829
#define GMODE_BLANK 2
1830

    
1831
static void vga_update_display(void *opaque)
1832
{
1833
    VGAState *s = opaque;
1834
    int full_update, graphic_mode;
1835

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

    
1865
/* force a full display refresh */
1866
static void vga_invalidate_display(void *opaque)
1867
{
1868
    VGAState *s = opaque;
1869

    
1870
    s->full_update = 1;
1871
}
1872

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

    
1940
static void vga_reset(void *opaque)
1941
{
1942
    VGAState *s =  opaque;
1943
    vga_common_reset(s);
1944
}
1945

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2074
        return;
2075
    case GMODE_GRAPH:
2076
        if (!full_update)
2077
            return;
2078

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

    
2088
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2089
        break;
2090
    }
2091

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

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

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

    
2109
    dpy_update(s->ds, 0, 0, s->last_width, height);
2110
}
2111

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

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

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

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

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

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

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

    
2170
    if (version_id > 2)
2171
        return -EINVAL;
2172

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

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

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

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

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

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

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

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

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

    
2267
/* used by both ISA and PCI */
2268
void vga_init(VGAState *s)
2269
{
2270
    int vga_io_memory;
2271

    
2272
    qemu_register_reset(vga_reset, s);
2273

    
2274
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2275

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

    
2281
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2282

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

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

    
2294
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2295
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2296

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

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

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

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

    
2318
/********************************************************/
2319
/* vga screen dump */
2320

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

    
2330
static void vga_save_dpy_resize(DisplayState *s)
2331
{
2332
}
2333

    
2334
static void vga_save_dpy_refresh(DisplayState *s)
2335
{
2336
}
2337

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

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

    
2376
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2377
{
2378
    DisplayChangeListener *dcl;
2379

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

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

    
2394
    if (!screen_dump_dcl)
2395
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2396

    
2397
    screen_dump_filename = (char *)filename;
2398
    vga_invalidate_display(s);
2399
    vga_hw_update();
2400
}
2401