Statistics
| Branch: | Revision:

root / hw / vga.c @ 47f5ba72

History | View | Annotate | Download (68.7 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
#ifdef CONFIG_BOCHS_VBE
1586
    if (s->vbe_mapped) {
1587
        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1588
                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1589
    }
1590
#endif
1591

    
1592
}
1593

    
1594
void vga_dirty_log_start(VGACommonState *s)
1595
{
1596
    if (kvm_enabled() && s->map_addr)
1597
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1598

    
1599
    if (kvm_enabled() && s->lfb_vram_mapped) {
1600
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1601
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1602
    }
1603

    
1604
#ifdef CONFIG_BOCHS_VBE
1605
    if (kvm_enabled() && s->vbe_mapped) {
1606
        kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1607
    }
1608
#endif
1609
}
1610

    
1611
void vga_dirty_log_stop(VGACommonState *s)
1612
{
1613
    if (kvm_enabled() && s->map_addr)
1614
        kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
1615

    
1616
    if (kvm_enabled() && s->lfb_vram_mapped) {
1617
        kvm_log_stop(isa_mem_base + 0xa0000, 0x80000);
1618
        kvm_log_stop(isa_mem_base + 0xa8000, 0x80000);
1619
    }
1620

    
1621
#ifdef CONFIG_BOCHS_VBE
1622
    if (kvm_enabled() && s->vbe_mapped) {
1623
        kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1624
    }
1625
#endif
1626
}
1627

    
1628
void vga_dirty_log_restart(VGACommonState *s)
1629
{
1630
    vga_dirty_log_stop(s);
1631
    vga_dirty_log_start(s);
1632
}
1633

    
1634
/*
1635
 * graphic modes
1636
 */
1637
static void vga_draw_graphic(VGACommonState *s, int full_update)
1638
{
1639
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1640
    int width, height, shift_control, line_offset, bwidth, bits;
1641
    ram_addr_t page0, page1, page_min, page_max;
1642
    int disp_width, multi_scan, multi_run;
1643
    uint8_t *d;
1644
    uint32_t v, addr1, addr;
1645
    vga_draw_line_func *vga_draw_line;
1646

    
1647
    full_update |= update_basic_params(s);
1648

    
1649
    if (!full_update)
1650
        vga_sync_dirty_bitmap(s);
1651

    
1652
    s->get_resolution(s, &width, &height);
1653
    disp_width = width;
1654

    
1655
    shift_control = (s->gr[0x05] >> 5) & 3;
1656
    double_scan = (s->cr[0x09] >> 7);
1657
    if (shift_control != 1) {
1658
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1659
    } else {
1660
        /* in CGA modes, multi_scan is ignored */
1661
        /* XXX: is it correct ? */
1662
        multi_scan = double_scan;
1663
    }
1664
    multi_run = multi_scan;
1665
    if (shift_control != s->shift_control ||
1666
        double_scan != s->double_scan) {
1667
        full_update = 1;
1668
        s->shift_control = shift_control;
1669
        s->double_scan = double_scan;
1670
    }
1671

    
1672
    if (shift_control == 0) {
1673
        if (s->sr[0x01] & 8) {
1674
            disp_width <<= 1;
1675
        }
1676
    } else if (shift_control == 1) {
1677
        if (s->sr[0x01] & 8) {
1678
            disp_width <<= 1;
1679
        }
1680
    }
1681

    
1682
    depth = s->get_bpp(s);
1683
    if (s->line_offset != s->last_line_offset ||
1684
        disp_width != s->last_width ||
1685
        height != s->last_height ||
1686
        s->last_depth != depth) {
1687
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1688
        if (depth == 16 || depth == 32) {
1689
#else
1690
        if (depth == 32) {
1691
#endif
1692
            qemu_free_displaysurface(s->ds);
1693
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1694
                    s->line_offset,
1695
                    s->vram_ptr + (s->start_addr * 4));
1696
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1697
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1698
#endif
1699
            dpy_resize(s->ds);
1700
        } else {
1701
            qemu_console_resize(s->ds, disp_width, height);
1702
        }
1703
        s->last_scr_width = disp_width;
1704
        s->last_scr_height = height;
1705
        s->last_width = disp_width;
1706
        s->last_height = height;
1707
        s->last_line_offset = s->line_offset;
1708
        s->last_depth = depth;
1709
        full_update = 1;
1710
    } else if (is_buffer_shared(s->ds->surface) &&
1711
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1712
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1713
        dpy_setdata(s->ds);
1714
    }
1715

    
1716
    s->rgb_to_pixel =
1717
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1718

    
1719
    if (shift_control == 0) {
1720
        full_update |= update_palette16(s);
1721
        if (s->sr[0x01] & 8) {
1722
            v = VGA_DRAW_LINE4D2;
1723
        } else {
1724
            v = VGA_DRAW_LINE4;
1725
        }
1726
        bits = 4;
1727
    } else if (shift_control == 1) {
1728
        full_update |= update_palette16(s);
1729
        if (s->sr[0x01] & 8) {
1730
            v = VGA_DRAW_LINE2D2;
1731
        } else {
1732
            v = VGA_DRAW_LINE2;
1733
        }
1734
        bits = 4;
1735
    } else {
1736
        switch(s->get_bpp(s)) {
1737
        default:
1738
        case 0:
1739
            full_update |= update_palette256(s);
1740
            v = VGA_DRAW_LINE8D2;
1741
            bits = 4;
1742
            break;
1743
        case 8:
1744
            full_update |= update_palette256(s);
1745
            v = VGA_DRAW_LINE8;
1746
            bits = 8;
1747
            break;
1748
        case 15:
1749
            v = VGA_DRAW_LINE15;
1750
            bits = 16;
1751
            break;
1752
        case 16:
1753
            v = VGA_DRAW_LINE16;
1754
            bits = 16;
1755
            break;
1756
        case 24:
1757
            v = VGA_DRAW_LINE24;
1758
            bits = 24;
1759
            break;
1760
        case 32:
1761
            v = VGA_DRAW_LINE32;
1762
            bits = 32;
1763
            break;
1764
        }
1765
    }
1766
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1767

    
1768
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1769
        s->cursor_invalidate(s);
1770

    
1771
    line_offset = s->line_offset;
1772
#if 0
1773
    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",
1774
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1775
#endif
1776
    addr1 = (s->start_addr * 4);
1777
    bwidth = (width * bits + 7) / 8;
1778
    y_start = -1;
1779
    page_min = -1;
1780
    page_max = 0;
1781
    d = ds_get_data(s->ds);
1782
    linesize = ds_get_linesize(s->ds);
1783
    y1 = 0;
1784
    for(y = 0; y < height; y++) {
1785
        addr = addr1;
1786
        if (!(s->cr[0x17] & 1)) {
1787
            int shift;
1788
            /* CGA compatibility handling */
1789
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1790
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1791
        }
1792
        if (!(s->cr[0x17] & 2)) {
1793
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1794
        }
1795
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1796
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1797
        update = full_update |
1798
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1799
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1800
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1801
            /* if wide line, can use another page */
1802
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1803
                                                    VGA_DIRTY_FLAG);
1804
        }
1805
        /* explicit invalidation for the hardware cursor */
1806
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1807
        if (update) {
1808
            if (y_start < 0)
1809
                y_start = y;
1810
            if (page0 < page_min)
1811
                page_min = page0;
1812
            if (page1 > page_max)
1813
                page_max = page1;
1814
            if (!(is_buffer_shared(s->ds->surface))) {
1815
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1816
                if (s->cursor_draw_line)
1817
                    s->cursor_draw_line(s, d, y);
1818
            }
1819
        } else {
1820
            if (y_start >= 0) {
1821
                /* flush to display */
1822
                dpy_update(s->ds, 0, y_start,
1823
                           disp_width, y - y_start);
1824
                y_start = -1;
1825
            }
1826
        }
1827
        if (!multi_run) {
1828
            mask = (s->cr[0x17] & 3) ^ 3;
1829
            if ((y1 & mask) == mask)
1830
                addr1 += line_offset;
1831
            y1++;
1832
            multi_run = multi_scan;
1833
        } else {
1834
            multi_run--;
1835
        }
1836
        /* line compare acts on the displayed lines */
1837
        if (y == s->line_compare)
1838
            addr1 = 0;
1839
        d += linesize;
1840
    }
1841
    if (y_start >= 0) {
1842
        /* flush to display */
1843
        dpy_update(s->ds, 0, y_start,
1844
                   disp_width, y - y_start);
1845
    }
1846
    /* reset modified pages */
1847
    if (page_max >= page_min) {
1848
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1849
                                        VGA_DIRTY_FLAG);
1850
    }
1851
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1852
}
1853

    
1854
static void vga_draw_blank(VGACommonState *s, int full_update)
1855
{
1856
    int i, w, val;
1857
    uint8_t *d;
1858

    
1859
    if (!full_update)
1860
        return;
1861
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1862
        return;
1863

    
1864
    s->rgb_to_pixel =
1865
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1866
    if (ds_get_bits_per_pixel(s->ds) == 8)
1867
        val = s->rgb_to_pixel(0, 0, 0);
1868
    else
1869
        val = 0;
1870
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1871
    d = ds_get_data(s->ds);
1872
    for(i = 0; i < s->last_scr_height; i++) {
1873
        memset(d, val, w);
1874
        d += ds_get_linesize(s->ds);
1875
    }
1876
    dpy_update(s->ds, 0, 0,
1877
               s->last_scr_width, s->last_scr_height);
1878
}
1879

    
1880
#define GMODE_TEXT     0
1881
#define GMODE_GRAPH    1
1882
#define GMODE_BLANK 2
1883

    
1884
static void vga_update_display(void *opaque)
1885
{
1886
    VGACommonState *s = opaque;
1887
    int full_update, graphic_mode;
1888

    
1889
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1890
        /* nothing to do */
1891
    } else {
1892
        full_update = 0;
1893
        if (!(s->ar_index & 0x20)) {
1894
            graphic_mode = GMODE_BLANK;
1895
        } else {
1896
            graphic_mode = s->gr[6] & 1;
1897
        }
1898
        if (graphic_mode != s->graphic_mode) {
1899
            s->graphic_mode = graphic_mode;
1900
            full_update = 1;
1901
        }
1902
        switch(graphic_mode) {
1903
        case GMODE_TEXT:
1904
            vga_draw_text(s, full_update);
1905
            break;
1906
        case GMODE_GRAPH:
1907
            vga_draw_graphic(s, full_update);
1908
            break;
1909
        case GMODE_BLANK:
1910
        default:
1911
            vga_draw_blank(s, full_update);
1912
            break;
1913
        }
1914
    }
1915
}
1916

    
1917
/* force a full display refresh */
1918
static void vga_invalidate_display(void *opaque)
1919
{
1920
    VGACommonState *s = opaque;
1921

    
1922
    s->last_width = -1;
1923
    s->last_height = -1;
1924
}
1925

    
1926
void vga_common_reset(VGACommonState *s)
1927
{
1928
    s->lfb_addr = 0;
1929
    s->lfb_end = 0;
1930
    s->map_addr = 0;
1931
    s->map_end = 0;
1932
    s->lfb_vram_mapped = 0;
1933
    s->bios_offset = 0;
1934
    s->bios_size = 0;
1935
    s->sr_index = 0;
1936
    memset(s->sr, '\0', sizeof(s->sr));
1937
    s->gr_index = 0;
1938
    memset(s->gr, '\0', sizeof(s->gr));
1939
    s->ar_index = 0;
1940
    memset(s->ar, '\0', sizeof(s->ar));
1941
    s->ar_flip_flop = 0;
1942
    s->cr_index = 0;
1943
    memset(s->cr, '\0', sizeof(s->cr));
1944
    s->msr = 0;
1945
    s->fcr = 0;
1946
    s->st00 = 0;
1947
    s->st01 = 0;
1948
    s->dac_state = 0;
1949
    s->dac_sub_index = 0;
1950
    s->dac_read_index = 0;
1951
    s->dac_write_index = 0;
1952
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1953
    s->dac_8bit = 0;
1954
    memset(s->palette, '\0', sizeof(s->palette));
1955
    s->bank_offset = 0;
1956
#ifdef CONFIG_BOCHS_VBE
1957
    s->vbe_index = 0;
1958
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1959
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1960
    s->vbe_start_addr = 0;
1961
    s->vbe_line_offset = 0;
1962
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1963
#endif
1964
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1965
    s->graphic_mode = -1; /* force full update */
1966
    s->shift_control = 0;
1967
    s->double_scan = 0;
1968
    s->line_offset = 0;
1969
    s->line_compare = 0;
1970
    s->start_addr = 0;
1971
    s->plane_updated = 0;
1972
    s->last_cw = 0;
1973
    s->last_ch = 0;
1974
    s->last_width = 0;
1975
    s->last_height = 0;
1976
    s->last_scr_width = 0;
1977
    s->last_scr_height = 0;
1978
    s->cursor_start = 0;
1979
    s->cursor_end = 0;
1980
    s->cursor_offset = 0;
1981
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1982
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1983
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1984
    switch (vga_retrace_method) {
1985
    case VGA_RETRACE_DUMB:
1986
        break;
1987
    case VGA_RETRACE_PRECISE:
1988
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1989
        break;
1990
    }
1991
}
1992

    
1993
static void vga_reset(void *opaque)
1994
{
1995
    VGACommonState *s =  opaque;
1996
    vga_common_reset(s);
1997
}
1998

    
1999
#define TEXTMODE_X(x)        ((x) % width)
2000
#define TEXTMODE_Y(x)        ((x) / width)
2001
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
2002
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2003
/* relay text rendering to the display driver
2004
 * instead of doing a full vga_update_display() */
2005
static void vga_update_text(void *opaque, console_ch_t *chardata)
2006
{
2007
    VGACommonState *s =  opaque;
2008
    int graphic_mode, i, cursor_offset, cursor_visible;
2009
    int cw, cheight, width, height, size, c_min, c_max;
2010
    uint32_t *src;
2011
    console_ch_t *dst, val;
2012
    char msg_buffer[80];
2013
    int full_update = 0;
2014

    
2015
    if (!(s->ar_index & 0x20)) {
2016
        graphic_mode = GMODE_BLANK;
2017
    } else {
2018
        graphic_mode = s->gr[6] & 1;
2019
    }
2020
    if (graphic_mode != s->graphic_mode) {
2021
        s->graphic_mode = graphic_mode;
2022
        full_update = 1;
2023
    }
2024
    if (s->last_width == -1) {
2025
        s->last_width = 0;
2026
        full_update = 1;
2027
    }
2028

    
2029
    switch (graphic_mode) {
2030
    case GMODE_TEXT:
2031
        /* TODO: update palette */
2032
        full_update |= update_basic_params(s);
2033

    
2034
        /* total width & height */
2035
        cheight = (s->cr[9] & 0x1f) + 1;
2036
        cw = 8;
2037
        if (!(s->sr[1] & 0x01))
2038
            cw = 9;
2039
        if (s->sr[1] & 0x08)
2040
            cw = 16; /* NOTE: no 18 pixel wide */
2041
        width = (s->cr[0x01] + 1);
2042
        if (s->cr[0x06] == 100) {
2043
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2044
            height = 100;
2045
        } else {
2046
            height = s->cr[0x12] | 
2047
                ((s->cr[0x07] & 0x02) << 7) | 
2048
                ((s->cr[0x07] & 0x40) << 3);
2049
            height = (height + 1) / cheight;
2050
        }
2051

    
2052
        size = (height * width);
2053
        if (size > CH_ATTR_SIZE) {
2054
            if (!full_update)
2055
                return;
2056

    
2057
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2058
                     width, height);
2059
            break;
2060
        }
2061

    
2062
        if (width != s->last_width || height != s->last_height ||
2063
            cw != s->last_cw || cheight != s->last_ch) {
2064
            s->last_scr_width = width * cw;
2065
            s->last_scr_height = height * cheight;
2066
            s->ds->surface->width = width;
2067
            s->ds->surface->height = height;
2068
            dpy_resize(s->ds);
2069
            s->last_width = width;
2070
            s->last_height = height;
2071
            s->last_ch = cheight;
2072
            s->last_cw = cw;
2073
            full_update = 1;
2074
        }
2075

    
2076
        /* Update "hardware" cursor */
2077
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2078
        if (cursor_offset != s->cursor_offset ||
2079
            s->cr[0xa] != s->cursor_start ||
2080
            s->cr[0xb] != s->cursor_end || full_update) {
2081
            cursor_visible = !(s->cr[0xa] & 0x20);
2082
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2083
                dpy_cursor(s->ds,
2084
                           TEXTMODE_X(cursor_offset),
2085
                           TEXTMODE_Y(cursor_offset));
2086
            else
2087
                dpy_cursor(s->ds, -1, -1);
2088
            s->cursor_offset = cursor_offset;
2089
            s->cursor_start = s->cr[0xa];
2090
            s->cursor_end = s->cr[0xb];
2091
        }
2092

    
2093
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2094
        dst = chardata;
2095

    
2096
        if (full_update) {
2097
            for (i = 0; i < size; src ++, dst ++, i ++)
2098
                console_write_ch(dst, VMEM2CHTYPE(*src));
2099

    
2100
            dpy_update(s->ds, 0, 0, width, height);
2101
        } else {
2102
            c_max = 0;
2103

    
2104
            for (i = 0; i < size; src ++, dst ++, i ++) {
2105
                console_write_ch(&val, VMEM2CHTYPE(*src));
2106
                if (*dst != val) {
2107
                    *dst = val;
2108
                    c_max = i;
2109
                    break;
2110
                }
2111
            }
2112
            c_min = i;
2113
            for (; i < size; src ++, dst ++, i ++) {
2114
                console_write_ch(&val, VMEM2CHTYPE(*src));
2115
                if (*dst != val) {
2116
                    *dst = val;
2117
                    c_max = i;
2118
                }
2119
            }
2120

    
2121
            if (c_min <= c_max) {
2122
                i = TEXTMODE_Y(c_min);
2123
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2124
            }
2125
        }
2126

    
2127
        return;
2128
    case GMODE_GRAPH:
2129
        if (!full_update)
2130
            return;
2131

    
2132
        s->get_resolution(s, &width, &height);
2133
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2134
                 width, height);
2135
        break;
2136
    case GMODE_BLANK:
2137
    default:
2138
        if (!full_update)
2139
            return;
2140

    
2141
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2142
        break;
2143
    }
2144

    
2145
    /* Display a message */
2146
    s->last_width = 60;
2147
    s->last_height = height = 3;
2148
    dpy_cursor(s->ds, -1, -1);
2149
    s->ds->surface->width = s->last_width;
2150
    s->ds->surface->height = height;
2151
    dpy_resize(s->ds);
2152

    
2153
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2154
        console_write_ch(dst ++, ' ');
2155

    
2156
    size = strlen(msg_buffer);
2157
    width = (s->last_width - size) / 2;
2158
    dst = chardata + s->last_width + width;
2159
    for (i = 0; i < size; i ++)
2160
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2161

    
2162
    dpy_update(s->ds, 0, 0, s->last_width, height);
2163
}
2164

    
2165
CPUReadMemoryFunc * const vga_mem_read[3] = {
2166
    vga_mem_readb,
2167
    vga_mem_readw,
2168
    vga_mem_readl,
2169
};
2170

    
2171
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2172
    vga_mem_writeb,
2173
    vga_mem_writew,
2174
    vga_mem_writel,
2175
};
2176

    
2177
static int vga_common_post_load(void *opaque, int version_id)
2178
{
2179
    VGACommonState *s = opaque;
2180

    
2181
    /* force refresh */
2182
    s->graphic_mode = -1;
2183
    return 0;
2184
}
2185

    
2186
const VMStateDescription vmstate_vga_common = {
2187
    .name = "vga",
2188
    .version_id = 2,
2189
    .minimum_version_id = 2,
2190
    .minimum_version_id_old = 2,
2191
    .post_load = vga_common_post_load,
2192
    .fields      = (VMStateField []) {
2193
        VMSTATE_UINT32(latch, VGACommonState),
2194
        VMSTATE_UINT8(sr_index, VGACommonState),
2195
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2196
        VMSTATE_UINT8(gr_index, VGACommonState),
2197
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2198
        VMSTATE_UINT8(ar_index, VGACommonState),
2199
        VMSTATE_BUFFER(ar, VGACommonState),
2200
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2201
        VMSTATE_UINT8(cr_index, VGACommonState),
2202
        VMSTATE_BUFFER(cr, VGACommonState),
2203
        VMSTATE_UINT8(msr, VGACommonState),
2204
        VMSTATE_UINT8(fcr, VGACommonState),
2205
        VMSTATE_UINT8(st00, VGACommonState),
2206
        VMSTATE_UINT8(st01, VGACommonState),
2207

    
2208
        VMSTATE_UINT8(dac_state, VGACommonState),
2209
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2210
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2211
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2212
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2213
        VMSTATE_BUFFER(palette, VGACommonState),
2214

    
2215
        VMSTATE_INT32(bank_offset, VGACommonState),
2216
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2217
#ifdef CONFIG_BOCHS_VBE
2218
        VMSTATE_UINT16(vbe_index, VGACommonState),
2219
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2220
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2221
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2222
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2223
#endif
2224
        VMSTATE_END_OF_LIST()
2225
    }
2226
};
2227

    
2228
void vga_common_init(VGACommonState *s, int vga_ram_size)
2229
{
2230
    int i, j, v, b;
2231

    
2232
    for(i = 0;i < 256; i++) {
2233
        v = 0;
2234
        for(j = 0; j < 8; j++) {
2235
            v |= ((i >> j) & 1) << (j * 4);
2236
        }
2237
        expand4[i] = v;
2238

    
2239
        v = 0;
2240
        for(j = 0; j < 4; j++) {
2241
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2242
        }
2243
        expand2[i] = v;
2244
    }
2245
    for(i = 0; i < 16; i++) {
2246
        v = 0;
2247
        for(j = 0; j < 4; j++) {
2248
            b = ((i >> j) & 1);
2249
            v |= b << (2 * j);
2250
            v |= b << (2 * j + 1);
2251
        }
2252
        expand4to8[i] = v;
2253
    }
2254

    
2255
#ifdef CONFIG_BOCHS_VBE
2256
    s->is_vbe_vmstate = 1;
2257
#else
2258
    s->is_vbe_vmstate = 0;
2259
#endif
2260
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2261
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2262
    s->vram_size = vga_ram_size;
2263
    s->get_bpp = vga_get_bpp;
2264
    s->get_offsets = vga_get_offsets;
2265
    s->get_resolution = vga_get_resolution;
2266
    s->update = vga_update_display;
2267
    s->invalidate = vga_invalidate_display;
2268
    s->screen_dump = vga_screen_dump;
2269
    s->text_update = vga_update_text;
2270
    switch (vga_retrace_method) {
2271
    case VGA_RETRACE_DUMB:
2272
        s->retrace = vga_dumb_retrace;
2273
        s->update_retrace_info = vga_dumb_update_retrace_info;
2274
        break;
2275

    
2276
    case VGA_RETRACE_PRECISE:
2277
        s->retrace = vga_precise_retrace;
2278
        s->update_retrace_info = vga_precise_update_retrace_info;
2279
        break;
2280
    }
2281
}
2282

    
2283
/* used by both ISA and PCI */
2284
void vga_init(VGACommonState *s)
2285
{
2286
    int vga_io_memory;
2287

    
2288
    qemu_register_reset(vga_reset, s);
2289

    
2290
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2291

    
2292
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2293
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2294
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2295
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2296

    
2297
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2298

    
2299
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2300
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2301
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2302
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2303
    s->bank_offset = 0;
2304

    
2305
#ifdef CONFIG_BOCHS_VBE
2306
#if defined (TARGET_I386)
2307
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2308
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2309

    
2310
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2311
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2312

    
2313
    /* old Bochs IO ports */
2314
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2315
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2316

    
2317
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2318
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2319
#else
2320
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2321
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2322

    
2323
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2324
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2325
#endif
2326
#endif /* CONFIG_BOCHS_VBE */
2327

    
2328
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2329
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2330
                                 vga_io_memory);
2331
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2332
}
2333

    
2334
void vga_init_vbe(VGACommonState *s)
2335
{
2336
#ifdef CONFIG_BOCHS_VBE
2337
    /* XXX: use optimized standard vga accesses */
2338
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2339
                                 VGA_RAM_SIZE, s->vram_offset);
2340
    s->vbe_mapped = 1;
2341
#endif 
2342
}
2343
/********************************************************/
2344
/* vga screen dump */
2345

    
2346
static void vga_save_dpy_update(DisplayState *ds,
2347
                                int x, int y, int w, int h)
2348
{
2349
    if (screen_dump_filename) {
2350
        ppm_save(screen_dump_filename, ds->surface);
2351
        screen_dump_filename = NULL;
2352
    }
2353
}
2354

    
2355
static void vga_save_dpy_resize(DisplayState *s)
2356
{
2357
}
2358

    
2359
static void vga_save_dpy_refresh(DisplayState *s)
2360
{
2361
}
2362

    
2363
int ppm_save(const char *filename, struct DisplaySurface *ds)
2364
{
2365
    FILE *f;
2366
    uint8_t *d, *d1;
2367
    uint32_t v;
2368
    int y, x;
2369
    uint8_t r, g, b;
2370

    
2371
    f = fopen(filename, "wb");
2372
    if (!f)
2373
        return -1;
2374
    fprintf(f, "P6\n%d %d\n%d\n",
2375
            ds->width, ds->height, 255);
2376
    d1 = ds->data;
2377
    for(y = 0; y < ds->height; y++) {
2378
        d = d1;
2379
        for(x = 0; x < ds->width; x++) {
2380
            if (ds->pf.bits_per_pixel == 32)
2381
                v = *(uint32_t *)d;
2382
            else
2383
                v = (uint32_t) (*(uint16_t *)d);
2384
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2385
                (ds->pf.rmax + 1);
2386
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2387
                (ds->pf.gmax + 1);
2388
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2389
                (ds->pf.bmax + 1);
2390
            fputc(r, f);
2391
            fputc(g, f);
2392
            fputc(b, f);
2393
            d += ds->pf.bytes_per_pixel;
2394
        }
2395
        d1 += ds->linesize;
2396
    }
2397
    fclose(f);
2398
    return 0;
2399
}
2400

    
2401
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2402
{
2403
    DisplayChangeListener *dcl;
2404

    
2405
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2406
    dcl->dpy_update = vga_save_dpy_update;
2407
    dcl->dpy_resize = vga_save_dpy_resize;
2408
    dcl->dpy_refresh = vga_save_dpy_refresh;
2409
    register_displaychangelistener(ds, dcl);
2410
    return dcl;
2411
}
2412

    
2413
/* save the vga display in a PPM image even if no display is
2414
   available */
2415
static void vga_screen_dump(void *opaque, const char *filename)
2416
{
2417
    VGACommonState *s = opaque;
2418

    
2419
    if (!screen_dump_dcl)
2420
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2421

    
2422
    screen_dump_filename = (char *)filename;
2423
    vga_invalidate_display(s);
2424
    vga_hw_update();
2425
}
2426