Statistics
| Branch: | Revision:

root / hw / vga.c @ 915cd3a9

History | View | Annotate | Download (68.6 kB)

1
/*
2
 * QEMU VGA Emulator.
3
 *
4
 * Copyright (c) 2003 Fabrice Bellard
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include "hw.h"
25
#include "console.h"
26
#include "pc.h"
27
#include "pci.h"
28
#include "vga_int.h"
29
#include "pixel_ops.h"
30
#include "qemu-timer.h"
31
#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
    if ((height * width) > CH_ATTR_SIZE) {
1307
        /* better than nothing: exit if transient size is too big */
1308
        return;
1309
    }
1310

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1584
#ifdef CONFIG_BOCHS_VBE
1585
    if (s->vbe_mapped) {
1586
        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1587
                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1588
    }
1589
#endif
1590

    
1591
}
1592

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

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

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

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

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

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

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

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

    
1646
    full_update |= update_basic_params(s);
1647

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2287
    qemu_register_reset(vga_reset, s);
2288

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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