Statistics
| Branch: | Revision:

root / hw / vga.c @ 2aebb3eb

History | View | Annotate | Download (51.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 "vl.h"
25

    
26
//#define DEBUG_VGA
27
//#define DEBUG_VGA_MEM
28
//#define DEBUG_VGA_REG
29

    
30
//#define DEBUG_S3
31
//#define DEBUG_BOCHS_VBE
32

    
33
#define CONFIG_S3VGA
34

    
35
#define MSR_COLOR_EMULATION 0x01
36
#define MSR_PAGE_SELECT     0x20
37

    
38
#define ST01_V_RETRACE      0x08
39
#define ST01_DISP_ENABLE    0x01
40

    
41
/* bochs VBE support */
42
#define CONFIG_BOCHS_VBE
43

    
44
#define VBE_DISPI_MAX_XRES              1024
45
#define VBE_DISPI_MAX_YRES              768
46

    
47
#define VBE_DISPI_INDEX_ID              0x0
48
#define VBE_DISPI_INDEX_XRES            0x1
49
#define VBE_DISPI_INDEX_YRES            0x2
50
#define VBE_DISPI_INDEX_BPP             0x3
51
#define VBE_DISPI_INDEX_ENABLE          0x4
52
#define VBE_DISPI_INDEX_BANK            0x5
53
#define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
54
#define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
55
#define VBE_DISPI_INDEX_X_OFFSET        0x8
56
#define VBE_DISPI_INDEX_Y_OFFSET        0x9
57
#define VBE_DISPI_INDEX_NB              0xa
58
      
59
#define VBE_DISPI_ID0                   0xB0C0
60
#define VBE_DISPI_ID1                   0xB0C1
61
#define VBE_DISPI_ID2                   0xB0C2
62
  
63
#define VBE_DISPI_DISABLED              0x00
64
#define VBE_DISPI_ENABLED               0x01
65
#define VBE_DISPI_LFB_ENABLED           0x40
66
#define VBE_DISPI_NOCLEARMEM            0x80
67
  
68
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
69

    
70
typedef struct VGAState {
71
    uint8_t *vram_ptr;
72
    unsigned long vram_offset;
73
    unsigned int vram_size;
74
    uint32_t latch;
75
    uint8_t sr_index;
76
    uint8_t sr[8];
77
    uint8_t gr_index;
78
    uint8_t gr[16];
79
    uint8_t ar_index;
80
    uint8_t ar[21];
81
    int ar_flip_flop;
82
    uint8_t cr_index;
83
    uint8_t cr[256]; /* CRT registers */
84
    uint8_t msr; /* Misc Output Register */
85
    uint8_t fcr; /* Feature Control Register */
86
    uint8_t st00; /* status 0 */
87
    uint8_t st01; /* status 1 */
88
    uint8_t dac_state;
89
    uint8_t dac_sub_index;
90
    uint8_t dac_read_index;
91
    uint8_t dac_write_index;
92
    uint8_t dac_cache[3]; /* used when writing */
93
    uint8_t palette[768];
94
    uint32_t bank_offset;
95
#ifdef CONFIG_BOCHS_VBE
96
    uint16_t vbe_index;
97
    uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
98
    uint32_t vbe_start_addr;
99
    uint32_t vbe_line_offset;
100
    uint32_t vbe_bank_mask;
101
#endif
102
    /* display refresh support */
103
    DisplayState *ds;
104
    uint32_t font_offsets[2];
105
    int graphic_mode;
106
    uint8_t shift_control;
107
    uint8_t double_scan;
108
    uint32_t line_offset;
109
    uint32_t line_compare;
110
    uint32_t start_addr;
111
    uint8_t last_cw, last_ch;
112
    uint32_t last_width, last_height; /* in chars or pixels */
113
    uint32_t last_scr_width, last_scr_height; /* in pixels */
114
    uint8_t cursor_start, cursor_end;
115
    uint32_t cursor_offset;
116
    unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
117
    /* tell for each page if it has been updated since the last time */
118
    uint32_t last_palette[256];
119
#define CH_ATTR_SIZE (160 * 100)
120
    uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
121
} VGAState;
122

    
123
/* force some bits to zero */
124
static const uint8_t sr_mask[8] = {
125
    (uint8_t)~0xfc,
126
    (uint8_t)~0xc2,
127
    (uint8_t)~0xf0,
128
    (uint8_t)~0xc0,
129
    (uint8_t)~0xf1,
130
    (uint8_t)~0xff,
131
    (uint8_t)~0xff,
132
    (uint8_t)~0x00,
133
};
134

    
135
static const uint8_t gr_mask[16] = {
136
    (uint8_t)~0xf0, /* 0x00 */
137
    (uint8_t)~0xf0, /* 0x01 */
138
    (uint8_t)~0xf0, /* 0x02 */
139
    (uint8_t)~0xe0, /* 0x03 */
140
    (uint8_t)~0xfc, /* 0x04 */
141
    (uint8_t)~0x84, /* 0x05 */
142
    (uint8_t)~0xf0, /* 0x06 */
143
    (uint8_t)~0xf0, /* 0x07 */
144
    (uint8_t)~0x00, /* 0x08 */
145
    (uint8_t)~0xff, /* 0x09 */
146
    (uint8_t)~0xff, /* 0x0a */
147
    (uint8_t)~0xff, /* 0x0b */
148
    (uint8_t)~0xff, /* 0x0c */
149
    (uint8_t)~0xff, /* 0x0d */
150
    (uint8_t)~0xff, /* 0x0e */
151
    (uint8_t)~0xff, /* 0x0f */
152
};
153

    
154
#define cbswap_32(__x) \
155
((uint32_t)( \
156
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
157
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
158
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
159
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
160

    
161
#ifdef WORDS_BIGENDIAN
162
#define PAT(x) cbswap_32(x)
163
#else
164
#define PAT(x) (x)
165
#endif
166

    
167
#ifdef WORDS_BIGENDIAN
168
#define BIG 1
169
#else
170
#define BIG 0
171
#endif
172

    
173
#ifdef WORDS_BIGENDIAN
174
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
175
#else
176
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
177
#endif
178

    
179
static const uint32_t mask16[16] = {
180
    PAT(0x00000000),
181
    PAT(0x000000ff),
182
    PAT(0x0000ff00),
183
    PAT(0x0000ffff),
184
    PAT(0x00ff0000),
185
    PAT(0x00ff00ff),
186
    PAT(0x00ffff00),
187
    PAT(0x00ffffff),
188
    PAT(0xff000000),
189
    PAT(0xff0000ff),
190
    PAT(0xff00ff00),
191
    PAT(0xff00ffff),
192
    PAT(0xffff0000),
193
    PAT(0xffff00ff),
194
    PAT(0xffffff00),
195
    PAT(0xffffffff),
196
};
197

    
198
#undef PAT
199

    
200
#ifdef WORDS_BIGENDIAN
201
#define PAT(x) (x)
202
#else
203
#define PAT(x) cbswap_32(x)
204
#endif
205

    
206
static const uint32_t dmask16[16] = {
207
    PAT(0x00000000),
208
    PAT(0x000000ff),
209
    PAT(0x0000ff00),
210
    PAT(0x0000ffff),
211
    PAT(0x00ff0000),
212
    PAT(0x00ff00ff),
213
    PAT(0x00ffff00),
214
    PAT(0x00ffffff),
215
    PAT(0xff000000),
216
    PAT(0xff0000ff),
217
    PAT(0xff00ff00),
218
    PAT(0xff00ffff),
219
    PAT(0xffff0000),
220
    PAT(0xffff00ff),
221
    PAT(0xffffff00),
222
    PAT(0xffffffff),
223
};
224

    
225
static const uint32_t dmask4[4] = {
226
    PAT(0x00000000),
227
    PAT(0x0000ffff),
228
    PAT(0xffff0000),
229
    PAT(0xffffffff),
230
};
231

    
232
static uint32_t expand4[256];
233
static uint16_t expand2[256];
234
static uint8_t expand4to8[16];
235

    
236
VGAState vga_state;
237
int vga_io_memory;
238

    
239
static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
240
{
241
    VGAState *s = opaque;
242
    int val, index;
243

    
244
    /* check port range access depending on color/monochrome mode */
245
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
246
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
247
        val = 0xff;
248
    } else {
249
        switch(addr) {
250
        case 0x3c0:
251
            if (s->ar_flip_flop == 0) {
252
                val = s->ar_index;
253
            } else {
254
                val = 0;
255
            }
256
            break;
257
        case 0x3c1:
258
            index = s->ar_index & 0x1f;
259
            if (index < 21) 
260
                val = s->ar[index];
261
            else
262
                val = 0;
263
            break;
264
        case 0x3c2:
265
            val = s->st00;
266
            break;
267
        case 0x3c4:
268
            val = s->sr_index;
269
            break;
270
        case 0x3c5:
271
            val = s->sr[s->sr_index];
272
#ifdef DEBUG_VGA_REG
273
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
274
#endif
275
            break;
276
        case 0x3c7:
277
            val = s->dac_state;
278
            break;
279
        case 0x3c9:
280
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
281
            if (++s->dac_sub_index == 3) {
282
                s->dac_sub_index = 0;
283
                s->dac_read_index++;
284
            }
285
            break;
286
        case 0x3ca:
287
            val = s->fcr;
288
            break;
289
        case 0x3cc:
290
            val = s->msr;
291
            break;
292
        case 0x3ce:
293
            val = s->gr_index;
294
            break;
295
        case 0x3cf:
296
            val = s->gr[s->gr_index];
297
#ifdef DEBUG_VGA_REG
298
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
299
#endif
300
            break;
301
        case 0x3b4:
302
        case 0x3d4:
303
            val = s->cr_index;
304
            break;
305
        case 0x3b5:
306
        case 0x3d5:
307
            val = s->cr[s->cr_index];
308
#ifdef DEBUG_VGA_REG
309
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
310
#endif
311
#ifdef DEBUG_S3
312
            if (s->cr_index >= 0x20)
313
                printf("S3: CR read index=0x%x val=0x%x\n",
314
                       s->cr_index, val);
315
#endif
316
            break;
317
        case 0x3ba:
318
        case 0x3da:
319
            /* just toggle to fool polling */
320
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
321
            val = s->st01;
322
            s->ar_flip_flop = 0;
323
            break;
324
        default:
325
            val = 0x00;
326
            break;
327
        }
328
    }
329
#if defined(DEBUG_VGA)
330
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
331
#endif
332
    return val;
333
}
334

    
335
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
336
{
337
    VGAState *s = opaque;
338
    int index, v;
339

    
340
    /* check port range access depending on color/monochrome mode */
341
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
342
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
343
        return;
344

    
345
#ifdef DEBUG_VGA
346
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
347
#endif
348

    
349
    switch(addr) {
350
    case 0x3c0:
351
        if (s->ar_flip_flop == 0) {
352
            val &= 0x3f;
353
            s->ar_index = val;
354
        } else {
355
            index = s->ar_index & 0x1f;
356
            switch(index) {
357
            case 0x00 ... 0x0f:
358
                s->ar[index] = val & 0x3f;
359
                break;
360
            case 0x10:
361
                s->ar[index] = val & ~0x10;
362
                break;
363
            case 0x11:
364
                s->ar[index] = val;
365
                break;
366
            case 0x12:
367
                s->ar[index] = val & ~0xc0;
368
                break;
369
            case 0x13:
370
                s->ar[index] = val & ~0xf0;
371
                break;
372
            case 0x14:
373
                s->ar[index] = val & ~0xf0;
374
                break;
375
            default:
376
                break;
377
            }
378
        }
379
        s->ar_flip_flop ^= 1;
380
        break;
381
    case 0x3c2:
382
        s->msr = val & ~0x10;
383
        break;
384
    case 0x3c4:
385
        s->sr_index = val & 7;
386
        break;
387
    case 0x3c5:
388
#ifdef DEBUG_VGA_REG
389
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
390
#endif
391
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
392
        break;
393
    case 0x3c7:
394
        s->dac_read_index = val;
395
        s->dac_sub_index = 0;
396
        s->dac_state = 3;
397
        break;
398
    case 0x3c8:
399
        s->dac_write_index = val;
400
        s->dac_sub_index = 0;
401
        s->dac_state = 0;
402
        break;
403
    case 0x3c9:
404
        s->dac_cache[s->dac_sub_index] = val;
405
        if (++s->dac_sub_index == 3) {
406
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
407
            s->dac_sub_index = 0;
408
            s->dac_write_index++;
409
        }
410
        break;
411
    case 0x3ce:
412
        s->gr_index = val & 0x0f;
413
        break;
414
    case 0x3cf:
415
#ifdef DEBUG_VGA_REG
416
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
417
#endif
418
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
419
        break;
420
    case 0x3b4:
421
    case 0x3d4:
422
        s->cr_index = val;
423
        break;
424
    case 0x3b5:
425
    case 0x3d5:
426
#ifdef DEBUG_VGA_REG
427
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
428
#endif
429
        /* handle CR0-7 protection */
430
        if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
431
            /* can always write bit 4 of CR7 */
432
            if (s->cr_index == 7)
433
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
434
            return;
435
        }
436
        switch(s->cr_index) {
437
        case 0x01: /* horizontal display end */
438
        case 0x07:
439
        case 0x09:
440
        case 0x0c:
441
        case 0x0d:
442
        case 0x12: /* veritcal display end */
443
            s->cr[s->cr_index] = val;
444
            break;
445

    
446
#ifdef CONFIG_S3VGA
447
            /* S3 registers */
448
        case 0x2d:
449
        case 0x2e:
450
        case 0x2f:
451
        case 0x30:
452
            /* chip ID, cannot write */
453
            break;
454
        case 0x31:
455
            /* update start address */
456
            s->cr[s->cr_index] = val;
457
            v = (val >> 4) & 3;
458
            s->cr[0x69] = (s->cr[69] & ~0x03) | v;
459
            break;
460
        case 0x51:
461
            /* update start address */
462
            s->cr[s->cr_index] = val;
463
            v = val & 3;
464
            s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
465
            break;
466
#endif
467
        default:
468
            s->cr[s->cr_index] = val;
469
            break;
470
        }
471
#ifdef DEBUG_S3
472
        if (s->cr_index >= 0x20)
473
            printf("S3: CR write index=0x%x val=0x%x\n",
474
                   s->cr_index, val);
475
#endif
476
        break;
477
    case 0x3ba:
478
    case 0x3da:
479
        s->fcr = val & 0x10;
480
        break;
481
    }
482
}
483

    
484
#ifdef CONFIG_BOCHS_VBE
485
static uint32_t vbe_ioport_read(void *opaque, uint32_t addr)
486
{
487
    VGAState *s = opaque;
488
    uint32_t val;
489

    
490
    addr &= 1;
491
    if (addr == 0) {
492
        val = s->vbe_index;
493
    } else {
494
        if (s->vbe_index <= VBE_DISPI_INDEX_NB)
495
            val = s->vbe_regs[s->vbe_index];
496
        else
497
            val = 0;
498
#ifdef DEBUG_BOCHS_VBE
499
        printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
500
#endif
501
    }
502
    return val;
503
}
504

    
505
static void vbe_ioport_write(void *opaque, uint32_t addr, uint32_t val)
506
{
507
    VGAState *s = opaque;
508

    
509
    addr &= 1;
510
    if (addr == 0) {
511
        s->vbe_index = val;
512
    } else if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
513
#ifdef DEBUG_BOCHS_VBE
514
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
515
#endif
516
        switch(s->vbe_index) {
517
        case VBE_DISPI_INDEX_ID:
518
            if (val == VBE_DISPI_ID0 ||
519
                val == VBE_DISPI_ID1 ||
520
                val == VBE_DISPI_ID2) {
521
                s->vbe_regs[s->vbe_index] = val;
522
            }
523
            break;
524
        case VBE_DISPI_INDEX_XRES:
525
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
526
                s->vbe_regs[s->vbe_index] = val;
527
            }
528
            break;
529
        case VBE_DISPI_INDEX_YRES:
530
            if (val <= VBE_DISPI_MAX_YRES) {
531
                s->vbe_regs[s->vbe_index] = val;
532
            }
533
            break;
534
        case VBE_DISPI_INDEX_BPP:
535
            if (val == 0)
536
                val = 8;
537
            if (val == 4 || val == 8 || val == 15 || 
538
                val == 16 || val == 24 || val == 32) {
539
                s->vbe_regs[s->vbe_index] = val;
540
            }
541
            break;
542
        case VBE_DISPI_INDEX_BANK:
543
            val &= s->vbe_bank_mask;
544
            s->vbe_regs[s->vbe_index] = val;
545
            s->bank_offset = (val << 16) - 0xa0000;
546
            break;
547
        case VBE_DISPI_INDEX_ENABLE:
548
            if (val & VBE_DISPI_ENABLED) {
549
                int h, shift_control;
550

    
551
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
552
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
553
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
554
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
555
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
556
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
557
                
558
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
559
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
560
                else
561
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
562
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
563
                s->vbe_start_addr = 0;
564
                
565
                /* clear the screen (should be done in BIOS) */
566
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
567
                    memset(s->vram_ptr, 0, 
568
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
569
                }
570
                
571
                /* we initialize the VGA graphic mode (should be done
572
                   in BIOS) */
573
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
574
                s->cr[0x17] |= 3; /* no CGA modes */
575
                s->cr[0x13] = s->vbe_line_offset >> 3;
576
                /* width */
577
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
578
                /* height */
579
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
580
                s->cr[0x12] = h;
581
                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
582
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
583
                /* line compare to 1023 */
584
                s->cr[0x18] = 0xff;
585
                s->cr[0x07] |= 0x10;
586
                s->cr[0x09] |= 0x40;
587
                
588
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
589
                    shift_control = 0;
590
                    s->sr[0x01] &= ~8; /* no double line */
591
                } else {
592
                    shift_control = 2;
593
                }
594
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
595
                s->cr[0x09] &= ~0x9f; /* no double scan */
596
                s->vbe_regs[s->vbe_index] = val;
597
            } else {
598
                /* XXX: the bios should do that */
599
                s->bank_offset = -0xa0000;
600
            }
601
            break;
602
        case VBE_DISPI_INDEX_VIRT_WIDTH:
603
            {
604
                int w, h, line_offset;
605

    
606
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
607
                    return;
608
                w = val;
609
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
610
                    line_offset = w >> 1;
611
                else
612
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
613
                h = s->vram_size / line_offset;
614
                /* XXX: support weird bochs semantics ? */
615
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
616
                    return;
617
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
618
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
619
                s->vbe_line_offset = line_offset;
620
            }
621
            break;
622
        case VBE_DISPI_INDEX_X_OFFSET:
623
        case VBE_DISPI_INDEX_Y_OFFSET:
624
            {
625
                int x;
626
                s->vbe_regs[s->vbe_index] = val;
627
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
628
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
629
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
630
                    s->vbe_start_addr += x >> 1;
631
                else
632
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
633
                s->vbe_start_addr >>= 2;
634
            }
635
            break;
636
        default:
637
            break;
638
        }
639
    }
640
}
641
#endif
642

    
643
/* called for accesses between 0xa0000 and 0xc0000 */
644
static uint32_t vga_mem_readb(uint32_t addr)
645
{
646
    VGAState *s = &vga_state;
647
    int memory_map_mode, plane;
648
    uint32_t ret;
649
    
650
    /* convert to VGA memory offset */
651
    memory_map_mode = (s->gr[6] >> 2) & 3;
652
    switch(memory_map_mode) {
653
    case 0:
654
        addr -= 0xa0000;
655
        break;
656
    case 1:
657
        if (addr >= 0xb0000)
658
            return 0xff;
659
        addr += s->bank_offset;
660
        break;
661
    case 2:
662
        addr -= 0xb0000;
663
        if (addr >= 0x8000)
664
            return 0xff;
665
        break;
666
    default:
667
    case 3:
668
        addr -= 0xb8000;
669
        if (addr >= 0x8000)
670
            return 0xff;
671
        break;
672
    }
673
    
674
    if (s->sr[4] & 0x08) {
675
        /* chain 4 mode : simplest access */
676
        ret = s->vram_ptr[addr];
677
    } else if (s->gr[5] & 0x10) {
678
        /* odd/even mode (aka text mode mapping) */
679
        plane = (s->gr[4] & 2) | (addr & 1);
680
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
681
    } else {
682
        /* standard VGA latched access */
683
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
684

    
685
        if (!(s->gr[5] & 0x08)) {
686
            /* read mode 0 */
687
            plane = s->gr[4];
688
            ret = GET_PLANE(s->latch, plane);
689
        } else {
690
            /* read mode 1 */
691
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
692
            ret |= ret >> 16;
693
            ret |= ret >> 8;
694
            ret = (~ret) & 0xff;
695
        }
696
    }
697
    return ret;
698
}
699

    
700
static uint32_t vga_mem_readw(uint32_t addr)
701
{
702
    uint32_t v;
703
    v = vga_mem_readb(addr);
704
    v |= vga_mem_readb(addr + 1) << 8;
705
    return v;
706
}
707

    
708
static uint32_t vga_mem_readl(uint32_t addr)
709
{
710
    uint32_t v;
711
    v = vga_mem_readb(addr);
712
    v |= vga_mem_readb(addr + 1) << 8;
713
    v |= vga_mem_readb(addr + 2) << 16;
714
    v |= vga_mem_readb(addr + 3) << 24;
715
    return v;
716
}
717

    
718
/* called for accesses between 0xa0000 and 0xc0000 */
719
static void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr)
720
{
721
    VGAState *s = &vga_state;
722
    int memory_map_mode, plane, write_mode, b, func_select;
723
    uint32_t write_mask, bit_mask, set_mask;
724

    
725
#ifdef DEBUG_VGA_MEM
726
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
727
#endif
728
    /* convert to VGA memory offset */
729
    memory_map_mode = (s->gr[6] >> 2) & 3;
730
    switch(memory_map_mode) {
731
    case 0:
732
        addr -= 0xa0000;
733
        break;
734
    case 1:
735
        if (addr >= 0xb0000)
736
            return;
737
        addr += s->bank_offset;
738
        break;
739
    case 2:
740
        addr -= 0xb0000;
741
        if (addr >= 0x8000)
742
            return;
743
        break;
744
    default:
745
    case 3:
746
        addr -= 0xb8000;
747
        if (addr >= 0x8000)
748
            return;
749
        break;
750
    }
751
    
752
    if (s->sr[4] & 0x08) {
753
        /* chain 4 mode : simplest access */
754
        plane = addr & 3;
755
        if (s->sr[2] & (1 << plane)) {
756
            s->vram_ptr[addr] = val;
757
#ifdef DEBUG_VGA_MEM
758
            printf("vga: chain4: [0x%x]\n", addr);
759
#endif
760
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
761
        }
762
    } else if (s->gr[5] & 0x10) {
763
        /* odd/even mode (aka text mode mapping) */
764
        plane = (s->gr[4] & 2) | (addr & 1);
765
        if (s->sr[2] & (1 << plane)) {
766
            addr = ((addr & ~1) << 1) | plane;
767
            s->vram_ptr[addr] = val;
768
#ifdef DEBUG_VGA_MEM
769
            printf("vga: odd/even: [0x%x]\n", addr);
770
#endif
771
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
772
        }
773
    } else {
774
        /* standard VGA latched access */
775
        write_mode = s->gr[5] & 3;
776
        switch(write_mode) {
777
        default:
778
        case 0:
779
            /* rotate */
780
            b = s->gr[3] & 7;
781
            val = ((val >> b) | (val << (8 - b))) & 0xff;
782
            val |= val << 8;
783
            val |= val << 16;
784

    
785
            /* apply set/reset mask */
786
            set_mask = mask16[s->gr[1]];
787
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
788
            bit_mask = s->gr[8];
789
            break;
790
        case 1:
791
            val = s->latch;
792
            goto do_write;
793
        case 2:
794
            val = mask16[val & 0x0f];
795
            bit_mask = s->gr[8];
796
            break;
797
        case 3:
798
            /* rotate */
799
            b = s->gr[3] & 7;
800
            val = (val >> b) | (val << (8 - b));
801

    
802
            bit_mask = s->gr[8] & val;
803
            val = mask16[s->gr[0]];
804
            break;
805
        }
806

    
807
        /* apply logical operation */
808
        func_select = s->gr[3] >> 3;
809
        switch(func_select) {
810
        case 0:
811
        default:
812
            /* nothing to do */
813
            break;
814
        case 1:
815
            /* and */
816
            val &= s->latch;
817
            break;
818
        case 2:
819
            /* or */
820
            val |= s->latch;
821
            break;
822
        case 3:
823
            /* xor */
824
            val ^= s->latch;
825
            break;
826
        }
827

    
828
        /* apply bit mask */
829
        bit_mask |= bit_mask << 8;
830
        bit_mask |= bit_mask << 16;
831
        val = (val & bit_mask) | (s->latch & ~bit_mask);
832

    
833
    do_write:
834
        /* mask data according to sr[2] */
835
        write_mask = mask16[s->sr[2]];
836
        ((uint32_t *)s->vram_ptr)[addr] = 
837
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
838
            (val & write_mask);
839
#ifdef DEBUG_VGA_MEM
840
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
841
                   addr * 4, write_mask, val);
842
#endif
843
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
844
    }
845
}
846

    
847
static void vga_mem_writew(uint32_t addr, uint32_t val, uint32_t vaddr)
848
{
849
    vga_mem_writeb(addr, val & 0xff, vaddr);
850
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
851
}
852

    
853
static void vga_mem_writel(uint32_t addr, uint32_t val, uint32_t vaddr)
854
{
855
    vga_mem_writeb(addr, val & 0xff, vaddr);
856
    vga_mem_writeb(addr + 1, (val >> 8) & 0xff, vaddr);
857
    vga_mem_writeb(addr + 2, (val >> 16) & 0xff, vaddr);
858
    vga_mem_writeb(addr + 3, (val >> 24) & 0xff, vaddr);
859
}
860

    
861
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
862
                             const uint8_t *font_ptr, int h,
863
                             uint32_t fgcol, uint32_t bgcol);
864
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
865
                                  const uint8_t *font_ptr, int h, 
866
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
867
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
868
                                const uint8_t *s, int width);
869

    
870
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
871
{
872
    /* XXX: TODO */
873
    return 0;
874
}
875

    
876
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
877
{
878
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
879
}
880

    
881
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
882
{
883
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
884
}
885

    
886
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
887
{
888
    return (r << 16) | (g << 8) | b;
889
}
890

    
891
#define DEPTH 8
892
#include "vga_template.h"
893

    
894
#define DEPTH 15
895
#include "vga_template.h"
896

    
897
#define DEPTH 16
898
#include "vga_template.h"
899

    
900
#define DEPTH 32
901
#include "vga_template.h"
902

    
903
static inline int c6_to_8(int v)
904
{
905
    int b;
906
    v &= 0x3f;
907
    b = v & 1;
908
    return (v << 2) | (b << 1) | b;
909
}
910

    
911
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
912
{
913
    unsigned int col;
914
    col = rgb_to_pixel8(r, g, b);
915
    col |= col << 8;
916
    col |= col << 16;
917
    return col;
918
}
919

    
920
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
921
{
922
    unsigned int col;
923
    col = rgb_to_pixel15(r, g, b);
924
    col |= col << 16;
925
    return col;
926
}
927

    
928
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
929
{
930
    unsigned int col;
931
    col = rgb_to_pixel16(r, g, b);
932
    col |= col << 16;
933
    return col;
934
}
935

    
936
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
937
{
938
    unsigned int col;
939
    col = rgb_to_pixel32(r, g, b);
940
    return col;
941
}
942

    
943
/* return true if the palette was modified */
944
static int update_palette16(VGAState *s)
945
{
946
    int full_update, i;
947
    uint32_t v, col, *palette;
948

    
949
    full_update = 0;
950
    palette = s->last_palette;
951
    for(i = 0; i < 16; i++) {
952
        v = s->ar[i];
953
        if (s->ar[0x10] & 0x80)
954
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
955
        else
956
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
957
        v = v * 3;
958
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
959
                              c6_to_8(s->palette[v + 1]), 
960
                              c6_to_8(s->palette[v + 2]));
961
        if (col != palette[i]) {
962
            full_update = 1;
963
            palette[i] = col;
964
        }
965
    }
966
    return full_update;
967
}
968

    
969
/* return true if the palette was modified */
970
static int update_palette256(VGAState *s)
971
{
972
    int full_update, i;
973
    uint32_t v, col, *palette;
974

    
975
    full_update = 0;
976
    palette = s->last_palette;
977
    v = 0;
978
    for(i = 0; i < 256; i++) {
979
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
980
                              c6_to_8(s->palette[v + 1]), 
981
                              c6_to_8(s->palette[v + 2]));
982
        if (col != palette[i]) {
983
            full_update = 1;
984
            palette[i] = col;
985
        }
986
        v += 3;
987
    }
988
    return full_update;
989
}
990

    
991
/* update start_addr and line_offset. Return TRUE if modified */
992
static int update_basic_params(VGAState *s)
993
{
994
    int full_update;
995
    uint32_t start_addr, line_offset, line_compare, v;
996
    
997
    full_update = 0;
998

    
999
#ifdef CONFIG_BOCHS_VBE
1000
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1001
        line_offset = s->vbe_line_offset;
1002
        start_addr = s->vbe_start_addr;
1003
    } else
1004
#endif
1005
    {  
1006
        /* compute line_offset in bytes */
1007
        line_offset = s->cr[0x13];
1008
#ifdef CONFIG_S3VGA
1009
        v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
1010
        if (v == 0)
1011
            v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
1012
        line_offset |= (v << 8);
1013
#endif
1014
        line_offset <<= 3;
1015
        
1016
        /* starting address */
1017
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1018
#ifdef CONFIG_S3VGA
1019
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
1020
#endif
1021
    }
1022
    
1023
    /* line compare */
1024
    line_compare = s->cr[0x18] | 
1025
        ((s->cr[0x07] & 0x10) << 4) |
1026
        ((s->cr[0x09] & 0x40) << 3);
1027

    
1028
    if (line_offset != s->line_offset ||
1029
        start_addr != s->start_addr ||
1030
        line_compare != s->line_compare) {
1031
        s->line_offset = line_offset;
1032
        s->start_addr = start_addr;
1033
        s->line_compare = line_compare;
1034
        full_update = 1;
1035
    }
1036
    return full_update;
1037
}
1038

    
1039
static inline int get_depth_index(int depth)
1040
{
1041
    switch(depth) {
1042
    default:
1043
    case 8:
1044
        return 0;
1045
    case 15:
1046
        return 1;
1047
    case 16:
1048
        return 2;
1049
    case 32:
1050
        return 3;
1051
    }
1052
}
1053

    
1054
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1055
    vga_draw_glyph8_8,
1056
    vga_draw_glyph8_16,
1057
    vga_draw_glyph8_16,
1058
    vga_draw_glyph8_32,
1059
};
1060

    
1061
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1062
    vga_draw_glyph16_8,
1063
    vga_draw_glyph16_16,
1064
    vga_draw_glyph16_16,
1065
    vga_draw_glyph16_32,
1066
};
1067

    
1068
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1069
    vga_draw_glyph9_8,
1070
    vga_draw_glyph9_16,
1071
    vga_draw_glyph9_16,
1072
    vga_draw_glyph9_32,
1073
};
1074
    
1075
static const uint8_t cursor_glyph[32 * 4] = {
1076
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1077
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1078
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1079
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1080
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1081
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1082
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1083
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1084
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1085
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1086
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1087
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1088
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1089
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1090
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1091
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1092
};    
1093

    
1094
/* 
1095
 * Text mode update 
1096
 * Missing:
1097
 * - double scan
1098
 * - double width 
1099
 * - underline
1100
 * - flashing
1101
 */
1102
static void vga_draw_text(VGAState *s, int full_update)
1103
{
1104
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1105
    int cx_min, cx_max, linesize, x_incr;
1106
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1107
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1108
    const uint8_t *font_ptr, *font_base[2];
1109
    int dup9, line_offset, depth_index;
1110
    uint32_t *palette;
1111
    uint32_t *ch_attr_ptr;
1112
    vga_draw_glyph8_func *vga_draw_glyph8;
1113
    vga_draw_glyph9_func *vga_draw_glyph9;
1114

    
1115
    full_update |= update_palette16(s);
1116
    palette = s->last_palette;
1117
    
1118
    /* compute font data address (in plane 2) */
1119
    v = s->sr[3];
1120
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1121
    if (offset != s->font_offsets[0]) {
1122
        s->font_offsets[0] = offset;
1123
        full_update = 1;
1124
    }
1125
    font_base[0] = s->vram_ptr + offset;
1126

    
1127
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1128
    font_base[1] = s->vram_ptr + offset;
1129
    if (offset != s->font_offsets[1]) {
1130
        s->font_offsets[1] = offset;
1131
        full_update = 1;
1132
    }
1133

    
1134
    full_update |= update_basic_params(s);
1135

    
1136
    line_offset = s->line_offset;
1137
    s1 = s->vram_ptr + (s->start_addr * 4);
1138

    
1139
    /* total width & height */
1140
    cheight = (s->cr[9] & 0x1f) + 1;
1141
    cw = 8;
1142
    if (!(s->sr[1] & 0x01))
1143
        cw = 9;
1144
    if (s->sr[1] & 0x08)
1145
        cw = 16; /* NOTE: no 18 pixel wide */
1146
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1147
    width = (s->cr[0x01] + 1);
1148
    if (s->cr[0x06] == 100) {
1149
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1150
        height = 100;
1151
    } else {
1152
        height = s->cr[0x12] | 
1153
            ((s->cr[0x07] & 0x02) << 7) | 
1154
            ((s->cr[0x07] & 0x40) << 3);
1155
        height = (height + 1) / cheight;
1156
    }
1157
    if (width != s->last_width || height != s->last_height ||
1158
        cw != s->last_cw || cheight != s->last_ch) {
1159
        s->last_scr_width = width * cw;
1160
        s->last_scr_height = height * cheight;
1161
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1162
        s->last_width = width;
1163
        s->last_height = height;
1164
        s->last_ch = cheight;
1165
        s->last_cw = cw;
1166
        full_update = 1;
1167
    }
1168
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1169
    if (cursor_offset != s->cursor_offset ||
1170
        s->cr[0xa] != s->cursor_start ||
1171
        s->cr[0xb] != s->cursor_end) {
1172
      /* if the cursor position changed, we update the old and new
1173
         chars */
1174
        if (s->cursor_offset < CH_ATTR_SIZE)
1175
            s->last_ch_attr[s->cursor_offset] = -1;
1176
        if (cursor_offset < CH_ATTR_SIZE)
1177
            s->last_ch_attr[cursor_offset] = -1;
1178
        s->cursor_offset = cursor_offset;
1179
        s->cursor_start = s->cr[0xa];
1180
        s->cursor_end = s->cr[0xb];
1181
    }
1182
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1183
    
1184
    depth_index = get_depth_index(s->ds->depth);
1185
    if (cw == 16)
1186
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1187
    else
1188
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1189
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1190
    
1191
    dest = s->ds->data;
1192
    linesize = s->ds->linesize;
1193
    ch_attr_ptr = s->last_ch_attr;
1194
    for(cy = 0; cy < height; cy++) {
1195
        d1 = dest;
1196
        src = s1;
1197
        cx_min = width;
1198
        cx_max = -1;
1199
        for(cx = 0; cx < width; cx++) {
1200
            ch_attr = *(uint16_t *)src;
1201
            if (full_update || ch_attr != *ch_attr_ptr) {
1202
                if (cx < cx_min)
1203
                    cx_min = cx;
1204
                if (cx > cx_max)
1205
                    cx_max = cx;
1206
                *ch_attr_ptr = ch_attr;
1207
#ifdef WORDS_BIGENDIAN
1208
                ch = ch_attr >> 8;
1209
                cattr = ch_attr & 0xff;
1210
#else
1211
                ch = ch_attr & 0xff;
1212
                cattr = ch_attr >> 8;
1213
#endif
1214
                font_ptr = font_base[(cattr >> 3) & 1];
1215
                font_ptr += 32 * 4 * ch;
1216
                bgcol = palette[cattr >> 4];
1217
                fgcol = palette[cattr & 0x0f];
1218
                if (cw != 9) {
1219
                    vga_draw_glyph8(d1, linesize, 
1220
                                    font_ptr, cheight, fgcol, bgcol);
1221
                } else {
1222
                    dup9 = 0;
1223
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1224
                        dup9 = 1;
1225
                    vga_draw_glyph9(d1, linesize, 
1226
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1227
                }
1228
                if (src == cursor_ptr &&
1229
                    !(s->cr[0x0a] & 0x20)) {
1230
                    int line_start, line_last, h;
1231
                    /* draw the cursor */
1232
                    line_start = s->cr[0x0a] & 0x1f;
1233
                    line_last = s->cr[0x0b] & 0x1f;
1234
                    /* XXX: check that */
1235
                    if (line_last > cheight - 1)
1236
                        line_last = cheight - 1;
1237
                    if (line_last >= line_start && line_start < cheight) {
1238
                        h = line_last - line_start + 1;
1239
                        d = d1 + linesize * line_start;
1240
                        if (cw != 9) {
1241
                            vga_draw_glyph8(d, linesize, 
1242
                                            cursor_glyph, h, fgcol, bgcol);
1243
                        } else {
1244
                            vga_draw_glyph9(d, linesize, 
1245
                                            cursor_glyph, h, fgcol, bgcol, 1);
1246
                        }
1247
                    }
1248
                }
1249
            }
1250
            d1 += x_incr;
1251
            src += 4;
1252
            ch_attr_ptr++;
1253
        }
1254
        if (cx_max != -1) {
1255
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1256
                       (cx_max - cx_min + 1) * cw, cheight);
1257
        }
1258
        dest += linesize * cheight;
1259
        s1 += line_offset;
1260
    }
1261
}
1262

    
1263
enum {
1264
    VGA_DRAW_LINE2,
1265
    VGA_DRAW_LINE2D2,
1266
    VGA_DRAW_LINE4,
1267
    VGA_DRAW_LINE4D2,
1268
    VGA_DRAW_LINE8D2,
1269
    VGA_DRAW_LINE8,
1270
    VGA_DRAW_LINE15,
1271
    VGA_DRAW_LINE16,
1272
    VGA_DRAW_LINE24,
1273
    VGA_DRAW_LINE32,
1274
    VGA_DRAW_LINE_NB,
1275
};
1276

    
1277
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1278
    vga_draw_line2_8,
1279
    vga_draw_line2_16,
1280
    vga_draw_line2_16,
1281
    vga_draw_line2_32,
1282

    
1283
    vga_draw_line2d2_8,
1284
    vga_draw_line2d2_16,
1285
    vga_draw_line2d2_16,
1286
    vga_draw_line2d2_32,
1287

    
1288
    vga_draw_line4_8,
1289
    vga_draw_line4_16,
1290
    vga_draw_line4_16,
1291
    vga_draw_line4_32,
1292

    
1293
    vga_draw_line4d2_8,
1294
    vga_draw_line4d2_16,
1295
    vga_draw_line4d2_16,
1296
    vga_draw_line4d2_32,
1297

    
1298
    vga_draw_line8d2_8,
1299
    vga_draw_line8d2_16,
1300
    vga_draw_line8d2_16,
1301
    vga_draw_line8d2_32,
1302

    
1303
    vga_draw_line8_8,
1304
    vga_draw_line8_16,
1305
    vga_draw_line8_16,
1306
    vga_draw_line8_32,
1307

    
1308
    vga_draw_line15_8,
1309
    vga_draw_line15_15,
1310
    vga_draw_line15_16,
1311
    vga_draw_line15_32,
1312

    
1313
    vga_draw_line16_8,
1314
    vga_draw_line16_15,
1315
    vga_draw_line16_16,
1316
    vga_draw_line16_32,
1317

    
1318
    vga_draw_line24_8,
1319
    vga_draw_line24_15,
1320
    vga_draw_line24_16,
1321
    vga_draw_line24_32,
1322

    
1323
    vga_draw_line32_8,
1324
    vga_draw_line32_15,
1325
    vga_draw_line32_16,
1326
    vga_draw_line32_32,
1327
};
1328

    
1329
/* 
1330
 * graphic modes
1331
 * Missing:
1332
 * - double scan
1333
 * - double width 
1334
 */
1335
static void vga_draw_graphic(VGAState *s, int full_update)
1336
{
1337
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1338
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1339
    int disp_width, multi_scan, multi_run;
1340
    uint8_t *d;
1341
    uint32_t v, addr1, addr;
1342
    vga_draw_line_func *vga_draw_line;
1343
    
1344
    full_update |= update_basic_params(s);
1345

    
1346
    width = (s->cr[0x01] + 1) * 8;
1347
    height = s->cr[0x12] | 
1348
        ((s->cr[0x07] & 0x02) << 7) | 
1349
        ((s->cr[0x07] & 0x40) << 3);
1350
    height = (height + 1);
1351
    disp_width = width;
1352
    
1353
    shift_control = (s->gr[0x05] >> 5) & 3;
1354
    double_scan = (s->cr[0x09] & 0x80);
1355
    if (shift_control > 1) {
1356
        multi_scan = (s->cr[0x09] & 0x1f);
1357
    } else {
1358
        multi_scan = 0;
1359
    }
1360
    multi_run = multi_scan;
1361
    if (shift_control != s->shift_control ||
1362
        double_scan != s->double_scan) {
1363
        full_update = 1;
1364
        s->shift_control = shift_control;
1365
        s->double_scan = double_scan;
1366
    }
1367
    
1368
    if (shift_control == 0) {
1369
        full_update |= update_palette16(s);
1370
        if (s->sr[0x01] & 8) {
1371
            v = VGA_DRAW_LINE4D2;
1372
            disp_width <<= 1;
1373
        } else {
1374
            v = VGA_DRAW_LINE4;
1375
        }
1376
    } else if (shift_control == 1) {
1377
        full_update |= update_palette16(s);
1378
        if (s->sr[0x01] & 8) {
1379
            v = VGA_DRAW_LINE2D2;
1380
            disp_width <<= 1;
1381
        } else {
1382
            v = VGA_DRAW_LINE2;
1383
        }
1384
    } else {
1385
#ifdef CONFIG_BOCHS_VBE
1386
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1387
            switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
1388
            default:
1389
            case 8:
1390
                full_update |= update_palette256(s);
1391
                v = VGA_DRAW_LINE8;
1392
                break;
1393
            case 15:
1394
                v = VGA_DRAW_LINE15;
1395
                break;
1396
            case 16:
1397
                v = VGA_DRAW_LINE16;
1398
                break;
1399
            case 24:
1400
                v = VGA_DRAW_LINE24;
1401
                break;
1402
            case 32:
1403
                v = VGA_DRAW_LINE32;
1404
                break;
1405
            }
1406
        } else 
1407
#endif
1408
        {
1409
            full_update |= update_palette256(s);
1410
            v = VGA_DRAW_LINE8D2;
1411
        }
1412
    }
1413
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1414

    
1415
    if (disp_width != s->last_width ||
1416
        height != s->last_height) {
1417
        dpy_resize(s->ds, disp_width, height);
1418
        s->last_scr_width = disp_width;
1419
        s->last_scr_height = height;
1420
        s->last_width = disp_width;
1421
        s->last_height = height;
1422
        full_update = 1;
1423
    }
1424

    
1425
    line_offset = s->line_offset;
1426
#if 0
1427
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1428
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1429
#endif
1430
    addr1 = (s->start_addr * 4);
1431
    bwidth = width * 4;
1432
    y_start = -1;
1433
    page_min = 0x7fffffff;
1434
    page_max = -1;
1435
    d = s->ds->data;
1436
    linesize = s->ds->linesize;
1437
    y1 = 0;
1438
    for(y = 0; y < height; y++) {
1439
        addr = addr1;
1440
        if (!(s->cr[0x17] & 1)) {
1441
            int shift;
1442
            /* CGA compatibility handling */
1443
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1444
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1445
        }
1446
        if (!(s->cr[0x17] & 2)) {
1447
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1448
        }
1449
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1450
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1451
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1452
            cpu_physical_memory_is_dirty(page1);
1453
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1454
            /* if wide line, can use another page */
1455
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1456
        }
1457
        if (update) {
1458
            if (y_start < 0)
1459
                y_start = y;
1460
            if (page0 < page_min)
1461
                page_min = page0;
1462
            if (page1 > page_max)
1463
                page_max = page1;
1464
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1465
        } else {
1466
            if (y_start >= 0) {
1467
                /* flush to display */
1468
                dpy_update(s->ds, 0, y_start, 
1469
                           disp_width, y - y_start);
1470
                y_start = -1;
1471
            }
1472
        }
1473
        if (!multi_run) {
1474
            if (!double_scan || (y & 1) != 0) {
1475
                if (y1 == s->line_compare) {
1476
                    addr1 = 0;
1477
                } else {
1478
                    mask = (s->cr[0x17] & 3) ^ 3;
1479
                    if ((y1 & mask) == mask)
1480
                        addr1 += line_offset;
1481
                }
1482
                y1++;
1483
            }
1484
            multi_run = multi_scan;
1485
        } else {
1486
            multi_run--;
1487
            y1++;
1488
        }
1489
        d += linesize;
1490
    }
1491
    if (y_start >= 0) {
1492
        /* flush to display */
1493
        dpy_update(s->ds, 0, y_start, 
1494
                   disp_width, y - y_start);
1495
    }
1496
    /* reset modified pages */
1497
    if (page_max != -1) {
1498
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1499
    }
1500
}
1501

    
1502
static void vga_draw_blank(VGAState *s, int full_update)
1503
{
1504
    int i, w, val;
1505
    uint8_t *d;
1506

    
1507
    if (!full_update)
1508
        return;
1509
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1510
        return;
1511
    if (s->ds->depth == 8) 
1512
        val = s->rgb_to_pixel(0, 0, 0);
1513
    else
1514
        val = 0;
1515
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1516
    d = s->ds->data;
1517
    for(i = 0; i < s->last_scr_height; i++) {
1518
        memset(d, val, w);
1519
        d += s->ds->linesize;
1520
    }
1521
    dpy_update(s->ds, 0, 0, 
1522
               s->last_scr_width, s->last_scr_height);
1523
}
1524

    
1525
#define GMODE_TEXT     0
1526
#define GMODE_GRAPH    1
1527
#define GMODE_BLANK 2 
1528

    
1529
void vga_update_display(void)
1530
{
1531
    VGAState *s = &vga_state;
1532
    int full_update, graphic_mode;
1533

    
1534
    if (s->ds->depth == 0) {
1535
        /* nothing to do */
1536
    } else {
1537
        switch(s->ds->depth) {
1538
        case 8:
1539
            s->rgb_to_pixel = rgb_to_pixel8_dup;
1540
            break;
1541
        case 15:
1542
            s->rgb_to_pixel = rgb_to_pixel15_dup;
1543
            break;
1544
        default:
1545
        case 16:
1546
            s->rgb_to_pixel = rgb_to_pixel16_dup;
1547
            break;
1548
        case 32:
1549
            s->rgb_to_pixel = rgb_to_pixel32_dup;
1550
            break;
1551
        }
1552
        
1553
        full_update = 0;
1554
        if (!(s->ar_index & 0x20)) {
1555
            graphic_mode = GMODE_BLANK;
1556
        } else {
1557
            graphic_mode = s->gr[6] & 1;
1558
        }
1559
        if (graphic_mode != s->graphic_mode) {
1560
            s->graphic_mode = graphic_mode;
1561
            full_update = 1;
1562
        }
1563
        switch(graphic_mode) {
1564
        case GMODE_TEXT:
1565
            vga_draw_text(s, full_update);
1566
            break;
1567
        case GMODE_GRAPH:
1568
            vga_draw_graphic(s, full_update);
1569
            break;
1570
        case GMODE_BLANK:
1571
        default:
1572
            vga_draw_blank(s, full_update);
1573
            break;
1574
        }
1575
    }
1576
}
1577

    
1578
static void vga_reset(VGAState *s)
1579
{
1580
    memset(s, 0, sizeof(VGAState));
1581
#ifdef CONFIG_S3VGA
1582
    /* chip ID for 8c968 */
1583
    s->cr[0x2d] = 0x88;
1584
    s->cr[0x2e] = 0xb0;
1585
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1586
    s->cr[0x30] = 0xe1;
1587
#endif
1588
    s->graphic_mode = -1; /* force full update */
1589
}
1590

    
1591
static CPUReadMemoryFunc *vga_mem_read[3] = {
1592
    vga_mem_readb,
1593
    vga_mem_readw,
1594
    vga_mem_readl,
1595
};
1596

    
1597
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1598
    vga_mem_writeb,
1599
    vga_mem_writew,
1600
    vga_mem_writel,
1601
};
1602

    
1603
static void vga_save(QEMUFile *f, void *opaque)
1604
{
1605
    VGAState *s = opaque;
1606
    int i;
1607

    
1608
    qemu_put_be32s(f, &s->latch);
1609
    qemu_put_8s(f, &s->sr_index);
1610
    qemu_put_buffer(f, s->sr, 8);
1611
    qemu_put_8s(f, &s->gr_index);
1612
    qemu_put_buffer(f, s->gr, 16);
1613
    qemu_put_8s(f, &s->ar_index);
1614
    qemu_put_buffer(f, s->ar, 21);
1615
    qemu_put_be32s(f, &s->ar_flip_flop);
1616
    qemu_put_8s(f, &s->cr_index);
1617
    qemu_put_buffer(f, s->cr, 256);
1618
    qemu_put_8s(f, &s->msr);
1619
    qemu_put_8s(f, &s->fcr);
1620
    qemu_put_8s(f, &s->st00);
1621
    qemu_put_8s(f, &s->st01);
1622

    
1623
    qemu_put_8s(f, &s->dac_state);
1624
    qemu_put_8s(f, &s->dac_sub_index);
1625
    qemu_put_8s(f, &s->dac_read_index);
1626
    qemu_put_8s(f, &s->dac_write_index);
1627
    qemu_put_buffer(f, s->dac_cache, 3);
1628
    qemu_put_buffer(f, s->palette, 768);
1629

    
1630
    qemu_put_be32s(f, &s->bank_offset);
1631
#ifdef CONFIG_BOCHS_VBE
1632
    qemu_put_byte(f, 1);
1633
    qemu_put_be16s(f, &s->vbe_index);
1634
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1635
        qemu_put_be16s(f, &s->vbe_regs[i]);
1636
    qemu_put_be32s(f, &s->vbe_start_addr);
1637
    qemu_put_be32s(f, &s->vbe_line_offset);
1638
    qemu_put_be32s(f, &s->vbe_bank_mask);
1639
#else
1640
    qemu_put_byte(f, 0);
1641
#endif
1642
}
1643

    
1644
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1645
{
1646
    VGAState *s = opaque;
1647
    int is_vbe, i;
1648

    
1649
    if (version_id != 1)
1650
        return -EINVAL;
1651

    
1652
    qemu_get_be32s(f, &s->latch);
1653
    qemu_get_8s(f, &s->sr_index);
1654
    qemu_get_buffer(f, s->sr, 8);
1655
    qemu_get_8s(f, &s->gr_index);
1656
    qemu_get_buffer(f, s->gr, 16);
1657
    qemu_get_8s(f, &s->ar_index);
1658
    qemu_get_buffer(f, s->ar, 21);
1659
    qemu_get_be32s(f, &s->ar_flip_flop);
1660
    qemu_get_8s(f, &s->cr_index);
1661
    qemu_get_buffer(f, s->cr, 256);
1662
    qemu_get_8s(f, &s->msr);
1663
    qemu_get_8s(f, &s->fcr);
1664
    qemu_get_8s(f, &s->st00);
1665
    qemu_get_8s(f, &s->st01);
1666

    
1667
    qemu_get_8s(f, &s->dac_state);
1668
    qemu_get_8s(f, &s->dac_sub_index);
1669
    qemu_get_8s(f, &s->dac_read_index);
1670
    qemu_get_8s(f, &s->dac_write_index);
1671
    qemu_get_buffer(f, s->dac_cache, 3);
1672
    qemu_get_buffer(f, s->palette, 768);
1673

    
1674
    qemu_get_be32s(f, &s->bank_offset);
1675
    is_vbe = qemu_get_byte(f);
1676
#ifdef CONFIG_BOCHS_VBE
1677
    if (!is_vbe)
1678
        return -EINVAL;
1679
    qemu_get_be16s(f, &s->vbe_index);
1680
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1681
        qemu_get_be16s(f, &s->vbe_regs[i]);
1682
    qemu_get_be32s(f, &s->vbe_start_addr);
1683
    qemu_get_be32s(f, &s->vbe_line_offset);
1684
    qemu_get_be32s(f, &s->vbe_bank_mask);
1685
#else
1686
    if (is_vbe)
1687
        return -EINVAL;
1688
#endif
1689

    
1690
    /* force refresh */
1691
    s->graphic_mode = -1;
1692
    return 0;
1693
}
1694

    
1695
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1696
                   unsigned long vga_ram_offset, int vga_ram_size)
1697
{
1698
    VGAState *s = &vga_state;
1699
    int i, j, v, b;
1700

    
1701
    for(i = 0;i < 256; i++) {
1702
        v = 0;
1703
        for(j = 0; j < 8; j++) {
1704
            v |= ((i >> j) & 1) << (j * 4);
1705
        }
1706
        expand4[i] = v;
1707

    
1708
        v = 0;
1709
        for(j = 0; j < 4; j++) {
1710
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1711
        }
1712
        expand2[i] = v;
1713
    }
1714
    for(i = 0; i < 16; i++) {
1715
        v = 0;
1716
        for(j = 0; j < 4; j++) {
1717
            b = ((i >> j) & 1);
1718
            v |= b << (2 * j);
1719
            v |= b << (2 * j + 1);
1720
        }
1721
        expand4to8[i] = v;
1722
    }
1723

    
1724
    vga_reset(s);
1725

    
1726
    s->vram_ptr = vga_ram_base;
1727
    s->vram_offset = vga_ram_offset;
1728
    s->vram_size = vga_ram_size;
1729
    s->ds = ds;
1730

    
1731
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1732

    
1733
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1734

    
1735
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1736
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1737
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1738
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1739

    
1740
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1741

    
1742
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1743
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1744
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1745
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1746
    s->bank_offset = -0xa0000;
1747

    
1748
#ifdef CONFIG_BOCHS_VBE
1749
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1750
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1751
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read, s);
1752
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read, s);
1753

    
1754
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write, s);
1755
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write, s);
1756
#endif
1757

    
1758
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1759
#if defined (TARGET_I386)
1760
    cpu_register_physical_memory(0x000a0000, 0x20000, vga_io_memory);
1761
#ifdef CONFIG_BOCHS_VBE
1762
    /* XXX: use optimized standard vga accesses */
1763
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1764
                                 vga_ram_size, vga_ram_offset);
1765
#endif
1766
#elif defined (TARGET_PPC)
1767
    cpu_register_physical_memory(0xf00a0000, 0x20000, vga_io_memory);
1768
#endif
1769
    return 0;
1770
}
1771

    
1772
/********************************************************/
1773
/* vga screen dump */
1774

    
1775
static int vga_save_w, vga_save_h;
1776

    
1777
static void vga_save_dpy_update(DisplayState *s, 
1778
                                int x, int y, int w, int h)
1779
{
1780
}
1781

    
1782
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1783
{
1784
    s->linesize = w * 4;
1785
    s->data = qemu_malloc(h * s->linesize);
1786
    vga_save_w = w;
1787
    vga_save_h = h;
1788
}
1789

    
1790
static void vga_save_dpy_refresh(DisplayState *s)
1791
{
1792
}
1793

    
1794
static int ppm_save(const char *filename, uint8_t *data, 
1795
                    int w, int h, int linesize)
1796
{
1797
    FILE *f;
1798
    uint8_t *d, *d1;
1799
    unsigned int v;
1800
    int y, x;
1801

    
1802
    f = fopen(filename, "wb");
1803
    if (!f)
1804
        return -1;
1805
    fprintf(f, "P6\n%d %d\n%d\n",
1806
            w, h, 255);
1807
    d1 = data;
1808
    for(y = 0; y < h; y++) {
1809
        d = d1;
1810
        for(x = 0; x < w; x++) {
1811
            v = *(uint32_t *)d;
1812
            fputc((v >> 16) & 0xff, f);
1813
            fputc((v >> 8) & 0xff, f);
1814
            fputc((v) & 0xff, f);
1815
            d += 4;
1816
        }
1817
        d1 += linesize;
1818
    }
1819
    fclose(f);
1820
    return 0;
1821
}
1822

    
1823
/* save the vga display in a PPM image even if no display is
1824
   available */
1825
void vga_screen_dump(const char *filename)
1826
{
1827
    VGAState *s = &vga_state;
1828
    DisplayState *saved_ds, ds1, *ds = &ds1;
1829
    
1830
    /* XXX: this is a little hackish */
1831
    s->last_width = -1;
1832
    s->last_height = -1;
1833
    saved_ds = s->ds;
1834

    
1835
    memset(ds, 0, sizeof(DisplayState));
1836
    ds->dpy_update = vga_save_dpy_update;
1837
    ds->dpy_resize = vga_save_dpy_resize;
1838
    ds->dpy_refresh = vga_save_dpy_refresh;
1839
    ds->depth = 32;
1840

    
1841
    s->ds = ds;
1842
    s->graphic_mode = -1;
1843
    vga_update_display();
1844
    
1845
    if (ds->data) {
1846
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1847
                 s->ds->linesize);
1848
        qemu_free(ds->data);
1849
    }
1850
    s->ds = saved_ds;
1851
}