Statistics
| Branch: | Revision:

root / hw / vga.c @ e9b43ea3

History | View | Annotate | Download (67.8 kB)

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

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

    
36
//#define DEBUG_BOCHS_VBE
37

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

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

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

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

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

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

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

    
113
#undef PAT
114

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

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

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

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

    
151
typedef VGACommonState VGAState;
152

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

    
157
static void vga_dumb_update_retrace_info(VGAState *s)
158
{
159
    (void) s;
160
}
161

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

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

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

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

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

    
193

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

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

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

    
262
        cur_tick = qemu_get_clock(vm_clock);
263

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

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

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

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

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

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

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

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

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

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

    
505
        switch(s->cr_index) {
506
        case 0x00:
507
        case 0x04:
508
        case 0x05:
509
        case 0x06:
510
        case 0x07:
511
        case 0x11:
512
        case 0x17:
513
            s->update_retrace_info(s);
514
            break;
515
        }
516
        break;
517
    case 0x3ba:
518
    case 0x3da:
519
        s->fcr = val & 0x10;
520
        break;
521
    }
522
}
523

    
524
#ifdef CONFIG_BOCHS_VBE
525
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
526
{
527
    VGAState *s = opaque;
528
    uint32_t val;
529
    val = s->vbe_index;
530
    return val;
531
}
532

    
533
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
534
{
535
    VGAState *s = opaque;
536
    uint32_t val;
537

    
538
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
539
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
540
            switch(s->vbe_index) {
541
                /* XXX: do not hardcode ? */
542
            case VBE_DISPI_INDEX_XRES:
543
                val = VBE_DISPI_MAX_XRES;
544
                break;
545
            case VBE_DISPI_INDEX_YRES:
546
                val = VBE_DISPI_MAX_YRES;
547
                break;
548
            case VBE_DISPI_INDEX_BPP:
549
                val = VBE_DISPI_MAX_BPP;
550
                break;
551
            default:
552
                val = s->vbe_regs[s->vbe_index];
553
                break;
554
            }
555
        } else {
556
            val = s->vbe_regs[s->vbe_index];
557
        }
558
    } else {
559
        val = 0;
560
    }
561
#ifdef DEBUG_BOCHS_VBE
562
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
563
#endif
564
    return val;
565
}
566

    
567
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
568
{
569
    VGAState *s = opaque;
570
    s->vbe_index = val;
571
}
572

    
573
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
574
{
575
    VGAState *s = opaque;
576

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

    
623
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
624
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
625
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
626
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
627
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
628
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
629

    
630
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
631
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
632
                else
633
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
634
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
635
                s->vbe_start_addr = 0;
636

    
637
                /* clear the screen (should be done in BIOS) */
638
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
639
                    memset(s->vram_ptr, 0,
640
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
641
                }
642

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

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

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

    
718
/* called for accesses between 0xa0000 and 0xc0000 */
719
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
720
{
721
    VGAState *s = opaque;
722
    int memory_map_mode, plane;
723
    uint32_t ret;
724

    
725
    /* convert to VGA memory offset */
726
    memory_map_mode = (s->gr[6] >> 2) & 3;
727
    addr &= 0x1ffff;
728
    switch(memory_map_mode) {
729
    case 0:
730
        break;
731
    case 1:
732
        if (addr >= 0x10000)
733
            return 0xff;
734
        addr += s->bank_offset;
735
        break;
736
    case 2:
737
        addr -= 0x10000;
738
        if (addr >= 0x8000)
739
            return 0xff;
740
        break;
741
    default:
742
    case 3:
743
        addr -= 0x18000;
744
        if (addr >= 0x8000)
745
            return 0xff;
746
        break;
747
    }
748

    
749
    if (s->sr[4] & 0x08) {
750
        /* chain 4 mode : simplest access */
751
        ret = s->vram_ptr[addr];
752
    } else if (s->gr[5] & 0x10) {
753
        /* odd/even mode (aka text mode mapping) */
754
        plane = (s->gr[4] & 2) | (addr & 1);
755
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
756
    } else {
757
        /* standard VGA latched access */
758
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
759

    
760
        if (!(s->gr[5] & 0x08)) {
761
            /* read mode 0 */
762
            plane = s->gr[4];
763
            ret = GET_PLANE(s->latch, plane);
764
        } else {
765
            /* read mode 1 */
766
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
767
            ret |= ret >> 16;
768
            ret |= ret >> 8;
769
            ret = (~ret) & 0xff;
770
        }
771
    }
772
    return ret;
773
}
774

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

    
788
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
789
{
790
    uint32_t v;
791
#ifdef TARGET_WORDS_BIGENDIAN
792
    v = vga_mem_readb(opaque, addr) << 24;
793
    v |= vga_mem_readb(opaque, addr + 1) << 16;
794
    v |= vga_mem_readb(opaque, addr + 2) << 8;
795
    v |= vga_mem_readb(opaque, addr + 3);
796
#else
797
    v = vga_mem_readb(opaque, addr);
798
    v |= vga_mem_readb(opaque, addr + 1) << 8;
799
    v |= vga_mem_readb(opaque, addr + 2) << 16;
800
    v |= vga_mem_readb(opaque, addr + 3) << 24;
801
#endif
802
    return v;
803
}
804

    
805
/* called for accesses between 0xa0000 and 0xc0000 */
806
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
807
{
808
    VGAState *s = opaque;
809
    int memory_map_mode, plane, write_mode, b, func_select, mask;
810
    uint32_t write_mask, bit_mask, set_mask;
811

    
812
#ifdef DEBUG_VGA_MEM
813
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
814
#endif
815
    /* convert to VGA memory offset */
816
    memory_map_mode = (s->gr[6] >> 2) & 3;
817
    addr &= 0x1ffff;
818
    switch(memory_map_mode) {
819
    case 0:
820
        break;
821
    case 1:
822
        if (addr >= 0x10000)
823
            return;
824
        addr += s->bank_offset;
825
        break;
826
    case 2:
827
        addr -= 0x10000;
828
        if (addr >= 0x8000)
829
            return;
830
        break;
831
    default:
832
    case 3:
833
        addr -= 0x18000;
834
        if (addr >= 0x8000)
835
            return;
836
        break;
837
    }
838

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

    
876
            /* apply set/reset mask */
877
            set_mask = mask16[s->gr[1]];
878
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
879
            bit_mask = s->gr[8];
880
            break;
881
        case 1:
882
            val = s->latch;
883
            goto do_write;
884
        case 2:
885
            val = mask16[val & 0x0f];
886
            bit_mask = s->gr[8];
887
            break;
888
        case 3:
889
            /* rotate */
890
            b = s->gr[3] & 7;
891
            val = (val >> b) | (val << (8 - b));
892

    
893
            bit_mask = s->gr[8] & val;
894
            val = mask16[s->gr[0]];
895
            break;
896
        }
897

    
898
        /* apply logical operation */
899
        func_select = s->gr[3] >> 3;
900
        switch(func_select) {
901
        case 0:
902
        default:
903
            /* nothing to do */
904
            break;
905
        case 1:
906
            /* and */
907
            val &= s->latch;
908
            break;
909
        case 2:
910
            /* or */
911
            val |= s->latch;
912
            break;
913
        case 3:
914
            /* xor */
915
            val ^= s->latch;
916
            break;
917
        }
918

    
919
        /* apply bit mask */
920
        bit_mask |= bit_mask << 8;
921
        bit_mask |= bit_mask << 16;
922
        val = (val & bit_mask) | (s->latch & ~bit_mask);
923

    
924
    do_write:
925
        /* mask data according to sr[2] */
926
        mask = s->sr[2];
927
        s->plane_updated |= mask; /* only used to detect font change */
928
        write_mask = mask16[mask];
929
        ((uint32_t *)s->vram_ptr)[addr] =
930
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
931
            (val & write_mask);
932
#ifdef DEBUG_VGA_MEM
933
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
934
               addr * 4, write_mask, val);
935
#endif
936
        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
937
    }
938
}
939

    
940
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
941
{
942
#ifdef TARGET_WORDS_BIGENDIAN
943
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
944
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
945
#else
946
    vga_mem_writeb(opaque, addr, val & 0xff);
947
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
948
#endif
949
}
950

    
951
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
952
{
953
#ifdef TARGET_WORDS_BIGENDIAN
954
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
955
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
956
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
957
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
958
#else
959
    vga_mem_writeb(opaque, addr, val & 0xff);
960
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
961
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
962
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
963
#endif
964
}
965

    
966
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
967
                             const uint8_t *font_ptr, int h,
968
                             uint32_t fgcol, uint32_t bgcol);
969
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
970
                                  const uint8_t *font_ptr, int h,
971
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
972
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
973
                                const uint8_t *s, int width);
974

    
975
#define DEPTH 8
976
#include "vga_template.h"
977

    
978
#define DEPTH 15
979
#include "vga_template.h"
980

    
981
#define BGR_FORMAT
982
#define DEPTH 15
983
#include "vga_template.h"
984

    
985
#define DEPTH 16
986
#include "vga_template.h"
987

    
988
#define BGR_FORMAT
989
#define DEPTH 16
990
#include "vga_template.h"
991

    
992
#define DEPTH 32
993
#include "vga_template.h"
994

    
995
#define BGR_FORMAT
996
#define DEPTH 32
997
#include "vga_template.h"
998

    
999
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
1000
{
1001
    unsigned int col;
1002
    col = rgb_to_pixel8(r, g, b);
1003
    col |= col << 8;
1004
    col |= col << 16;
1005
    return col;
1006
}
1007

    
1008
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1009
{
1010
    unsigned int col;
1011
    col = rgb_to_pixel15(r, g, b);
1012
    col |= col << 16;
1013
    return col;
1014
}
1015

    
1016
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1017
                                          unsigned int b)
1018
{
1019
    unsigned int col;
1020
    col = rgb_to_pixel15bgr(r, g, b);
1021
    col |= col << 16;
1022
    return col;
1023
}
1024

    
1025
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1026
{
1027
    unsigned int col;
1028
    col = rgb_to_pixel16(r, g, b);
1029
    col |= col << 16;
1030
    return col;
1031
}
1032

    
1033
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1034
                                          unsigned int b)
1035
{
1036
    unsigned int col;
1037
    col = rgb_to_pixel16bgr(r, g, b);
1038
    col |= col << 16;
1039
    return col;
1040
}
1041

    
1042
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1043
{
1044
    unsigned int col;
1045
    col = rgb_to_pixel32(r, g, b);
1046
    return col;
1047
}
1048

    
1049
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1050
{
1051
    unsigned int col;
1052
    col = rgb_to_pixel32bgr(r, g, b);
1053
    return col;
1054
}
1055

    
1056
/* return true if the palette was modified */
1057
static int update_palette16(VGAState *s)
1058
{
1059
    int full_update, i;
1060
    uint32_t v, col, *palette;
1061

    
1062
    full_update = 0;
1063
    palette = s->last_palette;
1064
    for(i = 0; i < 16; i++) {
1065
        v = s->ar[i];
1066
        if (s->ar[0x10] & 0x80)
1067
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1068
        else
1069
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1070
        v = v * 3;
1071
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1072
                              c6_to_8(s->palette[v + 1]),
1073
                              c6_to_8(s->palette[v + 2]));
1074
        if (col != palette[i]) {
1075
            full_update = 1;
1076
            palette[i] = col;
1077
        }
1078
    }
1079
    return full_update;
1080
}
1081

    
1082
/* return true if the palette was modified */
1083
static int update_palette256(VGAState *s)
1084
{
1085
    int full_update, i;
1086
    uint32_t v, col, *palette;
1087

    
1088
    full_update = 0;
1089
    palette = s->last_palette;
1090
    v = 0;
1091
    for(i = 0; i < 256; i++) {
1092
        if (s->dac_8bit) {
1093
          col = s->rgb_to_pixel(s->palette[v],
1094
                                s->palette[v + 1],
1095
                                s->palette[v + 2]);
1096
        } else {
1097
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1098
                                c6_to_8(s->palette[v + 1]),
1099
                                c6_to_8(s->palette[v + 2]));
1100
        }
1101
        if (col != palette[i]) {
1102
            full_update = 1;
1103
            palette[i] = col;
1104
        }
1105
        v += 3;
1106
    }
1107
    return full_update;
1108
}
1109

    
1110
static void vga_get_offsets(VGAState *s,
1111
                            uint32_t *pline_offset,
1112
                            uint32_t *pstart_addr,
1113
                            uint32_t *pline_compare)
1114
{
1115
    uint32_t start_addr, line_offset, line_compare;
1116
#ifdef CONFIG_BOCHS_VBE
1117
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1118
        line_offset = s->vbe_line_offset;
1119
        start_addr = s->vbe_start_addr;
1120
        line_compare = 65535;
1121
    } else
1122
#endif
1123
    {
1124
        /* compute line_offset in bytes */
1125
        line_offset = s->cr[0x13];
1126
        line_offset <<= 3;
1127

    
1128
        /* starting address */
1129
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1130

    
1131
        /* line compare */
1132
        line_compare = s->cr[0x18] |
1133
            ((s->cr[0x07] & 0x10) << 4) |
1134
            ((s->cr[0x09] & 0x40) << 3);
1135
    }
1136
    *pline_offset = line_offset;
1137
    *pstart_addr = start_addr;
1138
    *pline_compare = line_compare;
1139
}
1140

    
1141
/* update start_addr and line_offset. Return TRUE if modified */
1142
static int update_basic_params(VGAState *s)
1143
{
1144
    int full_update;
1145
    uint32_t start_addr, line_offset, line_compare;
1146

    
1147
    full_update = 0;
1148

    
1149
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1150

    
1151
    if (line_offset != s->line_offset ||
1152
        start_addr != s->start_addr ||
1153
        line_compare != s->line_compare) {
1154
        s->line_offset = line_offset;
1155
        s->start_addr = start_addr;
1156
        s->line_compare = line_compare;
1157
        full_update = 1;
1158
    }
1159
    return full_update;
1160
}
1161

    
1162
#define NB_DEPTHS 7
1163

    
1164
static inline int get_depth_index(DisplayState *s)
1165
{
1166
    switch(ds_get_bits_per_pixel(s)) {
1167
    default:
1168
    case 8:
1169
        return 0;
1170
    case 15:
1171
        return 1;
1172
    case 16:
1173
        return 2;
1174
    case 32:
1175
        if (is_surface_bgr(s->surface))
1176
            return 4;
1177
        else
1178
            return 3;
1179
    }
1180
}
1181

    
1182
static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1183
    vga_draw_glyph8_8,
1184
    vga_draw_glyph8_16,
1185
    vga_draw_glyph8_16,
1186
    vga_draw_glyph8_32,
1187
    vga_draw_glyph8_32,
1188
    vga_draw_glyph8_16,
1189
    vga_draw_glyph8_16,
1190
};
1191

    
1192
static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1193
    vga_draw_glyph16_8,
1194
    vga_draw_glyph16_16,
1195
    vga_draw_glyph16_16,
1196
    vga_draw_glyph16_32,
1197
    vga_draw_glyph16_32,
1198
    vga_draw_glyph16_16,
1199
    vga_draw_glyph16_16,
1200
};
1201

    
1202
static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1203
    vga_draw_glyph9_8,
1204
    vga_draw_glyph9_16,
1205
    vga_draw_glyph9_16,
1206
    vga_draw_glyph9_32,
1207
    vga_draw_glyph9_32,
1208
    vga_draw_glyph9_16,
1209
    vga_draw_glyph9_16,
1210
};
1211

    
1212
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1224
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1225
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1226
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1227
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1228
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1229
};
1230

    
1231
static void vga_get_text_resolution(VGAState *s, int *pwidth, int *pheight,
1232
                                    int *pcwidth, int *pcheight)
1233
{
1234
    int width, cwidth, height, cheight;
1235

    
1236
    /* total width & height */
1237
    cheight = (s->cr[9] & 0x1f) + 1;
1238
    cwidth = 8;
1239
    if (!(s->sr[1] & 0x01))
1240
        cwidth = 9;
1241
    if (s->sr[1] & 0x08)
1242
        cwidth = 16; /* NOTE: no 18 pixel wide */
1243
    width = (s->cr[0x01] + 1);
1244
    if (s->cr[0x06] == 100) {
1245
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1246
        height = 100;
1247
    } else {
1248
        height = s->cr[0x12] |
1249
            ((s->cr[0x07] & 0x02) << 7) |
1250
            ((s->cr[0x07] & 0x40) << 3);
1251
        height = (height + 1) / cheight;
1252
    }
1253

    
1254
    *pwidth = width;
1255
    *pheight = height;
1256
    *pcwidth = cwidth;
1257
    *pcheight = cheight;
1258
}
1259

    
1260
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1261

    
1262
static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1263
    rgb_to_pixel8_dup,
1264
    rgb_to_pixel15_dup,
1265
    rgb_to_pixel16_dup,
1266
    rgb_to_pixel32_dup,
1267
    rgb_to_pixel32bgr_dup,
1268
    rgb_to_pixel15bgr_dup,
1269
    rgb_to_pixel16bgr_dup,
1270
};
1271

    
1272
/*
1273
 * Text mode update
1274
 * Missing:
1275
 * - double scan
1276
 * - double width
1277
 * - underline
1278
 * - flashing
1279
 */
1280
static void vga_draw_text(VGAState *s, int full_update)
1281
{
1282
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1283
    int cx_min, cx_max, linesize, x_incr;
1284
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1285
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1286
    const uint8_t *font_ptr, *font_base[2];
1287
    int dup9, line_offset, depth_index;
1288
    uint32_t *palette;
1289
    uint32_t *ch_attr_ptr;
1290
    vga_draw_glyph8_func *vga_draw_glyph8;
1291
    vga_draw_glyph9_func *vga_draw_glyph9;
1292

    
1293
    /* compute font data address (in plane 2) */
1294
    v = s->sr[3];
1295
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1296
    if (offset != s->font_offsets[0]) {
1297
        s->font_offsets[0] = offset;
1298
        full_update = 1;
1299
    }
1300
    font_base[0] = s->vram_ptr + offset;
1301

    
1302
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1303
    font_base[1] = s->vram_ptr + offset;
1304
    if (offset != s->font_offsets[1]) {
1305
        s->font_offsets[1] = offset;
1306
        full_update = 1;
1307
    }
1308
    if (s->plane_updated & (1 << 2)) {
1309
        /* if the plane 2 was modified since the last display, it
1310
           indicates the font may have been modified */
1311
        s->plane_updated = 0;
1312
        full_update = 1;
1313
    }
1314
    full_update |= update_basic_params(s);
1315

    
1316
    line_offset = s->line_offset;
1317
    s1 = s->vram_ptr + (s->start_addr * 4);
1318

    
1319
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1320
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1321
    if ((height * width) > CH_ATTR_SIZE) {
1322
        /* better than nothing: exit if transient size is too big */
1323
        return;
1324
    }
1325

    
1326
    if (width != s->last_width || height != s->last_height ||
1327
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1328
        s->last_scr_width = width * cw;
1329
        s->last_scr_height = height * cheight;
1330
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1331
        s->last_depth = 0;
1332
        s->last_width = width;
1333
        s->last_height = height;
1334
        s->last_ch = cheight;
1335
        s->last_cw = cw;
1336
        full_update = 1;
1337
    }
1338
    s->rgb_to_pixel =
1339
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1340
    full_update |= update_palette16(s);
1341
    palette = s->last_palette;
1342
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1343

    
1344
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1345
    if (cursor_offset != s->cursor_offset ||
1346
        s->cr[0xa] != s->cursor_start ||
1347
        s->cr[0xb] != s->cursor_end) {
1348
      /* if the cursor position changed, we update the old and new
1349
         chars */
1350
        if (s->cursor_offset < CH_ATTR_SIZE)
1351
            s->last_ch_attr[s->cursor_offset] = -1;
1352
        if (cursor_offset < CH_ATTR_SIZE)
1353
            s->last_ch_attr[cursor_offset] = -1;
1354
        s->cursor_offset = cursor_offset;
1355
        s->cursor_start = s->cr[0xa];
1356
        s->cursor_end = s->cr[0xb];
1357
    }
1358
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1359

    
1360
    depth_index = get_depth_index(s->ds);
1361
    if (cw == 16)
1362
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1363
    else
1364
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1365
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1366

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

    
1439
enum {
1440
    VGA_DRAW_LINE2,
1441
    VGA_DRAW_LINE2D2,
1442
    VGA_DRAW_LINE4,
1443
    VGA_DRAW_LINE4D2,
1444
    VGA_DRAW_LINE8D2,
1445
    VGA_DRAW_LINE8,
1446
    VGA_DRAW_LINE15,
1447
    VGA_DRAW_LINE16,
1448
    VGA_DRAW_LINE24,
1449
    VGA_DRAW_LINE32,
1450
    VGA_DRAW_LINE_NB,
1451
};
1452

    
1453
static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1454
    vga_draw_line2_8,
1455
    vga_draw_line2_16,
1456
    vga_draw_line2_16,
1457
    vga_draw_line2_32,
1458
    vga_draw_line2_32,
1459
    vga_draw_line2_16,
1460
    vga_draw_line2_16,
1461

    
1462
    vga_draw_line2d2_8,
1463
    vga_draw_line2d2_16,
1464
    vga_draw_line2d2_16,
1465
    vga_draw_line2d2_32,
1466
    vga_draw_line2d2_32,
1467
    vga_draw_line2d2_16,
1468
    vga_draw_line2d2_16,
1469

    
1470
    vga_draw_line4_8,
1471
    vga_draw_line4_16,
1472
    vga_draw_line4_16,
1473
    vga_draw_line4_32,
1474
    vga_draw_line4_32,
1475
    vga_draw_line4_16,
1476
    vga_draw_line4_16,
1477

    
1478
    vga_draw_line4d2_8,
1479
    vga_draw_line4d2_16,
1480
    vga_draw_line4d2_16,
1481
    vga_draw_line4d2_32,
1482
    vga_draw_line4d2_32,
1483
    vga_draw_line4d2_16,
1484
    vga_draw_line4d2_16,
1485

    
1486
    vga_draw_line8d2_8,
1487
    vga_draw_line8d2_16,
1488
    vga_draw_line8d2_16,
1489
    vga_draw_line8d2_32,
1490
    vga_draw_line8d2_32,
1491
    vga_draw_line8d2_16,
1492
    vga_draw_line8d2_16,
1493

    
1494
    vga_draw_line8_8,
1495
    vga_draw_line8_16,
1496
    vga_draw_line8_16,
1497
    vga_draw_line8_32,
1498
    vga_draw_line8_32,
1499
    vga_draw_line8_16,
1500
    vga_draw_line8_16,
1501

    
1502
    vga_draw_line15_8,
1503
    vga_draw_line15_15,
1504
    vga_draw_line15_16,
1505
    vga_draw_line15_32,
1506
    vga_draw_line15_32bgr,
1507
    vga_draw_line15_15bgr,
1508
    vga_draw_line15_16bgr,
1509

    
1510
    vga_draw_line16_8,
1511
    vga_draw_line16_15,
1512
    vga_draw_line16_16,
1513
    vga_draw_line16_32,
1514
    vga_draw_line16_32bgr,
1515
    vga_draw_line16_15bgr,
1516
    vga_draw_line16_16bgr,
1517

    
1518
    vga_draw_line24_8,
1519
    vga_draw_line24_15,
1520
    vga_draw_line24_16,
1521
    vga_draw_line24_32,
1522
    vga_draw_line24_32bgr,
1523
    vga_draw_line24_15bgr,
1524
    vga_draw_line24_16bgr,
1525

    
1526
    vga_draw_line32_8,
1527
    vga_draw_line32_15,
1528
    vga_draw_line32_16,
1529
    vga_draw_line32_32,
1530
    vga_draw_line32_32bgr,
1531
    vga_draw_line32_15bgr,
1532
    vga_draw_line32_16bgr,
1533
};
1534

    
1535
static int vga_get_bpp(VGAState *s)
1536
{
1537
    int ret;
1538
#ifdef CONFIG_BOCHS_VBE
1539
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1540
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1541
    } else
1542
#endif
1543
    {
1544
        ret = 0;
1545
    }
1546
    return ret;
1547
}
1548

    
1549
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1550
{
1551
    int width, height;
1552

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

    
1570
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1571
{
1572
    int y;
1573
    if (y1 >= VGA_MAX_HEIGHT)
1574
        return;
1575
    if (y2 >= VGA_MAX_HEIGHT)
1576
        y2 = VGA_MAX_HEIGHT;
1577
    for(y = y1; y < y2; y++) {
1578
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1579
    }
1580
}
1581

    
1582
static void vga_sync_dirty_bitmap(VGAState *s)
1583
{
1584
    if (s->map_addr)
1585
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1586

    
1587
    if (s->lfb_vram_mapped) {
1588
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1589
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1590
    }
1591
}
1592

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

    
1606
    full_update |= update_basic_params(s);
1607

    
1608
    if (!full_update)
1609
        vga_sync_dirty_bitmap(s);
1610

    
1611
    s->get_resolution(s, &width, &height);
1612
    disp_width = width;
1613

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

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

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

    
1675
    s->rgb_to_pixel =
1676
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1677

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

    
1727
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1728
        s->cursor_invalidate(s);
1729

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

    
1813
static void vga_draw_blank(VGAState *s, int full_update)
1814
{
1815
    int i, w, val;
1816
    uint8_t *d;
1817

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

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

    
1839
#define GMODE_TEXT     0
1840
#define GMODE_GRAPH    1
1841
#define GMODE_BLANK 2
1842

    
1843
static void vga_update_display(void *opaque)
1844
{
1845
    VGAState *s = opaque;
1846
    int full_update, graphic_mode;
1847

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

    
1877
/* force a full display refresh */
1878
static void vga_invalidate_display(void *opaque)
1879
{
1880
    VGAState *s = opaque;
1881

    
1882
    s->full_update = 1;
1883
}
1884

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

    
1952
static void vga_reset(void *opaque)
1953
{
1954
    VGAState *s =  opaque;
1955
    vga_common_reset(s);
1956
}
1957

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2086
        return;
2087
    case GMODE_GRAPH:
2088
        if (!full_update)
2089
            return;
2090

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

    
2100
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2101
        break;
2102
    }
2103

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

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

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

    
2121
    dpy_update(s->ds, 0, 0, s->last_width, height);
2122
}
2123

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

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

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

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

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

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

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

    
2182
    if (version_id > 2)
2183
        return -EINVAL;
2184

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

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

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

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

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

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

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

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

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

    
2279
/* used by both ISA and PCI */
2280
void vga_init(VGAState *s)
2281
{
2282
    int vga_io_memory;
2283

    
2284
    qemu_register_reset(vga_reset, s);
2285

    
2286
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2287

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

    
2293
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2294

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

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

    
2306
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2307
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2308

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

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

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

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

    
2330
/********************************************************/
2331
/* vga screen dump */
2332

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

    
2342
static void vga_save_dpy_resize(DisplayState *s)
2343
{
2344
}
2345

    
2346
static void vga_save_dpy_refresh(DisplayState *s)
2347
{
2348
}
2349

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

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

    
2388
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2389
{
2390
    DisplayChangeListener *dcl;
2391

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

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

    
2406
    if (!screen_dump_dcl)
2407
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2408

    
2409
    screen_dump_filename = (char *)filename;
2410
    vga_invalidate_display(s);
2411
    vga_hw_update();
2412
}
2413