Statistics
| Branch: | Revision:

root / hw / vga.c @ fbdaa002

History | View | Annotate | Download (68 kB)

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

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

    
37
//#define DEBUG_BOCHS_VBE
38

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

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

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

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

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

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

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

    
114
#undef PAT
115

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

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

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

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

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

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

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

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

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

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

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

    
192

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

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

    
200
    chars_per_sec = clk_hz[clock_sel] / dots;
201

    
202
    htotal_chars <<= clocking_mode;
203

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

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

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

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

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

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

    
261
        cur_tick = qemu_get_clock(vm_clock);
262

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1134
    full_update = 0;
1135

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

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

    
1149
#define NB_DEPTHS 7
1150

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

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

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

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

    
1199
static const uint8_t cursor_glyph[32 * 4] = {
1200
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1201
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1202
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1203
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1204
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1205
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216
};
1217

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

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

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

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

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

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

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

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

    
1303
    line_offset = s->line_offset;
1304
    s1 = s->vram_ptr + (s->start_addr * 4);
1305

    
1306
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1307
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1308
    if ((height * width) > CH_ATTR_SIZE) {
1309
        /* better than nothing: exit if transient size is too big */
1310
        return;
1311
    }
1312

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

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

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

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

    
1426
enum {
1427
    VGA_DRAW_LINE2,
1428
    VGA_DRAW_LINE2D2,
1429
    VGA_DRAW_LINE4,
1430
    VGA_DRAW_LINE4D2,
1431
    VGA_DRAW_LINE8D2,
1432
    VGA_DRAW_LINE8,
1433
    VGA_DRAW_LINE15,
1434
    VGA_DRAW_LINE16,
1435
    VGA_DRAW_LINE24,
1436
    VGA_DRAW_LINE32,
1437
    VGA_DRAW_LINE_NB,
1438
};
1439

    
1440
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1441
    vga_draw_line2_8,
1442
    vga_draw_line2_16,
1443
    vga_draw_line2_16,
1444
    vga_draw_line2_32,
1445
    vga_draw_line2_32,
1446
    vga_draw_line2_16,
1447
    vga_draw_line2_16,
1448

    
1449
    vga_draw_line2d2_8,
1450
    vga_draw_line2d2_16,
1451
    vga_draw_line2d2_16,
1452
    vga_draw_line2d2_32,
1453
    vga_draw_line2d2_32,
1454
    vga_draw_line2d2_16,
1455
    vga_draw_line2d2_16,
1456

    
1457
    vga_draw_line4_8,
1458
    vga_draw_line4_16,
1459
    vga_draw_line4_16,
1460
    vga_draw_line4_32,
1461
    vga_draw_line4_32,
1462
    vga_draw_line4_16,
1463
    vga_draw_line4_16,
1464

    
1465
    vga_draw_line4d2_8,
1466
    vga_draw_line4d2_16,
1467
    vga_draw_line4d2_16,
1468
    vga_draw_line4d2_32,
1469
    vga_draw_line4d2_32,
1470
    vga_draw_line4d2_16,
1471
    vga_draw_line4d2_16,
1472

    
1473
    vga_draw_line8d2_8,
1474
    vga_draw_line8d2_16,
1475
    vga_draw_line8d2_16,
1476
    vga_draw_line8d2_32,
1477
    vga_draw_line8d2_32,
1478
    vga_draw_line8d2_16,
1479
    vga_draw_line8d2_16,
1480

    
1481
    vga_draw_line8_8,
1482
    vga_draw_line8_16,
1483
    vga_draw_line8_16,
1484
    vga_draw_line8_32,
1485
    vga_draw_line8_32,
1486
    vga_draw_line8_16,
1487
    vga_draw_line8_16,
1488

    
1489
    vga_draw_line15_8,
1490
    vga_draw_line15_15,
1491
    vga_draw_line15_16,
1492
    vga_draw_line15_32,
1493
    vga_draw_line15_32bgr,
1494
    vga_draw_line15_15bgr,
1495
    vga_draw_line15_16bgr,
1496

    
1497
    vga_draw_line16_8,
1498
    vga_draw_line16_15,
1499
    vga_draw_line16_16,
1500
    vga_draw_line16_32,
1501
    vga_draw_line16_32bgr,
1502
    vga_draw_line16_15bgr,
1503
    vga_draw_line16_16bgr,
1504

    
1505
    vga_draw_line24_8,
1506
    vga_draw_line24_15,
1507
    vga_draw_line24_16,
1508
    vga_draw_line24_32,
1509
    vga_draw_line24_32bgr,
1510
    vga_draw_line24_15bgr,
1511
    vga_draw_line24_16bgr,
1512

    
1513
    vga_draw_line32_8,
1514
    vga_draw_line32_15,
1515
    vga_draw_line32_16,
1516
    vga_draw_line32_32,
1517
    vga_draw_line32_32bgr,
1518
    vga_draw_line32_15bgr,
1519
    vga_draw_line32_16bgr,
1520
};
1521

    
1522
static int vga_get_bpp(VGACommonState *s)
1523
{
1524
    int ret;
1525
#ifdef CONFIG_BOCHS_VBE
1526
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1527
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1528
    } else
1529
#endif
1530
    {
1531
        ret = 0;
1532
    }
1533
    return ret;
1534
}
1535

    
1536
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1537
{
1538
    int width, height;
1539

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

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

    
1569
static void vga_sync_dirty_bitmap(VGACommonState *s)
1570
{
1571
    if (s->map_addr)
1572
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1573

    
1574
    if (s->lfb_vram_mapped) {
1575
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1576
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1577
    }
1578
}
1579

    
1580
void vga_dirty_log_start(VGACommonState *s)
1581
{
1582
    if (kvm_enabled() && s->map_addr)
1583
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1584

    
1585
    if (kvm_enabled() && s->lfb_vram_mapped) {
1586
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1587
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1588
    }
1589
}
1590

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

    
1604
    full_update |= update_basic_params(s);
1605

    
1606
    if (!full_update)
1607
        vga_sync_dirty_bitmap(s);
1608

    
1609
    s->get_resolution(s, &width, &height);
1610
    disp_width = width;
1611

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

    
1629
    if (shift_control == 0) {
1630
        if (s->sr[0x01] & 8) {
1631
            disp_width <<= 1;
1632
        }
1633
    } else if (shift_control == 1) {
1634
        if (s->sr[0x01] & 8) {
1635
            disp_width <<= 1;
1636
        }
1637
    }
1638

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

    
1673
    s->rgb_to_pixel =
1674
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1675

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

    
1725
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1726
        s->cursor_invalidate(s);
1727

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

    
1811
static void vga_draw_blank(VGACommonState *s, int full_update)
1812
{
1813
    int i, w, val;
1814
    uint8_t *d;
1815

    
1816
    if (!full_update)
1817
        return;
1818
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1819
        return;
1820

    
1821
    s->rgb_to_pixel =
1822
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1823
    if (ds_get_bits_per_pixel(s->ds) == 8)
1824
        val = s->rgb_to_pixel(0, 0, 0);
1825
    else
1826
        val = 0;
1827
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1828
    d = ds_get_data(s->ds);
1829
    for(i = 0; i < s->last_scr_height; i++) {
1830
        memset(d, val, w);
1831
        d += ds_get_linesize(s->ds);
1832
    }
1833
    dpy_update(s->ds, 0, 0,
1834
               s->last_scr_width, s->last_scr_height);
1835
}
1836

    
1837
#define GMODE_TEXT     0
1838
#define GMODE_GRAPH    1
1839
#define GMODE_BLANK 2
1840

    
1841
static void vga_update_display(void *opaque)
1842
{
1843
    VGACommonState *s = opaque;
1844
    int full_update, graphic_mode;
1845

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

    
1875
/* force a full display refresh */
1876
static void vga_invalidate_display(void *opaque)
1877
{
1878
    VGACommonState *s = opaque;
1879

    
1880
    s->full_update = 1;
1881
}
1882

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

    
1950
static void vga_reset(void *opaque)
1951
{
1952
    VGACommonState *s =  opaque;
1953
    vga_common_reset(s);
1954
}
1955

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

    
1972
    if (!(s->ar_index & 0x20)) {
1973
        graphic_mode = GMODE_BLANK;
1974
    } else {
1975
        graphic_mode = s->gr[6] & 1;
1976
    }
1977
    if (graphic_mode != s->graphic_mode) {
1978
        s->graphic_mode = graphic_mode;
1979
        full_update = 1;
1980
    }
1981
    if (s->last_width == -1) {
1982
        s->last_width = 0;
1983
        full_update = 1;
1984
    }
1985

    
1986
    switch (graphic_mode) {
1987
    case GMODE_TEXT:
1988
        /* TODO: update palette */
1989
        full_update |= update_basic_params(s);
1990

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

    
2009
        size = (height * width);
2010
        if (size > CH_ATTR_SIZE) {
2011
            if (!full_update)
2012
                return;
2013

    
2014
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2015
                     width, height);
2016
            break;
2017
        }
2018

    
2019
        if (width != s->last_width || height != s->last_height ||
2020
            cw != s->last_cw || cheight != s->last_ch) {
2021
            s->last_scr_width = width * cw;
2022
            s->last_scr_height = height * cheight;
2023
            s->ds->surface->width = width;
2024
            s->ds->surface->height = height;
2025
            dpy_resize(s->ds);
2026
            s->last_width = width;
2027
            s->last_height = height;
2028
            s->last_ch = cheight;
2029
            s->last_cw = cw;
2030
            full_update = 1;
2031
        }
2032

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

    
2050
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2051
        dst = chardata;
2052

    
2053
        if (full_update) {
2054
            for (i = 0; i < size; src ++, dst ++, i ++)
2055
                console_write_ch(dst, VMEM2CHTYPE(*src));
2056

    
2057
            dpy_update(s->ds, 0, 0, width, height);
2058
        } else {
2059
            c_max = 0;
2060

    
2061
            for (i = 0; i < size; src ++, dst ++, i ++) {
2062
                console_write_ch(&val, VMEM2CHTYPE(*src));
2063
                if (*dst != val) {
2064
                    *dst = val;
2065
                    c_max = i;
2066
                    break;
2067
                }
2068
            }
2069
            c_min = i;
2070
            for (; i < size; src ++, dst ++, i ++) {
2071
                console_write_ch(&val, VMEM2CHTYPE(*src));
2072
                if (*dst != val) {
2073
                    *dst = val;
2074
                    c_max = i;
2075
                }
2076
            }
2077

    
2078
            if (c_min <= c_max) {
2079
                i = TEXTMODE_Y(c_min);
2080
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2081
            }
2082
        }
2083

    
2084
        return;
2085
    case GMODE_GRAPH:
2086
        if (!full_update)
2087
            return;
2088

    
2089
        s->get_resolution(s, &width, &height);
2090
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2091
                 width, height);
2092
        break;
2093
    case GMODE_BLANK:
2094
    default:
2095
        if (!full_update)
2096
            return;
2097

    
2098
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2099
        break;
2100
    }
2101

    
2102
    /* Display a message */
2103
    s->last_width = 60;
2104
    s->last_height = height = 3;
2105
    dpy_cursor(s->ds, -1, -1);
2106
    s->ds->surface->width = s->last_width;
2107
    s->ds->surface->height = height;
2108
    dpy_resize(s->ds);
2109

    
2110
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2111
        console_write_ch(dst ++, ' ');
2112

    
2113
    size = strlen(msg_buffer);
2114
    width = (s->last_width - size) / 2;
2115
    dst = chardata + s->last_width + width;
2116
    for (i = 0; i < size; i ++)
2117
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2118

    
2119
    dpy_update(s->ds, 0, 0, s->last_width, height);
2120
}
2121

    
2122
CPUReadMemoryFunc * const vga_mem_read[3] = {
2123
    vga_mem_readb,
2124
    vga_mem_readw,
2125
    vga_mem_readl,
2126
};
2127

    
2128
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2129
    vga_mem_writeb,
2130
    vga_mem_writew,
2131
    vga_mem_writel,
2132
};
2133

    
2134
void vga_common_save(QEMUFile *f, void *opaque)
2135
{
2136
    VGACommonState *s = opaque;
2137
    int i;
2138

    
2139
    qemu_put_be32s(f, &s->latch);
2140
    qemu_put_8s(f, &s->sr_index);
2141
    qemu_put_buffer(f, s->sr, 8);
2142
    qemu_put_8s(f, &s->gr_index);
2143
    qemu_put_buffer(f, s->gr, 16);
2144
    qemu_put_8s(f, &s->ar_index);
2145
    qemu_put_buffer(f, s->ar, 21);
2146
    qemu_put_be32(f, s->ar_flip_flop);
2147
    qemu_put_8s(f, &s->cr_index);
2148
    qemu_put_buffer(f, s->cr, 256);
2149
    qemu_put_8s(f, &s->msr);
2150
    qemu_put_8s(f, &s->fcr);
2151
    qemu_put_byte(f, s->st00);
2152
    qemu_put_8s(f, &s->st01);
2153

    
2154
    qemu_put_8s(f, &s->dac_state);
2155
    qemu_put_8s(f, &s->dac_sub_index);
2156
    qemu_put_8s(f, &s->dac_read_index);
2157
    qemu_put_8s(f, &s->dac_write_index);
2158
    qemu_put_buffer(f, s->dac_cache, 3);
2159
    qemu_put_buffer(f, s->palette, 768);
2160

    
2161
    qemu_put_be32(f, s->bank_offset);
2162
#ifdef CONFIG_BOCHS_VBE
2163
    qemu_put_byte(f, 1);
2164
    qemu_put_be16s(f, &s->vbe_index);
2165
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2166
        qemu_put_be16s(f, &s->vbe_regs[i]);
2167
    qemu_put_be32s(f, &s->vbe_start_addr);
2168
    qemu_put_be32s(f, &s->vbe_line_offset);
2169
    qemu_put_be32s(f, &s->vbe_bank_mask);
2170
#else
2171
    qemu_put_byte(f, 0);
2172
#endif
2173
}
2174

    
2175
int vga_common_load(QEMUFile *f, void *opaque, int version_id)
2176
{
2177
    VGACommonState *s = opaque;
2178
    int is_vbe, i;
2179

    
2180
    if (version_id > 2)
2181
        return -EINVAL;
2182

    
2183
    qemu_get_be32s(f, &s->latch);
2184
    qemu_get_8s(f, &s->sr_index);
2185
    qemu_get_buffer(f, s->sr, 8);
2186
    qemu_get_8s(f, &s->gr_index);
2187
    qemu_get_buffer(f, s->gr, 16);
2188
    qemu_get_8s(f, &s->ar_index);
2189
    qemu_get_buffer(f, s->ar, 21);
2190
    s->ar_flip_flop=qemu_get_be32(f);
2191
    qemu_get_8s(f, &s->cr_index);
2192
    qemu_get_buffer(f, s->cr, 256);
2193
    qemu_get_8s(f, &s->msr);
2194
    qemu_get_8s(f, &s->fcr);
2195
    qemu_get_8s(f, &s->st00);
2196
    qemu_get_8s(f, &s->st01);
2197

    
2198
    qemu_get_8s(f, &s->dac_state);
2199
    qemu_get_8s(f, &s->dac_sub_index);
2200
    qemu_get_8s(f, &s->dac_read_index);
2201
    qemu_get_8s(f, &s->dac_write_index);
2202
    qemu_get_buffer(f, s->dac_cache, 3);
2203
    qemu_get_buffer(f, s->palette, 768);
2204

    
2205
    s->bank_offset=qemu_get_be32(f);
2206
    is_vbe = qemu_get_byte(f);
2207
#ifdef CONFIG_BOCHS_VBE
2208
    if (!is_vbe)
2209
        return -EINVAL;
2210
    qemu_get_be16s(f, &s->vbe_index);
2211
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2212
        qemu_get_be16s(f, &s->vbe_regs[i]);
2213
    qemu_get_be32s(f, &s->vbe_start_addr);
2214
    qemu_get_be32s(f, &s->vbe_line_offset);
2215
    qemu_get_be32s(f, &s->vbe_bank_mask);
2216
#else
2217
    if (is_vbe)
2218
        return -EINVAL;
2219
#endif
2220

    
2221
    /* force refresh */
2222
    s->graphic_mode = -1;
2223
    return 0;
2224
}
2225

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

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

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

    
2253
    s->vram_offset = qemu_ram_alloc(vga_ram_size);
2254
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2255
    s->vram_size = vga_ram_size;
2256
    s->get_bpp = vga_get_bpp;
2257
    s->get_offsets = vga_get_offsets;
2258
    s->get_resolution = vga_get_resolution;
2259
    s->update = vga_update_display;
2260
    s->invalidate = vga_invalidate_display;
2261
    s->screen_dump = vga_screen_dump;
2262
    s->text_update = vga_update_text;
2263
    switch (vga_retrace_method) {
2264
    case VGA_RETRACE_DUMB:
2265
        s->retrace = vga_dumb_retrace;
2266
        s->update_retrace_info = vga_dumb_update_retrace_info;
2267
        break;
2268

    
2269
    case VGA_RETRACE_PRECISE:
2270
        s->retrace = vga_precise_retrace;
2271
        s->update_retrace_info = vga_precise_update_retrace_info;
2272
        break;
2273
    }
2274
    vga_reset(s);
2275
}
2276

    
2277
/* used by both ISA and PCI */
2278
void vga_init(VGACommonState *s)
2279
{
2280
    int vga_io_memory;
2281

    
2282
    qemu_register_reset(vga_reset, s);
2283

    
2284
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2285

    
2286
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2287
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2288
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2289
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2290

    
2291
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2292

    
2293
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2294
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2295
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2296
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2297
    s->bank_offset = 0;
2298

    
2299
#ifdef CONFIG_BOCHS_VBE
2300
#if defined (TARGET_I386)
2301
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2302
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2303

    
2304
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2305
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2306

    
2307
    /* old Bochs IO ports */
2308
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2309
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2310

    
2311
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2312
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2313
#else
2314
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2315
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2316

    
2317
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2318
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2319
#endif
2320
#endif /* CONFIG_BOCHS_VBE */
2321

    
2322
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2323
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2324
                                 vga_io_memory);
2325
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2326
}
2327

    
2328
/********************************************************/
2329
/* vga screen dump */
2330

    
2331
static void vga_save_dpy_update(DisplayState *ds,
2332
                                int x, int y, int w, int h)
2333
{
2334
    if (screen_dump_filename) {
2335
        ppm_save(screen_dump_filename, ds->surface);
2336
        screen_dump_filename = NULL;
2337
    }
2338
}
2339

    
2340
static void vga_save_dpy_resize(DisplayState *s)
2341
{
2342
}
2343

    
2344
static void vga_save_dpy_refresh(DisplayState *s)
2345
{
2346
}
2347

    
2348
int ppm_save(const char *filename, struct DisplaySurface *ds)
2349
{
2350
    FILE *f;
2351
    uint8_t *d, *d1;
2352
    uint32_t v;
2353
    int y, x;
2354
    uint8_t r, g, b;
2355

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

    
2386
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2387
{
2388
    DisplayChangeListener *dcl;
2389

    
2390
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2391
    dcl->dpy_update = vga_save_dpy_update;
2392
    dcl->dpy_resize = vga_save_dpy_resize;
2393
    dcl->dpy_refresh = vga_save_dpy_refresh;
2394
    register_displaychangelistener(ds, dcl);
2395
    return dcl;
2396
}
2397

    
2398
/* save the vga display in a PPM image even if no display is
2399
   available */
2400
static void vga_screen_dump(void *opaque, const char *filename)
2401
{
2402
    VGACommonState *s = opaque;
2403

    
2404
    if (!screen_dump_dcl)
2405
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2406

    
2407
    screen_dump_filename = (char *)filename;
2408
    vga_invalidate_display(s);
2409
    vga_hw_update();
2410
}
2411