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