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