Statistics
| Branch: | Revision:

root / hw / vga.c @ af92284b

History | View | Annotate | Download (68.7 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 if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
546
        val = s->vram_size / (64 * 1024);
547
    } else {
548
        val = 0;
549
    }
550
#ifdef DEBUG_BOCHS_VBE
551
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
552
#endif
553
    return val;
554
}
555

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
964
#define DEPTH 8
965
#include "vga_template.h"
966

    
967
#define DEPTH 15
968
#include "vga_template.h"
969

    
970
#define BGR_FORMAT
971
#define DEPTH 15
972
#include "vga_template.h"
973

    
974
#define DEPTH 16
975
#include "vga_template.h"
976

    
977
#define BGR_FORMAT
978
#define DEPTH 16
979
#include "vga_template.h"
980

    
981
#define DEPTH 32
982
#include "vga_template.h"
983

    
984
#define BGR_FORMAT
985
#define DEPTH 32
986
#include "vga_template.h"
987

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1136
    full_update = 0;
1137

    
1138
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1139

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

    
1151
#define NB_DEPTHS 7
1152

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

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

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

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

    
1201
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218
};
1219

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

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

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

    
1249
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1250

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

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

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

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

    
1305
    line_offset = s->line_offset;
1306

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

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

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

    
1456
    vga_draw_line2d2_8,
1457
    vga_draw_line2d2_16,
1458
    vga_draw_line2d2_16,
1459
    vga_draw_line2d2_32,
1460
    vga_draw_line2d2_32,
1461
    vga_draw_line2d2_16,
1462
    vga_draw_line2d2_16,
1463

    
1464
    vga_draw_line4_8,
1465
    vga_draw_line4_16,
1466
    vga_draw_line4_16,
1467
    vga_draw_line4_32,
1468
    vga_draw_line4_32,
1469
    vga_draw_line4_16,
1470
    vga_draw_line4_16,
1471

    
1472
    vga_draw_line4d2_8,
1473
    vga_draw_line4d2_16,
1474
    vga_draw_line4d2_16,
1475
    vga_draw_line4d2_32,
1476
    vga_draw_line4d2_32,
1477
    vga_draw_line4d2_16,
1478
    vga_draw_line4d2_16,
1479

    
1480
    vga_draw_line8d2_8,
1481
    vga_draw_line8d2_16,
1482
    vga_draw_line8d2_16,
1483
    vga_draw_line8d2_32,
1484
    vga_draw_line8d2_32,
1485
    vga_draw_line8d2_16,
1486
    vga_draw_line8d2_16,
1487

    
1488
    vga_draw_line8_8,
1489
    vga_draw_line8_16,
1490
    vga_draw_line8_16,
1491
    vga_draw_line8_32,
1492
    vga_draw_line8_32,
1493
    vga_draw_line8_16,
1494
    vga_draw_line8_16,
1495

    
1496
    vga_draw_line15_8,
1497
    vga_draw_line15_15,
1498
    vga_draw_line15_16,
1499
    vga_draw_line15_32,
1500
    vga_draw_line15_32bgr,
1501
    vga_draw_line15_15bgr,
1502
    vga_draw_line15_16bgr,
1503

    
1504
    vga_draw_line16_8,
1505
    vga_draw_line16_15,
1506
    vga_draw_line16_16,
1507
    vga_draw_line16_32,
1508
    vga_draw_line16_32bgr,
1509
    vga_draw_line16_15bgr,
1510
    vga_draw_line16_16bgr,
1511

    
1512
    vga_draw_line24_8,
1513
    vga_draw_line24_15,
1514
    vga_draw_line24_16,
1515
    vga_draw_line24_32,
1516
    vga_draw_line24_32bgr,
1517
    vga_draw_line24_15bgr,
1518
    vga_draw_line24_16bgr,
1519

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

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

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

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

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

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

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

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

    
1593
}
1594

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

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

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

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

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

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

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

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

    
1648
    full_update |= update_basic_params(s);
1649

    
1650
    if (!full_update)
1651
        vga_sync_dirty_bitmap(s);
1652

    
1653
    s->get_resolution(s, &width, &height);
1654
    disp_width = width;
1655

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

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

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

    
1717
    s->rgb_to_pixel =
1718
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1719

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

    
1769
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1770
        s->cursor_invalidate(s);
1771

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

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

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

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

    
1881
#define GMODE_TEXT     0
1882
#define GMODE_GRAPH    1
1883
#define GMODE_BLANK 2
1884

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

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

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

    
1923
    s->last_width = -1;
1924
    s->last_height = -1;
1925
}
1926

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2128
        return;
2129
    case GMODE_GRAPH:
2130
        if (!full_update)
2131
            return;
2132

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

    
2142
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2143
        break;
2144
    }
2145

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

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

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

    
2163
    dpy_update(s->ds, 0, 0, s->last_width, height);
2164
}
2165

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2289
    qemu_register_reset(vga_reset, s);
2290

    
2291
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2292

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

    
2298
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2299

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

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

    
2311
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2312
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2313

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

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

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

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

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

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

    
2356
static void vga_save_dpy_resize(DisplayState *s)
2357
{
2358
}
2359

    
2360
static void vga_save_dpy_refresh(DisplayState *s)
2361
{
2362
}
2363

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

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

    
2402
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2403
{
2404
    DisplayChangeListener *dcl;
2405

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

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

    
2420
    if (!screen_dump_dcl)
2421
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2422

    
2423
    screen_dump_filename = (char *)filename;
2424
    vga_invalidate_display(s);
2425
    vga_hw_update();
2426
}
2427