partial big endian fixes - change VESA VBE ports for non i386 targets to avoid unalig...
[qemu] / hw / vga.c
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 /* S3 VGA is deprecated - another graphic card will be emulated */
34 //#define CONFIG_S3VGA
35
36 #define MSR_COLOR_EMULATION 0x01
37 #define MSR_PAGE_SELECT     0x20
38
39 #define ST01_V_RETRACE      0x08
40 #define ST01_DISP_ENABLE    0x01
41
42 /* bochs VBE support */
43 #define CONFIG_BOCHS_VBE
44
45 #define VBE_DISPI_MAX_XRES              1024
46 #define VBE_DISPI_MAX_YRES              768
47
48 #define VBE_DISPI_INDEX_ID              0x0
49 #define VBE_DISPI_INDEX_XRES            0x1
50 #define VBE_DISPI_INDEX_YRES            0x2
51 #define VBE_DISPI_INDEX_BPP             0x3
52 #define VBE_DISPI_INDEX_ENABLE          0x4
53 #define VBE_DISPI_INDEX_BANK            0x5
54 #define VBE_DISPI_INDEX_VIRT_WIDTH      0x6
55 #define VBE_DISPI_INDEX_VIRT_HEIGHT     0x7
56 #define VBE_DISPI_INDEX_X_OFFSET        0x8
57 #define VBE_DISPI_INDEX_Y_OFFSET        0x9
58 #define VBE_DISPI_INDEX_NB              0xa
59       
60 #define VBE_DISPI_ID0                   0xB0C0
61 #define VBE_DISPI_ID1                   0xB0C1
62 #define VBE_DISPI_ID2                   0xB0C2
63   
64 #define VBE_DISPI_DISABLED              0x00
65 #define VBE_DISPI_ENABLED               0x01
66 #define VBE_DISPI_LFB_ENABLED           0x40
67 #define VBE_DISPI_NOCLEARMEM            0x80
68   
69 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS  0xE0000000
70
71 typedef struct VGAState {
72     uint8_t *vram_ptr;
73     unsigned long vram_offset;
74     unsigned int vram_size;
75     uint32_t latch;
76     uint8_t sr_index;
77     uint8_t sr[8];
78     uint8_t gr_index;
79     uint8_t gr[16];
80     uint8_t ar_index;
81     uint8_t ar[21];
82     int ar_flip_flop;
83     uint8_t cr_index;
84     uint8_t cr[256]; /* CRT registers */
85     uint8_t msr; /* Misc Output Register */
86     uint8_t fcr; /* Feature Control Register */
87     uint8_t st00; /* status 0 */
88     uint8_t st01; /* status 1 */
89     uint8_t dac_state;
90     uint8_t dac_sub_index;
91     uint8_t dac_read_index;
92     uint8_t dac_write_index;
93     uint8_t dac_cache[3]; /* used when writing */
94     uint8_t palette[768];
95     int32_t bank_offset;
96 #ifdef CONFIG_BOCHS_VBE
97     uint16_t vbe_index;
98     uint16_t vbe_regs[VBE_DISPI_INDEX_NB];
99     uint32_t vbe_start_addr;
100     uint32_t vbe_line_offset;
101     uint32_t vbe_bank_mask;
102 #endif
103     /* display refresh support */
104     DisplayState *ds;
105     uint32_t font_offsets[2];
106     int graphic_mode;
107     uint8_t shift_control;
108     uint8_t double_scan;
109     uint32_t line_offset;
110     uint32_t line_compare;
111     uint32_t start_addr;
112     uint8_t last_cw, last_ch;
113     uint32_t last_width, last_height; /* in chars or pixels */
114     uint32_t last_scr_width, last_scr_height; /* in pixels */
115     uint8_t cursor_start, cursor_end;
116     uint32_t cursor_offset;
117     unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned b);
118     /* tell for each page if it has been updated since the last time */
119     uint32_t last_palette[256];
120 #define CH_ATTR_SIZE (160 * 100)
121     uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
122 } VGAState;
123
124 /* force some bits to zero */
125 static const uint8_t sr_mask[8] = {
126     (uint8_t)~0xfc,
127     (uint8_t)~0xc2,
128     (uint8_t)~0xf0,
129     (uint8_t)~0xc0,
130     (uint8_t)~0xf1,
131     (uint8_t)~0xff,
132     (uint8_t)~0xff,
133     (uint8_t)~0x00,
134 };
135
136 static const uint8_t gr_mask[16] = {
137     (uint8_t)~0xf0, /* 0x00 */
138     (uint8_t)~0xf0, /* 0x01 */
139     (uint8_t)~0xf0, /* 0x02 */
140     (uint8_t)~0xe0, /* 0x03 */
141     (uint8_t)~0xfc, /* 0x04 */
142     (uint8_t)~0x84, /* 0x05 */
143     (uint8_t)~0xf0, /* 0x06 */
144     (uint8_t)~0xf0, /* 0x07 */
145     (uint8_t)~0x00, /* 0x08 */
146     (uint8_t)~0xff, /* 0x09 */
147     (uint8_t)~0xff, /* 0x0a */
148     (uint8_t)~0xff, /* 0x0b */
149     (uint8_t)~0xff, /* 0x0c */
150     (uint8_t)~0xff, /* 0x0d */
151     (uint8_t)~0xff, /* 0x0e */
152     (uint8_t)~0xff, /* 0x0f */
153 };
154
155 #define cbswap_32(__x) \
156 ((uint32_t)( \
157                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
158                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
159                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
160                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
161
162 #ifdef WORDS_BIGENDIAN
163 #define PAT(x) cbswap_32(x)
164 #else
165 #define PAT(x) (x)
166 #endif
167
168 #ifdef WORDS_BIGENDIAN
169 #define BIG 1
170 #else
171 #define BIG 0
172 #endif
173
174 #ifdef WORDS_BIGENDIAN
175 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
176 #else
177 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
178 #endif
179
180 static const uint32_t mask16[16] = {
181     PAT(0x00000000),
182     PAT(0x000000ff),
183     PAT(0x0000ff00),
184     PAT(0x0000ffff),
185     PAT(0x00ff0000),
186     PAT(0x00ff00ff),
187     PAT(0x00ffff00),
188     PAT(0x00ffffff),
189     PAT(0xff000000),
190     PAT(0xff0000ff),
191     PAT(0xff00ff00),
192     PAT(0xff00ffff),
193     PAT(0xffff0000),
194     PAT(0xffff00ff),
195     PAT(0xffffff00),
196     PAT(0xffffffff),
197 };
198
199 #undef PAT
200
201 #ifdef WORDS_BIGENDIAN
202 #define PAT(x) (x)
203 #else
204 #define PAT(x) cbswap_32(x)
205 #endif
206
207 static const uint32_t dmask16[16] = {
208     PAT(0x00000000),
209     PAT(0x000000ff),
210     PAT(0x0000ff00),
211     PAT(0x0000ffff),
212     PAT(0x00ff0000),
213     PAT(0x00ff00ff),
214     PAT(0x00ffff00),
215     PAT(0x00ffffff),
216     PAT(0xff000000),
217     PAT(0xff0000ff),
218     PAT(0xff00ff00),
219     PAT(0xff00ffff),
220     PAT(0xffff0000),
221     PAT(0xffff00ff),
222     PAT(0xffffff00),
223     PAT(0xffffffff),
224 };
225
226 static const uint32_t dmask4[4] = {
227     PAT(0x00000000),
228     PAT(0x0000ffff),
229     PAT(0xffff0000),
230     PAT(0xffffffff),
231 };
232
233 static uint32_t expand4[256];
234 static uint16_t expand2[256];
235 static uint8_t expand4to8[16];
236
237 VGAState vga_state;
238 int vga_io_memory;
239
240 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
241 {
242     VGAState *s = opaque;
243     int val, index;
244
245     /* check port range access depending on color/monochrome mode */
246     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
247         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
248         val = 0xff;
249     } else {
250         switch(addr) {
251         case 0x3c0:
252             if (s->ar_flip_flop == 0) {
253                 val = s->ar_index;
254             } else {
255                 val = 0;
256             }
257             break;
258         case 0x3c1:
259             index = s->ar_index & 0x1f;
260             if (index < 21) 
261                 val = s->ar[index];
262             else
263                 val = 0;
264             break;
265         case 0x3c2:
266             val = s->st00;
267             break;
268         case 0x3c4:
269             val = s->sr_index;
270             break;
271         case 0x3c5:
272             val = s->sr[s->sr_index];
273 #ifdef DEBUG_VGA_REG
274             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
275 #endif
276             break;
277         case 0x3c7:
278             val = s->dac_state;
279             break;
280         case 0x3c9:
281             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
282             if (++s->dac_sub_index == 3) {
283                 s->dac_sub_index = 0;
284                 s->dac_read_index++;
285             }
286             break;
287         case 0x3ca:
288             val = s->fcr;
289             break;
290         case 0x3cc:
291             val = s->msr;
292             break;
293         case 0x3ce:
294             val = s->gr_index;
295             break;
296         case 0x3cf:
297             val = s->gr[s->gr_index];
298 #ifdef DEBUG_VGA_REG
299             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
300 #endif
301             break;
302         case 0x3b4:
303         case 0x3d4:
304             val = s->cr_index;
305             break;
306         case 0x3b5:
307         case 0x3d5:
308             val = s->cr[s->cr_index];
309 #ifdef DEBUG_VGA_REG
310             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
311 #endif
312 #ifdef DEBUG_S3
313             if (s->cr_index >= 0x20)
314                 printf("S3: CR read index=0x%x val=0x%x\n",
315                        s->cr_index, val);
316 #endif
317             break;
318         case 0x3ba:
319         case 0x3da:
320             /* just toggle to fool polling */
321             s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
322             val = s->st01;
323             s->ar_flip_flop = 0;
324             break;
325         default:
326             val = 0x00;
327             break;
328         }
329     }
330 #if defined(DEBUG_VGA)
331     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
332 #endif
333     return val;
334 }
335
336 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
337 {
338     VGAState *s = opaque;
339     int index;
340
341     /* check port range access depending on color/monochrome mode */
342     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
343         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
344         return;
345
346 #ifdef DEBUG_VGA
347     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
348 #endif
349
350     switch(addr) {
351     case 0x3c0:
352         if (s->ar_flip_flop == 0) {
353             val &= 0x3f;
354             s->ar_index = val;
355         } else {
356             index = s->ar_index & 0x1f;
357             switch(index) {
358             case 0x00 ... 0x0f:
359                 s->ar[index] = val & 0x3f;
360                 break;
361             case 0x10:
362                 s->ar[index] = val & ~0x10;
363                 break;
364             case 0x11:
365                 s->ar[index] = val;
366                 break;
367             case 0x12:
368                 s->ar[index] = val & ~0xc0;
369                 break;
370             case 0x13:
371                 s->ar[index] = val & ~0xf0;
372                 break;
373             case 0x14:
374                 s->ar[index] = val & ~0xf0;
375                 break;
376             default:
377                 break;
378             }
379         }
380         s->ar_flip_flop ^= 1;
381         break;
382     case 0x3c2:
383         s->msr = val & ~0x10;
384         break;
385     case 0x3c4:
386         s->sr_index = val & 7;
387         break;
388     case 0x3c5:
389 #ifdef DEBUG_VGA_REG
390         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
391 #endif
392         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
393         break;
394     case 0x3c7:
395         s->dac_read_index = val;
396         s->dac_sub_index = 0;
397         s->dac_state = 3;
398         break;
399     case 0x3c8:
400         s->dac_write_index = val;
401         s->dac_sub_index = 0;
402         s->dac_state = 0;
403         break;
404     case 0x3c9:
405         s->dac_cache[s->dac_sub_index] = val;
406         if (++s->dac_sub_index == 3) {
407             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
408             s->dac_sub_index = 0;
409             s->dac_write_index++;
410         }
411         break;
412     case 0x3ce:
413         s->gr_index = val & 0x0f;
414         break;
415     case 0x3cf:
416 #ifdef DEBUG_VGA_REG
417         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
418 #endif
419         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
420         break;
421     case 0x3b4:
422     case 0x3d4:
423         s->cr_index = val;
424         break;
425     case 0x3b5:
426     case 0x3d5:
427 #ifdef DEBUG_VGA_REG
428         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
429 #endif
430         /* handle CR0-7 protection */
431         if ((s->cr[11] & 0x80) && s->cr_index <= 7) {
432             /* can always write bit 4 of CR7 */
433             if (s->cr_index == 7)
434                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
435             return;
436         }
437         switch(s->cr_index) {
438         case 0x01: /* horizontal display end */
439         case 0x07:
440         case 0x09:
441         case 0x0c:
442         case 0x0d:
443         case 0x12: /* veritcal display end */
444             s->cr[s->cr_index] = val;
445             break;
446
447 #ifdef CONFIG_S3VGA
448             /* S3 registers */
449         case 0x2d:
450         case 0x2e:
451         case 0x2f:
452         case 0x30:
453             /* chip ID, cannot write */
454             break;
455         case 0x31:
456             /* update start address */
457             {
458                 int v;
459                 s->cr[s->cr_index] = val;
460                 v = (val >> 4) & 3;
461                 s->cr[0x69] = (s->cr[69] & ~0x03) | v;
462             }
463             break;
464         case 0x51:
465             /* update start address */
466             {
467                 int v;
468                 s->cr[s->cr_index] = val;
469                 v = val & 3;
470                 s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
471             }
472             break;
473 #endif
474         default:
475             s->cr[s->cr_index] = val;
476             break;
477         }
478 #ifdef DEBUG_S3
479         if (s->cr_index >= 0x20)
480             printf("S3: CR write index=0x%x val=0x%x\n",
481                    s->cr_index, val);
482 #endif
483         break;
484     case 0x3ba:
485     case 0x3da:
486         s->fcr = val & 0x10;
487         break;
488     }
489 }
490
491 #ifdef CONFIG_BOCHS_VBE
492 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
493 {
494     VGAState *s = opaque;
495     uint32_t val;
496     val = s->vbe_index;
497     return val;
498 }
499
500 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
501 {
502     VGAState *s = opaque;
503     uint32_t val;
504
505     if (s->vbe_index <= VBE_DISPI_INDEX_NB)
506         val = s->vbe_regs[s->vbe_index];
507     else
508         val = 0;
509 #ifdef DEBUG_BOCHS_VBE
510     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
511 #endif
512     return val;
513 }
514
515 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
516 {
517     VGAState *s = opaque;
518     s->vbe_index = val;
519 }
520
521 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
522 {
523     VGAState *s = opaque;
524
525     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
526 #ifdef DEBUG_BOCHS_VBE
527         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
528 #endif
529         switch(s->vbe_index) {
530         case VBE_DISPI_INDEX_ID:
531             if (val == VBE_DISPI_ID0 ||
532                 val == VBE_DISPI_ID1 ||
533                 val == VBE_DISPI_ID2) {
534                 s->vbe_regs[s->vbe_index] = val;
535             }
536             break;
537         case VBE_DISPI_INDEX_XRES:
538             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
539                 s->vbe_regs[s->vbe_index] = val;
540             }
541             break;
542         case VBE_DISPI_INDEX_YRES:
543             if (val <= VBE_DISPI_MAX_YRES) {
544                 s->vbe_regs[s->vbe_index] = val;
545             }
546             break;
547         case VBE_DISPI_INDEX_BPP:
548             if (val == 0)
549                 val = 8;
550             if (val == 4 || val == 8 || val == 15 || 
551                 val == 16 || val == 24 || val == 32) {
552                 s->vbe_regs[s->vbe_index] = val;
553             }
554             break;
555         case VBE_DISPI_INDEX_BANK:
556             val &= s->vbe_bank_mask;
557             s->vbe_regs[s->vbe_index] = val;
558             s->bank_offset = (val << 16);
559             break;
560         case VBE_DISPI_INDEX_ENABLE:
561             if (val & VBE_DISPI_ENABLED) {
562                 int h, shift_control;
563
564                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
565                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
566                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
567                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
568                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
569                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
570                 
571                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
572                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
573                 else
574                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
575                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
576                 s->vbe_start_addr = 0;
577                 
578                 /* clear the screen (should be done in BIOS) */
579                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
580                     memset(s->vram_ptr, 0, 
581                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
582                 }
583                 
584                 /* we initialize the VGA graphic mode (should be done
585                    in BIOS) */
586                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
587                 s->cr[0x17] |= 3; /* no CGA modes */
588                 s->cr[0x13] = s->vbe_line_offset >> 3;
589                 /* width */
590                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
591                 /* height */
592                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
593                 s->cr[0x12] = h;
594                 s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
595                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
596                 /* line compare to 1023 */
597                 s->cr[0x18] = 0xff;
598                 s->cr[0x07] |= 0x10;
599                 s->cr[0x09] |= 0x40;
600                 
601                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
602                     shift_control = 0;
603                     s->sr[0x01] &= ~8; /* no double line */
604                 } else {
605                     shift_control = 2;
606                     s->sr[4] |= 0x08; /* set chain 4 mode */
607                     s->sr[2] |= 0x0f; /* activate all planes */
608                 }
609                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
610                 s->cr[0x09] &= ~0x9f; /* no double scan */
611             } else {
612                 /* XXX: the bios should do that */
613                 s->bank_offset = 0;
614             }
615             s->vbe_regs[s->vbe_index] = val;
616             break;
617         case VBE_DISPI_INDEX_VIRT_WIDTH:
618             {
619                 int w, h, line_offset;
620
621                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
622                     return;
623                 w = val;
624                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
625                     line_offset = w >> 1;
626                 else
627                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
628                 h = s->vram_size / line_offset;
629                 /* XXX: support weird bochs semantics ? */
630                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
631                     return;
632                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
633                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
634                 s->vbe_line_offset = line_offset;
635             }
636             break;
637         case VBE_DISPI_INDEX_X_OFFSET:
638         case VBE_DISPI_INDEX_Y_OFFSET:
639             {
640                 int x;
641                 s->vbe_regs[s->vbe_index] = val;
642                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
643                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
644                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
645                     s->vbe_start_addr += x >> 1;
646                 else
647                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
648                 s->vbe_start_addr >>= 2;
649             }
650             break;
651         default:
652             break;
653         }
654     }
655 }
656 #endif
657
658 /* called for accesses between 0xa0000 and 0xc0000 */
659 static uint32_t vga_mem_readb(target_phys_addr_t addr)
660 {
661     VGAState *s = &vga_state;
662     int memory_map_mode, plane;
663     uint32_t ret;
664     
665     /* convert to VGA memory offset */
666     memory_map_mode = (s->gr[6] >> 2) & 3;
667     addr &= 0x1ffff;
668     switch(memory_map_mode) {
669     case 0:
670         break;
671     case 1:
672         if (addr >= 0x10000)
673             return 0xff;
674         addr += s->bank_offset;
675         break;
676     case 2:
677         addr -= 0x10000;
678         if (addr >= 0x8000)
679             return 0xff;
680         break;
681     default:
682     case 3:
683         addr -= 0x18000;
684         if (addr >= 0x8000)
685             return 0xff;
686         break;
687     }
688     
689     if (s->sr[4] & 0x08) {
690         /* chain 4 mode : simplest access */
691         ret = s->vram_ptr[addr];
692     } else if (s->gr[5] & 0x10) {
693         /* odd/even mode (aka text mode mapping) */
694         plane = (s->gr[4] & 2) | (addr & 1);
695         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
696     } else {
697         /* standard VGA latched access */
698         s->latch = ((uint32_t *)s->vram_ptr)[addr];
699
700         if (!(s->gr[5] & 0x08)) {
701             /* read mode 0 */
702             plane = s->gr[4];
703             ret = GET_PLANE(s->latch, plane);
704         } else {
705             /* read mode 1 */
706             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
707             ret |= ret >> 16;
708             ret |= ret >> 8;
709             ret = (~ret) & 0xff;
710         }
711     }
712     return ret;
713 }
714
715 static uint32_t vga_mem_readw(target_phys_addr_t addr)
716 {
717     uint32_t v;
718 #ifdef TARGET_WORDS_BIGENDIAN
719     v = vga_mem_readb(addr) << 8;
720     v |= vga_mem_readb(addr + 1);
721 #else
722     v = vga_mem_readb(addr);
723     v |= vga_mem_readb(addr + 1) << 8;
724 #endif
725     return v;
726 }
727
728 static uint32_t vga_mem_readl(target_phys_addr_t addr)
729 {
730     uint32_t v;
731 #ifdef TARGET_WORDS_BIGENDIAN
732     v = vga_mem_readb(addr) << 24;
733     v |= vga_mem_readb(addr + 1) << 16;
734     v |= vga_mem_readb(addr + 2) << 8;
735     v |= vga_mem_readb(addr + 3);
736 #else
737     v = vga_mem_readb(addr);
738     v |= vga_mem_readb(addr + 1) << 8;
739     v |= vga_mem_readb(addr + 2) << 16;
740     v |= vga_mem_readb(addr + 3) << 24;
741 #endif
742     return v;
743 }
744
745 /* called for accesses between 0xa0000 and 0xc0000 */
746 static void vga_mem_writeb(target_phys_addr_t addr, uint32_t val)
747 {
748     VGAState *s = &vga_state;
749     int memory_map_mode, plane, write_mode, b, func_select;
750     uint32_t write_mask, bit_mask, set_mask;
751
752 #ifdef DEBUG_VGA_MEM
753     printf("vga: [0x%x] = 0x%02x\n", addr, val);
754 #endif
755     /* convert to VGA memory offset */
756     memory_map_mode = (s->gr[6] >> 2) & 3;
757     addr &= 0x1ffff;
758     switch(memory_map_mode) {
759     case 0:
760         break;
761     case 1:
762         if (addr >= 0x10000)
763             return;
764         addr += s->bank_offset;
765         break;
766     case 2:
767         addr -= 0x10000;
768         if (addr >= 0x8000)
769             return;
770         break;
771     default:
772     case 3:
773         addr -= 0x18000;
774         if (addr >= 0x8000)
775             return;
776         break;
777     }
778     
779     if (s->sr[4] & 0x08) {
780         /* chain 4 mode : simplest access */
781         plane = addr & 3;
782         if (s->sr[2] & (1 << plane)) {
783             s->vram_ptr[addr] = val;
784 #ifdef DEBUG_VGA_MEM
785             printf("vga: chain4: [0x%x]\n", addr);
786 #endif
787             cpu_physical_memory_set_dirty(s->vram_offset + addr);
788         }
789     } else if (s->gr[5] & 0x10) {
790         /* odd/even mode (aka text mode mapping) */
791         plane = (s->gr[4] & 2) | (addr & 1);
792         if (s->sr[2] & (1 << plane)) {
793             addr = ((addr & ~1) << 1) | plane;
794             s->vram_ptr[addr] = val;
795 #ifdef DEBUG_VGA_MEM
796             printf("vga: odd/even: [0x%x]\n", addr);
797 #endif
798             cpu_physical_memory_set_dirty(s->vram_offset + addr);
799         }
800     } else {
801         /* standard VGA latched access */
802         write_mode = s->gr[5] & 3;
803         switch(write_mode) {
804         default:
805         case 0:
806             /* rotate */
807             b = s->gr[3] & 7;
808             val = ((val >> b) | (val << (8 - b))) & 0xff;
809             val |= val << 8;
810             val |= val << 16;
811
812             /* apply set/reset mask */
813             set_mask = mask16[s->gr[1]];
814             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
815             bit_mask = s->gr[8];
816             break;
817         case 1:
818             val = s->latch;
819             goto do_write;
820         case 2:
821             val = mask16[val & 0x0f];
822             bit_mask = s->gr[8];
823             break;
824         case 3:
825             /* rotate */
826             b = s->gr[3] & 7;
827             val = (val >> b) | (val << (8 - b));
828
829             bit_mask = s->gr[8] & val;
830             val = mask16[s->gr[0]];
831             break;
832         }
833
834         /* apply logical operation */
835         func_select = s->gr[3] >> 3;
836         switch(func_select) {
837         case 0:
838         default:
839             /* nothing to do */
840             break;
841         case 1:
842             /* and */
843             val &= s->latch;
844             break;
845         case 2:
846             /* or */
847             val |= s->latch;
848             break;
849         case 3:
850             /* xor */
851             val ^= s->latch;
852             break;
853         }
854
855         /* apply bit mask */
856         bit_mask |= bit_mask << 8;
857         bit_mask |= bit_mask << 16;
858         val = (val & bit_mask) | (s->latch & ~bit_mask);
859
860     do_write:
861         /* mask data according to sr[2] */
862         write_mask = mask16[s->sr[2]];
863         ((uint32_t *)s->vram_ptr)[addr] = 
864             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
865             (val & write_mask);
866 #ifdef DEBUG_VGA_MEM
867             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
868                    addr * 4, write_mask, val);
869 #endif
870             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
871     }
872 }
873
874 static void vga_mem_writew(target_phys_addr_t addr, uint32_t val)
875 {
876 #ifdef TARGET_WORDS_BIGENDIAN
877     vga_mem_writeb(addr, (val >> 8) & 0xff);
878     vga_mem_writeb(addr + 1, val & 0xff);
879 #else
880     vga_mem_writeb(addr, val & 0xff);
881     vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
882 #endif
883 }
884
885 static void vga_mem_writel(target_phys_addr_t addr, uint32_t val)
886 {
887 #ifdef TARGET_WORDS_BIGENDIAN
888     vga_mem_writeb(addr, (val >> 24) & 0xff);
889     vga_mem_writeb(addr + 1, (val >> 16) & 0xff);
890     vga_mem_writeb(addr + 2, (val >> 8) & 0xff);
891     vga_mem_writeb(addr + 3, val & 0xff);
892 #else
893     vga_mem_writeb(addr, val & 0xff);
894     vga_mem_writeb(addr + 1, (val >> 8) & 0xff);
895     vga_mem_writeb(addr + 2, (val >> 16) & 0xff);
896     vga_mem_writeb(addr + 3, (val >> 24) & 0xff);
897 #endif
898 }
899
900 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
901                              const uint8_t *font_ptr, int h,
902                              uint32_t fgcol, uint32_t bgcol);
903 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
904                                   const uint8_t *font_ptr, int h, 
905                                   uint32_t fgcol, uint32_t bgcol, int dup9);
906 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
907                                 const uint8_t *s, int width);
908
909 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
910 {
911     /* XXX: TODO */
912     return 0;
913 }
914
915 static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
916 {
917     return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
918 }
919
920 static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
921 {
922     return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
923 }
924
925 static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
926 {
927     return (r << 16) | (g << 8) | b;
928 }
929
930 #define DEPTH 8
931 #include "vga_template.h"
932
933 #define DEPTH 15
934 #include "vga_template.h"
935
936 #define DEPTH 16
937 #include "vga_template.h"
938
939 #define DEPTH 32
940 #include "vga_template.h"
941
942 static inline int c6_to_8(int v)
943 {
944     int b;
945     v &= 0x3f;
946     b = v & 1;
947     return (v << 2) | (b << 1) | b;
948 }
949
950 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
951 {
952     unsigned int col;
953     col = rgb_to_pixel8(r, g, b);
954     col |= col << 8;
955     col |= col << 16;
956     return col;
957 }
958
959 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
960 {
961     unsigned int col;
962     col = rgb_to_pixel15(r, g, b);
963     col |= col << 16;
964     return col;
965 }
966
967 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
968 {
969     unsigned int col;
970     col = rgb_to_pixel16(r, g, b);
971     col |= col << 16;
972     return col;
973 }
974
975 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
976 {
977     unsigned int col;
978     col = rgb_to_pixel32(r, g, b);
979     return col;
980 }
981
982 /* return true if the palette was modified */
983 static int update_palette16(VGAState *s)
984 {
985     int full_update, i;
986     uint32_t v, col, *palette;
987
988     full_update = 0;
989     palette = s->last_palette;
990     for(i = 0; i < 16; i++) {
991         v = s->ar[i];
992         if (s->ar[0x10] & 0x80)
993             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
994         else
995             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
996         v = v * 3;
997         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
998                               c6_to_8(s->palette[v + 1]), 
999                               c6_to_8(s->palette[v + 2]));
1000         if (col != palette[i]) {
1001             full_update = 1;
1002             palette[i] = col;
1003         }
1004     }
1005     return full_update;
1006 }
1007
1008 /* return true if the palette was modified */
1009 static int update_palette256(VGAState *s)
1010 {
1011     int full_update, i;
1012     uint32_t v, col, *palette;
1013
1014     full_update = 0;
1015     palette = s->last_palette;
1016     v = 0;
1017     for(i = 0; i < 256; i++) {
1018         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
1019                               c6_to_8(s->palette[v + 1]), 
1020                               c6_to_8(s->palette[v + 2]));
1021         if (col != palette[i]) {
1022             full_update = 1;
1023             palette[i] = col;
1024         }
1025         v += 3;
1026     }
1027     return full_update;
1028 }
1029
1030 /* update start_addr and line_offset. Return TRUE if modified */
1031 static int update_basic_params(VGAState *s)
1032 {
1033     int full_update;
1034     uint32_t start_addr, line_offset, line_compare;
1035     
1036     full_update = 0;
1037
1038 #ifdef CONFIG_BOCHS_VBE
1039     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1040         line_offset = s->vbe_line_offset;
1041         start_addr = s->vbe_start_addr;
1042     } else
1043 #endif
1044     {  
1045         /* compute line_offset in bytes */
1046         line_offset = s->cr[0x13];
1047 #ifdef CONFIG_S3VGA
1048         {
1049             uinr32_t v;
1050             v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
1051             if (v == 0)
1052                 v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
1053             line_offset |= (v << 8);
1054         }
1055 #endif
1056         line_offset <<= 3;
1057         
1058         /* starting address */
1059         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1060 #ifdef CONFIG_S3VGA
1061         start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
1062 #endif
1063     }
1064     
1065     /* line compare */
1066     line_compare = s->cr[0x18] | 
1067         ((s->cr[0x07] & 0x10) << 4) |
1068         ((s->cr[0x09] & 0x40) << 3);
1069
1070     if (line_offset != s->line_offset ||
1071         start_addr != s->start_addr ||
1072         line_compare != s->line_compare) {
1073         s->line_offset = line_offset;
1074         s->start_addr = start_addr;
1075         s->line_compare = line_compare;
1076         full_update = 1;
1077     }
1078     return full_update;
1079 }
1080
1081 static inline int get_depth_index(int depth)
1082 {
1083     switch(depth) {
1084     default:
1085     case 8:
1086         return 0;
1087     case 15:
1088         return 1;
1089     case 16:
1090         return 2;
1091     case 32:
1092         return 3;
1093     }
1094 }
1095
1096 static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1097     vga_draw_glyph8_8,
1098     vga_draw_glyph8_16,
1099     vga_draw_glyph8_16,
1100     vga_draw_glyph8_32,
1101 };
1102
1103 static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1104     vga_draw_glyph16_8,
1105     vga_draw_glyph16_16,
1106     vga_draw_glyph16_16,
1107     vga_draw_glyph16_32,
1108 };
1109
1110 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1111     vga_draw_glyph9_8,
1112     vga_draw_glyph9_16,
1113     vga_draw_glyph9_16,
1114     vga_draw_glyph9_32,
1115 };
1116     
1117 static const uint8_t cursor_glyph[32 * 4] = {
1118     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1119     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1120     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1121     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1122     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1123     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1124     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1125     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1126     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1127     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1128     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1129     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1130     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1131     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1132     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1133     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1134 };    
1135
1136 /* 
1137  * Text mode update 
1138  * Missing:
1139  * - double scan
1140  * - double width 
1141  * - underline
1142  * - flashing
1143  */
1144 static void vga_draw_text(VGAState *s, int full_update)
1145 {
1146     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1147     int cx_min, cx_max, linesize, x_incr;
1148     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1149     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1150     const uint8_t *font_ptr, *font_base[2];
1151     int dup9, line_offset, depth_index;
1152     uint32_t *palette;
1153     uint32_t *ch_attr_ptr;
1154     vga_draw_glyph8_func *vga_draw_glyph8;
1155     vga_draw_glyph9_func *vga_draw_glyph9;
1156
1157     full_update |= update_palette16(s);
1158     palette = s->last_palette;
1159     
1160     /* compute font data address (in plane 2) */
1161     v = s->sr[3];
1162     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1163     if (offset != s->font_offsets[0]) {
1164         s->font_offsets[0] = offset;
1165         full_update = 1;
1166     }
1167     font_base[0] = s->vram_ptr + offset;
1168
1169     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1170     font_base[1] = s->vram_ptr + offset;
1171     if (offset != s->font_offsets[1]) {
1172         s->font_offsets[1] = offset;
1173         full_update = 1;
1174     }
1175
1176     full_update |= update_basic_params(s);
1177
1178     line_offset = s->line_offset;
1179     s1 = s->vram_ptr + (s->start_addr * 4);
1180
1181     /* total width & height */
1182     cheight = (s->cr[9] & 0x1f) + 1;
1183     cw = 8;
1184     if (!(s->sr[1] & 0x01))
1185         cw = 9;
1186     if (s->sr[1] & 0x08)
1187         cw = 16; /* NOTE: no 18 pixel wide */
1188     x_incr = cw * ((s->ds->depth + 7) >> 3);
1189     width = (s->cr[0x01] + 1);
1190     if (s->cr[0x06] == 100) {
1191         /* ugly hack for CGA 160x100x16 - explain me the logic */
1192         height = 100;
1193     } else {
1194         height = s->cr[0x12] | 
1195             ((s->cr[0x07] & 0x02) << 7) | 
1196             ((s->cr[0x07] & 0x40) << 3);
1197         height = (height + 1) / cheight;
1198     }
1199     if ((height * width) > CH_ATTR_SIZE) {
1200         /* better than nothing: exit if transient size is too big */
1201         return;
1202     }
1203
1204     if (width != s->last_width || height != s->last_height ||
1205         cw != s->last_cw || cheight != s->last_ch) {
1206         s->last_scr_width = width * cw;
1207         s->last_scr_height = height * cheight;
1208         dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1209         s->last_width = width;
1210         s->last_height = height;
1211         s->last_ch = cheight;
1212         s->last_cw = cw;
1213         full_update = 1;
1214     }
1215     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1216     if (cursor_offset != s->cursor_offset ||
1217         s->cr[0xa] != s->cursor_start ||
1218         s->cr[0xb] != s->cursor_end) {
1219       /* if the cursor position changed, we update the old and new
1220          chars */
1221         if (s->cursor_offset < CH_ATTR_SIZE)
1222             s->last_ch_attr[s->cursor_offset] = -1;
1223         if (cursor_offset < CH_ATTR_SIZE)
1224             s->last_ch_attr[cursor_offset] = -1;
1225         s->cursor_offset = cursor_offset;
1226         s->cursor_start = s->cr[0xa];
1227         s->cursor_end = s->cr[0xb];
1228     }
1229     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1230     
1231     depth_index = get_depth_index(s->ds->depth);
1232     if (cw == 16)
1233         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1234     else
1235         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1236     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1237     
1238     dest = s->ds->data;
1239     linesize = s->ds->linesize;
1240     ch_attr_ptr = s->last_ch_attr;
1241     for(cy = 0; cy < height; cy++) {
1242         d1 = dest;
1243         src = s1;
1244         cx_min = width;
1245         cx_max = -1;
1246         for(cx = 0; cx < width; cx++) {
1247             ch_attr = *(uint16_t *)src;
1248             if (full_update || ch_attr != *ch_attr_ptr) {
1249                 if (cx < cx_min)
1250                     cx_min = cx;
1251                 if (cx > cx_max)
1252                     cx_max = cx;
1253                 *ch_attr_ptr = ch_attr;
1254 #ifdef WORDS_BIGENDIAN
1255                 ch = ch_attr >> 8;
1256                 cattr = ch_attr & 0xff;
1257 #else
1258                 ch = ch_attr & 0xff;
1259                 cattr = ch_attr >> 8;
1260 #endif
1261                 font_ptr = font_base[(cattr >> 3) & 1];
1262                 font_ptr += 32 * 4 * ch;
1263                 bgcol = palette[cattr >> 4];
1264                 fgcol = palette[cattr & 0x0f];
1265                 if (cw != 9) {
1266                     vga_draw_glyph8(d1, linesize, 
1267                                     font_ptr, cheight, fgcol, bgcol);
1268                 } else {
1269                     dup9 = 0;
1270                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1271                         dup9 = 1;
1272                     vga_draw_glyph9(d1, linesize, 
1273                                     font_ptr, cheight, fgcol, bgcol, dup9);
1274                 }
1275                 if (src == cursor_ptr &&
1276                     !(s->cr[0x0a] & 0x20)) {
1277                     int line_start, line_last, h;
1278                     /* draw the cursor */
1279                     line_start = s->cr[0x0a] & 0x1f;
1280                     line_last = s->cr[0x0b] & 0x1f;
1281                     /* XXX: check that */
1282                     if (line_last > cheight - 1)
1283                         line_last = cheight - 1;
1284                     if (line_last >= line_start && line_start < cheight) {
1285                         h = line_last - line_start + 1;
1286                         d = d1 + linesize * line_start;
1287                         if (cw != 9) {
1288                             vga_draw_glyph8(d, linesize, 
1289                                             cursor_glyph, h, fgcol, bgcol);
1290                         } else {
1291                             vga_draw_glyph9(d, linesize, 
1292                                             cursor_glyph, h, fgcol, bgcol, 1);
1293                         }
1294                     }
1295                 }
1296             }
1297             d1 += x_incr;
1298             src += 4;
1299             ch_attr_ptr++;
1300         }
1301         if (cx_max != -1) {
1302             dpy_update(s->ds, cx_min * cw, cy * cheight, 
1303                        (cx_max - cx_min + 1) * cw, cheight);
1304         }
1305         dest += linesize * cheight;
1306         s1 += line_offset;
1307     }
1308 }
1309
1310 enum {
1311     VGA_DRAW_LINE2,
1312     VGA_DRAW_LINE2D2,
1313     VGA_DRAW_LINE4,
1314     VGA_DRAW_LINE4D2,
1315     VGA_DRAW_LINE8D2,
1316     VGA_DRAW_LINE8,
1317     VGA_DRAW_LINE15,
1318     VGA_DRAW_LINE16,
1319     VGA_DRAW_LINE24,
1320     VGA_DRAW_LINE32,
1321     VGA_DRAW_LINE_NB,
1322 };
1323
1324 static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1325     vga_draw_line2_8,
1326     vga_draw_line2_16,
1327     vga_draw_line2_16,
1328     vga_draw_line2_32,
1329
1330     vga_draw_line2d2_8,
1331     vga_draw_line2d2_16,
1332     vga_draw_line2d2_16,
1333     vga_draw_line2d2_32,
1334
1335     vga_draw_line4_8,
1336     vga_draw_line4_16,
1337     vga_draw_line4_16,
1338     vga_draw_line4_32,
1339
1340     vga_draw_line4d2_8,
1341     vga_draw_line4d2_16,
1342     vga_draw_line4d2_16,
1343     vga_draw_line4d2_32,
1344
1345     vga_draw_line8d2_8,
1346     vga_draw_line8d2_16,
1347     vga_draw_line8d2_16,
1348     vga_draw_line8d2_32,
1349
1350     vga_draw_line8_8,
1351     vga_draw_line8_16,
1352     vga_draw_line8_16,
1353     vga_draw_line8_32,
1354
1355     vga_draw_line15_8,
1356     vga_draw_line15_15,
1357     vga_draw_line15_16,
1358     vga_draw_line15_32,
1359
1360     vga_draw_line16_8,
1361     vga_draw_line16_15,
1362     vga_draw_line16_16,
1363     vga_draw_line16_32,
1364
1365     vga_draw_line24_8,
1366     vga_draw_line24_15,
1367     vga_draw_line24_16,
1368     vga_draw_line24_32,
1369
1370     vga_draw_line32_8,
1371     vga_draw_line32_15,
1372     vga_draw_line32_16,
1373     vga_draw_line32_32,
1374 };
1375
1376 /* 
1377  * graphic modes
1378  * Missing:
1379  * - double scan
1380  * - double width 
1381  */
1382 static void vga_draw_graphic(VGAState *s, int full_update)
1383 {
1384     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1385     int width, height, shift_control, line_offset, page0, page1, bwidth;
1386     int disp_width, multi_scan, multi_run;
1387     uint8_t *d;
1388     uint32_t v, addr1, addr;
1389     vga_draw_line_func *vga_draw_line;
1390     
1391     full_update |= update_basic_params(s);
1392
1393     width = (s->cr[0x01] + 1) * 8;
1394     height = s->cr[0x12] | 
1395         ((s->cr[0x07] & 0x02) << 7) | 
1396         ((s->cr[0x07] & 0x40) << 3);
1397     height = (height + 1);
1398     disp_width = width;
1399
1400     shift_control = (s->gr[0x05] >> 5) & 3;
1401     double_scan = (s->cr[0x09] & 0x80);
1402     if (shift_control > 1) {
1403         multi_scan = (s->cr[0x09] & 0x1f);
1404     } else {
1405         multi_scan = 0;
1406     }
1407     multi_run = multi_scan;
1408     if (shift_control != s->shift_control ||
1409         double_scan != s->double_scan) {
1410         full_update = 1;
1411         s->shift_control = shift_control;
1412         s->double_scan = double_scan;
1413     }
1414     
1415     if (shift_control == 0) {
1416         full_update |= update_palette16(s);
1417         if (s->sr[0x01] & 8) {
1418             v = VGA_DRAW_LINE4D2;
1419             disp_width <<= 1;
1420         } else {
1421             v = VGA_DRAW_LINE4;
1422         }
1423     } else if (shift_control == 1) {
1424         full_update |= update_palette16(s);
1425         if (s->sr[0x01] & 8) {
1426             v = VGA_DRAW_LINE2D2;
1427             disp_width <<= 1;
1428         } else {
1429             v = VGA_DRAW_LINE2;
1430         }
1431     } else {
1432 #ifdef CONFIG_BOCHS_VBE
1433         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1434             switch(s->vbe_regs[VBE_DISPI_INDEX_BPP]) {
1435             default:
1436             case 8:
1437                 full_update |= update_palette256(s);
1438                 v = VGA_DRAW_LINE8;
1439                 break;
1440             case 15:
1441                 v = VGA_DRAW_LINE15;
1442                 break;
1443             case 16:
1444                 v = VGA_DRAW_LINE16;
1445                 break;
1446             case 24:
1447                 v = VGA_DRAW_LINE24;
1448                 break;
1449             case 32:
1450                 v = VGA_DRAW_LINE32;
1451                 break;
1452             }
1453         } else 
1454 #endif
1455         {
1456             full_update |= update_palette256(s);
1457             v = VGA_DRAW_LINE8D2;
1458         }
1459     }
1460     vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1461
1462     if (disp_width != s->last_width ||
1463         height != s->last_height) {
1464         dpy_resize(s->ds, disp_width, height);
1465         s->last_scr_width = disp_width;
1466         s->last_scr_height = height;
1467         s->last_width = disp_width;
1468         s->last_height = height;
1469         full_update = 1;
1470     }
1471
1472     line_offset = s->line_offset;
1473 #if 0
1474     printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1475            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1476 #endif
1477     addr1 = (s->start_addr * 4);
1478     bwidth = width * 4;
1479     y_start = -1;
1480     page_min = 0x7fffffff;
1481     page_max = -1;
1482     d = s->ds->data;
1483     linesize = s->ds->linesize;
1484     y1 = 0;
1485     for(y = 0; y < height; y++) {
1486         addr = addr1;
1487         if (!(s->cr[0x17] & 1)) {
1488             int shift;
1489             /* CGA compatibility handling */
1490             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1491             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1492         }
1493         if (!(s->cr[0x17] & 2)) {
1494             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1495         }
1496         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1497         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1498         update = full_update | cpu_physical_memory_is_dirty(page0) |
1499             cpu_physical_memory_is_dirty(page1);
1500         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1501             /* if wide line, can use another page */
1502             update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1503         }
1504         if (update) {
1505             if (y_start < 0)
1506                 y_start = y;
1507             if (page0 < page_min)
1508                 page_min = page0;
1509             if (page1 > page_max)
1510                 page_max = page1;
1511             vga_draw_line(s, d, s->vram_ptr + addr, width);
1512         } else {
1513             if (y_start >= 0) {
1514                 /* flush to display */
1515                 dpy_update(s->ds, 0, y_start, 
1516                            disp_width, y - y_start);
1517                 y_start = -1;
1518             }
1519         }
1520         if (!multi_run) {
1521             if (!double_scan || (y & 1) != 0) {
1522                 if (y1 == s->line_compare) {
1523                     addr1 = 0;
1524                 } else {
1525                     mask = (s->cr[0x17] & 3) ^ 3;
1526                     if ((y1 & mask) == mask)
1527                         addr1 += line_offset;
1528                 }
1529                 y1++;
1530             }
1531             multi_run = multi_scan;
1532         } else {
1533             multi_run--;
1534             y1++;
1535         }
1536         d += linesize;
1537     }
1538     if (y_start >= 0) {
1539         /* flush to display */
1540         dpy_update(s->ds, 0, y_start, 
1541                    disp_width, y - y_start);
1542     }
1543     /* reset modified pages */
1544     if (page_max != -1) {
1545         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1546     }
1547 }
1548
1549 static void vga_draw_blank(VGAState *s, int full_update)
1550 {
1551     int i, w, val;
1552     uint8_t *d;
1553
1554     if (!full_update)
1555         return;
1556     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1557         return;
1558     if (s->ds->depth == 8) 
1559         val = s->rgb_to_pixel(0, 0, 0);
1560     else
1561         val = 0;
1562     w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1563     d = s->ds->data;
1564     for(i = 0; i < s->last_scr_height; i++) {
1565         memset(d, val, w);
1566         d += s->ds->linesize;
1567     }
1568     dpy_update(s->ds, 0, 0, 
1569                s->last_scr_width, s->last_scr_height);
1570 }
1571
1572 #define GMODE_TEXT     0
1573 #define GMODE_GRAPH    1
1574 #define GMODE_BLANK 2 
1575
1576 void vga_update_display(void)
1577 {
1578     VGAState *s = &vga_state;
1579     int full_update, graphic_mode;
1580
1581     if (s->ds->depth == 0) {
1582         /* nothing to do */
1583     } else {
1584         switch(s->ds->depth) {
1585         case 8:
1586             s->rgb_to_pixel = rgb_to_pixel8_dup;
1587             break;
1588         case 15:
1589             s->rgb_to_pixel = rgb_to_pixel15_dup;
1590             break;
1591         default:
1592         case 16:
1593             s->rgb_to_pixel = rgb_to_pixel16_dup;
1594             break;
1595         case 32:
1596             s->rgb_to_pixel = rgb_to_pixel32_dup;
1597             break;
1598         }
1599         
1600         full_update = 0;
1601         if (!(s->ar_index & 0x20)) {
1602             graphic_mode = GMODE_BLANK;
1603         } else {
1604             graphic_mode = s->gr[6] & 1;
1605         }
1606         if (graphic_mode != s->graphic_mode) {
1607             s->graphic_mode = graphic_mode;
1608             full_update = 1;
1609         }
1610         switch(graphic_mode) {
1611         case GMODE_TEXT:
1612             vga_draw_text(s, full_update);
1613             break;
1614         case GMODE_GRAPH:
1615             vga_draw_graphic(s, full_update);
1616             break;
1617         case GMODE_BLANK:
1618         default:
1619             vga_draw_blank(s, full_update);
1620             break;
1621         }
1622     }
1623 }
1624
1625 static void vga_reset(VGAState *s)
1626 {
1627     memset(s, 0, sizeof(VGAState));
1628 #ifdef CONFIG_S3VGA
1629     /* chip ID for 8c968 */
1630     s->cr[0x2d] = 0x88;
1631     s->cr[0x2e] = 0xb0;
1632     s->cr[0x2f] = 0x01; /* XXX: check revision code */
1633     s->cr[0x30] = 0xe1;
1634 #endif
1635     s->graphic_mode = -1; /* force full update */
1636 }
1637
1638 static CPUReadMemoryFunc *vga_mem_read[3] = {
1639     vga_mem_readb,
1640     vga_mem_readw,
1641     vga_mem_readl,
1642 };
1643
1644 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1645     vga_mem_writeb,
1646     vga_mem_writew,
1647     vga_mem_writel,
1648 };
1649
1650 static void vga_save(QEMUFile *f, void *opaque)
1651 {
1652     VGAState *s = opaque;
1653     int i;
1654
1655     qemu_put_be32s(f, &s->latch);
1656     qemu_put_8s(f, &s->sr_index);
1657     qemu_put_buffer(f, s->sr, 8);
1658     qemu_put_8s(f, &s->gr_index);
1659     qemu_put_buffer(f, s->gr, 16);
1660     qemu_put_8s(f, &s->ar_index);
1661     qemu_put_buffer(f, s->ar, 21);
1662     qemu_put_be32s(f, &s->ar_flip_flop);
1663     qemu_put_8s(f, &s->cr_index);
1664     qemu_put_buffer(f, s->cr, 256);
1665     qemu_put_8s(f, &s->msr);
1666     qemu_put_8s(f, &s->fcr);
1667     qemu_put_8s(f, &s->st00);
1668     qemu_put_8s(f, &s->st01);
1669
1670     qemu_put_8s(f, &s->dac_state);
1671     qemu_put_8s(f, &s->dac_sub_index);
1672     qemu_put_8s(f, &s->dac_read_index);
1673     qemu_put_8s(f, &s->dac_write_index);
1674     qemu_put_buffer(f, s->dac_cache, 3);
1675     qemu_put_buffer(f, s->palette, 768);
1676
1677     qemu_put_be32s(f, &s->bank_offset);
1678 #ifdef CONFIG_BOCHS_VBE
1679     qemu_put_byte(f, 1);
1680     qemu_put_be16s(f, &s->vbe_index);
1681     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1682         qemu_put_be16s(f, &s->vbe_regs[i]);
1683     qemu_put_be32s(f, &s->vbe_start_addr);
1684     qemu_put_be32s(f, &s->vbe_line_offset);
1685     qemu_put_be32s(f, &s->vbe_bank_mask);
1686 #else
1687     qemu_put_byte(f, 0);
1688 #endif
1689 }
1690
1691 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1692 {
1693     VGAState *s = opaque;
1694     int is_vbe, i;
1695
1696     if (version_id != 1)
1697         return -EINVAL;
1698
1699     qemu_get_be32s(f, &s->latch);
1700     qemu_get_8s(f, &s->sr_index);
1701     qemu_get_buffer(f, s->sr, 8);
1702     qemu_get_8s(f, &s->gr_index);
1703     qemu_get_buffer(f, s->gr, 16);
1704     qemu_get_8s(f, &s->ar_index);
1705     qemu_get_buffer(f, s->ar, 21);
1706     qemu_get_be32s(f, &s->ar_flip_flop);
1707     qemu_get_8s(f, &s->cr_index);
1708     qemu_get_buffer(f, s->cr, 256);
1709     qemu_get_8s(f, &s->msr);
1710     qemu_get_8s(f, &s->fcr);
1711     qemu_get_8s(f, &s->st00);
1712     qemu_get_8s(f, &s->st01);
1713
1714     qemu_get_8s(f, &s->dac_state);
1715     qemu_get_8s(f, &s->dac_sub_index);
1716     qemu_get_8s(f, &s->dac_read_index);
1717     qemu_get_8s(f, &s->dac_write_index);
1718     qemu_get_buffer(f, s->dac_cache, 3);
1719     qemu_get_buffer(f, s->palette, 768);
1720
1721     qemu_get_be32s(f, &s->bank_offset);
1722     is_vbe = qemu_get_byte(f);
1723 #ifdef CONFIG_BOCHS_VBE
1724     if (!is_vbe)
1725         return -EINVAL;
1726     qemu_get_be16s(f, &s->vbe_index);
1727     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1728         qemu_get_be16s(f, &s->vbe_regs[i]);
1729     qemu_get_be32s(f, &s->vbe_start_addr);
1730     qemu_get_be32s(f, &s->vbe_line_offset);
1731     qemu_get_be32s(f, &s->vbe_bank_mask);
1732 #else
1733     if (is_vbe)
1734         return -EINVAL;
1735 #endif
1736
1737     /* force refresh */
1738     s->graphic_mode = -1;
1739     return 0;
1740 }
1741
1742 static void vga_map(PCIDevice *pci_dev, int region_num, 
1743                     uint32_t addr, uint32_t size, int type)
1744 {
1745     VGAState *s = &vga_state;
1746
1747     cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1748 }
1749
1750 int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1751                    unsigned long vga_ram_offset, int vga_ram_size, 
1752                    int is_pci)
1753 {
1754     VGAState *s = &vga_state;
1755     int i, j, v, b;
1756
1757     for(i = 0;i < 256; i++) {
1758         v = 0;
1759         for(j = 0; j < 8; j++) {
1760             v |= ((i >> j) & 1) << (j * 4);
1761         }
1762         expand4[i] = v;
1763
1764         v = 0;
1765         for(j = 0; j < 4; j++) {
1766             v |= ((i >> (2 * j)) & 3) << (j * 4);
1767         }
1768         expand2[i] = v;
1769     }
1770     for(i = 0; i < 16; i++) {
1771         v = 0;
1772         for(j = 0; j < 4; j++) {
1773             b = ((i >> j) & 1);
1774             v |= b << (2 * j);
1775             v |= b << (2 * j + 1);
1776         }
1777         expand4to8[i] = v;
1778     }
1779
1780     vga_reset(s);
1781
1782     s->vram_ptr = vga_ram_base;
1783     s->vram_offset = vga_ram_offset;
1784     s->vram_size = vga_ram_size;
1785     s->ds = ds;
1786
1787     register_savevm("vga", 0, 1, vga_save, vga_load, s);
1788
1789     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1790
1791     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1792     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1793     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1794     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1795
1796     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1797
1798     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1799     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1800     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1801     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1802     s->bank_offset = 0;
1803
1804 #ifdef CONFIG_BOCHS_VBE
1805     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1806     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1807 #if defined (TARGET_I386)
1808     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1809     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1810
1811     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1812     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1813
1814     /* old Bochs IO ports */
1815     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1816     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1817
1818     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1819     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1820 #else
1821     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1822     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1823
1824     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1825     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1826 #endif
1827 #endif /* CONFIG_BOCHS_VBE */
1828
1829     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write);
1830     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1831                                  vga_io_memory);
1832
1833     if (is_pci) {
1834         PCIDevice *d;
1835         uint8_t *pci_conf;
1836
1837         d = pci_register_device("VGA", 
1838                                 sizeof(PCIDevice),
1839                                 0, -1, 
1840                                 NULL, NULL);
1841         pci_conf = d->config;
1842         pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1843         pci_conf[0x01] = 0x12;
1844         pci_conf[0x02] = 0x11;
1845         pci_conf[0x03] = 0x11;
1846         pci_conf[0x0a] = 0x00; // VGA controller 
1847         pci_conf[0x0b] = 0x03;
1848         pci_conf[0x0e] = 0x00; // header_type
1849
1850         /* XXX: vga_ram_size must be a power of two */
1851         pci_register_io_region(d, 0, vga_ram_size, 
1852                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1853     } else {
1854 #ifdef CONFIG_BOCHS_VBE
1855         /* XXX: use optimized standard vga accesses */
1856         cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1857                                      vga_ram_size, vga_ram_offset);
1858 #endif
1859     }
1860     return 0;
1861 }
1862
1863 /********************************************************/
1864 /* vga screen dump */
1865
1866 static int vga_save_w, vga_save_h;
1867
1868 static void vga_save_dpy_update(DisplayState *s, 
1869                                 int x, int y, int w, int h)
1870 {
1871 }
1872
1873 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1874 {
1875     s->linesize = w * 4;
1876     s->data = qemu_malloc(h * s->linesize);
1877     vga_save_w = w;
1878     vga_save_h = h;
1879 }
1880
1881 static void vga_save_dpy_refresh(DisplayState *s)
1882 {
1883 }
1884
1885 static int ppm_save(const char *filename, uint8_t *data, 
1886                     int w, int h, int linesize)
1887 {
1888     FILE *f;
1889     uint8_t *d, *d1;
1890     unsigned int v;
1891     int y, x;
1892
1893     f = fopen(filename, "wb");
1894     if (!f)
1895         return -1;
1896     fprintf(f, "P6\n%d %d\n%d\n",
1897             w, h, 255);
1898     d1 = data;
1899     for(y = 0; y < h; y++) {
1900         d = d1;
1901         for(x = 0; x < w; x++) {
1902             v = *(uint32_t *)d;
1903             fputc((v >> 16) & 0xff, f);
1904             fputc((v >> 8) & 0xff, f);
1905             fputc((v) & 0xff, f);
1906             d += 4;
1907         }
1908         d1 += linesize;
1909     }
1910     fclose(f);
1911     return 0;
1912 }
1913
1914 /* save the vga display in a PPM image even if no display is
1915    available */
1916 void vga_screen_dump(const char *filename)
1917 {
1918     VGAState *s = &vga_state;
1919     DisplayState *saved_ds, ds1, *ds = &ds1;
1920     
1921     /* XXX: this is a little hackish */
1922     s->last_width = -1;
1923     s->last_height = -1;
1924     saved_ds = s->ds;
1925
1926     memset(ds, 0, sizeof(DisplayState));
1927     ds->dpy_update = vga_save_dpy_update;
1928     ds->dpy_resize = vga_save_dpy_resize;
1929     ds->dpy_refresh = vga_save_dpy_refresh;
1930     ds->depth = 32;
1931
1932     s->ds = ds;
1933     s->graphic_mode = -1;
1934     vga_update_display();
1935     
1936     if (ds->data) {
1937         ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1938                  s->ds->linesize);
1939         qemu_free(ds->data);
1940     }
1941     s->ds = saved_ds;
1942 }