Statistics
| Branch: | Revision:

root / hw / vga.c @ 9159f679

History | View | Annotate | Download (67.8 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 dots;
173
#if 0
174
    int div2, sldiv2;
175
#endif
176
    int clocking_mode;
177
    int clock_sel;
178
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
179
    int64_t chars_per_sec;
180
    struct vga_precise_retrace *r = &s->retrace_info.precise;
181

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

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

    
195

    
196

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

    
201
    chars_per_sec = clk_hz[clock_sel] / dots;
202

    
203
    htotal_chars <<= clocking_mode;
204

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

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

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

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

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

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

    
264
        cur_tick = qemu_get_clock(vm_clock);
265

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
767
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
768
{
769
    uint32_t v;
770
    v = vga_mem_readb(opaque, addr);
771
    v |= vga_mem_readb(opaque, addr + 1) << 8;
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
    v = vga_mem_readb(opaque, addr);
779
    v |= vga_mem_readb(opaque, addr + 1) << 8;
780
    v |= vga_mem_readb(opaque, addr + 2) << 16;
781
    v |= vga_mem_readb(opaque, addr + 3) << 24;
782
    return v;
783
}
784

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1115
    full_update = 0;
1116

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

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

    
1130
#define NB_DEPTHS 7
1131

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1284
    line_offset = s->line_offset;
1285

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1572
}
1573

    
1574
void vga_dirty_log_start(VGACommonState *s)
1575
{
1576
    if (kvm_enabled() && s->map_addr)
1577
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1578

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

    
1584
#ifdef CONFIG_BOCHS_VBE
1585
    if (kvm_enabled() && s->vbe_mapped) {
1586
        kvm_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 (kvm_enabled() && s->map_addr)
1594
        kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
1595

    
1596
    if (kvm_enabled() && s->lfb_vram_mapped) {
1597
        kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
1598
        kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
1599
    }
1600

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

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

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

    
1627
    full_update |= update_basic_params(s);
1628

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2261
/* used by both ISA and PCI */
2262
void vga_init(VGACommonState *s)
2263
{
2264
    int vga_io_memory;
2265

    
2266
    qemu_register_reset(vga_reset, s);
2267

    
2268
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2269

    
2270
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2271
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2272
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2273
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2274

    
2275
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2276

    
2277
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2278
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2279
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2280
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2281
    s->bank_offset = 0;
2282

    
2283
#ifdef CONFIG_BOCHS_VBE
2284
#if defined (TARGET_I386)
2285
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2286
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2287

    
2288
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2289
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2290
#else
2291
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2292
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2293

    
2294
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2295
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2296
#endif
2297
#endif /* CONFIG_BOCHS_VBE */
2298

    
2299
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s,
2300
                                           DEVICE_LITTLE_ENDIAN);
2301
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2302
                                 vga_io_memory);
2303
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2304
}
2305

    
2306
void vga_init_vbe(VGACommonState *s)
2307
{
2308
#ifdef CONFIG_BOCHS_VBE
2309
    /* XXX: use optimized standard vga accesses */
2310
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2311
                                 VGA_RAM_SIZE, s->vram_offset);
2312
    s->vbe_mapped = 1;
2313
#endif 
2314
}
2315
/********************************************************/
2316
/* vga screen dump */
2317

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

    
2327
static void vga_save_dpy_resize(DisplayState *s)
2328
{
2329
}
2330

    
2331
static void vga_save_dpy_refresh(DisplayState *s)
2332
{
2333
}
2334

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

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

    
2373
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2374
{
2375
    DisplayChangeListener *dcl;
2376

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

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

    
2391
    if (!screen_dump_dcl)
2392
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2393

    
2394
    screen_dump_filename = (char *)filename;
2395
    vga_invalidate_display(s);
2396
    vga_hw_update();
2397
}
2398