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