Statistics
| Branch: | Revision:

root / hw / vga.c @ e00e365e

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
#include "kvm.h"
32

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

    
37
//#define DEBUG_BOCHS_VBE
38

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

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

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

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

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

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

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

    
114
#undef PAT
115

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

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

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

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

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

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

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

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

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

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

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

    
192

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

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

    
200
    chars_per_sec = clk_hz[clock_sel] / dots;
201

    
202
    htotal_chars <<= clocking_mode;
203

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

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

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

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

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

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

    
261
        cur_tick = qemu_get_clock(vm_clock);
262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1134
    full_update = 0;
1135

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

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

    
1149
#define NB_DEPTHS 7
1150

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1303
    line_offset = s->line_offset;
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
    line = 0;
1357
    offset = s->start_addr * 4;
1358
    for(cy = 0; cy < height; cy++) {
1359
        d1 = dest;
1360
        src = s->vram_ptr + offset;
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
        line1 = line + cheight;
1424
        offset += line_offset;
1425
        if (line < s->line_compare && line1 >= s->line_compare) {
1426
            offset = 0;
1427
        }
1428
        line = line1;
1429
    }
1430
}
1431

    
1432
enum {
1433
    VGA_DRAW_LINE2,
1434
    VGA_DRAW_LINE2D2,
1435
    VGA_DRAW_LINE4,
1436
    VGA_DRAW_LINE4D2,
1437
    VGA_DRAW_LINE8D2,
1438
    VGA_DRAW_LINE8,
1439
    VGA_DRAW_LINE15,
1440
    VGA_DRAW_LINE16,
1441
    VGA_DRAW_LINE24,
1442
    VGA_DRAW_LINE32,
1443
    VGA_DRAW_LINE_NB,
1444
};
1445

    
1446
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1447
    vga_draw_line2_8,
1448
    vga_draw_line2_16,
1449
    vga_draw_line2_16,
1450
    vga_draw_line2_32,
1451
    vga_draw_line2_32,
1452
    vga_draw_line2_16,
1453
    vga_draw_line2_16,
1454

    
1455
    vga_draw_line2d2_8,
1456
    vga_draw_line2d2_16,
1457
    vga_draw_line2d2_16,
1458
    vga_draw_line2d2_32,
1459
    vga_draw_line2d2_32,
1460
    vga_draw_line2d2_16,
1461
    vga_draw_line2d2_16,
1462

    
1463
    vga_draw_line4_8,
1464
    vga_draw_line4_16,
1465
    vga_draw_line4_16,
1466
    vga_draw_line4_32,
1467
    vga_draw_line4_32,
1468
    vga_draw_line4_16,
1469
    vga_draw_line4_16,
1470

    
1471
    vga_draw_line4d2_8,
1472
    vga_draw_line4d2_16,
1473
    vga_draw_line4d2_16,
1474
    vga_draw_line4d2_32,
1475
    vga_draw_line4d2_32,
1476
    vga_draw_line4d2_16,
1477
    vga_draw_line4d2_16,
1478

    
1479
    vga_draw_line8d2_8,
1480
    vga_draw_line8d2_16,
1481
    vga_draw_line8d2_16,
1482
    vga_draw_line8d2_32,
1483
    vga_draw_line8d2_32,
1484
    vga_draw_line8d2_16,
1485
    vga_draw_line8d2_16,
1486

    
1487
    vga_draw_line8_8,
1488
    vga_draw_line8_16,
1489
    vga_draw_line8_16,
1490
    vga_draw_line8_32,
1491
    vga_draw_line8_32,
1492
    vga_draw_line8_16,
1493
    vga_draw_line8_16,
1494

    
1495
    vga_draw_line15_8,
1496
    vga_draw_line15_15,
1497
    vga_draw_line15_16,
1498
    vga_draw_line15_32,
1499
    vga_draw_line15_32bgr,
1500
    vga_draw_line15_15bgr,
1501
    vga_draw_line15_16bgr,
1502

    
1503
    vga_draw_line16_8,
1504
    vga_draw_line16_15,
1505
    vga_draw_line16_16,
1506
    vga_draw_line16_32,
1507
    vga_draw_line16_32bgr,
1508
    vga_draw_line16_15bgr,
1509
    vga_draw_line16_16bgr,
1510

    
1511
    vga_draw_line24_8,
1512
    vga_draw_line24_15,
1513
    vga_draw_line24_16,
1514
    vga_draw_line24_32,
1515
    vga_draw_line24_32bgr,
1516
    vga_draw_line24_15bgr,
1517
    vga_draw_line24_16bgr,
1518

    
1519
    vga_draw_line32_8,
1520
    vga_draw_line32_15,
1521
    vga_draw_line32_16,
1522
    vga_draw_line32_32,
1523
    vga_draw_line32_32bgr,
1524
    vga_draw_line32_15bgr,
1525
    vga_draw_line32_16bgr,
1526
};
1527

    
1528
static int vga_get_bpp(VGACommonState *s)
1529
{
1530
    int ret;
1531
#ifdef CONFIG_BOCHS_VBE
1532
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1533
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1534
    } else
1535
#endif
1536
    {
1537
        ret = 0;
1538
    }
1539
    return ret;
1540
}
1541

    
1542
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1543
{
1544
    int width, height;
1545

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

    
1563
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1564
{
1565
    int y;
1566
    if (y1 >= VGA_MAX_HEIGHT)
1567
        return;
1568
    if (y2 >= VGA_MAX_HEIGHT)
1569
        y2 = VGA_MAX_HEIGHT;
1570
    for(y = y1; y < y2; y++) {
1571
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1572
    }
1573
}
1574

    
1575
static void vga_sync_dirty_bitmap(VGACommonState *s)
1576
{
1577
    if (s->map_addr)
1578
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1579

    
1580
    if (s->lfb_vram_mapped) {
1581
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1582
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1583
    }
1584
}
1585

    
1586
void vga_dirty_log_start(VGACommonState *s)
1587
{
1588
    if (kvm_enabled() && s->map_addr)
1589
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1590

    
1591
    if (kvm_enabled() && s->lfb_vram_mapped) {
1592
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1593
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1594
    }
1595
}
1596

    
1597
/*
1598
 * graphic modes
1599
 */
1600
static void vga_draw_graphic(VGACommonState *s, int full_update)
1601
{
1602
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1603
    int width, height, shift_control, line_offset, bwidth, bits;
1604
    ram_addr_t page0, page1, page_min, page_max;
1605
    int disp_width, multi_scan, multi_run;
1606
    uint8_t *d;
1607
    uint32_t v, addr1, addr;
1608
    vga_draw_line_func *vga_draw_line;
1609

    
1610
    full_update |= update_basic_params(s);
1611

    
1612
    if (!full_update)
1613
        vga_sync_dirty_bitmap(s);
1614

    
1615
    s->get_resolution(s, &width, &height);
1616
    disp_width = width;
1617

    
1618
    shift_control = (s->gr[0x05] >> 5) & 3;
1619
    double_scan = (s->cr[0x09] >> 7);
1620
    if (shift_control != 1) {
1621
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1622
    } else {
1623
        /* in CGA modes, multi_scan is ignored */
1624
        /* XXX: is it correct ? */
1625
        multi_scan = double_scan;
1626
    }
1627
    multi_run = multi_scan;
1628
    if (shift_control != s->shift_control ||
1629
        double_scan != s->double_scan) {
1630
        full_update = 1;
1631
        s->shift_control = shift_control;
1632
        s->double_scan = double_scan;
1633
    }
1634

    
1635
    if (shift_control == 0) {
1636
        if (s->sr[0x01] & 8) {
1637
            disp_width <<= 1;
1638
        }
1639
    } else if (shift_control == 1) {
1640
        if (s->sr[0x01] & 8) {
1641
            disp_width <<= 1;
1642
        }
1643
    }
1644

    
1645
    depth = s->get_bpp(s);
1646
    if (s->line_offset != s->last_line_offset ||
1647
        disp_width != s->last_width ||
1648
        height != s->last_height ||
1649
        s->last_depth != depth) {
1650
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1651
        if (depth == 16 || depth == 32) {
1652
#else
1653
        if (depth == 32) {
1654
#endif
1655
            qemu_free_displaysurface(s->ds);
1656
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1657
                    s->line_offset,
1658
                    s->vram_ptr + (s->start_addr * 4));
1659
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1660
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1661
#endif
1662
            dpy_resize(s->ds);
1663
        } else {
1664
            qemu_console_resize(s->ds, disp_width, height);
1665
        }
1666
        s->last_scr_width = disp_width;
1667
        s->last_scr_height = height;
1668
        s->last_width = disp_width;
1669
        s->last_height = height;
1670
        s->last_line_offset = s->line_offset;
1671
        s->last_depth = depth;
1672
        full_update = 1;
1673
    } else if (is_buffer_shared(s->ds->surface) &&
1674
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1675
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1676
        dpy_setdata(s->ds);
1677
    }
1678

    
1679
    s->rgb_to_pixel =
1680
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1681

    
1682
    if (shift_control == 0) {
1683
        full_update |= update_palette16(s);
1684
        if (s->sr[0x01] & 8) {
1685
            v = VGA_DRAW_LINE4D2;
1686
        } else {
1687
            v = VGA_DRAW_LINE4;
1688
        }
1689
        bits = 4;
1690
    } else if (shift_control == 1) {
1691
        full_update |= update_palette16(s);
1692
        if (s->sr[0x01] & 8) {
1693
            v = VGA_DRAW_LINE2D2;
1694
        } else {
1695
            v = VGA_DRAW_LINE2;
1696
        }
1697
        bits = 4;
1698
    } else {
1699
        switch(s->get_bpp(s)) {
1700
        default:
1701
        case 0:
1702
            full_update |= update_palette256(s);
1703
            v = VGA_DRAW_LINE8D2;
1704
            bits = 4;
1705
            break;
1706
        case 8:
1707
            full_update |= update_palette256(s);
1708
            v = VGA_DRAW_LINE8;
1709
            bits = 8;
1710
            break;
1711
        case 15:
1712
            v = VGA_DRAW_LINE15;
1713
            bits = 16;
1714
            break;
1715
        case 16:
1716
            v = VGA_DRAW_LINE16;
1717
            bits = 16;
1718
            break;
1719
        case 24:
1720
            v = VGA_DRAW_LINE24;
1721
            bits = 24;
1722
            break;
1723
        case 32:
1724
            v = VGA_DRAW_LINE32;
1725
            bits = 32;
1726
            break;
1727
        }
1728
    }
1729
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1730

    
1731
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1732
        s->cursor_invalidate(s);
1733

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

    
1817
static void vga_draw_blank(VGACommonState *s, int full_update)
1818
{
1819
    int i, w, val;
1820
    uint8_t *d;
1821

    
1822
    if (!full_update)
1823
        return;
1824
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1825
        return;
1826

    
1827
    s->rgb_to_pixel =
1828
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1829
    if (ds_get_bits_per_pixel(s->ds) == 8)
1830
        val = s->rgb_to_pixel(0, 0, 0);
1831
    else
1832
        val = 0;
1833
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1834
    d = ds_get_data(s->ds);
1835
    for(i = 0; i < s->last_scr_height; i++) {
1836
        memset(d, val, w);
1837
        d += ds_get_linesize(s->ds);
1838
    }
1839
    dpy_update(s->ds, 0, 0,
1840
               s->last_scr_width, s->last_scr_height);
1841
}
1842

    
1843
#define GMODE_TEXT     0
1844
#define GMODE_GRAPH    1
1845
#define GMODE_BLANK 2
1846

    
1847
static void vga_update_display(void *opaque)
1848
{
1849
    VGACommonState *s = opaque;
1850
    int full_update, graphic_mode;
1851

    
1852
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1853
        /* nothing to do */
1854
    } else {
1855
        full_update = 0;
1856
        if (!(s->ar_index & 0x20)) {
1857
            graphic_mode = GMODE_BLANK;
1858
        } else {
1859
            graphic_mode = s->gr[6] & 1;
1860
        }
1861
        if (graphic_mode != s->graphic_mode) {
1862
            s->graphic_mode = graphic_mode;
1863
            full_update = 1;
1864
        }
1865
        switch(graphic_mode) {
1866
        case GMODE_TEXT:
1867
            vga_draw_text(s, full_update);
1868
            break;
1869
        case GMODE_GRAPH:
1870
            vga_draw_graphic(s, full_update);
1871
            break;
1872
        case GMODE_BLANK:
1873
        default:
1874
            vga_draw_blank(s, full_update);
1875
            break;
1876
        }
1877
    }
1878
}
1879

    
1880
/* force a full display refresh */
1881
static void vga_invalidate_display(void *opaque)
1882
{
1883
    VGACommonState *s = opaque;
1884

    
1885
    s->last_width = -1;
1886
    s->last_height = -1;
1887
}
1888

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

    
1956
static void vga_reset(void *opaque)
1957
{
1958
    VGACommonState *s =  opaque;
1959
    vga_common_reset(s);
1960
}
1961

    
1962
#define TEXTMODE_X(x)        ((x) % width)
1963
#define TEXTMODE_Y(x)        ((x) / width)
1964
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1965
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1966
/* relay text rendering to the display driver
1967
 * instead of doing a full vga_update_display() */
1968
static void vga_update_text(void *opaque, console_ch_t *chardata)
1969
{
1970
    VGACommonState *s =  opaque;
1971
    int graphic_mode, i, cursor_offset, cursor_visible;
1972
    int cw, cheight, width, height, size, c_min, c_max;
1973
    uint32_t *src;
1974
    console_ch_t *dst, val;
1975
    char msg_buffer[80];
1976
    int full_update = 0;
1977

    
1978
    if (!(s->ar_index & 0x20)) {
1979
        graphic_mode = GMODE_BLANK;
1980
    } else {
1981
        graphic_mode = s->gr[6] & 1;
1982
    }
1983
    if (graphic_mode != s->graphic_mode) {
1984
        s->graphic_mode = graphic_mode;
1985
        full_update = 1;
1986
    }
1987
    if (s->last_width == -1) {
1988
        s->last_width = 0;
1989
        full_update = 1;
1990
    }
1991

    
1992
    switch (graphic_mode) {
1993
    case GMODE_TEXT:
1994
        /* TODO: update palette */
1995
        full_update |= update_basic_params(s);
1996

    
1997
        /* total width & height */
1998
        cheight = (s->cr[9] & 0x1f) + 1;
1999
        cw = 8;
2000
        if (!(s->sr[1] & 0x01))
2001
            cw = 9;
2002
        if (s->sr[1] & 0x08)
2003
            cw = 16; /* NOTE: no 18 pixel wide */
2004
        width = (s->cr[0x01] + 1);
2005
        if (s->cr[0x06] == 100) {
2006
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2007
            height = 100;
2008
        } else {
2009
            height = s->cr[0x12] | 
2010
                ((s->cr[0x07] & 0x02) << 7) | 
2011
                ((s->cr[0x07] & 0x40) << 3);
2012
            height = (height + 1) / cheight;
2013
        }
2014

    
2015
        size = (height * width);
2016
        if (size > CH_ATTR_SIZE) {
2017
            if (!full_update)
2018
                return;
2019

    
2020
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2021
                     width, height);
2022
            break;
2023
        }
2024

    
2025
        if (width != s->last_width || height != s->last_height ||
2026
            cw != s->last_cw || cheight != s->last_ch) {
2027
            s->last_scr_width = width * cw;
2028
            s->last_scr_height = height * cheight;
2029
            s->ds->surface->width = width;
2030
            s->ds->surface->height = height;
2031
            dpy_resize(s->ds);
2032
            s->last_width = width;
2033
            s->last_height = height;
2034
            s->last_ch = cheight;
2035
            s->last_cw = cw;
2036
            full_update = 1;
2037
        }
2038

    
2039
        /* Update "hardware" cursor */
2040
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2041
        if (cursor_offset != s->cursor_offset ||
2042
            s->cr[0xa] != s->cursor_start ||
2043
            s->cr[0xb] != s->cursor_end || full_update) {
2044
            cursor_visible = !(s->cr[0xa] & 0x20);
2045
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2046
                dpy_cursor(s->ds,
2047
                           TEXTMODE_X(cursor_offset),
2048
                           TEXTMODE_Y(cursor_offset));
2049
            else
2050
                dpy_cursor(s->ds, -1, -1);
2051
            s->cursor_offset = cursor_offset;
2052
            s->cursor_start = s->cr[0xa];
2053
            s->cursor_end = s->cr[0xb];
2054
        }
2055

    
2056
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2057
        dst = chardata;
2058

    
2059
        if (full_update) {
2060
            for (i = 0; i < size; src ++, dst ++, i ++)
2061
                console_write_ch(dst, VMEM2CHTYPE(*src));
2062

    
2063
            dpy_update(s->ds, 0, 0, width, height);
2064
        } else {
2065
            c_max = 0;
2066

    
2067
            for (i = 0; i < size; src ++, dst ++, i ++) {
2068
                console_write_ch(&val, VMEM2CHTYPE(*src));
2069
                if (*dst != val) {
2070
                    *dst = val;
2071
                    c_max = i;
2072
                    break;
2073
                }
2074
            }
2075
            c_min = i;
2076
            for (; i < size; src ++, dst ++, i ++) {
2077
                console_write_ch(&val, VMEM2CHTYPE(*src));
2078
                if (*dst != val) {
2079
                    *dst = val;
2080
                    c_max = i;
2081
                }
2082
            }
2083

    
2084
            if (c_min <= c_max) {
2085
                i = TEXTMODE_Y(c_min);
2086
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2087
            }
2088
        }
2089

    
2090
        return;
2091
    case GMODE_GRAPH:
2092
        if (!full_update)
2093
            return;
2094

    
2095
        s->get_resolution(s, &width, &height);
2096
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2097
                 width, height);
2098
        break;
2099
    case GMODE_BLANK:
2100
    default:
2101
        if (!full_update)
2102
            return;
2103

    
2104
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2105
        break;
2106
    }
2107

    
2108
    /* Display a message */
2109
    s->last_width = 60;
2110
    s->last_height = height = 3;
2111
    dpy_cursor(s->ds, -1, -1);
2112
    s->ds->surface->width = s->last_width;
2113
    s->ds->surface->height = height;
2114
    dpy_resize(s->ds);
2115

    
2116
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2117
        console_write_ch(dst ++, ' ');
2118

    
2119
    size = strlen(msg_buffer);
2120
    width = (s->last_width - size) / 2;
2121
    dst = chardata + s->last_width + width;
2122
    for (i = 0; i < size; i ++)
2123
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2124

    
2125
    dpy_update(s->ds, 0, 0, s->last_width, height);
2126
}
2127

    
2128
CPUReadMemoryFunc * const vga_mem_read[3] = {
2129
    vga_mem_readb,
2130
    vga_mem_readw,
2131
    vga_mem_readl,
2132
};
2133

    
2134
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2135
    vga_mem_writeb,
2136
    vga_mem_writew,
2137
    vga_mem_writel,
2138
};
2139

    
2140
static int vga_common_post_load(void *opaque, int version_id)
2141
{
2142
    VGACommonState *s = opaque;
2143

    
2144
    /* force refresh */
2145
    s->graphic_mode = -1;
2146
    return 0;
2147
}
2148

    
2149
const VMStateDescription vmstate_vga_common = {
2150
    .name = "vga",
2151
    .version_id = 2,
2152
    .minimum_version_id = 2,
2153
    .minimum_version_id_old = 2,
2154
    .post_load = vga_common_post_load,
2155
    .fields      = (VMStateField []) {
2156
        VMSTATE_UINT32(latch, VGACommonState),
2157
        VMSTATE_UINT8(sr_index, VGACommonState),
2158
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2159
        VMSTATE_UINT8(gr_index, VGACommonState),
2160
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2161
        VMSTATE_UINT8(ar_index, VGACommonState),
2162
        VMSTATE_BUFFER(ar, VGACommonState),
2163
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2164
        VMSTATE_UINT8(cr_index, VGACommonState),
2165
        VMSTATE_BUFFER(cr, VGACommonState),
2166
        VMSTATE_UINT8(msr, VGACommonState),
2167
        VMSTATE_UINT8(fcr, VGACommonState),
2168
        VMSTATE_UINT8(st00, VGACommonState),
2169
        VMSTATE_UINT8(st01, VGACommonState),
2170

    
2171
        VMSTATE_UINT8(dac_state, VGACommonState),
2172
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2173
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2174
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2175
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2176
        VMSTATE_BUFFER(palette, VGACommonState),
2177

    
2178
        VMSTATE_INT32(bank_offset, VGACommonState),
2179
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2180
#ifdef CONFIG_BOCHS_VBE
2181
        VMSTATE_UINT16(vbe_index, VGACommonState),
2182
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2183
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2184
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2185
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2186
#endif
2187
        VMSTATE_END_OF_LIST()
2188
    }
2189
};
2190

    
2191
void vga_common_init(VGACommonState *s, int vga_ram_size)
2192
{
2193
    int i, j, v, b;
2194

    
2195
    for(i = 0;i < 256; i++) {
2196
        v = 0;
2197
        for(j = 0; j < 8; j++) {
2198
            v |= ((i >> j) & 1) << (j * 4);
2199
        }
2200
        expand4[i] = v;
2201

    
2202
        v = 0;
2203
        for(j = 0; j < 4; j++) {
2204
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2205
        }
2206
        expand2[i] = v;
2207
    }
2208
    for(i = 0; i < 16; i++) {
2209
        v = 0;
2210
        for(j = 0; j < 4; j++) {
2211
            b = ((i >> j) & 1);
2212
            v |= b << (2 * j);
2213
            v |= b << (2 * j + 1);
2214
        }
2215
        expand4to8[i] = v;
2216
    }
2217

    
2218
#ifdef CONFIG_BOCHS_VBE
2219
    s->is_vbe_vmstate = 1;
2220
#else
2221
    s->is_vbe_vmstate = 0;
2222
#endif
2223
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2224
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2225
    s->vram_size = vga_ram_size;
2226
    s->get_bpp = vga_get_bpp;
2227
    s->get_offsets = vga_get_offsets;
2228
    s->get_resolution = vga_get_resolution;
2229
    s->update = vga_update_display;
2230
    s->invalidate = vga_invalidate_display;
2231
    s->screen_dump = vga_screen_dump;
2232
    s->text_update = vga_update_text;
2233
    switch (vga_retrace_method) {
2234
    case VGA_RETRACE_DUMB:
2235
        s->retrace = vga_dumb_retrace;
2236
        s->update_retrace_info = vga_dumb_update_retrace_info;
2237
        break;
2238

    
2239
    case VGA_RETRACE_PRECISE:
2240
        s->retrace = vga_precise_retrace;
2241
        s->update_retrace_info = vga_precise_update_retrace_info;
2242
        break;
2243
    }
2244
}
2245

    
2246
/* used by both ISA and PCI */
2247
void vga_init(VGACommonState *s)
2248
{
2249
    int vga_io_memory;
2250

    
2251
    qemu_register_reset(vga_reset, s);
2252

    
2253
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2254

    
2255
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2256
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2257
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2258
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2259

    
2260
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2261

    
2262
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2263
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2264
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2265
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2266
    s->bank_offset = 0;
2267

    
2268
#ifdef CONFIG_BOCHS_VBE
2269
#if defined (TARGET_I386)
2270
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2271
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2272

    
2273
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2274
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2275

    
2276
    /* old Bochs IO ports */
2277
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2278
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2279

    
2280
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2281
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2282
#else
2283
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2284
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2285

    
2286
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2287
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2288
#endif
2289
#endif /* CONFIG_BOCHS_VBE */
2290

    
2291
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2292
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2293
                                 vga_io_memory);
2294
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2295
}
2296

    
2297
/********************************************************/
2298
/* vga screen dump */
2299

    
2300
static void vga_save_dpy_update(DisplayState *ds,
2301
                                int x, int y, int w, int h)
2302
{
2303
    if (screen_dump_filename) {
2304
        ppm_save(screen_dump_filename, ds->surface);
2305
        screen_dump_filename = NULL;
2306
    }
2307
}
2308

    
2309
static void vga_save_dpy_resize(DisplayState *s)
2310
{
2311
}
2312

    
2313
static void vga_save_dpy_refresh(DisplayState *s)
2314
{
2315
}
2316

    
2317
int ppm_save(const char *filename, struct DisplaySurface *ds)
2318
{
2319
    FILE *f;
2320
    uint8_t *d, *d1;
2321
    uint32_t v;
2322
    int y, x;
2323
    uint8_t r, g, b;
2324

    
2325
    f = fopen(filename, "wb");
2326
    if (!f)
2327
        return -1;
2328
    fprintf(f, "P6\n%d %d\n%d\n",
2329
            ds->width, ds->height, 255);
2330
    d1 = ds->data;
2331
    for(y = 0; y < ds->height; y++) {
2332
        d = d1;
2333
        for(x = 0; x < ds->width; x++) {
2334
            if (ds->pf.bits_per_pixel == 32)
2335
                v = *(uint32_t *)d;
2336
            else
2337
                v = (uint32_t) (*(uint16_t *)d);
2338
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2339
                (ds->pf.rmax + 1);
2340
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2341
                (ds->pf.gmax + 1);
2342
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2343
                (ds->pf.bmax + 1);
2344
            fputc(r, f);
2345
            fputc(g, f);
2346
            fputc(b, f);
2347
            d += ds->pf.bytes_per_pixel;
2348
        }
2349
        d1 += ds->linesize;
2350
    }
2351
    fclose(f);
2352
    return 0;
2353
}
2354

    
2355
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2356
{
2357
    DisplayChangeListener *dcl;
2358

    
2359
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2360
    dcl->dpy_update = vga_save_dpy_update;
2361
    dcl->dpy_resize = vga_save_dpy_resize;
2362
    dcl->dpy_refresh = vga_save_dpy_refresh;
2363
    register_displaychangelistener(ds, dcl);
2364
    return dcl;
2365
}
2366

    
2367
/* save the vga display in a PPM image even if no display is
2368
   available */
2369
static void vga_screen_dump(void *opaque, const char *filename)
2370
{
2371
    VGACommonState *s = opaque;
2372

    
2373
    if (!screen_dump_dcl)
2374
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2375

    
2376
    screen_dump_filename = (char *)filename;
2377
    vga_invalidate_display(s);
2378
    vga_hw_update();
2379
}
2380