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