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