Statistics
| Branch: | Revision:

root / hw / vga.c @ 74475455

History | View | Annotate | Download (67.9 kB)

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

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

    
36
//#define DEBUG_BOCHS_VBE
37

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

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

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

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

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

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

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

    
113
#undef PAT
114

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

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

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

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

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

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

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

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

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

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

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

    
194

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

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

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

    
263
        cur_tick = qemu_get_clock_ns(vm_clock);
264

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
558
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
559
{
560
    VGACommonState *s = opaque;
561
    s->vbe_index = val;
562
}
563

    
564
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
565
{
566
    VGACommonState *s = opaque;
567

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

    
614
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
615
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
616
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
617
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
618
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
619
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
620

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

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

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

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

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

    
709
/* called for accesses between 0xa0000 and 0xc0000 */
710
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
711
{
712
    VGACommonState *s = opaque;
713
    int memory_map_mode, plane;
714
    uint32_t ret;
715

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

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

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

    
766
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
767
{
768
    uint32_t v;
769
    v = vga_mem_readb(opaque, addr);
770
    v |= vga_mem_readb(opaque, addr + 1) << 8;
771
    return v;
772
}
773

    
774
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
775
{
776
    uint32_t v;
777
    v = vga_mem_readb(opaque, addr);
778
    v |= vga_mem_readb(opaque, addr + 1) << 8;
779
    v |= vga_mem_readb(opaque, addr + 2) << 16;
780
    v |= vga_mem_readb(opaque, addr + 3) << 24;
781
    return v;
782
}
783

    
784
/* called for accesses between 0xa0000 and 0xc0000 */
785
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
786
{
787
    VGACommonState *s = opaque;
788
    int memory_map_mode, plane, write_mode, b, func_select, mask;
789
    uint32_t write_mask, bit_mask, set_mask;
790

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

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

    
855
            /* apply set/reset mask */
856
            set_mask = mask16[s->gr[1]];
857
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
858
            bit_mask = s->gr[8];
859
            break;
860
        case 1:
861
            val = s->latch;
862
            goto do_write;
863
        case 2:
864
            val = mask16[val & 0x0f];
865
            bit_mask = s->gr[8];
866
            break;
867
        case 3:
868
            /* rotate */
869
            b = s->gr[3] & 7;
870
            val = (val >> b) | (val << (8 - b));
871

    
872
            bit_mask = s->gr[8] & val;
873
            val = mask16[s->gr[0]];
874
            break;
875
        }
876

    
877
        /* apply logical operation */
878
        func_select = s->gr[3] >> 3;
879
        switch(func_select) {
880
        case 0:
881
        default:
882
            /* nothing to do */
883
            break;
884
        case 1:
885
            /* and */
886
            val &= s->latch;
887
            break;
888
        case 2:
889
            /* or */
890
            val |= s->latch;
891
            break;
892
        case 3:
893
            /* xor */
894
            val ^= s->latch;
895
            break;
896
        }
897

    
898
        /* apply bit mask */
899
        bit_mask |= bit_mask << 8;
900
        bit_mask |= bit_mask << 16;
901
        val = (val & bit_mask) | (s->latch & ~bit_mask);
902

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

    
919
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
920
{
921
    vga_mem_writeb(opaque, addr, val & 0xff);
922
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
923
}
924

    
925
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
926
{
927
    vga_mem_writeb(opaque, addr, val & 0xff);
928
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
929
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
930
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
931
}
932

    
933
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
934
                             const uint8_t *font_ptr, int h,
935
                             uint32_t fgcol, uint32_t bgcol);
936
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
937
                                  const uint8_t *font_ptr, int h,
938
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
939
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
940
                                const uint8_t *s, int width);
941

    
942
#define DEPTH 8
943
#include "vga_template.h"
944

    
945
#define DEPTH 15
946
#include "vga_template.h"
947

    
948
#define BGR_FORMAT
949
#define DEPTH 15
950
#include "vga_template.h"
951

    
952
#define DEPTH 16
953
#include "vga_template.h"
954

    
955
#define BGR_FORMAT
956
#define DEPTH 16
957
#include "vga_template.h"
958

    
959
#define DEPTH 32
960
#include "vga_template.h"
961

    
962
#define BGR_FORMAT
963
#define DEPTH 32
964
#include "vga_template.h"
965

    
966
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
967
{
968
    unsigned int col;
969
    col = rgb_to_pixel8(r, g, b);
970
    col |= col << 8;
971
    col |= col << 16;
972
    return col;
973
}
974

    
975
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
976
{
977
    unsigned int col;
978
    col = rgb_to_pixel15(r, g, b);
979
    col |= col << 16;
980
    return col;
981
}
982

    
983
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
984
                                          unsigned int b)
985
{
986
    unsigned int col;
987
    col = rgb_to_pixel15bgr(r, g, b);
988
    col |= col << 16;
989
    return col;
990
}
991

    
992
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
993
{
994
    unsigned int col;
995
    col = rgb_to_pixel16(r, g, b);
996
    col |= col << 16;
997
    return col;
998
}
999

    
1000
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1001
                                          unsigned int b)
1002
{
1003
    unsigned int col;
1004
    col = rgb_to_pixel16bgr(r, g, b);
1005
    col |= col << 16;
1006
    return col;
1007
}
1008

    
1009
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1010
{
1011
    unsigned int col;
1012
    col = rgb_to_pixel32(r, g, b);
1013
    return col;
1014
}
1015

    
1016
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1017
{
1018
    unsigned int col;
1019
    col = rgb_to_pixel32bgr(r, g, b);
1020
    return col;
1021
}
1022

    
1023
/* return true if the palette was modified */
1024
static int update_palette16(VGACommonState *s)
1025
{
1026
    int full_update, i;
1027
    uint32_t v, col, *palette;
1028

    
1029
    full_update = 0;
1030
    palette = s->last_palette;
1031
    for(i = 0; i < 16; i++) {
1032
        v = s->ar[i];
1033
        if (s->ar[0x10] & 0x80)
1034
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1035
        else
1036
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1037
        v = v * 3;
1038
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1039
                              c6_to_8(s->palette[v + 1]),
1040
                              c6_to_8(s->palette[v + 2]));
1041
        if (col != palette[i]) {
1042
            full_update = 1;
1043
            palette[i] = col;
1044
        }
1045
    }
1046
    return full_update;
1047
}
1048

    
1049
/* return true if the palette was modified */
1050
static int update_palette256(VGACommonState *s)
1051
{
1052
    int full_update, i;
1053
    uint32_t v, col, *palette;
1054

    
1055
    full_update = 0;
1056
    palette = s->last_palette;
1057
    v = 0;
1058
    for(i = 0; i < 256; i++) {
1059
        if (s->dac_8bit) {
1060
          col = s->rgb_to_pixel(s->palette[v],
1061
                                s->palette[v + 1],
1062
                                s->palette[v + 2]);
1063
        } else {
1064
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1065
                                c6_to_8(s->palette[v + 1]),
1066
                                c6_to_8(s->palette[v + 2]));
1067
        }
1068
        if (col != palette[i]) {
1069
            full_update = 1;
1070
            palette[i] = col;
1071
        }
1072
        v += 3;
1073
    }
1074
    return full_update;
1075
}
1076

    
1077
static void vga_get_offsets(VGACommonState *s,
1078
                            uint32_t *pline_offset,
1079
                            uint32_t *pstart_addr,
1080
                            uint32_t *pline_compare)
1081
{
1082
    uint32_t start_addr, line_offset, line_compare;
1083
#ifdef CONFIG_BOCHS_VBE
1084
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1085
        line_offset = s->vbe_line_offset;
1086
        start_addr = s->vbe_start_addr;
1087
        line_compare = 65535;
1088
    } else
1089
#endif
1090
    {
1091
        /* compute line_offset in bytes */
1092
        line_offset = s->cr[0x13];
1093
        line_offset <<= 3;
1094

    
1095
        /* starting address */
1096
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1097

    
1098
        /* line compare */
1099
        line_compare = s->cr[0x18] |
1100
            ((s->cr[0x07] & 0x10) << 4) |
1101
            ((s->cr[0x09] & 0x40) << 3);
1102
    }
1103
    *pline_offset = line_offset;
1104
    *pstart_addr = start_addr;
1105
    *pline_compare = line_compare;
1106
}
1107

    
1108
/* update start_addr and line_offset. Return TRUE if modified */
1109
static int update_basic_params(VGACommonState *s)
1110
{
1111
    int full_update;
1112
    uint32_t start_addr, line_offset, line_compare;
1113

    
1114
    full_update = 0;
1115

    
1116
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1117

    
1118
    if (line_offset != s->line_offset ||
1119
        start_addr != s->start_addr ||
1120
        line_compare != s->line_compare) {
1121
        s->line_offset = line_offset;
1122
        s->start_addr = start_addr;
1123
        s->line_compare = line_compare;
1124
        full_update = 1;
1125
    }
1126
    return full_update;
1127
}
1128

    
1129
#define NB_DEPTHS 7
1130

    
1131
static inline int get_depth_index(DisplayState *s)
1132
{
1133
    switch(ds_get_bits_per_pixel(s)) {
1134
    default:
1135
    case 8:
1136
        return 0;
1137
    case 15:
1138
        return 1;
1139
    case 16:
1140
        return 2;
1141
    case 32:
1142
        if (is_surface_bgr(s->surface))
1143
            return 4;
1144
        else
1145
            return 3;
1146
    }
1147
}
1148

    
1149
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1150
    vga_draw_glyph8_8,
1151
    vga_draw_glyph8_16,
1152
    vga_draw_glyph8_16,
1153
    vga_draw_glyph8_32,
1154
    vga_draw_glyph8_32,
1155
    vga_draw_glyph8_16,
1156
    vga_draw_glyph8_16,
1157
};
1158

    
1159
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1160
    vga_draw_glyph16_8,
1161
    vga_draw_glyph16_16,
1162
    vga_draw_glyph16_16,
1163
    vga_draw_glyph16_32,
1164
    vga_draw_glyph16_32,
1165
    vga_draw_glyph16_16,
1166
    vga_draw_glyph16_16,
1167
};
1168

    
1169
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1170
    vga_draw_glyph9_8,
1171
    vga_draw_glyph9_16,
1172
    vga_draw_glyph9_16,
1173
    vga_draw_glyph9_32,
1174
    vga_draw_glyph9_32,
1175
    vga_draw_glyph9_16,
1176
    vga_draw_glyph9_16,
1177
};
1178

    
1179
static const uint8_t cursor_glyph[32 * 4] = {
1180
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1181
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1182
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1183
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1184
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1185
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1186
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1187
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1188
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1189
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1190
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1191
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1192
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1193
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1194
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1195
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1196
};
1197

    
1198
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1199
                                    int *pcwidth, int *pcheight)
1200
{
1201
    int width, cwidth, height, cheight;
1202

    
1203
    /* total width & height */
1204
    cheight = (s->cr[9] & 0x1f) + 1;
1205
    cwidth = 8;
1206
    if (!(s->sr[1] & 0x01))
1207
        cwidth = 9;
1208
    if (s->sr[1] & 0x08)
1209
        cwidth = 16; /* NOTE: no 18 pixel wide */
1210
    width = (s->cr[0x01] + 1);
1211
    if (s->cr[0x06] == 100) {
1212
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1213
        height = 100;
1214
    } else {
1215
        height = s->cr[0x12] |
1216
            ((s->cr[0x07] & 0x02) << 7) |
1217
            ((s->cr[0x07] & 0x40) << 3);
1218
        height = (height + 1) / cheight;
1219
    }
1220

    
1221
    *pwidth = width;
1222
    *pheight = height;
1223
    *pcwidth = cwidth;
1224
    *pcheight = cheight;
1225
}
1226

    
1227
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1228

    
1229
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1230
    rgb_to_pixel8_dup,
1231
    rgb_to_pixel15_dup,
1232
    rgb_to_pixel16_dup,
1233
    rgb_to_pixel32_dup,
1234
    rgb_to_pixel32bgr_dup,
1235
    rgb_to_pixel15bgr_dup,
1236
    rgb_to_pixel16bgr_dup,
1237
};
1238

    
1239
/*
1240
 * Text mode update
1241
 * Missing:
1242
 * - double scan
1243
 * - double width
1244
 * - underline
1245
 * - flashing
1246
 */
1247
static void vga_draw_text(VGACommonState *s, int full_update)
1248
{
1249
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1250
    int cx_min, cx_max, linesize, x_incr, line, line1;
1251
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1252
    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1253
    const uint8_t *font_ptr, *font_base[2];
1254
    int dup9, line_offset, depth_index;
1255
    uint32_t *palette;
1256
    uint32_t *ch_attr_ptr;
1257
    vga_draw_glyph8_func *vga_draw_glyph8;
1258
    vga_draw_glyph9_func *vga_draw_glyph9;
1259

    
1260
    /* compute font data address (in plane 2) */
1261
    v = s->sr[3];
1262
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1263
    if (offset != s->font_offsets[0]) {
1264
        s->font_offsets[0] = offset;
1265
        full_update = 1;
1266
    }
1267
    font_base[0] = s->vram_ptr + offset;
1268

    
1269
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1270
    font_base[1] = s->vram_ptr + offset;
1271
    if (offset != s->font_offsets[1]) {
1272
        s->font_offsets[1] = offset;
1273
        full_update = 1;
1274
    }
1275
    if (s->plane_updated & (1 << 2)) {
1276
        /* if the plane 2 was modified since the last display, it
1277
           indicates the font may have been modified */
1278
        s->plane_updated = 0;
1279
        full_update = 1;
1280
    }
1281
    full_update |= update_basic_params(s);
1282

    
1283
    line_offset = s->line_offset;
1284

    
1285
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1286
    if ((height * width) > CH_ATTR_SIZE) {
1287
        /* better than nothing: exit if transient size is too big */
1288
        return;
1289
    }
1290

    
1291
    if (width != s->last_width || height != s->last_height ||
1292
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1293
        s->last_scr_width = width * cw;
1294
        s->last_scr_height = height * cheight;
1295
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1296
        s->last_depth = 0;
1297
        s->last_width = width;
1298
        s->last_height = height;
1299
        s->last_ch = cheight;
1300
        s->last_cw = cw;
1301
        full_update = 1;
1302
    }
1303
    s->rgb_to_pixel =
1304
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1305
    full_update |= update_palette16(s);
1306
    palette = s->last_palette;
1307
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1308

    
1309
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1310
    if (cursor_offset != s->cursor_offset ||
1311
        s->cr[0xa] != s->cursor_start ||
1312
        s->cr[0xb] != s->cursor_end) {
1313
      /* if the cursor position changed, we update the old and new
1314
         chars */
1315
        if (s->cursor_offset < CH_ATTR_SIZE)
1316
            s->last_ch_attr[s->cursor_offset] = -1;
1317
        if (cursor_offset < CH_ATTR_SIZE)
1318
            s->last_ch_attr[cursor_offset] = -1;
1319
        s->cursor_offset = cursor_offset;
1320
        s->cursor_start = s->cr[0xa];
1321
        s->cursor_end = s->cr[0xb];
1322
    }
1323
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1324

    
1325
    depth_index = get_depth_index(s->ds);
1326
    if (cw == 16)
1327
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1328
    else
1329
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1330
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1331

    
1332
    dest = ds_get_data(s->ds);
1333
    linesize = ds_get_linesize(s->ds);
1334
    ch_attr_ptr = s->last_ch_attr;
1335
    line = 0;
1336
    offset = s->start_addr * 4;
1337
    for(cy = 0; cy < height; cy++) {
1338
        d1 = dest;
1339
        src = s->vram_ptr + offset;
1340
        cx_min = width;
1341
        cx_max = -1;
1342
        for(cx = 0; cx < width; cx++) {
1343
            ch_attr = *(uint16_t *)src;
1344
            if (full_update || ch_attr != *ch_attr_ptr) {
1345
                if (cx < cx_min)
1346
                    cx_min = cx;
1347
                if (cx > cx_max)
1348
                    cx_max = cx;
1349
                *ch_attr_ptr = ch_attr;
1350
#ifdef HOST_WORDS_BIGENDIAN
1351
                ch = ch_attr >> 8;
1352
                cattr = ch_attr & 0xff;
1353
#else
1354
                ch = ch_attr & 0xff;
1355
                cattr = ch_attr >> 8;
1356
#endif
1357
                font_ptr = font_base[(cattr >> 3) & 1];
1358
                font_ptr += 32 * 4 * ch;
1359
                bgcol = palette[cattr >> 4];
1360
                fgcol = palette[cattr & 0x0f];
1361
                if (cw != 9) {
1362
                    vga_draw_glyph8(d1, linesize,
1363
                                    font_ptr, cheight, fgcol, bgcol);
1364
                } else {
1365
                    dup9 = 0;
1366
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1367
                        dup9 = 1;
1368
                    vga_draw_glyph9(d1, linesize,
1369
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1370
                }
1371
                if (src == cursor_ptr &&
1372
                    !(s->cr[0x0a] & 0x20)) {
1373
                    int line_start, line_last, h;
1374
                    /* draw the cursor */
1375
                    line_start = s->cr[0x0a] & 0x1f;
1376
                    line_last = s->cr[0x0b] & 0x1f;
1377
                    /* XXX: check that */
1378
                    if (line_last > cheight - 1)
1379
                        line_last = cheight - 1;
1380
                    if (line_last >= line_start && line_start < cheight) {
1381
                        h = line_last - line_start + 1;
1382
                        d = d1 + linesize * line_start;
1383
                        if (cw != 9) {
1384
                            vga_draw_glyph8(d, linesize,
1385
                                            cursor_glyph, h, fgcol, bgcol);
1386
                        } else {
1387
                            vga_draw_glyph9(d, linesize,
1388
                                            cursor_glyph, h, fgcol, bgcol, 1);
1389
                        }
1390
                    }
1391
                }
1392
            }
1393
            d1 += x_incr;
1394
            src += 4;
1395
            ch_attr_ptr++;
1396
        }
1397
        if (cx_max != -1) {
1398
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1399
                       (cx_max - cx_min + 1) * cw, cheight);
1400
        }
1401
        dest += linesize * cheight;
1402
        line1 = line + cheight;
1403
        offset += line_offset;
1404
        if (line < s->line_compare && line1 >= s->line_compare) {
1405
            offset = 0;
1406
        }
1407
        line = line1;
1408
    }
1409
}
1410

    
1411
enum {
1412
    VGA_DRAW_LINE2,
1413
    VGA_DRAW_LINE2D2,
1414
    VGA_DRAW_LINE4,
1415
    VGA_DRAW_LINE4D2,
1416
    VGA_DRAW_LINE8D2,
1417
    VGA_DRAW_LINE8,
1418
    VGA_DRAW_LINE15,
1419
    VGA_DRAW_LINE16,
1420
    VGA_DRAW_LINE24,
1421
    VGA_DRAW_LINE32,
1422
    VGA_DRAW_LINE_NB,
1423
};
1424

    
1425
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1426
    vga_draw_line2_8,
1427
    vga_draw_line2_16,
1428
    vga_draw_line2_16,
1429
    vga_draw_line2_32,
1430
    vga_draw_line2_32,
1431
    vga_draw_line2_16,
1432
    vga_draw_line2_16,
1433

    
1434
    vga_draw_line2d2_8,
1435
    vga_draw_line2d2_16,
1436
    vga_draw_line2d2_16,
1437
    vga_draw_line2d2_32,
1438
    vga_draw_line2d2_32,
1439
    vga_draw_line2d2_16,
1440
    vga_draw_line2d2_16,
1441

    
1442
    vga_draw_line4_8,
1443
    vga_draw_line4_16,
1444
    vga_draw_line4_16,
1445
    vga_draw_line4_32,
1446
    vga_draw_line4_32,
1447
    vga_draw_line4_16,
1448
    vga_draw_line4_16,
1449

    
1450
    vga_draw_line4d2_8,
1451
    vga_draw_line4d2_16,
1452
    vga_draw_line4d2_16,
1453
    vga_draw_line4d2_32,
1454
    vga_draw_line4d2_32,
1455
    vga_draw_line4d2_16,
1456
    vga_draw_line4d2_16,
1457

    
1458
    vga_draw_line8d2_8,
1459
    vga_draw_line8d2_16,
1460
    vga_draw_line8d2_16,
1461
    vga_draw_line8d2_32,
1462
    vga_draw_line8d2_32,
1463
    vga_draw_line8d2_16,
1464
    vga_draw_line8d2_16,
1465

    
1466
    vga_draw_line8_8,
1467
    vga_draw_line8_16,
1468
    vga_draw_line8_16,
1469
    vga_draw_line8_32,
1470
    vga_draw_line8_32,
1471
    vga_draw_line8_16,
1472
    vga_draw_line8_16,
1473

    
1474
    vga_draw_line15_8,
1475
    vga_draw_line15_15,
1476
    vga_draw_line15_16,
1477
    vga_draw_line15_32,
1478
    vga_draw_line15_32bgr,
1479
    vga_draw_line15_15bgr,
1480
    vga_draw_line15_16bgr,
1481

    
1482
    vga_draw_line16_8,
1483
    vga_draw_line16_15,
1484
    vga_draw_line16_16,
1485
    vga_draw_line16_32,
1486
    vga_draw_line16_32bgr,
1487
    vga_draw_line16_15bgr,
1488
    vga_draw_line16_16bgr,
1489

    
1490
    vga_draw_line24_8,
1491
    vga_draw_line24_15,
1492
    vga_draw_line24_16,
1493
    vga_draw_line24_32,
1494
    vga_draw_line24_32bgr,
1495
    vga_draw_line24_15bgr,
1496
    vga_draw_line24_16bgr,
1497

    
1498
    vga_draw_line32_8,
1499
    vga_draw_line32_15,
1500
    vga_draw_line32_16,
1501
    vga_draw_line32_32,
1502
    vga_draw_line32_32bgr,
1503
    vga_draw_line32_15bgr,
1504
    vga_draw_line32_16bgr,
1505
};
1506

    
1507
static int vga_get_bpp(VGACommonState *s)
1508
{
1509
    int ret;
1510
#ifdef CONFIG_BOCHS_VBE
1511
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1512
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1513
    } else
1514
#endif
1515
    {
1516
        ret = 0;
1517
    }
1518
    return ret;
1519
}
1520

    
1521
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1522
{
1523
    int width, height;
1524

    
1525
#ifdef CONFIG_BOCHS_VBE
1526
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1527
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1528
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1529
    } else
1530
#endif
1531
    {
1532
        width = (s->cr[0x01] + 1) * 8;
1533
        height = s->cr[0x12] |
1534
            ((s->cr[0x07] & 0x02) << 7) |
1535
            ((s->cr[0x07] & 0x40) << 3);
1536
        height = (height + 1);
1537
    }
1538
    *pwidth = width;
1539
    *pheight = height;
1540
}
1541

    
1542
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1543
{
1544
    int y;
1545
    if (y1 >= VGA_MAX_HEIGHT)
1546
        return;
1547
    if (y2 >= VGA_MAX_HEIGHT)
1548
        y2 = VGA_MAX_HEIGHT;
1549
    for(y = y1; y < y2; y++) {
1550
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1551
    }
1552
}
1553

    
1554
static void vga_sync_dirty_bitmap(VGACommonState *s)
1555
{
1556
    if (s->map_addr)
1557
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1558

    
1559
    if (s->lfb_vram_mapped) {
1560
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1561
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1562
    }
1563

    
1564
#ifdef CONFIG_BOCHS_VBE
1565
    if (s->vbe_mapped) {
1566
        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1567
                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1568
    }
1569
#endif
1570

    
1571
}
1572

    
1573
void vga_dirty_log_start(VGACommonState *s)
1574
{
1575
    if (s->map_addr) {
1576
        cpu_physical_log_start(s->map_addr, s->map_end - s->map_addr);
1577
    }
1578

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

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

    
1591
void vga_dirty_log_stop(VGACommonState *s)
1592
{
1593
    if (s->map_addr) {
1594
        cpu_physical_log_stop(s->map_addr, s->map_end - s->map_addr);
1595
    }
1596

    
1597
    if (s->lfb_vram_mapped) {
1598
        cpu_physical_log_stop(isa_mem_base + 0xa0000, 0x8000);
1599
        cpu_physical_log_stop(isa_mem_base + 0xa8000, 0x8000);
1600
    }
1601

    
1602
#ifdef CONFIG_BOCHS_VBE
1603
    if (s->vbe_mapped) {
1604
        cpu_physical_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1605
    }
1606
#endif
1607
}
1608

    
1609
void vga_dirty_log_restart(VGACommonState *s)
1610
{
1611
    vga_dirty_log_stop(s);
1612
    vga_dirty_log_start(s);
1613
}
1614

    
1615
/*
1616
 * graphic modes
1617
 */
1618
static void vga_draw_graphic(VGACommonState *s, int full_update)
1619
{
1620
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1621
    int width, height, shift_control, line_offset, bwidth, bits;
1622
    ram_addr_t page0, page1, page_min, page_max;
1623
    int disp_width, multi_scan, multi_run;
1624
    uint8_t *d;
1625
    uint32_t v, addr1, addr;
1626
    vga_draw_line_func *vga_draw_line;
1627

    
1628
    full_update |= update_basic_params(s);
1629

    
1630
    if (!full_update)
1631
        vga_sync_dirty_bitmap(s);
1632

    
1633
    s->get_resolution(s, &width, &height);
1634
    disp_width = width;
1635

    
1636
    shift_control = (s->gr[0x05] >> 5) & 3;
1637
    double_scan = (s->cr[0x09] >> 7);
1638
    if (shift_control != 1) {
1639
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1640
    } else {
1641
        /* in CGA modes, multi_scan is ignored */
1642
        /* XXX: is it correct ? */
1643
        multi_scan = double_scan;
1644
    }
1645
    multi_run = multi_scan;
1646
    if (shift_control != s->shift_control ||
1647
        double_scan != s->double_scan) {
1648
        full_update = 1;
1649
        s->shift_control = shift_control;
1650
        s->double_scan = double_scan;
1651
    }
1652

    
1653
    if (shift_control == 0) {
1654
        if (s->sr[0x01] & 8) {
1655
            disp_width <<= 1;
1656
        }
1657
    } else if (shift_control == 1) {
1658
        if (s->sr[0x01] & 8) {
1659
            disp_width <<= 1;
1660
        }
1661
    }
1662

    
1663
    depth = s->get_bpp(s);
1664
    if (s->line_offset != s->last_line_offset ||
1665
        disp_width != s->last_width ||
1666
        height != s->last_height ||
1667
        s->last_depth != depth) {
1668
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1669
        if (depth == 16 || depth == 32) {
1670
#else
1671
        if (depth == 32) {
1672
#endif
1673
            qemu_free_displaysurface(s->ds);
1674
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1675
                    s->line_offset,
1676
                    s->vram_ptr + (s->start_addr * 4));
1677
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1678
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1679
#endif
1680
            dpy_resize(s->ds);
1681
        } else {
1682
            qemu_console_resize(s->ds, disp_width, height);
1683
        }
1684
        s->last_scr_width = disp_width;
1685
        s->last_scr_height = height;
1686
        s->last_width = disp_width;
1687
        s->last_height = height;
1688
        s->last_line_offset = s->line_offset;
1689
        s->last_depth = depth;
1690
        full_update = 1;
1691
    } else if (is_buffer_shared(s->ds->surface) &&
1692
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1693
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1694
        dpy_setdata(s->ds);
1695
    }
1696

    
1697
    s->rgb_to_pixel =
1698
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1699

    
1700
    if (shift_control == 0) {
1701
        full_update |= update_palette16(s);
1702
        if (s->sr[0x01] & 8) {
1703
            v = VGA_DRAW_LINE4D2;
1704
        } else {
1705
            v = VGA_DRAW_LINE4;
1706
        }
1707
        bits = 4;
1708
    } else if (shift_control == 1) {
1709
        full_update |= update_palette16(s);
1710
        if (s->sr[0x01] & 8) {
1711
            v = VGA_DRAW_LINE2D2;
1712
        } else {
1713
            v = VGA_DRAW_LINE2;
1714
        }
1715
        bits = 4;
1716
    } else {
1717
        switch(s->get_bpp(s)) {
1718
        default:
1719
        case 0:
1720
            full_update |= update_palette256(s);
1721
            v = VGA_DRAW_LINE8D2;
1722
            bits = 4;
1723
            break;
1724
        case 8:
1725
            full_update |= update_palette256(s);
1726
            v = VGA_DRAW_LINE8;
1727
            bits = 8;
1728
            break;
1729
        case 15:
1730
            v = VGA_DRAW_LINE15;
1731
            bits = 16;
1732
            break;
1733
        case 16:
1734
            v = VGA_DRAW_LINE16;
1735
            bits = 16;
1736
            break;
1737
        case 24:
1738
            v = VGA_DRAW_LINE24;
1739
            bits = 24;
1740
            break;
1741
        case 32:
1742
            v = VGA_DRAW_LINE32;
1743
            bits = 32;
1744
            break;
1745
        }
1746
    }
1747
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1748

    
1749
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1750
        s->cursor_invalidate(s);
1751

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

    
1835
static void vga_draw_blank(VGACommonState *s, int full_update)
1836
{
1837
    int i, w, val;
1838
    uint8_t *d;
1839

    
1840
    if (!full_update)
1841
        return;
1842
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1843
        return;
1844

    
1845
    s->rgb_to_pixel =
1846
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1847
    if (ds_get_bits_per_pixel(s->ds) == 8)
1848
        val = s->rgb_to_pixel(0, 0, 0);
1849
    else
1850
        val = 0;
1851
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1852
    d = ds_get_data(s->ds);
1853
    for(i = 0; i < s->last_scr_height; i++) {
1854
        memset(d, val, w);
1855
        d += ds_get_linesize(s->ds);
1856
    }
1857
    dpy_update(s->ds, 0, 0,
1858
               s->last_scr_width, s->last_scr_height);
1859
}
1860

    
1861
#define GMODE_TEXT     0
1862
#define GMODE_GRAPH    1
1863
#define GMODE_BLANK 2
1864

    
1865
static void vga_update_display(void *opaque)
1866
{
1867
    VGACommonState *s = opaque;
1868
    int full_update, graphic_mode;
1869

    
1870
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1871
        /* nothing to do */
1872
    } else {
1873
        full_update = 0;
1874
        if (!(s->ar_index & 0x20)) {
1875
            graphic_mode = GMODE_BLANK;
1876
        } else {
1877
            graphic_mode = s->gr[6] & 1;
1878
        }
1879
        if (graphic_mode != s->graphic_mode) {
1880
            s->graphic_mode = graphic_mode;
1881
            full_update = 1;
1882
        }
1883
        switch(graphic_mode) {
1884
        case GMODE_TEXT:
1885
            vga_draw_text(s, full_update);
1886
            break;
1887
        case GMODE_GRAPH:
1888
            vga_draw_graphic(s, full_update);
1889
            break;
1890
        case GMODE_BLANK:
1891
        default:
1892
            vga_draw_blank(s, full_update);
1893
            break;
1894
        }
1895
    }
1896
}
1897

    
1898
/* force a full display refresh */
1899
static void vga_invalidate_display(void *opaque)
1900
{
1901
    VGACommonState *s = opaque;
1902

    
1903
    s->last_width = -1;
1904
    s->last_height = -1;
1905
}
1906

    
1907
void vga_common_reset(VGACommonState *s)
1908
{
1909
    s->lfb_addr = 0;
1910
    s->lfb_end = 0;
1911
    s->map_addr = 0;
1912
    s->map_end = 0;
1913
    s->lfb_vram_mapped = 0;
1914
    s->sr_index = 0;
1915
    memset(s->sr, '\0', sizeof(s->sr));
1916
    s->gr_index = 0;
1917
    memset(s->gr, '\0', sizeof(s->gr));
1918
    s->ar_index = 0;
1919
    memset(s->ar, '\0', sizeof(s->ar));
1920
    s->ar_flip_flop = 0;
1921
    s->cr_index = 0;
1922
    memset(s->cr, '\0', sizeof(s->cr));
1923
    s->msr = 0;
1924
    s->fcr = 0;
1925
    s->st00 = 0;
1926
    s->st01 = 0;
1927
    s->dac_state = 0;
1928
    s->dac_sub_index = 0;
1929
    s->dac_read_index = 0;
1930
    s->dac_write_index = 0;
1931
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1932
    s->dac_8bit = 0;
1933
    memset(s->palette, '\0', sizeof(s->palette));
1934
    s->bank_offset = 0;
1935
#ifdef CONFIG_BOCHS_VBE
1936
    s->vbe_index = 0;
1937
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1938
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1939
    s->vbe_start_addr = 0;
1940
    s->vbe_line_offset = 0;
1941
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1942
#endif
1943
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1944
    s->graphic_mode = -1; /* force full update */
1945
    s->shift_control = 0;
1946
    s->double_scan = 0;
1947
    s->line_offset = 0;
1948
    s->line_compare = 0;
1949
    s->start_addr = 0;
1950
    s->plane_updated = 0;
1951
    s->last_cw = 0;
1952
    s->last_ch = 0;
1953
    s->last_width = 0;
1954
    s->last_height = 0;
1955
    s->last_scr_width = 0;
1956
    s->last_scr_height = 0;
1957
    s->cursor_start = 0;
1958
    s->cursor_end = 0;
1959
    s->cursor_offset = 0;
1960
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1961
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1962
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1963
    switch (vga_retrace_method) {
1964
    case VGA_RETRACE_DUMB:
1965
        break;
1966
    case VGA_RETRACE_PRECISE:
1967
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1968
        break;
1969
    }
1970
}
1971

    
1972
static void vga_reset(void *opaque)
1973
{
1974
    VGACommonState *s =  opaque;
1975
    vga_common_reset(s);
1976
}
1977

    
1978
#define TEXTMODE_X(x)        ((x) % width)
1979
#define TEXTMODE_Y(x)        ((x) / width)
1980
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1981
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1982
/* relay text rendering to the display driver
1983
 * instead of doing a full vga_update_display() */
1984
static void vga_update_text(void *opaque, console_ch_t *chardata)
1985
{
1986
    VGACommonState *s =  opaque;
1987
    int graphic_mode, i, cursor_offset, cursor_visible;
1988
    int cw, cheight, width, height, size, c_min, c_max;
1989
    uint32_t *src;
1990
    console_ch_t *dst, val;
1991
    char msg_buffer[80];
1992
    int full_update = 0;
1993

    
1994
    if (!(s->ar_index & 0x20)) {
1995
        graphic_mode = GMODE_BLANK;
1996
    } else {
1997
        graphic_mode = s->gr[6] & 1;
1998
    }
1999
    if (graphic_mode != s->graphic_mode) {
2000
        s->graphic_mode = graphic_mode;
2001
        full_update = 1;
2002
    }
2003
    if (s->last_width == -1) {
2004
        s->last_width = 0;
2005
        full_update = 1;
2006
    }
2007

    
2008
    switch (graphic_mode) {
2009
    case GMODE_TEXT:
2010
        /* TODO: update palette */
2011
        full_update |= update_basic_params(s);
2012

    
2013
        /* total width & height */
2014
        cheight = (s->cr[9] & 0x1f) + 1;
2015
        cw = 8;
2016
        if (!(s->sr[1] & 0x01))
2017
            cw = 9;
2018
        if (s->sr[1] & 0x08)
2019
            cw = 16; /* NOTE: no 18 pixel wide */
2020
        width = (s->cr[0x01] + 1);
2021
        if (s->cr[0x06] == 100) {
2022
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2023
            height = 100;
2024
        } else {
2025
            height = s->cr[0x12] | 
2026
                ((s->cr[0x07] & 0x02) << 7) | 
2027
                ((s->cr[0x07] & 0x40) << 3);
2028
            height = (height + 1) / cheight;
2029
        }
2030

    
2031
        size = (height * width);
2032
        if (size > CH_ATTR_SIZE) {
2033
            if (!full_update)
2034
                return;
2035

    
2036
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2037
                     width, height);
2038
            break;
2039
        }
2040

    
2041
        if (width != s->last_width || height != s->last_height ||
2042
            cw != s->last_cw || cheight != s->last_ch) {
2043
            s->last_scr_width = width * cw;
2044
            s->last_scr_height = height * cheight;
2045
            s->ds->surface->width = width;
2046
            s->ds->surface->height = height;
2047
            dpy_resize(s->ds);
2048
            s->last_width = width;
2049
            s->last_height = height;
2050
            s->last_ch = cheight;
2051
            s->last_cw = cw;
2052
            full_update = 1;
2053
        }
2054

    
2055
        /* Update "hardware" cursor */
2056
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2057
        if (cursor_offset != s->cursor_offset ||
2058
            s->cr[0xa] != s->cursor_start ||
2059
            s->cr[0xb] != s->cursor_end || full_update) {
2060
            cursor_visible = !(s->cr[0xa] & 0x20);
2061
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2062
                dpy_cursor(s->ds,
2063
                           TEXTMODE_X(cursor_offset),
2064
                           TEXTMODE_Y(cursor_offset));
2065
            else
2066
                dpy_cursor(s->ds, -1, -1);
2067
            s->cursor_offset = cursor_offset;
2068
            s->cursor_start = s->cr[0xa];
2069
            s->cursor_end = s->cr[0xb];
2070
        }
2071

    
2072
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2073
        dst = chardata;
2074

    
2075
        if (full_update) {
2076
            for (i = 0; i < size; src ++, dst ++, i ++)
2077
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2078

    
2079
            dpy_update(s->ds, 0, 0, width, height);
2080
        } else {
2081
            c_max = 0;
2082

    
2083
            for (i = 0; i < size; src ++, dst ++, i ++) {
2084
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2085
                if (*dst != val) {
2086
                    *dst = val;
2087
                    c_max = i;
2088
                    break;
2089
                }
2090
            }
2091
            c_min = i;
2092
            for (; i < size; src ++, dst ++, i ++) {
2093
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2094
                if (*dst != val) {
2095
                    *dst = val;
2096
                    c_max = i;
2097
                }
2098
            }
2099

    
2100
            if (c_min <= c_max) {
2101
                i = TEXTMODE_Y(c_min);
2102
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2103
            }
2104
        }
2105

    
2106
        return;
2107
    case GMODE_GRAPH:
2108
        if (!full_update)
2109
            return;
2110

    
2111
        s->get_resolution(s, &width, &height);
2112
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2113
                 width, height);
2114
        break;
2115
    case GMODE_BLANK:
2116
    default:
2117
        if (!full_update)
2118
            return;
2119

    
2120
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2121
        break;
2122
    }
2123

    
2124
    /* Display a message */
2125
    s->last_width = 60;
2126
    s->last_height = height = 3;
2127
    dpy_cursor(s->ds, -1, -1);
2128
    s->ds->surface->width = s->last_width;
2129
    s->ds->surface->height = height;
2130
    dpy_resize(s->ds);
2131

    
2132
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2133
        console_write_ch(dst ++, ' ');
2134

    
2135
    size = strlen(msg_buffer);
2136
    width = (s->last_width - size) / 2;
2137
    dst = chardata + s->last_width + width;
2138
    for (i = 0; i < size; i ++)
2139
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2140

    
2141
    dpy_update(s->ds, 0, 0, s->last_width, height);
2142
}
2143

    
2144
CPUReadMemoryFunc * const vga_mem_read[3] = {
2145
    vga_mem_readb,
2146
    vga_mem_readw,
2147
    vga_mem_readl,
2148
};
2149

    
2150
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2151
    vga_mem_writeb,
2152
    vga_mem_writew,
2153
    vga_mem_writel,
2154
};
2155

    
2156
static int vga_common_post_load(void *opaque, int version_id)
2157
{
2158
    VGACommonState *s = opaque;
2159

    
2160
    /* force refresh */
2161
    s->graphic_mode = -1;
2162
    return 0;
2163
}
2164

    
2165
const VMStateDescription vmstate_vga_common = {
2166
    .name = "vga",
2167
    .version_id = 2,
2168
    .minimum_version_id = 2,
2169
    .minimum_version_id_old = 2,
2170
    .post_load = vga_common_post_load,
2171
    .fields      = (VMStateField []) {
2172
        VMSTATE_UINT32(latch, VGACommonState),
2173
        VMSTATE_UINT8(sr_index, VGACommonState),
2174
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2175
        VMSTATE_UINT8(gr_index, VGACommonState),
2176
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2177
        VMSTATE_UINT8(ar_index, VGACommonState),
2178
        VMSTATE_BUFFER(ar, VGACommonState),
2179
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2180
        VMSTATE_UINT8(cr_index, VGACommonState),
2181
        VMSTATE_BUFFER(cr, VGACommonState),
2182
        VMSTATE_UINT8(msr, VGACommonState),
2183
        VMSTATE_UINT8(fcr, VGACommonState),
2184
        VMSTATE_UINT8(st00, VGACommonState),
2185
        VMSTATE_UINT8(st01, VGACommonState),
2186

    
2187
        VMSTATE_UINT8(dac_state, VGACommonState),
2188
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2189
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2190
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2191
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2192
        VMSTATE_BUFFER(palette, VGACommonState),
2193

    
2194
        VMSTATE_INT32(bank_offset, VGACommonState),
2195
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2196
#ifdef CONFIG_BOCHS_VBE
2197
        VMSTATE_UINT16(vbe_index, VGACommonState),
2198
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2199
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2200
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2201
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2202
#endif
2203
        VMSTATE_END_OF_LIST()
2204
    }
2205
};
2206

    
2207
void vga_common_init(VGACommonState *s, int vga_ram_size)
2208
{
2209
    int i, j, v, b;
2210

    
2211
    for(i = 0;i < 256; i++) {
2212
        v = 0;
2213
        for(j = 0; j < 8; j++) {
2214
            v |= ((i >> j) & 1) << (j * 4);
2215
        }
2216
        expand4[i] = v;
2217

    
2218
        v = 0;
2219
        for(j = 0; j < 4; j++) {
2220
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2221
        }
2222
        expand2[i] = v;
2223
    }
2224
    for(i = 0; i < 16; i++) {
2225
        v = 0;
2226
        for(j = 0; j < 4; j++) {
2227
            b = ((i >> j) & 1);
2228
            v |= b << (2 * j);
2229
            v |= b << (2 * j + 1);
2230
        }
2231
        expand4to8[i] = v;
2232
    }
2233

    
2234
#ifdef CONFIG_BOCHS_VBE
2235
    s->is_vbe_vmstate = 1;
2236
#else
2237
    s->is_vbe_vmstate = 0;
2238
#endif
2239
    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
2240
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2241
    s->vram_size = vga_ram_size;
2242
    s->get_bpp = vga_get_bpp;
2243
    s->get_offsets = vga_get_offsets;
2244
    s->get_resolution = vga_get_resolution;
2245
    s->update = vga_update_display;
2246
    s->invalidate = vga_invalidate_display;
2247
    s->screen_dump = vga_screen_dump;
2248
    s->text_update = vga_update_text;
2249
    switch (vga_retrace_method) {
2250
    case VGA_RETRACE_DUMB:
2251
        s->retrace = vga_dumb_retrace;
2252
        s->update_retrace_info = vga_dumb_update_retrace_info;
2253
        break;
2254

    
2255
    case VGA_RETRACE_PRECISE:
2256
        s->retrace = vga_precise_retrace;
2257
        s->update_retrace_info = vga_precise_update_retrace_info;
2258
        break;
2259
    }
2260
}
2261

    
2262
/* used by both ISA and PCI */
2263
int vga_init_io(VGACommonState *s)
2264
{
2265
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2266

    
2267
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2268
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2269
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2270
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2271

    
2272
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2273

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

    
2279
#ifdef CONFIG_BOCHS_VBE
2280
#if defined (TARGET_I386)
2281
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2282
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2283

    
2284
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2285
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2286
#else
2287
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2288
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2289

    
2290
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2291
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2292
#endif
2293
#endif /* CONFIG_BOCHS_VBE */
2294

    
2295
    return cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
2296
                                  DEVICE_LITTLE_ENDIAN);
2297
}
2298

    
2299
void vga_init(VGACommonState *s)
2300
{
2301
    int vga_io_memory;
2302

    
2303
    qemu_register_reset(vga_reset, s);
2304

    
2305
    s->bank_offset = 0;
2306

    
2307
    vga_io_memory = vga_init_io(s);
2308
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2309
                                 vga_io_memory);
2310
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2311
}
2312

    
2313
void vga_init_vbe(VGACommonState *s)
2314
{
2315
#ifdef CONFIG_BOCHS_VBE
2316
    /* XXX: use optimized standard vga accesses */
2317
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2318
                                 VGA_RAM_SIZE, s->vram_offset);
2319
    s->vbe_mapped = 1;
2320
#endif 
2321
}
2322
/********************************************************/
2323
/* vga screen dump */
2324

    
2325
static void vga_save_dpy_update(DisplayState *ds,
2326
                                int x, int y, int w, int h)
2327
{
2328
    if (screen_dump_filename) {
2329
        ppm_save(screen_dump_filename, ds->surface);
2330
        screen_dump_filename = NULL;
2331
    }
2332
}
2333

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

    
2338
static void vga_save_dpy_refresh(DisplayState *s)
2339
{
2340
}
2341

    
2342
int ppm_save(const char *filename, struct DisplaySurface *ds)
2343
{
2344
    FILE *f;
2345
    uint8_t *d, *d1;
2346
    uint32_t v;
2347
    int y, x;
2348
    uint8_t r, g, b;
2349

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

    
2380
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2381
{
2382
    DisplayChangeListener *dcl;
2383

    
2384
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2385
    dcl->dpy_update = vga_save_dpy_update;
2386
    dcl->dpy_resize = vga_save_dpy_resize;
2387
    dcl->dpy_refresh = vga_save_dpy_refresh;
2388
    register_displaychangelistener(ds, dcl);
2389
    return dcl;
2390
}
2391

    
2392
/* save the vga display in a PPM image even if no display is
2393
   available */
2394
static void vga_screen_dump(void *opaque, const char *filename)
2395
{
2396
    VGACommonState *s = opaque;
2397

    
2398
    if (!screen_dump_dcl)
2399
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2400

    
2401
    screen_dump_filename = (char *)filename;
2402
    vga_invalidate_display(s);
2403
    vga_hw_update();
2404
}
2405