Statistics
| Branch: | Revision:

root / hw / vga.c @ de00982e

History | View | Annotate | Download (66.6 kB)

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

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

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

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

    
766
/* called for accesses between 0xa0000 and 0xc0000 */
767
void vga_mem_writeb(VGACommonState *s, target_phys_addr_t addr, uint32_t val)
768
{
769
    int memory_map_mode, plane, write_mode, b, func_select, mask;
770
    uint32_t write_mask, bit_mask, set_mask;
771

    
772
#ifdef DEBUG_VGA_MEM
773
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
774
#endif
775
    /* convert to VGA memory offset */
776
    memory_map_mode = (s->gr[6] >> 2) & 3;
777
    addr &= 0x1ffff;
778
    switch(memory_map_mode) {
779
    case 0:
780
        break;
781
    case 1:
782
        if (addr >= 0x10000)
783
            return;
784
        addr += s->bank_offset;
785
        break;
786
    case 2:
787
        addr -= 0x10000;
788
        if (addr >= 0x8000)
789
            return;
790
        break;
791
    default:
792
    case 3:
793
        addr -= 0x18000;
794
        if (addr >= 0x8000)
795
            return;
796
        break;
797
    }
798

    
799
    if (s->sr[4] & 0x08) {
800
        /* chain 4 mode : simplest access */
801
        plane = addr & 3;
802
        mask = (1 << plane);
803
        if (s->sr[2] & mask) {
804
            s->vram_ptr[addr] = val;
805
#ifdef DEBUG_VGA_MEM
806
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
807
#endif
808
            s->plane_updated |= mask; /* only used to detect font change */
809
            memory_region_set_dirty(&s->vram, addr);
810
        }
811
    } else if (s->gr[5] & 0x10) {
812
        /* odd/even mode (aka text mode mapping) */
813
        plane = (s->gr[4] & 2) | (addr & 1);
814
        mask = (1 << plane);
815
        if (s->sr[2] & mask) {
816
            addr = ((addr & ~1) << 1) | plane;
817
            s->vram_ptr[addr] = val;
818
#ifdef DEBUG_VGA_MEM
819
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
820
#endif
821
            s->plane_updated |= mask; /* only used to detect font change */
822
            memory_region_set_dirty(&s->vram, addr);
823
        }
824
    } else {
825
        /* standard VGA latched access */
826
        write_mode = s->gr[5] & 3;
827
        switch(write_mode) {
828
        default:
829
        case 0:
830
            /* rotate */
831
            b = s->gr[3] & 7;
832
            val = ((val >> b) | (val << (8 - b))) & 0xff;
833
            val |= val << 8;
834
            val |= val << 16;
835

    
836
            /* apply set/reset mask */
837
            set_mask = mask16[s->gr[1]];
838
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
839
            bit_mask = s->gr[8];
840
            break;
841
        case 1:
842
            val = s->latch;
843
            goto do_write;
844
        case 2:
845
            val = mask16[val & 0x0f];
846
            bit_mask = s->gr[8];
847
            break;
848
        case 3:
849
            /* rotate */
850
            b = s->gr[3] & 7;
851
            val = (val >> b) | (val << (8 - b));
852

    
853
            bit_mask = s->gr[8] & val;
854
            val = mask16[s->gr[0]];
855
            break;
856
        }
857

    
858
        /* apply logical operation */
859
        func_select = s->gr[3] >> 3;
860
        switch(func_select) {
861
        case 0:
862
        default:
863
            /* nothing to do */
864
            break;
865
        case 1:
866
            /* and */
867
            val &= s->latch;
868
            break;
869
        case 2:
870
            /* or */
871
            val |= s->latch;
872
            break;
873
        case 3:
874
            /* xor */
875
            val ^= s->latch;
876
            break;
877
        }
878

    
879
        /* apply bit mask */
880
        bit_mask |= bit_mask << 8;
881
        bit_mask |= bit_mask << 16;
882
        val = (val & bit_mask) | (s->latch & ~bit_mask);
883

    
884
    do_write:
885
        /* mask data according to sr[2] */
886
        mask = s->sr[2];
887
        s->plane_updated |= mask; /* only used to detect font change */
888
        write_mask = mask16[mask];
889
        ((uint32_t *)s->vram_ptr)[addr] =
890
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
891
            (val & write_mask);
892
#ifdef DEBUG_VGA_MEM
893
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
894
               addr * 4, write_mask, val);
895
#endif
896
        memory_region_set_dirty(&s->vram, addr << 2);
897
    }
898
}
899

    
900
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
901
                             const uint8_t *font_ptr, int h,
902
                             uint32_t fgcol, uint32_t bgcol);
903
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
904
                                  const uint8_t *font_ptr, int h,
905
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
906
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
907
                                const uint8_t *s, int width);
908

    
909
#define DEPTH 8
910
#include "vga_template.h"
911

    
912
#define DEPTH 15
913
#include "vga_template.h"
914

    
915
#define BGR_FORMAT
916
#define DEPTH 15
917
#include "vga_template.h"
918

    
919
#define DEPTH 16
920
#include "vga_template.h"
921

    
922
#define BGR_FORMAT
923
#define DEPTH 16
924
#include "vga_template.h"
925

    
926
#define DEPTH 32
927
#include "vga_template.h"
928

    
929
#define BGR_FORMAT
930
#define DEPTH 32
931
#include "vga_template.h"
932

    
933
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
934
{
935
    unsigned int col;
936
    col = rgb_to_pixel8(r, g, b);
937
    col |= col << 8;
938
    col |= col << 16;
939
    return col;
940
}
941

    
942
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
943
{
944
    unsigned int col;
945
    col = rgb_to_pixel15(r, g, b);
946
    col |= col << 16;
947
    return col;
948
}
949

    
950
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
951
                                          unsigned int b)
952
{
953
    unsigned int col;
954
    col = rgb_to_pixel15bgr(r, g, b);
955
    col |= col << 16;
956
    return col;
957
}
958

    
959
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
960
{
961
    unsigned int col;
962
    col = rgb_to_pixel16(r, g, b);
963
    col |= col << 16;
964
    return col;
965
}
966

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

    
976
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
977
{
978
    unsigned int col;
979
    col = rgb_to_pixel32(r, g, b);
980
    return col;
981
}
982

    
983
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
984
{
985
    unsigned int col;
986
    col = rgb_to_pixel32bgr(r, g, b);
987
    return col;
988
}
989

    
990
/* return true if the palette was modified */
991
static int update_palette16(VGACommonState *s)
992
{
993
    int full_update, i;
994
    uint32_t v, col, *palette;
995

    
996
    full_update = 0;
997
    palette = s->last_palette;
998
    for(i = 0; i < 16; i++) {
999
        v = s->ar[i];
1000
        if (s->ar[0x10] & 0x80)
1001
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1002
        else
1003
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1004
        v = v * 3;
1005
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1006
                              c6_to_8(s->palette[v + 1]),
1007
                              c6_to_8(s->palette[v + 2]));
1008
        if (col != palette[i]) {
1009
            full_update = 1;
1010
            palette[i] = col;
1011
        }
1012
    }
1013
    return full_update;
1014
}
1015

    
1016
/* return true if the palette was modified */
1017
static int update_palette256(VGACommonState *s)
1018
{
1019
    int full_update, i;
1020
    uint32_t v, col, *palette;
1021

    
1022
    full_update = 0;
1023
    palette = s->last_palette;
1024
    v = 0;
1025
    for(i = 0; i < 256; i++) {
1026
        if (s->dac_8bit) {
1027
          col = s->rgb_to_pixel(s->palette[v],
1028
                                s->palette[v + 1],
1029
                                s->palette[v + 2]);
1030
        } else {
1031
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1032
                                c6_to_8(s->palette[v + 1]),
1033
                                c6_to_8(s->palette[v + 2]));
1034
        }
1035
        if (col != palette[i]) {
1036
            full_update = 1;
1037
            palette[i] = col;
1038
        }
1039
        v += 3;
1040
    }
1041
    return full_update;
1042
}
1043

    
1044
static void vga_get_offsets(VGACommonState *s,
1045
                            uint32_t *pline_offset,
1046
                            uint32_t *pstart_addr,
1047
                            uint32_t *pline_compare)
1048
{
1049
    uint32_t start_addr, line_offset, line_compare;
1050
#ifdef CONFIG_BOCHS_VBE
1051
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1052
        line_offset = s->vbe_line_offset;
1053
        start_addr = s->vbe_start_addr;
1054
        line_compare = 65535;
1055
    } else
1056
#endif
1057
    {
1058
        /* compute line_offset in bytes */
1059
        line_offset = s->cr[0x13];
1060
        line_offset <<= 3;
1061

    
1062
        /* starting address */
1063
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1064

    
1065
        /* line compare */
1066
        line_compare = s->cr[0x18] |
1067
            ((s->cr[0x07] & 0x10) << 4) |
1068
            ((s->cr[0x09] & 0x40) << 3);
1069
    }
1070
    *pline_offset = line_offset;
1071
    *pstart_addr = start_addr;
1072
    *pline_compare = line_compare;
1073
}
1074

    
1075
/* update start_addr and line_offset. Return TRUE if modified */
1076
static int update_basic_params(VGACommonState *s)
1077
{
1078
    int full_update;
1079
    uint32_t start_addr, line_offset, line_compare;
1080

    
1081
    full_update = 0;
1082

    
1083
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1084

    
1085
    if (line_offset != s->line_offset ||
1086
        start_addr != s->start_addr ||
1087
        line_compare != s->line_compare) {
1088
        s->line_offset = line_offset;
1089
        s->start_addr = start_addr;
1090
        s->line_compare = line_compare;
1091
        full_update = 1;
1092
    }
1093
    return full_update;
1094
}
1095

    
1096
#define NB_DEPTHS 7
1097

    
1098
static inline int get_depth_index(DisplayState *s)
1099
{
1100
    switch(ds_get_bits_per_pixel(s)) {
1101
    default:
1102
    case 8:
1103
        return 0;
1104
    case 15:
1105
        return 1;
1106
    case 16:
1107
        return 2;
1108
    case 32:
1109
        if (is_surface_bgr(s->surface))
1110
            return 4;
1111
        else
1112
            return 3;
1113
    }
1114
}
1115

    
1116
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1117
    vga_draw_glyph8_8,
1118
    vga_draw_glyph8_16,
1119
    vga_draw_glyph8_16,
1120
    vga_draw_glyph8_32,
1121
    vga_draw_glyph8_32,
1122
    vga_draw_glyph8_16,
1123
    vga_draw_glyph8_16,
1124
};
1125

    
1126
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1127
    vga_draw_glyph16_8,
1128
    vga_draw_glyph16_16,
1129
    vga_draw_glyph16_16,
1130
    vga_draw_glyph16_32,
1131
    vga_draw_glyph16_32,
1132
    vga_draw_glyph16_16,
1133
    vga_draw_glyph16_16,
1134
};
1135

    
1136
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1137
    vga_draw_glyph9_8,
1138
    vga_draw_glyph9_16,
1139
    vga_draw_glyph9_16,
1140
    vga_draw_glyph9_32,
1141
    vga_draw_glyph9_32,
1142
    vga_draw_glyph9_16,
1143
    vga_draw_glyph9_16,
1144
};
1145

    
1146
static const uint8_t cursor_glyph[32 * 4] = {
1147
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1148
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1149
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1150
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1151
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1152
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1153
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1154
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1155
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1156
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1157
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1158
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1159
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1160
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1161
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1162
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1163
};
1164

    
1165
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1166
                                    int *pcwidth, int *pcheight)
1167
{
1168
    int width, cwidth, height, cheight;
1169

    
1170
    /* total width & height */
1171
    cheight = (s->cr[9] & 0x1f) + 1;
1172
    cwidth = 8;
1173
    if (!(s->sr[1] & 0x01))
1174
        cwidth = 9;
1175
    if (s->sr[1] & 0x08)
1176
        cwidth = 16; /* NOTE: no 18 pixel wide */
1177
    width = (s->cr[0x01] + 1);
1178
    if (s->cr[0x06] == 100) {
1179
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1180
        height = 100;
1181
    } else {
1182
        height = s->cr[0x12] |
1183
            ((s->cr[0x07] & 0x02) << 7) |
1184
            ((s->cr[0x07] & 0x40) << 3);
1185
        height = (height + 1) / cheight;
1186
    }
1187

    
1188
    *pwidth = width;
1189
    *pheight = height;
1190
    *pcwidth = cwidth;
1191
    *pcheight = cheight;
1192
}
1193

    
1194
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1195

    
1196
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1197
    rgb_to_pixel8_dup,
1198
    rgb_to_pixel15_dup,
1199
    rgb_to_pixel16_dup,
1200
    rgb_to_pixel32_dup,
1201
    rgb_to_pixel32bgr_dup,
1202
    rgb_to_pixel15bgr_dup,
1203
    rgb_to_pixel16bgr_dup,
1204
};
1205

    
1206
/*
1207
 * Text mode update
1208
 * Missing:
1209
 * - double scan
1210
 * - double width
1211
 * - underline
1212
 * - flashing
1213
 */
1214
static void vga_draw_text(VGACommonState *s, int full_update)
1215
{
1216
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1217
    int cx_min, cx_max, linesize, x_incr, line, line1;
1218
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1219
    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1220
    const uint8_t *font_ptr, *font_base[2];
1221
    int dup9, line_offset, depth_index;
1222
    uint32_t *palette;
1223
    uint32_t *ch_attr_ptr;
1224
    vga_draw_glyph8_func *vga_draw_glyph8;
1225
    vga_draw_glyph9_func *vga_draw_glyph9;
1226

    
1227
    /* compute font data address (in plane 2) */
1228
    v = s->sr[3];
1229
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1230
    if (offset != s->font_offsets[0]) {
1231
        s->font_offsets[0] = offset;
1232
        full_update = 1;
1233
    }
1234
    font_base[0] = s->vram_ptr + offset;
1235

    
1236
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1237
    font_base[1] = s->vram_ptr + offset;
1238
    if (offset != s->font_offsets[1]) {
1239
        s->font_offsets[1] = offset;
1240
        full_update = 1;
1241
    }
1242
    if (s->plane_updated & (1 << 2)) {
1243
        /* if the plane 2 was modified since the last display, it
1244
           indicates the font may have been modified */
1245
        s->plane_updated = 0;
1246
        full_update = 1;
1247
    }
1248
    full_update |= update_basic_params(s);
1249

    
1250
    line_offset = s->line_offset;
1251

    
1252
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1253
    if ((height * width) > CH_ATTR_SIZE) {
1254
        /* better than nothing: exit if transient size is too big */
1255
        return;
1256
    }
1257

    
1258
    if (width != s->last_width || height != s->last_height ||
1259
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1260
        s->last_scr_width = width * cw;
1261
        s->last_scr_height = height * cheight;
1262
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1263
        s->last_depth = 0;
1264
        s->last_width = width;
1265
        s->last_height = height;
1266
        s->last_ch = cheight;
1267
        s->last_cw = cw;
1268
        full_update = 1;
1269
    }
1270
    s->rgb_to_pixel =
1271
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1272
    full_update |= update_palette16(s);
1273
    palette = s->last_palette;
1274
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1275

    
1276
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1277
    if (cursor_offset != s->cursor_offset ||
1278
        s->cr[0xa] != s->cursor_start ||
1279
        s->cr[0xb] != s->cursor_end) {
1280
      /* if the cursor position changed, we update the old and new
1281
         chars */
1282
        if (s->cursor_offset < CH_ATTR_SIZE)
1283
            s->last_ch_attr[s->cursor_offset] = -1;
1284
        if (cursor_offset < CH_ATTR_SIZE)
1285
            s->last_ch_attr[cursor_offset] = -1;
1286
        s->cursor_offset = cursor_offset;
1287
        s->cursor_start = s->cr[0xa];
1288
        s->cursor_end = s->cr[0xb];
1289
    }
1290
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1291

    
1292
    depth_index = get_depth_index(s->ds);
1293
    if (cw == 16)
1294
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1295
    else
1296
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1297
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1298

    
1299
    dest = ds_get_data(s->ds);
1300
    linesize = ds_get_linesize(s->ds);
1301
    ch_attr_ptr = s->last_ch_attr;
1302
    line = 0;
1303
    offset = s->start_addr * 4;
1304
    for(cy = 0; cy < height; cy++) {
1305
        d1 = dest;
1306
        src = s->vram_ptr + offset;
1307
        cx_min = width;
1308
        cx_max = -1;
1309
        for(cx = 0; cx < width; cx++) {
1310
            ch_attr = *(uint16_t *)src;
1311
            if (full_update || ch_attr != *ch_attr_ptr) {
1312
                if (cx < cx_min)
1313
                    cx_min = cx;
1314
                if (cx > cx_max)
1315
                    cx_max = cx;
1316
                *ch_attr_ptr = ch_attr;
1317
#ifdef HOST_WORDS_BIGENDIAN
1318
                ch = ch_attr >> 8;
1319
                cattr = ch_attr & 0xff;
1320
#else
1321
                ch = ch_attr & 0xff;
1322
                cattr = ch_attr >> 8;
1323
#endif
1324
                font_ptr = font_base[(cattr >> 3) & 1];
1325
                font_ptr += 32 * 4 * ch;
1326
                bgcol = palette[cattr >> 4];
1327
                fgcol = palette[cattr & 0x0f];
1328
                if (cw != 9) {
1329
                    vga_draw_glyph8(d1, linesize,
1330
                                    font_ptr, cheight, fgcol, bgcol);
1331
                } else {
1332
                    dup9 = 0;
1333
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1334
                        dup9 = 1;
1335
                    vga_draw_glyph9(d1, linesize,
1336
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1337
                }
1338
                if (src == cursor_ptr &&
1339
                    !(s->cr[0x0a] & 0x20)) {
1340
                    int line_start, line_last, h;
1341
                    /* draw the cursor */
1342
                    line_start = s->cr[0x0a] & 0x1f;
1343
                    line_last = s->cr[0x0b] & 0x1f;
1344
                    /* XXX: check that */
1345
                    if (line_last > cheight - 1)
1346
                        line_last = cheight - 1;
1347
                    if (line_last >= line_start && line_start < cheight) {
1348
                        h = line_last - line_start + 1;
1349
                        d = d1 + linesize * line_start;
1350
                        if (cw != 9) {
1351
                            vga_draw_glyph8(d, linesize,
1352
                                            cursor_glyph, h, fgcol, bgcol);
1353
                        } else {
1354
                            vga_draw_glyph9(d, linesize,
1355
                                            cursor_glyph, h, fgcol, bgcol, 1);
1356
                        }
1357
                    }
1358
                }
1359
            }
1360
            d1 += x_incr;
1361
            src += 4;
1362
            ch_attr_ptr++;
1363
        }
1364
        if (cx_max != -1) {
1365
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1366
                       (cx_max - cx_min + 1) * cw, cheight);
1367
        }
1368
        dest += linesize * cheight;
1369
        line1 = line + cheight;
1370
        offset += line_offset;
1371
        if (line < s->line_compare && line1 >= s->line_compare) {
1372
            offset = 0;
1373
        }
1374
        line = line1;
1375
    }
1376
}
1377

    
1378
enum {
1379
    VGA_DRAW_LINE2,
1380
    VGA_DRAW_LINE2D2,
1381
    VGA_DRAW_LINE4,
1382
    VGA_DRAW_LINE4D2,
1383
    VGA_DRAW_LINE8D2,
1384
    VGA_DRAW_LINE8,
1385
    VGA_DRAW_LINE15,
1386
    VGA_DRAW_LINE16,
1387
    VGA_DRAW_LINE24,
1388
    VGA_DRAW_LINE32,
1389
    VGA_DRAW_LINE_NB,
1390
};
1391

    
1392
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1393
    vga_draw_line2_8,
1394
    vga_draw_line2_16,
1395
    vga_draw_line2_16,
1396
    vga_draw_line2_32,
1397
    vga_draw_line2_32,
1398
    vga_draw_line2_16,
1399
    vga_draw_line2_16,
1400

    
1401
    vga_draw_line2d2_8,
1402
    vga_draw_line2d2_16,
1403
    vga_draw_line2d2_16,
1404
    vga_draw_line2d2_32,
1405
    vga_draw_line2d2_32,
1406
    vga_draw_line2d2_16,
1407
    vga_draw_line2d2_16,
1408

    
1409
    vga_draw_line4_8,
1410
    vga_draw_line4_16,
1411
    vga_draw_line4_16,
1412
    vga_draw_line4_32,
1413
    vga_draw_line4_32,
1414
    vga_draw_line4_16,
1415
    vga_draw_line4_16,
1416

    
1417
    vga_draw_line4d2_8,
1418
    vga_draw_line4d2_16,
1419
    vga_draw_line4d2_16,
1420
    vga_draw_line4d2_32,
1421
    vga_draw_line4d2_32,
1422
    vga_draw_line4d2_16,
1423
    vga_draw_line4d2_16,
1424

    
1425
    vga_draw_line8d2_8,
1426
    vga_draw_line8d2_16,
1427
    vga_draw_line8d2_16,
1428
    vga_draw_line8d2_32,
1429
    vga_draw_line8d2_32,
1430
    vga_draw_line8d2_16,
1431
    vga_draw_line8d2_16,
1432

    
1433
    vga_draw_line8_8,
1434
    vga_draw_line8_16,
1435
    vga_draw_line8_16,
1436
    vga_draw_line8_32,
1437
    vga_draw_line8_32,
1438
    vga_draw_line8_16,
1439
    vga_draw_line8_16,
1440

    
1441
    vga_draw_line15_8,
1442
    vga_draw_line15_15,
1443
    vga_draw_line15_16,
1444
    vga_draw_line15_32,
1445
    vga_draw_line15_32bgr,
1446
    vga_draw_line15_15bgr,
1447
    vga_draw_line15_16bgr,
1448

    
1449
    vga_draw_line16_8,
1450
    vga_draw_line16_15,
1451
    vga_draw_line16_16,
1452
    vga_draw_line16_32,
1453
    vga_draw_line16_32bgr,
1454
    vga_draw_line16_15bgr,
1455
    vga_draw_line16_16bgr,
1456

    
1457
    vga_draw_line24_8,
1458
    vga_draw_line24_15,
1459
    vga_draw_line24_16,
1460
    vga_draw_line24_32,
1461
    vga_draw_line24_32bgr,
1462
    vga_draw_line24_15bgr,
1463
    vga_draw_line24_16bgr,
1464

    
1465
    vga_draw_line32_8,
1466
    vga_draw_line32_15,
1467
    vga_draw_line32_16,
1468
    vga_draw_line32_32,
1469
    vga_draw_line32_32bgr,
1470
    vga_draw_line32_15bgr,
1471
    vga_draw_line32_16bgr,
1472
};
1473

    
1474
static int vga_get_bpp(VGACommonState *s)
1475
{
1476
    int ret;
1477
#ifdef CONFIG_BOCHS_VBE
1478
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1479
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1480
    } else
1481
#endif
1482
    {
1483
        ret = 0;
1484
    }
1485
    return ret;
1486
}
1487

    
1488
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1489
{
1490
    int width, height;
1491

    
1492
#ifdef CONFIG_BOCHS_VBE
1493
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1494
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1495
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1496
    } else
1497
#endif
1498
    {
1499
        width = (s->cr[0x01] + 1) * 8;
1500
        height = s->cr[0x12] |
1501
            ((s->cr[0x07] & 0x02) << 7) |
1502
            ((s->cr[0x07] & 0x40) << 3);
1503
        height = (height + 1);
1504
    }
1505
    *pwidth = width;
1506
    *pheight = height;
1507
}
1508

    
1509
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1510
{
1511
    int y;
1512
    if (y1 >= VGA_MAX_HEIGHT)
1513
        return;
1514
    if (y2 >= VGA_MAX_HEIGHT)
1515
        y2 = VGA_MAX_HEIGHT;
1516
    for(y = y1; y < y2; y++) {
1517
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1518
    }
1519
}
1520

    
1521
static void vga_sync_dirty_bitmap(VGACommonState *s)
1522
{
1523
    memory_region_sync_dirty_bitmap(&s->vram);
1524
}
1525

    
1526
void vga_dirty_log_start(VGACommonState *s)
1527
{
1528
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1529
}
1530

    
1531
void vga_dirty_log_stop(VGACommonState *s)
1532
{
1533
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1534
}
1535

    
1536
void vga_dirty_log_restart(VGACommonState *s)
1537
{
1538
    vga_dirty_log_stop(s);
1539
    vga_dirty_log_start(s);
1540
}
1541

    
1542
/*
1543
 * graphic modes
1544
 */
1545
static void vga_draw_graphic(VGACommonState *s, int full_update)
1546
{
1547
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1548
    int width, height, shift_control, line_offset, bwidth, bits;
1549
    ram_addr_t page0, page1, page_min, page_max;
1550
    int disp_width, multi_scan, multi_run;
1551
    uint8_t *d;
1552
    uint32_t v, addr1, addr;
1553
    vga_draw_line_func *vga_draw_line;
1554

    
1555
    full_update |= update_basic_params(s);
1556

    
1557
    if (!full_update)
1558
        vga_sync_dirty_bitmap(s);
1559

    
1560
    s->get_resolution(s, &width, &height);
1561
    disp_width = width;
1562

    
1563
    shift_control = (s->gr[0x05] >> 5) & 3;
1564
    double_scan = (s->cr[0x09] >> 7);
1565
    if (shift_control != 1) {
1566
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1567
    } else {
1568
        /* in CGA modes, multi_scan is ignored */
1569
        /* XXX: is it correct ? */
1570
        multi_scan = double_scan;
1571
    }
1572
    multi_run = multi_scan;
1573
    if (shift_control != s->shift_control ||
1574
        double_scan != s->double_scan) {
1575
        full_update = 1;
1576
        s->shift_control = shift_control;
1577
        s->double_scan = double_scan;
1578
    }
1579

    
1580
    if (shift_control == 0) {
1581
        if (s->sr[0x01] & 8) {
1582
            disp_width <<= 1;
1583
        }
1584
    } else if (shift_control == 1) {
1585
        if (s->sr[0x01] & 8) {
1586
            disp_width <<= 1;
1587
        }
1588
    }
1589

    
1590
    depth = s->get_bpp(s);
1591
    if (s->line_offset != s->last_line_offset ||
1592
        disp_width != s->last_width ||
1593
        height != s->last_height ||
1594
        s->last_depth != depth) {
1595
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1596
        if (depth == 16 || depth == 32) {
1597
#else
1598
        if (depth == 32) {
1599
#endif
1600
            qemu_free_displaysurface(s->ds);
1601
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1602
                    s->line_offset,
1603
                    s->vram_ptr + (s->start_addr * 4));
1604
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1605
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1606
#endif
1607
            dpy_resize(s->ds);
1608
        } else {
1609
            qemu_console_resize(s->ds, disp_width, height);
1610
        }
1611
        s->last_scr_width = disp_width;
1612
        s->last_scr_height = height;
1613
        s->last_width = disp_width;
1614
        s->last_height = height;
1615
        s->last_line_offset = s->line_offset;
1616
        s->last_depth = depth;
1617
        full_update = 1;
1618
    } else if (is_buffer_shared(s->ds->surface) &&
1619
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1620
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1621
        dpy_setdata(s->ds);
1622
    }
1623

    
1624
    s->rgb_to_pixel =
1625
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1626

    
1627
    if (shift_control == 0) {
1628
        full_update |= update_palette16(s);
1629
        if (s->sr[0x01] & 8) {
1630
            v = VGA_DRAW_LINE4D2;
1631
        } else {
1632
            v = VGA_DRAW_LINE4;
1633
        }
1634
        bits = 4;
1635
    } else if (shift_control == 1) {
1636
        full_update |= update_palette16(s);
1637
        if (s->sr[0x01] & 8) {
1638
            v = VGA_DRAW_LINE2D2;
1639
        } else {
1640
            v = VGA_DRAW_LINE2;
1641
        }
1642
        bits = 4;
1643
    } else {
1644
        switch(s->get_bpp(s)) {
1645
        default:
1646
        case 0:
1647
            full_update |= update_palette256(s);
1648
            v = VGA_DRAW_LINE8D2;
1649
            bits = 4;
1650
            break;
1651
        case 8:
1652
            full_update |= update_palette256(s);
1653
            v = VGA_DRAW_LINE8;
1654
            bits = 8;
1655
            break;
1656
        case 15:
1657
            v = VGA_DRAW_LINE15;
1658
            bits = 16;
1659
            break;
1660
        case 16:
1661
            v = VGA_DRAW_LINE16;
1662
            bits = 16;
1663
            break;
1664
        case 24:
1665
            v = VGA_DRAW_LINE24;
1666
            bits = 24;
1667
            break;
1668
        case 32:
1669
            v = VGA_DRAW_LINE32;
1670
            bits = 32;
1671
            break;
1672
        }
1673
    }
1674
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1675

    
1676
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1677
        s->cursor_invalidate(s);
1678

    
1679
    line_offset = s->line_offset;
1680
#if 0
1681
    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",
1682
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1683
#endif
1684
    addr1 = (s->start_addr * 4);
1685
    bwidth = (width * bits + 7) / 8;
1686
    y_start = -1;
1687
    page_min = -1;
1688
    page_max = 0;
1689
    d = ds_get_data(s->ds);
1690
    linesize = ds_get_linesize(s->ds);
1691
    y1 = 0;
1692
    for(y = 0; y < height; y++) {
1693
        addr = addr1;
1694
        if (!(s->cr[0x17] & 1)) {
1695
            int shift;
1696
            /* CGA compatibility handling */
1697
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1698
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1699
        }
1700
        if (!(s->cr[0x17] & 2)) {
1701
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1702
        }
1703
        page0 = addr & TARGET_PAGE_MASK;
1704
        page1 = (addr + bwidth - 1) & TARGET_PAGE_MASK;
1705
        update = full_update |
1706
            memory_region_get_dirty(&s->vram, page0, DIRTY_MEMORY_VGA) |
1707
            memory_region_get_dirty(&s->vram, page1, DIRTY_MEMORY_VGA);
1708
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1709
            /* if wide line, can use another page */
1710
            update |= memory_region_get_dirty(&s->vram,
1711
                                              page0 + TARGET_PAGE_SIZE,
1712
                                              DIRTY_MEMORY_VGA);
1713
        }
1714
        /* explicit invalidation for the hardware cursor */
1715
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1716
        if (update) {
1717
            if (y_start < 0)
1718
                y_start = y;
1719
            if (page0 < page_min)
1720
                page_min = page0;
1721
            if (page1 > page_max)
1722
                page_max = page1;
1723
            if (!(is_buffer_shared(s->ds->surface))) {
1724
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1725
                if (s->cursor_draw_line)
1726
                    s->cursor_draw_line(s, d, y);
1727
            }
1728
        } else {
1729
            if (y_start >= 0) {
1730
                /* flush to display */
1731
                dpy_update(s->ds, 0, y_start,
1732
                           disp_width, y - y_start);
1733
                y_start = -1;
1734
            }
1735
        }
1736
        if (!multi_run) {
1737
            mask = (s->cr[0x17] & 3) ^ 3;
1738
            if ((y1 & mask) == mask)
1739
                addr1 += line_offset;
1740
            y1++;
1741
            multi_run = multi_scan;
1742
        } else {
1743
            multi_run--;
1744
        }
1745
        /* line compare acts on the displayed lines */
1746
        if (y == s->line_compare)
1747
            addr1 = 0;
1748
        d += linesize;
1749
    }
1750
    if (y_start >= 0) {
1751
        /* flush to display */
1752
        dpy_update(s->ds, 0, y_start,
1753
                   disp_width, y - y_start);
1754
    }
1755
    /* reset modified pages */
1756
    if (page_max >= page_min) {
1757
        memory_region_reset_dirty(&s->vram,
1758
                                  page_min,
1759
                                  page_max + TARGET_PAGE_SIZE - page_min,
1760
                                  DIRTY_MEMORY_VGA);
1761
    }
1762
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1763
}
1764

    
1765
static void vga_draw_blank(VGACommonState *s, int full_update)
1766
{
1767
    int i, w, val;
1768
    uint8_t *d;
1769

    
1770
    if (!full_update)
1771
        return;
1772
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1773
        return;
1774

    
1775
    s->rgb_to_pixel =
1776
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1777
    if (ds_get_bits_per_pixel(s->ds) == 8)
1778
        val = s->rgb_to_pixel(0, 0, 0);
1779
    else
1780
        val = 0;
1781
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1782
    d = ds_get_data(s->ds);
1783
    for(i = 0; i < s->last_scr_height; i++) {
1784
        memset(d, val, w);
1785
        d += ds_get_linesize(s->ds);
1786
    }
1787
    dpy_update(s->ds, 0, 0,
1788
               s->last_scr_width, s->last_scr_height);
1789
}
1790

    
1791
#define GMODE_TEXT     0
1792
#define GMODE_GRAPH    1
1793
#define GMODE_BLANK 2
1794

    
1795
static void vga_update_display(void *opaque)
1796
{
1797
    VGACommonState *s = opaque;
1798
    int full_update, graphic_mode;
1799

    
1800
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1801
        /* nothing to do */
1802
    } else {
1803
        full_update = 0;
1804
        if (!(s->ar_index & 0x20)) {
1805
            graphic_mode = GMODE_BLANK;
1806
        } else {
1807
            graphic_mode = s->gr[6] & 1;
1808
        }
1809
        if (graphic_mode != s->graphic_mode) {
1810
            s->graphic_mode = graphic_mode;
1811
            full_update = 1;
1812
        }
1813
        switch(graphic_mode) {
1814
        case GMODE_TEXT:
1815
            vga_draw_text(s, full_update);
1816
            break;
1817
        case GMODE_GRAPH:
1818
            vga_draw_graphic(s, full_update);
1819
            break;
1820
        case GMODE_BLANK:
1821
        default:
1822
            vga_draw_blank(s, full_update);
1823
            break;
1824
        }
1825
    }
1826
}
1827

    
1828
/* force a full display refresh */
1829
static void vga_invalidate_display(void *opaque)
1830
{
1831
    VGACommonState *s = opaque;
1832

    
1833
    s->last_width = -1;
1834
    s->last_height = -1;
1835
}
1836

    
1837
void vga_common_reset(VGACommonState *s)
1838
{
1839
    s->sr_index = 0;
1840
    memset(s->sr, '\0', sizeof(s->sr));
1841
    s->gr_index = 0;
1842
    memset(s->gr, '\0', sizeof(s->gr));
1843
    s->ar_index = 0;
1844
    memset(s->ar, '\0', sizeof(s->ar));
1845
    s->ar_flip_flop = 0;
1846
    s->cr_index = 0;
1847
    memset(s->cr, '\0', sizeof(s->cr));
1848
    s->msr = 0;
1849
    s->fcr = 0;
1850
    s->st00 = 0;
1851
    s->st01 = 0;
1852
    s->dac_state = 0;
1853
    s->dac_sub_index = 0;
1854
    s->dac_read_index = 0;
1855
    s->dac_write_index = 0;
1856
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1857
    s->dac_8bit = 0;
1858
    memset(s->palette, '\0', sizeof(s->palette));
1859
    s->bank_offset = 0;
1860
#ifdef CONFIG_BOCHS_VBE
1861
    s->vbe_index = 0;
1862
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1863
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1864
    s->vbe_start_addr = 0;
1865
    s->vbe_line_offset = 0;
1866
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1867
#endif
1868
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1869
    s->graphic_mode = -1; /* force full update */
1870
    s->shift_control = 0;
1871
    s->double_scan = 0;
1872
    s->line_offset = 0;
1873
    s->line_compare = 0;
1874
    s->start_addr = 0;
1875
    s->plane_updated = 0;
1876
    s->last_cw = 0;
1877
    s->last_ch = 0;
1878
    s->last_width = 0;
1879
    s->last_height = 0;
1880
    s->last_scr_width = 0;
1881
    s->last_scr_height = 0;
1882
    s->cursor_start = 0;
1883
    s->cursor_end = 0;
1884
    s->cursor_offset = 0;
1885
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1886
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1887
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1888
    switch (vga_retrace_method) {
1889
    case VGA_RETRACE_DUMB:
1890
        break;
1891
    case VGA_RETRACE_PRECISE:
1892
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1893
        break;
1894
    }
1895
}
1896

    
1897
static void vga_reset(void *opaque)
1898
{
1899
    VGACommonState *s =  opaque;
1900
    vga_common_reset(s);
1901
}
1902

    
1903
#define TEXTMODE_X(x)        ((x) % width)
1904
#define TEXTMODE_Y(x)        ((x) / width)
1905
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1906
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1907
/* relay text rendering to the display driver
1908
 * instead of doing a full vga_update_display() */
1909
static void vga_update_text(void *opaque, console_ch_t *chardata)
1910
{
1911
    VGACommonState *s =  opaque;
1912
    int graphic_mode, i, cursor_offset, cursor_visible;
1913
    int cw, cheight, width, height, size, c_min, c_max;
1914
    uint32_t *src;
1915
    console_ch_t *dst, val;
1916
    char msg_buffer[80];
1917
    int full_update = 0;
1918

    
1919
    if (!(s->ar_index & 0x20)) {
1920
        graphic_mode = GMODE_BLANK;
1921
    } else {
1922
        graphic_mode = s->gr[6] & 1;
1923
    }
1924
    if (graphic_mode != s->graphic_mode) {
1925
        s->graphic_mode = graphic_mode;
1926
        full_update = 1;
1927
    }
1928
    if (s->last_width == -1) {
1929
        s->last_width = 0;
1930
        full_update = 1;
1931
    }
1932

    
1933
    switch (graphic_mode) {
1934
    case GMODE_TEXT:
1935
        /* TODO: update palette */
1936
        full_update |= update_basic_params(s);
1937

    
1938
        /* total width & height */
1939
        cheight = (s->cr[9] & 0x1f) + 1;
1940
        cw = 8;
1941
        if (!(s->sr[1] & 0x01))
1942
            cw = 9;
1943
        if (s->sr[1] & 0x08)
1944
            cw = 16; /* NOTE: no 18 pixel wide */
1945
        width = (s->cr[0x01] + 1);
1946
        if (s->cr[0x06] == 100) {
1947
            /* ugly hack for CGA 160x100x16 - explain me the logic */
1948
            height = 100;
1949
        } else {
1950
            height = s->cr[0x12] | 
1951
                ((s->cr[0x07] & 0x02) << 7) | 
1952
                ((s->cr[0x07] & 0x40) << 3);
1953
            height = (height + 1) / cheight;
1954
        }
1955

    
1956
        size = (height * width);
1957
        if (size > CH_ATTR_SIZE) {
1958
            if (!full_update)
1959
                return;
1960

    
1961
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1962
                     width, height);
1963
            break;
1964
        }
1965

    
1966
        if (width != s->last_width || height != s->last_height ||
1967
            cw != s->last_cw || cheight != s->last_ch) {
1968
            s->last_scr_width = width * cw;
1969
            s->last_scr_height = height * cheight;
1970
            s->ds->surface->width = width;
1971
            s->ds->surface->height = height;
1972
            dpy_resize(s->ds);
1973
            s->last_width = width;
1974
            s->last_height = height;
1975
            s->last_ch = cheight;
1976
            s->last_cw = cw;
1977
            full_update = 1;
1978
        }
1979

    
1980
        /* Update "hardware" cursor */
1981
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1982
        if (cursor_offset != s->cursor_offset ||
1983
            s->cr[0xa] != s->cursor_start ||
1984
            s->cr[0xb] != s->cursor_end || full_update) {
1985
            cursor_visible = !(s->cr[0xa] & 0x20);
1986
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1987
                dpy_cursor(s->ds,
1988
                           TEXTMODE_X(cursor_offset),
1989
                           TEXTMODE_Y(cursor_offset));
1990
            else
1991
                dpy_cursor(s->ds, -1, -1);
1992
            s->cursor_offset = cursor_offset;
1993
            s->cursor_start = s->cr[0xa];
1994
            s->cursor_end = s->cr[0xb];
1995
        }
1996

    
1997
        src = (uint32_t *) s->vram_ptr + s->start_addr;
1998
        dst = chardata;
1999

    
2000
        if (full_update) {
2001
            for (i = 0; i < size; src ++, dst ++, i ++)
2002
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2003

    
2004
            dpy_update(s->ds, 0, 0, width, height);
2005
        } else {
2006
            c_max = 0;
2007

    
2008
            for (i = 0; i < size; src ++, dst ++, i ++) {
2009
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2010
                if (*dst != val) {
2011
                    *dst = val;
2012
                    c_max = i;
2013
                    break;
2014
                }
2015
            }
2016
            c_min = i;
2017
            for (; i < size; src ++, dst ++, i ++) {
2018
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2019
                if (*dst != val) {
2020
                    *dst = val;
2021
                    c_max = i;
2022
                }
2023
            }
2024

    
2025
            if (c_min <= c_max) {
2026
                i = TEXTMODE_Y(c_min);
2027
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2028
            }
2029
        }
2030

    
2031
        return;
2032
    case GMODE_GRAPH:
2033
        if (!full_update)
2034
            return;
2035

    
2036
        s->get_resolution(s, &width, &height);
2037
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2038
                 width, height);
2039
        break;
2040
    case GMODE_BLANK:
2041
    default:
2042
        if (!full_update)
2043
            return;
2044

    
2045
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2046
        break;
2047
    }
2048

    
2049
    /* Display a message */
2050
    s->last_width = 60;
2051
    s->last_height = height = 3;
2052
    dpy_cursor(s->ds, -1, -1);
2053
    s->ds->surface->width = s->last_width;
2054
    s->ds->surface->height = height;
2055
    dpy_resize(s->ds);
2056

    
2057
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2058
        console_write_ch(dst ++, ' ');
2059

    
2060
    size = strlen(msg_buffer);
2061
    width = (s->last_width - size) / 2;
2062
    dst = chardata + s->last_width + width;
2063
    for (i = 0; i < size; i ++)
2064
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2065

    
2066
    dpy_update(s->ds, 0, 0, s->last_width, height);
2067
}
2068

    
2069
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2070
                             unsigned size)
2071
{
2072
    VGACommonState *s = opaque;
2073

    
2074
    return vga_mem_readb(s, addr);
2075
}
2076

    
2077
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2078
                          uint64_t data, unsigned size)
2079
{
2080
    VGACommonState *s = opaque;
2081

    
2082
    return vga_mem_writeb(s, addr, data);
2083
}
2084

    
2085
const MemoryRegionOps vga_mem_ops = {
2086
    .read = vga_mem_read,
2087
    .write = vga_mem_write,
2088
    .endianness = DEVICE_LITTLE_ENDIAN,
2089
    .impl = {
2090
        .min_access_size = 1,
2091
        .max_access_size = 1,
2092
    },
2093
};
2094

    
2095
static int vga_common_post_load(void *opaque, int version_id)
2096
{
2097
    VGACommonState *s = opaque;
2098

    
2099
    /* force refresh */
2100
    s->graphic_mode = -1;
2101
    return 0;
2102
}
2103

    
2104
const VMStateDescription vmstate_vga_common = {
2105
    .name = "vga",
2106
    .version_id = 2,
2107
    .minimum_version_id = 2,
2108
    .minimum_version_id_old = 2,
2109
    .post_load = vga_common_post_load,
2110
    .fields      = (VMStateField []) {
2111
        VMSTATE_UINT32(latch, VGACommonState),
2112
        VMSTATE_UINT8(sr_index, VGACommonState),
2113
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2114
        VMSTATE_UINT8(gr_index, VGACommonState),
2115
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2116
        VMSTATE_UINT8(ar_index, VGACommonState),
2117
        VMSTATE_BUFFER(ar, VGACommonState),
2118
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2119
        VMSTATE_UINT8(cr_index, VGACommonState),
2120
        VMSTATE_BUFFER(cr, VGACommonState),
2121
        VMSTATE_UINT8(msr, VGACommonState),
2122
        VMSTATE_UINT8(fcr, VGACommonState),
2123
        VMSTATE_UINT8(st00, VGACommonState),
2124
        VMSTATE_UINT8(st01, VGACommonState),
2125

    
2126
        VMSTATE_UINT8(dac_state, VGACommonState),
2127
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2128
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2129
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2130
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2131
        VMSTATE_BUFFER(palette, VGACommonState),
2132

    
2133
        VMSTATE_INT32(bank_offset, VGACommonState),
2134
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2135
#ifdef CONFIG_BOCHS_VBE
2136
        VMSTATE_UINT16(vbe_index, VGACommonState),
2137
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2138
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2139
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2140
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2141
#endif
2142
        VMSTATE_END_OF_LIST()
2143
    }
2144
};
2145

    
2146
void vga_common_init(VGACommonState *s, int vga_ram_size)
2147
{
2148
    int i, j, v, b;
2149

    
2150
    for(i = 0;i < 256; i++) {
2151
        v = 0;
2152
        for(j = 0; j < 8; j++) {
2153
            v |= ((i >> j) & 1) << (j * 4);
2154
        }
2155
        expand4[i] = v;
2156

    
2157
        v = 0;
2158
        for(j = 0; j < 4; j++) {
2159
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2160
        }
2161
        expand2[i] = v;
2162
    }
2163
    for(i = 0; i < 16; i++) {
2164
        v = 0;
2165
        for(j = 0; j < 4; j++) {
2166
            b = ((i >> j) & 1);
2167
            v |= b << (2 * j);
2168
            v |= b << (2 * j + 1);
2169
        }
2170
        expand4to8[i] = v;
2171
    }
2172

    
2173
#ifdef CONFIG_BOCHS_VBE
2174
    s->is_vbe_vmstate = 1;
2175
#else
2176
    s->is_vbe_vmstate = 0;
2177
#endif
2178
    memory_region_init_ram(&s->vram, NULL, "vga.vram", vga_ram_size);
2179
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2180
    s->vram_size = vga_ram_size;
2181
    s->get_bpp = vga_get_bpp;
2182
    s->get_offsets = vga_get_offsets;
2183
    s->get_resolution = vga_get_resolution;
2184
    s->update = vga_update_display;
2185
    s->invalidate = vga_invalidate_display;
2186
    s->screen_dump = vga_screen_dump;
2187
    s->text_update = vga_update_text;
2188
    switch (vga_retrace_method) {
2189
    case VGA_RETRACE_DUMB:
2190
        s->retrace = vga_dumb_retrace;
2191
        s->update_retrace_info = vga_dumb_update_retrace_info;
2192
        break;
2193

    
2194
    case VGA_RETRACE_PRECISE:
2195
        s->retrace = vga_precise_retrace;
2196
        s->update_retrace_info = vga_precise_update_retrace_info;
2197
        break;
2198
    }
2199
    vga_dirty_log_start(s);
2200
}
2201

    
2202
/* used by both ISA and PCI */
2203
MemoryRegion *vga_init_io(VGACommonState *s)
2204
{
2205
    MemoryRegion *vga_mem;
2206

    
2207
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2208

    
2209
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2210
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2211
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2212
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2213

    
2214
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2215

    
2216
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2217
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2218
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2219
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2220

    
2221
#ifdef CONFIG_BOCHS_VBE
2222
#if defined (TARGET_I386)
2223
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2224
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2225

    
2226
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2227
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2228
#else
2229
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2230
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2231

    
2232
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2233
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2234
#endif
2235
#endif /* CONFIG_BOCHS_VBE */
2236

    
2237
    vga_mem = qemu_malloc(sizeof(*vga_mem));
2238
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2239
                          "vga-lowmem", 0x20000);
2240

    
2241
    return vga_mem;
2242
}
2243

    
2244
void vga_init(VGACommonState *s)
2245
{
2246
    MemoryRegion *vga_io_memory;
2247

    
2248
    qemu_register_reset(vga_reset, s);
2249

    
2250
    s->bank_offset = 0;
2251

    
2252
    vga_io_memory = vga_init_io(s);
2253
    memory_region_add_subregion_overlap(get_system_memory(),
2254
                                        isa_mem_base + 0x000a0000,
2255
                                        vga_io_memory,
2256
                                        1);
2257
    memory_region_set_coalescing(vga_io_memory);
2258
}
2259

    
2260
void vga_init_vbe(VGACommonState *s)
2261
{
2262
#ifdef CONFIG_BOCHS_VBE
2263
    /* XXX: use optimized standard vga accesses */
2264
    memory_region_add_subregion(get_system_memory(),
2265
                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2266
                                &s->vram);
2267
    s->vbe_mapped = 1;
2268
#endif 
2269
}
2270
/********************************************************/
2271
/* vga screen dump */
2272

    
2273
static void vga_save_dpy_update(DisplayState *ds,
2274
                                int x, int y, int w, int h)
2275
{
2276
    if (screen_dump_filename) {
2277
        ppm_save(screen_dump_filename, ds->surface);
2278
        screen_dump_filename = NULL;
2279
    }
2280
}
2281

    
2282
static void vga_save_dpy_resize(DisplayState *s)
2283
{
2284
}
2285

    
2286
static void vga_save_dpy_refresh(DisplayState *s)
2287
{
2288
}
2289

    
2290
int ppm_save(const char *filename, struct DisplaySurface *ds)
2291
{
2292
    FILE *f;
2293
    uint8_t *d, *d1;
2294
    uint32_t v;
2295
    int y, x;
2296
    uint8_t r, g, b;
2297
    int ret;
2298
    char *linebuf, *pbuf;
2299

    
2300
    f = fopen(filename, "wb");
2301
    if (!f)
2302
        return -1;
2303
    fprintf(f, "P6\n%d %d\n%d\n",
2304
            ds->width, ds->height, 255);
2305
    linebuf = qemu_malloc(ds->width * 3);
2306
    d1 = ds->data;
2307
    for(y = 0; y < ds->height; y++) {
2308
        d = d1;
2309
        pbuf = linebuf;
2310
        for(x = 0; x < ds->width; x++) {
2311
            if (ds->pf.bits_per_pixel == 32)
2312
                v = *(uint32_t *)d;
2313
            else
2314
                v = (uint32_t) (*(uint16_t *)d);
2315
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2316
                (ds->pf.rmax + 1);
2317
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2318
                (ds->pf.gmax + 1);
2319
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2320
                (ds->pf.bmax + 1);
2321
            *pbuf++ = r;
2322
            *pbuf++ = g;
2323
            *pbuf++ = b;
2324
            d += ds->pf.bytes_per_pixel;
2325
        }
2326
        d1 += ds->linesize;
2327
        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2328
        (void)ret;
2329
    }
2330
    qemu_free(linebuf);
2331
    fclose(f);
2332
    return 0;
2333
}
2334

    
2335
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2336
{
2337
    DisplayChangeListener *dcl;
2338

    
2339
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2340
    dcl->dpy_update = vga_save_dpy_update;
2341
    dcl->dpy_resize = vga_save_dpy_resize;
2342
    dcl->dpy_refresh = vga_save_dpy_refresh;
2343
    register_displaychangelistener(ds, dcl);
2344
    return dcl;
2345
}
2346

    
2347
/* save the vga display in a PPM image even if no display is
2348
   available */
2349
static void vga_screen_dump(void *opaque, const char *filename)
2350
{
2351
    VGACommonState *s = opaque;
2352

    
2353
    if (!screen_dump_dcl)
2354
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2355

    
2356
    screen_dump_filename = (char *)filename;
2357
    vga_invalidate_display(s);
2358
    vga_hw_update();
2359
}
2360