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