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