Update ARM board documentation.
[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 static inline unsigned int rgb_to_pixel32bgr(unsigned int r, unsigned int g, unsigned b)
812 {
813     return (b << 16) | (g << 8) | r;
814 }
815
816 #define DEPTH 8
817 #include "vga_template.h"
818
819 #define DEPTH 15
820 #include "vga_template.h"
821
822 #define DEPTH 16
823 #include "vga_template.h"
824
825 #define DEPTH 32
826 #include "vga_template.h"
827
828 #define BGR_FORMAT
829 #define DEPTH 32
830 #include "vga_template.h"
831
832 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
833 {
834     unsigned int col;
835     col = rgb_to_pixel8(r, g, b);
836     col |= col << 8;
837     col |= col << 16;
838     return col;
839 }
840
841 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
842 {
843     unsigned int col;
844     col = rgb_to_pixel15(r, g, b);
845     col |= col << 16;
846     return col;
847 }
848
849 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
850 {
851     unsigned int col;
852     col = rgb_to_pixel16(r, g, b);
853     col |= col << 16;
854     return col;
855 }
856
857 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
858 {
859     unsigned int col;
860     col = rgb_to_pixel32(r, g, b);
861     return col;
862 }
863
864 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
865 {
866     unsigned int col;
867     col = rgb_to_pixel32bgr(r, g, b);
868     return col;
869 }
870
871 /* return true if the palette was modified */
872 static int update_palette16(VGAState *s)
873 {
874     int full_update, i;
875     uint32_t v, col, *palette;
876
877     full_update = 0;
878     palette = s->last_palette;
879     for(i = 0; i < 16; i++) {
880         v = s->ar[i];
881         if (s->ar[0x10] & 0x80)
882             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
883         else
884             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
885         v = v * 3;
886         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
887                               c6_to_8(s->palette[v + 1]), 
888                               c6_to_8(s->palette[v + 2]));
889         if (col != palette[i]) {
890             full_update = 1;
891             palette[i] = col;
892         }
893     }
894     return full_update;
895 }
896
897 /* return true if the palette was modified */
898 static int update_palette256(VGAState *s)
899 {
900     int full_update, i;
901     uint32_t v, col, *palette;
902
903     full_update = 0;
904     palette = s->last_palette;
905     v = 0;
906     for(i = 0; i < 256; i++) {
907         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
908                               c6_to_8(s->palette[v + 1]), 
909                               c6_to_8(s->palette[v + 2]));
910         if (col != palette[i]) {
911             full_update = 1;
912             palette[i] = col;
913         }
914         v += 3;
915     }
916     return full_update;
917 }
918
919 static void vga_get_offsets(VGAState *s, 
920                             uint32_t *pline_offset, 
921                             uint32_t *pstart_addr)
922 {
923     uint32_t start_addr, line_offset;
924 #ifdef CONFIG_BOCHS_VBE
925     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
926         line_offset = s->vbe_line_offset;
927         start_addr = s->vbe_start_addr;
928     } else
929 #endif
930     {  
931         /* compute line_offset in bytes */
932         line_offset = s->cr[0x13];
933         line_offset <<= 3;
934
935         /* starting address */
936         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
937     }
938     *pline_offset = line_offset;
939     *pstart_addr = start_addr;
940 }
941
942 /* update start_addr and line_offset. Return TRUE if modified */
943 static int update_basic_params(VGAState *s)
944 {
945     int full_update;
946     uint32_t start_addr, line_offset, line_compare;
947     
948     full_update = 0;
949
950     s->get_offsets(s, &line_offset, &start_addr);
951     /* line compare */
952     line_compare = s->cr[0x18] | 
953         ((s->cr[0x07] & 0x10) << 4) |
954         ((s->cr[0x09] & 0x40) << 3);
955
956     if (line_offset != s->line_offset ||
957         start_addr != s->start_addr ||
958         line_compare != s->line_compare) {
959         s->line_offset = line_offset;
960         s->start_addr = start_addr;
961         s->line_compare = line_compare;
962         full_update = 1;
963     }
964     return full_update;
965 }
966
967 #define NB_DEPTHS 5
968
969 static inline int get_depth_index(DisplayState *s)
970 {
971     switch(s->depth) {
972     default:
973     case 8:
974         return 0;
975     case 15:
976         return 1;
977     case 16:
978         return 2;
979     case 32:
980         if (s->bgr)
981             return 4;
982         else
983             return 3;
984     }
985 }
986
987 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
988     vga_draw_glyph8_8,
989     vga_draw_glyph8_16,
990     vga_draw_glyph8_16,
991     vga_draw_glyph8_32,
992     vga_draw_glyph8_32,
993 };
994
995 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
996     vga_draw_glyph16_8,
997     vga_draw_glyph16_16,
998     vga_draw_glyph16_16,
999     vga_draw_glyph16_32,
1000     vga_draw_glyph16_32,
1001 };
1002
1003 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1004     vga_draw_glyph9_8,
1005     vga_draw_glyph9_16,
1006     vga_draw_glyph9_16,
1007     vga_draw_glyph9_32,
1008     vga_draw_glyph9_32,
1009 };
1010     
1011 static const uint8_t cursor_glyph[32 * 4] = {
1012     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1013     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1014     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1015     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1016     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1017     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1018     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1019     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1020     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1021     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1022     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1023     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1024     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1025     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1026     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1027     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1028 };    
1029
1030 /* 
1031  * Text mode update 
1032  * Missing:
1033  * - double scan
1034  * - double width 
1035  * - underline
1036  * - flashing
1037  */
1038 static void vga_draw_text(VGAState *s, int full_update)
1039 {
1040     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1041     int cx_min, cx_max, linesize, x_incr;
1042     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1043     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1044     const uint8_t *font_ptr, *font_base[2];
1045     int dup9, line_offset, depth_index;
1046     uint32_t *palette;
1047     uint32_t *ch_attr_ptr;
1048     vga_draw_glyph8_func *vga_draw_glyph8;
1049     vga_draw_glyph9_func *vga_draw_glyph9;
1050
1051     full_update |= update_palette16(s);
1052     palette = s->last_palette;
1053     
1054     /* compute font data address (in plane 2) */
1055     v = s->sr[3];
1056     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1057     if (offset != s->font_offsets[0]) {
1058         s->font_offsets[0] = offset;
1059         full_update = 1;
1060     }
1061     font_base[0] = s->vram_ptr + offset;
1062
1063     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1064     font_base[1] = s->vram_ptr + offset;
1065     if (offset != s->font_offsets[1]) {
1066         s->font_offsets[1] = offset;
1067         full_update = 1;
1068     }
1069     if (s->plane_updated & (1 << 2)) {
1070         /* if the plane 2 was modified since the last display, it
1071            indicates the font may have been modified */
1072         s->plane_updated = 0;
1073         full_update = 1;
1074     }
1075     full_update |= update_basic_params(s);
1076
1077     line_offset = s->line_offset;
1078     s1 = s->vram_ptr + (s->start_addr * 4);
1079
1080     /* total width & height */
1081     cheight = (s->cr[9] & 0x1f) + 1;
1082     cw = 8;
1083     if (!(s->sr[1] & 0x01))
1084         cw = 9;
1085     if (s->sr[1] & 0x08)
1086         cw = 16; /* NOTE: no 18 pixel wide */
1087     x_incr = cw * ((s->ds->depth + 7) >> 3);
1088     width = (s->cr[0x01] + 1);
1089     if (s->cr[0x06] == 100) {
1090         /* ugly hack for CGA 160x100x16 - explain me the logic */
1091         height = 100;
1092     } else {
1093         height = s->cr[0x12] | 
1094             ((s->cr[0x07] & 0x02) << 7) | 
1095             ((s->cr[0x07] & 0x40) << 3);
1096         height = (height + 1) / cheight;
1097     }
1098     if ((height * width) > CH_ATTR_SIZE) {
1099         /* better than nothing: exit if transient size is too big */
1100         return;
1101     }
1102
1103     if (width != s->last_width || height != s->last_height ||
1104         cw != s->last_cw || cheight != s->last_ch) {
1105         s->last_scr_width = width * cw;
1106         s->last_scr_height = height * cheight;
1107         dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1108         s->last_width = width;
1109         s->last_height = height;
1110         s->last_ch = cheight;
1111         s->last_cw = cw;
1112         full_update = 1;
1113     }
1114     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1115     if (cursor_offset != s->cursor_offset ||
1116         s->cr[0xa] != s->cursor_start ||
1117         s->cr[0xb] != s->cursor_end) {
1118       /* if the cursor position changed, we update the old and new
1119          chars */
1120         if (s->cursor_offset < CH_ATTR_SIZE)
1121             s->last_ch_attr[s->cursor_offset] = -1;
1122         if (cursor_offset < CH_ATTR_SIZE)
1123             s->last_ch_attr[cursor_offset] = -1;
1124         s->cursor_offset = cursor_offset;
1125         s->cursor_start = s->cr[0xa];
1126         s->cursor_end = s->cr[0xb];
1127     }
1128     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1129     
1130     depth_index = get_depth_index(s->ds);
1131     if (cw == 16)
1132         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1133     else
1134         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1135     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1136     
1137     dest = s->ds->data;
1138     linesize = s->ds->linesize;
1139     ch_attr_ptr = s->last_ch_attr;
1140     for(cy = 0; cy < height; cy++) {
1141         d1 = dest;
1142         src = s1;
1143         cx_min = width;
1144         cx_max = -1;
1145         for(cx = 0; cx < width; cx++) {
1146             ch_attr = *(uint16_t *)src;
1147             if (full_update || ch_attr != *ch_attr_ptr) {
1148                 if (cx < cx_min)
1149                     cx_min = cx;
1150                 if (cx > cx_max)
1151                     cx_max = cx;
1152                 *ch_attr_ptr = ch_attr;
1153 #ifdef WORDS_BIGENDIAN
1154                 ch = ch_attr >> 8;
1155                 cattr = ch_attr & 0xff;
1156 #else
1157                 ch = ch_attr & 0xff;
1158                 cattr = ch_attr >> 8;
1159 #endif
1160                 font_ptr = font_base[(cattr >> 3) & 1];
1161                 font_ptr += 32 * 4 * ch;
1162                 bgcol = palette[cattr >> 4];
1163                 fgcol = palette[cattr & 0x0f];
1164                 if (cw != 9) {
1165                     vga_draw_glyph8(d1, linesize, 
1166                                     font_ptr, cheight, fgcol, bgcol);
1167                 } else {
1168                     dup9 = 0;
1169                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1170                         dup9 = 1;
1171                     vga_draw_glyph9(d1, linesize, 
1172                                     font_ptr, cheight, fgcol, bgcol, dup9);
1173                 }
1174                 if (src == cursor_ptr &&
1175                     !(s->cr[0x0a] & 0x20)) {
1176                     int line_start, line_last, h;
1177                     /* draw the cursor */
1178                     line_start = s->cr[0x0a] & 0x1f;
1179                     line_last = s->cr[0x0b] & 0x1f;
1180                     /* XXX: check that */
1181                     if (line_last > cheight - 1)
1182                         line_last = cheight - 1;
1183                     if (line_last >= line_start && line_start < cheight) {
1184                         h = line_last - line_start + 1;
1185                         d = d1 + linesize * line_start;
1186                         if (cw != 9) {
1187                             vga_draw_glyph8(d, linesize, 
1188                                             cursor_glyph, h, fgcol, bgcol);
1189                         } else {
1190                             vga_draw_glyph9(d, linesize, 
1191                                             cursor_glyph, h, fgcol, bgcol, 1);
1192                         }
1193                     }
1194                 }
1195             }
1196             d1 += x_incr;
1197             src += 4;
1198             ch_attr_ptr++;
1199         }
1200         if (cx_max != -1) {
1201             dpy_update(s->ds, cx_min * cw, cy * cheight, 
1202                        (cx_max - cx_min + 1) * cw, cheight);
1203         }
1204         dest += linesize * cheight;
1205         s1 += line_offset;
1206     }
1207 }
1208
1209 enum {
1210     VGA_DRAW_LINE2,
1211     VGA_DRAW_LINE2D2,
1212     VGA_DRAW_LINE4,
1213     VGA_DRAW_LINE4D2,
1214     VGA_DRAW_LINE8D2,
1215     VGA_DRAW_LINE8,
1216     VGA_DRAW_LINE15,
1217     VGA_DRAW_LINE16,
1218     VGA_DRAW_LINE24,
1219     VGA_DRAW_LINE32,
1220     VGA_DRAW_LINE_NB,
1221 };
1222
1223 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1224     vga_draw_line2_8,
1225     vga_draw_line2_16,
1226     vga_draw_line2_16,
1227     vga_draw_line2_32,
1228     vga_draw_line2_32,
1229
1230     vga_draw_line2d2_8,
1231     vga_draw_line2d2_16,
1232     vga_draw_line2d2_16,
1233     vga_draw_line2d2_32,
1234     vga_draw_line2d2_32,
1235
1236     vga_draw_line4_8,
1237     vga_draw_line4_16,
1238     vga_draw_line4_16,
1239     vga_draw_line4_32,
1240     vga_draw_line4_32,
1241
1242     vga_draw_line4d2_8,
1243     vga_draw_line4d2_16,
1244     vga_draw_line4d2_16,
1245     vga_draw_line4d2_32,
1246     vga_draw_line4d2_32,
1247
1248     vga_draw_line8d2_8,
1249     vga_draw_line8d2_16,
1250     vga_draw_line8d2_16,
1251     vga_draw_line8d2_32,
1252     vga_draw_line8d2_32,
1253
1254     vga_draw_line8_8,
1255     vga_draw_line8_16,
1256     vga_draw_line8_16,
1257     vga_draw_line8_32,
1258     vga_draw_line8_32,
1259
1260     vga_draw_line15_8,
1261     vga_draw_line15_15,
1262     vga_draw_line15_16,
1263     vga_draw_line15_32,
1264     vga_draw_line15_32bgr,
1265
1266     vga_draw_line16_8,
1267     vga_draw_line16_15,
1268     vga_draw_line16_16,
1269     vga_draw_line16_32,
1270     vga_draw_line16_32bgr,
1271
1272     vga_draw_line24_8,
1273     vga_draw_line24_15,
1274     vga_draw_line24_16,
1275     vga_draw_line24_32,
1276     vga_draw_line24_32bgr,
1277
1278     vga_draw_line32_8,
1279     vga_draw_line32_15,
1280     vga_draw_line32_16,
1281     vga_draw_line32_32,
1282     vga_draw_line32_32bgr,
1283 };
1284
1285 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1286
1287 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1288     rgb_to_pixel8_dup,
1289     rgb_to_pixel15_dup,
1290     rgb_to_pixel16_dup,
1291     rgb_to_pixel32_dup,
1292     rgb_to_pixel32bgr_dup,
1293 };
1294
1295 static int vga_get_bpp(VGAState *s)
1296 {
1297     int ret;
1298 #ifdef CONFIG_BOCHS_VBE
1299     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1300         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1301     } else 
1302 #endif
1303     {
1304         ret = 0;
1305     }
1306     return ret;
1307 }
1308
1309 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1310 {
1311     int width, height;
1312     
1313     width = (s->cr[0x01] + 1) * 8;
1314     height = s->cr[0x12] | 
1315         ((s->cr[0x07] & 0x02) << 7) | 
1316         ((s->cr[0x07] & 0x40) << 3);
1317     height = (height + 1);
1318     *pwidth = width;
1319     *pheight = height;
1320 }
1321
1322 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1323 {
1324     int y;
1325     if (y1 >= VGA_MAX_HEIGHT)
1326         return;
1327     if (y2 >= VGA_MAX_HEIGHT)
1328         y2 = VGA_MAX_HEIGHT;
1329     for(y = y1; y < y2; y++) {
1330         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1331     }
1332 }
1333
1334 /* 
1335  * graphic modes
1336  */
1337 static void vga_draw_graphic(VGAState *s, int full_update)
1338 {
1339     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1340     int width, height, shift_control, line_offset, page0, page1, bwidth;
1341     int disp_width, multi_scan, multi_run;
1342     uint8_t *d;
1343     uint32_t v, addr1, addr;
1344     vga_draw_line_func *vga_draw_line;
1345     
1346     full_update |= update_basic_params(s);
1347
1348     s->get_resolution(s, &width, &height);
1349     disp_width = width;
1350
1351     shift_control = (s->gr[0x05] >> 5) & 3;
1352     double_scan = (s->cr[0x09] >> 7);
1353     if (shift_control != 1) {
1354         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1355     } else {
1356         /* in CGA modes, multi_scan is ignored */
1357         /* XXX: is it correct ? */
1358         multi_scan = double_scan;
1359     }
1360     multi_run = multi_scan;
1361     if (shift_control != s->shift_control ||
1362         double_scan != s->double_scan) {
1363         full_update = 1;
1364         s->shift_control = shift_control;
1365         s->double_scan = double_scan;
1366     }
1367     
1368     if (shift_control == 0) {
1369         full_update |= update_palette16(s);
1370         if (s->sr[0x01] & 8) {
1371             v = VGA_DRAW_LINE4D2;
1372             disp_width <<= 1;
1373         } else {
1374             v = VGA_DRAW_LINE4;
1375         }
1376     } else if (shift_control == 1) {
1377         full_update |= update_palette16(s);
1378         if (s->sr[0x01] & 8) {
1379             v = VGA_DRAW_LINE2D2;
1380             disp_width <<= 1;
1381         } else {
1382             v = VGA_DRAW_LINE2;
1383         }
1384     } else {
1385         switch(s->get_bpp(s)) {
1386         default:
1387         case 0:
1388             full_update |= update_palette256(s);
1389             v = VGA_DRAW_LINE8D2;
1390             break;
1391         case 8:
1392             full_update |= update_palette256(s);
1393             v = VGA_DRAW_LINE8;
1394             break;
1395         case 15:
1396             v = VGA_DRAW_LINE15;
1397             break;
1398         case 16:
1399             v = VGA_DRAW_LINE16;
1400             break;
1401         case 24:
1402             v = VGA_DRAW_LINE24;
1403             break;
1404         case 32:
1405             v = VGA_DRAW_LINE32;
1406             break;
1407         }
1408     }
1409     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1410
1411     if (disp_width != s->last_width ||
1412         height != s->last_height) {
1413         dpy_resize(s->ds, disp_width, height);
1414         s->last_scr_width = disp_width;
1415         s->last_scr_height = height;
1416         s->last_width = disp_width;
1417         s->last_height = height;
1418         full_update = 1;
1419     }
1420     if (s->cursor_invalidate)
1421         s->cursor_invalidate(s);
1422     
1423     line_offset = s->line_offset;
1424 #if 0
1425     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",
1426            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1427 #endif
1428     addr1 = (s->start_addr * 4);
1429     bwidth = width * 4;
1430     y_start = -1;
1431     page_min = 0x7fffffff;
1432     page_max = -1;
1433     d = s->ds->data;
1434     linesize = s->ds->linesize;
1435     y1 = 0;
1436     for(y = 0; y < height; y++) {
1437         addr = addr1;
1438         if (!(s->cr[0x17] & 1)) {
1439             int shift;
1440             /* CGA compatibility handling */
1441             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1442             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1443         }
1444         if (!(s->cr[0x17] & 2)) {
1445             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1446         }
1447         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1448         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1449         update = full_update | 
1450             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1451             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1452         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1453             /* if wide line, can use another page */
1454             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, 
1455                                                     VGA_DIRTY_FLAG);
1456         }
1457         /* explicit invalidation for the hardware cursor */
1458         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1459         if (update) {
1460             if (y_start < 0)
1461                 y_start = y;
1462             if (page0 < page_min)
1463                 page_min = page0;
1464             if (page1 > page_max)
1465                 page_max = page1;
1466             vga_draw_line(s, d, s->vram_ptr + addr, width);
1467             if (s->cursor_draw_line)
1468                 s->cursor_draw_line(s, d, y);
1469         } else {
1470             if (y_start >= 0) {
1471                 /* flush to display */
1472                 dpy_update(s->ds, 0, y_start, 
1473                            disp_width, y - y_start);
1474                 y_start = -1;
1475             }
1476         }
1477         if (!multi_run) {
1478             mask = (s->cr[0x17] & 3) ^ 3;
1479             if ((y1 & mask) == mask)
1480                 addr1 += line_offset;
1481             y1++;
1482             multi_run = multi_scan;
1483         } else {
1484             multi_run--;
1485         }
1486         /* line compare acts on the displayed lines */
1487         if (y == s->line_compare)
1488             addr1 = 0;
1489         d += linesize;
1490     }
1491     if (y_start >= 0) {
1492         /* flush to display */
1493         dpy_update(s->ds, 0, y_start, 
1494                    disp_width, y - y_start);
1495     }
1496     /* reset modified pages */
1497     if (page_max != -1) {
1498         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1499                                         VGA_DIRTY_FLAG);
1500     }
1501     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1502 }
1503
1504 static void vga_draw_blank(VGAState *s, int full_update)
1505 {
1506     int i, w, val;
1507     uint8_t *d;
1508
1509     if (!full_update)
1510         return;
1511     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1512         return;
1513     if (s->ds->depth == 8) 
1514         val = s->rgb_to_pixel(0, 0, 0);
1515     else
1516         val = 0;
1517     w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1518     d = s->ds->data;
1519     for(i = 0; i < s->last_scr_height; i++) {
1520         memset(d, val, w);
1521         d += s->ds->linesize;
1522     }
1523     dpy_update(s->ds, 0, 0, 
1524                s->last_scr_width, s->last_scr_height);
1525 }
1526
1527 #define GMODE_TEXT     0
1528 #define GMODE_GRAPH    1
1529 #define GMODE_BLANK 2 
1530
1531 static void vga_update_display(void *opaque)
1532 {
1533     VGAState *s = (VGAState *)opaque;
1534     int full_update, graphic_mode;
1535
1536     if (s->ds->depth == 0) {
1537         /* nothing to do */
1538     } else {
1539         s->rgb_to_pixel = 
1540             rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1541         
1542         full_update = 0;
1543         if (!(s->ar_index & 0x20)) {
1544             graphic_mode = GMODE_BLANK;
1545         } else {
1546             graphic_mode = s->gr[6] & 1;
1547         }
1548         if (graphic_mode != s->graphic_mode) {
1549             s->graphic_mode = graphic_mode;
1550             full_update = 1;
1551         }
1552         switch(graphic_mode) {
1553         case GMODE_TEXT:
1554             vga_draw_text(s, full_update);
1555             break;
1556         case GMODE_GRAPH:
1557             vga_draw_graphic(s, full_update);
1558             break;
1559         case GMODE_BLANK:
1560         default:
1561             vga_draw_blank(s, full_update);
1562             break;
1563         }
1564     }
1565 }
1566
1567 /* force a full display refresh */
1568 static void vga_invalidate_display(void *opaque)
1569 {
1570     VGAState *s = (VGAState *)opaque;
1571     
1572     s->last_width = -1;
1573     s->last_height = -1;
1574 }
1575
1576 static void vga_reset(VGAState *s)
1577 {
1578     memset(s, 0, sizeof(VGAState));
1579     s->graphic_mode = -1; /* force full update */
1580 }
1581
1582 static CPUReadMemoryFunc *vga_mem_read[3] = {
1583     vga_mem_readb,
1584     vga_mem_readw,
1585     vga_mem_readl,
1586 };
1587
1588 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1589     vga_mem_writeb,
1590     vga_mem_writew,
1591     vga_mem_writel,
1592 };
1593
1594 static void vga_save(QEMUFile *f, void *opaque)
1595 {
1596     VGAState *s = opaque;
1597     int i;
1598
1599     qemu_put_be32s(f, &s->latch);
1600     qemu_put_8s(f, &s->sr_index);
1601     qemu_put_buffer(f, s->sr, 8);
1602     qemu_put_8s(f, &s->gr_index);
1603     qemu_put_buffer(f, s->gr, 16);
1604     qemu_put_8s(f, &s->ar_index);
1605     qemu_put_buffer(f, s->ar, 21);
1606     qemu_put_be32s(f, &s->ar_flip_flop);
1607     qemu_put_8s(f, &s->cr_index);
1608     qemu_put_buffer(f, s->cr, 256);
1609     qemu_put_8s(f, &s->msr);
1610     qemu_put_8s(f, &s->fcr);
1611     qemu_put_8s(f, &s->st00);
1612     qemu_put_8s(f, &s->st01);
1613
1614     qemu_put_8s(f, &s->dac_state);
1615     qemu_put_8s(f, &s->dac_sub_index);
1616     qemu_put_8s(f, &s->dac_read_index);
1617     qemu_put_8s(f, &s->dac_write_index);
1618     qemu_put_buffer(f, s->dac_cache, 3);
1619     qemu_put_buffer(f, s->palette, 768);
1620
1621     qemu_put_be32s(f, &s->bank_offset);
1622 #ifdef CONFIG_BOCHS_VBE
1623     qemu_put_byte(f, 1);
1624     qemu_put_be16s(f, &s->vbe_index);
1625     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1626         qemu_put_be16s(f, &s->vbe_regs[i]);
1627     qemu_put_be32s(f, &s->vbe_start_addr);
1628     qemu_put_be32s(f, &s->vbe_line_offset);
1629     qemu_put_be32s(f, &s->vbe_bank_mask);
1630 #else
1631     qemu_put_byte(f, 0);
1632 #endif
1633 }
1634
1635 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1636 {
1637     VGAState *s = opaque;
1638     int is_vbe, i;
1639
1640     if (version_id != 1)
1641         return -EINVAL;
1642
1643     qemu_get_be32s(f, &s->latch);
1644     qemu_get_8s(f, &s->sr_index);
1645     qemu_get_buffer(f, s->sr, 8);
1646     qemu_get_8s(f, &s->gr_index);
1647     qemu_get_buffer(f, s->gr, 16);
1648     qemu_get_8s(f, &s->ar_index);
1649     qemu_get_buffer(f, s->ar, 21);
1650     qemu_get_be32s(f, &s->ar_flip_flop);
1651     qemu_get_8s(f, &s->cr_index);
1652     qemu_get_buffer(f, s->cr, 256);
1653     qemu_get_8s(f, &s->msr);
1654     qemu_get_8s(f, &s->fcr);
1655     qemu_get_8s(f, &s->st00);
1656     qemu_get_8s(f, &s->st01);
1657
1658     qemu_get_8s(f, &s->dac_state);
1659     qemu_get_8s(f, &s->dac_sub_index);
1660     qemu_get_8s(f, &s->dac_read_index);
1661     qemu_get_8s(f, &s->dac_write_index);
1662     qemu_get_buffer(f, s->dac_cache, 3);
1663     qemu_get_buffer(f, s->palette, 768);
1664
1665     qemu_get_be32s(f, &s->bank_offset);
1666     is_vbe = qemu_get_byte(f);
1667 #ifdef CONFIG_BOCHS_VBE
1668     if (!is_vbe)
1669         return -EINVAL;
1670     qemu_get_be16s(f, &s->vbe_index);
1671     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1672         qemu_get_be16s(f, &s->vbe_regs[i]);
1673     qemu_get_be32s(f, &s->vbe_start_addr);
1674     qemu_get_be32s(f, &s->vbe_line_offset);
1675     qemu_get_be32s(f, &s->vbe_bank_mask);
1676 #else
1677     if (is_vbe)
1678         return -EINVAL;
1679 #endif
1680
1681     /* force refresh */
1682     s->graphic_mode = -1;
1683     return 0;
1684 }
1685
1686 static void vga_map(PCIDevice *pci_dev, int region_num, 
1687                     uint32_t addr, uint32_t size, int type)
1688 {
1689     VGAState *s = vga_state;
1690     if (region_num == PCI_ROM_SLOT) {
1691         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
1692     } else {
1693         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1694     }
1695 }
1696
1697 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1698                      unsigned long vga_ram_offset, int vga_ram_size)
1699 {
1700     int i, j, v, b;
1701
1702     for(i = 0;i < 256; i++) {
1703         v = 0;
1704         for(j = 0; j < 8; j++) {
1705             v |= ((i >> j) & 1) << (j * 4);
1706         }
1707         expand4[i] = v;
1708
1709         v = 0;
1710         for(j = 0; j < 4; j++) {
1711             v |= ((i >> (2 * j)) & 3) << (j * 4);
1712         }
1713         expand2[i] = v;
1714     }
1715     for(i = 0; i < 16; i++) {
1716         v = 0;
1717         for(j = 0; j < 4; j++) {
1718             b = ((i >> j) & 1);
1719             v |= b << (2 * j);
1720             v |= b << (2 * j + 1);
1721         }
1722         expand4to8[i] = v;
1723     }
1724
1725     vga_reset(s);
1726
1727     s->vram_ptr = vga_ram_base;
1728     s->vram_offset = vga_ram_offset;
1729     s->vram_size = vga_ram_size;
1730     s->ds = ds;
1731     s->get_bpp = vga_get_bpp;
1732     s->get_offsets = vga_get_offsets;
1733     s->get_resolution = vga_get_resolution;
1734     graphic_console_init(s->ds, vga_update_display, vga_invalidate_display,
1735                          vga_screen_dump, s);
1736     /* XXX: currently needed for display */
1737     vga_state = s;
1738 }
1739
1740
1741 int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1742                    unsigned long vga_ram_offset, int vga_ram_size,
1743                    unsigned long vga_bios_offset, int vga_bios_size)
1744 {
1745     VGAState *s;
1746
1747     s = qemu_mallocz(sizeof(VGAState));
1748     if (!s)
1749         return -1;
1750
1751     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1752
1753     register_savevm("vga", 0, 1, vga_save, vga_load, s);
1754
1755     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1756
1757     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1758     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1759     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1760     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1761
1762     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1763
1764     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1765     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1766     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1767     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1768     s->bank_offset = 0;
1769
1770 #ifdef CONFIG_BOCHS_VBE
1771     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1772     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1773 #if defined (TARGET_I386)
1774     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1775     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1776
1777     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1778     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1779
1780     /* old Bochs IO ports */
1781     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1782     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1783
1784     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1785     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1786 #else
1787     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1788     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1789
1790     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1791     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1792 #endif
1793 #endif /* CONFIG_BOCHS_VBE */
1794
1795     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1796     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1797                                  vga_io_memory);
1798
1799     if (bus) {
1800         PCIDevice *d;
1801         uint8_t *pci_conf;
1802
1803         d = pci_register_device(bus, "VGA", 
1804                                 sizeof(PCIDevice),
1805                                 -1, NULL, NULL);
1806         pci_conf = d->config;
1807         pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1808         pci_conf[0x01] = 0x12;
1809         pci_conf[0x02] = 0x11;
1810         pci_conf[0x03] = 0x11;
1811         pci_conf[0x0a] = 0x00; // VGA controller 
1812         pci_conf[0x0b] = 0x03;
1813         pci_conf[0x0e] = 0x00; // header_type
1814
1815         /* XXX: vga_ram_size must be a power of two */
1816         pci_register_io_region(d, 0, vga_ram_size, 
1817                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1818         if (vga_bios_size != 0) {
1819             unsigned int bios_total_size;
1820             s->bios_offset = vga_bios_offset;
1821             s->bios_size = vga_bios_size;
1822             /* must be a power of two */
1823             bios_total_size = 1;
1824             while (bios_total_size < vga_bios_size)
1825                 bios_total_size <<= 1;
1826             pci_register_io_region(d, PCI_ROM_SLOT, bios_total_size, 
1827                                    PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1828         }
1829     } else {
1830 #ifdef CONFIG_BOCHS_VBE
1831         /* XXX: use optimized standard vga accesses */
1832         cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1833                                      vga_ram_size, vga_ram_offset);
1834 #endif
1835     }
1836     return 0;
1837 }
1838
1839 /********************************************************/
1840 /* vga screen dump */
1841
1842 static int vga_save_w, vga_save_h;
1843
1844 static void vga_save_dpy_update(DisplayState *s, 
1845                                 int x, int y, int w, int h)
1846 {
1847 }
1848
1849 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1850 {
1851     s->linesize = w * 4;
1852     s->data = qemu_malloc(h * s->linesize);
1853     vga_save_w = w;
1854     vga_save_h = h;
1855 }
1856
1857 static void vga_save_dpy_refresh(DisplayState *s)
1858 {
1859 }
1860
1861 static int ppm_save(const char *filename, uint8_t *data, 
1862                     int w, int h, int linesize)
1863 {
1864     FILE *f;
1865     uint8_t *d, *d1;
1866     unsigned int v;
1867     int y, x;
1868
1869     f = fopen(filename, "wb");
1870     if (!f)
1871         return -1;
1872     fprintf(f, "P6\n%d %d\n%d\n",
1873             w, h, 255);
1874     d1 = data;
1875     for(y = 0; y < h; y++) {
1876         d = d1;
1877         for(x = 0; x < w; x++) {
1878             v = *(uint32_t *)d;
1879             fputc((v >> 16) & 0xff, f);
1880             fputc((v >> 8) & 0xff, f);
1881             fputc((v) & 0xff, f);
1882             d += 4;
1883         }
1884         d1 += linesize;
1885     }
1886     fclose(f);
1887     return 0;
1888 }
1889
1890 /* save the vga display in a PPM image even if no display is
1891    available */
1892 static void vga_screen_dump(void *opaque, const char *filename)
1893 {
1894     VGAState *s = (VGAState *)opaque;
1895     DisplayState *saved_ds, ds1, *ds = &ds1;
1896     
1897     /* XXX: this is a little hackish */
1898     vga_invalidate_display(s);
1899     saved_ds = s->ds;
1900
1901     memset(ds, 0, sizeof(DisplayState));
1902     ds->dpy_update = vga_save_dpy_update;
1903     ds->dpy_resize = vga_save_dpy_resize;
1904     ds->dpy_refresh = vga_save_dpy_refresh;
1905     ds->depth = 32;
1906
1907     s->ds = ds;
1908     s->graphic_mode = -1;
1909     vga_update_display(s);
1910     
1911     if (ds->data) {
1912         ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1913                  s->ds->linesize);
1914         qemu_free(ds->data);
1915     }
1916     s->ds = saved_ds;
1917 }