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