keyboard support (Blue Swirl)
[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, mask;
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         mask = (1 << plane);
699         if (s->sr[2] & mask) {
700             s->vram_ptr[addr] = val;
701 #ifdef DEBUG_VGA_MEM
702             printf("vga: chain4: [0x%x]\n", addr);
703 #endif
704             s->plane_updated |= mask; /* only used to detect font change */
705             cpu_physical_memory_set_dirty(s->vram_offset + addr);
706         }
707     } else if (s->gr[5] & 0x10) {
708         /* odd/even mode (aka text mode mapping) */
709         plane = (s->gr[4] & 2) | (addr & 1);
710         mask = (1 << plane);
711         if (s->sr[2] & mask) {
712             addr = ((addr & ~1) << 1) | plane;
713             s->vram_ptr[addr] = val;
714 #ifdef DEBUG_VGA_MEM
715             printf("vga: odd/even: [0x%x]\n", addr);
716 #endif
717             s->plane_updated |= mask; /* only used to detect font change */
718             cpu_physical_memory_set_dirty(s->vram_offset + addr);
719         }
720     } else {
721         /* standard VGA latched access */
722         write_mode = s->gr[5] & 3;
723         switch(write_mode) {
724         default:
725         case 0:
726             /* rotate */
727             b = s->gr[3] & 7;
728             val = ((val >> b) | (val << (8 - b))) & 0xff;
729             val |= val << 8;
730             val |= val << 16;
731
732             /* apply set/reset mask */
733             set_mask = mask16[s->gr[1]];
734             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
735             bit_mask = s->gr[8];
736             break;
737         case 1:
738             val = s->latch;
739             goto do_write;
740         case 2:
741             val = mask16[val & 0x0f];
742             bit_mask = s->gr[8];
743             break;
744         case 3:
745             /* rotate */
746             b = s->gr[3] & 7;
747             val = (val >> b) | (val << (8 - b));
748
749             bit_mask = s->gr[8] & val;
750             val = mask16[s->gr[0]];
751             break;
752         }
753
754         /* apply logical operation */
755         func_select = s->gr[3] >> 3;
756         switch(func_select) {
757         case 0:
758         default:
759             /* nothing to do */
760             break;
761         case 1:
762             /* and */
763             val &= s->latch;
764             break;
765         case 2:
766             /* or */
767             val |= s->latch;
768             break;
769         case 3:
770             /* xor */
771             val ^= s->latch;
772             break;
773         }
774
775         /* apply bit mask */
776         bit_mask |= bit_mask << 8;
777         bit_mask |= bit_mask << 16;
778         val = (val & bit_mask) | (s->latch & ~bit_mask);
779
780     do_write:
781         /* mask data according to sr[2] */
782         mask = s->sr[2];
783         s->plane_updated |= mask; /* only used to detect font change */
784         write_mask = mask16[mask];
785         ((uint32_t *)s->vram_ptr)[addr] = 
786             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
787             (val & write_mask);
788 #ifdef DEBUG_VGA_MEM
789             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
790                    addr * 4, write_mask, val);
791 #endif
792             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
793     }
794 }
795
796 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
797 {
798 #ifdef TARGET_WORDS_BIGENDIAN
799     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
800     vga_mem_writeb(opaque, addr + 1, val & 0xff);
801 #else
802     vga_mem_writeb(opaque, addr, val & 0xff);
803     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
804 #endif
805 }
806
807 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
808 {
809 #ifdef TARGET_WORDS_BIGENDIAN
810     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
811     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
812     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
813     vga_mem_writeb(opaque, addr + 3, val & 0xff);
814 #else
815     vga_mem_writeb(opaque, addr, val & 0xff);
816     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
817     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
818     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
819 #endif
820 }
821
822 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
823                              const uint8_t *font_ptr, int h,
824                              uint32_t fgcol, uint32_t bgcol);
825 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
826                                   const uint8_t *font_ptr, int h, 
827                                   uint32_t fgcol, uint32_t bgcol, int dup9);
828 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
829                                 const uint8_t *s, int width);
830
831 static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
832 {
833     return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
834 }
835
836 static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
837 {
838     return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
839 }
840
841 static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
842 {
843     return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
844 }
845
846 static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
847 {
848     return (r << 16) | (g << 8) | b;
849 }
850
851 #define DEPTH 8
852 #include "vga_template.h"
853
854 #define DEPTH 15
855 #include "vga_template.h"
856
857 #define DEPTH 16
858 #include "vga_template.h"
859
860 #define DEPTH 32
861 #include "vga_template.h"
862
863 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
864 {
865     unsigned int col;
866     col = rgb_to_pixel8(r, g, b);
867     col |= col << 8;
868     col |= col << 16;
869     return col;
870 }
871
872 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
873 {
874     unsigned int col;
875     col = rgb_to_pixel15(r, g, b);
876     col |= col << 16;
877     return col;
878 }
879
880 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
881 {
882     unsigned int col;
883     col = rgb_to_pixel16(r, g, b);
884     col |= col << 16;
885     return col;
886 }
887
888 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
889 {
890     unsigned int col;
891     col = rgb_to_pixel32(r, g, b);
892     return col;
893 }
894
895 /* return true if the palette was modified */
896 static int update_palette16(VGAState *s)
897 {
898     int full_update, i;
899     uint32_t v, col, *palette;
900
901     full_update = 0;
902     palette = s->last_palette;
903     for(i = 0; i < 16; i++) {
904         v = s->ar[i];
905         if (s->ar[0x10] & 0x80)
906             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
907         else
908             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
909         v = v * 3;
910         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
911                               c6_to_8(s->palette[v + 1]), 
912                               c6_to_8(s->palette[v + 2]));
913         if (col != palette[i]) {
914             full_update = 1;
915             palette[i] = col;
916         }
917     }
918     return full_update;
919 }
920
921 /* return true if the palette was modified */
922 static int update_palette256(VGAState *s)
923 {
924     int full_update, i;
925     uint32_t v, col, *palette;
926
927     full_update = 0;
928     palette = s->last_palette;
929     v = 0;
930     for(i = 0; i < 256; i++) {
931         col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
932                               c6_to_8(s->palette[v + 1]), 
933                               c6_to_8(s->palette[v + 2]));
934         if (col != palette[i]) {
935             full_update = 1;
936             palette[i] = col;
937         }
938         v += 3;
939     }
940     return full_update;
941 }
942
943 static void vga_get_offsets(VGAState *s, 
944                             uint32_t *pline_offset, 
945                             uint32_t *pstart_addr)
946 {
947     uint32_t start_addr, line_offset;
948 #ifdef CONFIG_BOCHS_VBE
949     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
950         line_offset = s->vbe_line_offset;
951         start_addr = s->vbe_start_addr;
952     } else
953 #endif
954     {  
955         /* compute line_offset in bytes */
956         line_offset = s->cr[0x13];
957 #ifdef CONFIG_S3VGA
958         {
959             uinr32_t v;
960             v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
961             if (v == 0)
962                 v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
963             line_offset |= (v << 8);
964         }
965 #endif
966         line_offset <<= 3;
967         
968         /* starting address */
969         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
970 #ifdef CONFIG_S3VGA
971         start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
972 #endif
973     }
974     *pline_offset = line_offset;
975     *pstart_addr = start_addr;
976 }
977
978 /* update start_addr and line_offset. Return TRUE if modified */
979 static int update_basic_params(VGAState *s)
980 {
981     int full_update;
982     uint32_t start_addr, line_offset, line_compare;
983     
984     full_update = 0;
985
986     s->get_offsets(s, &line_offset, &start_addr);
987     /* line compare */
988     line_compare = s->cr[0x18] | 
989         ((s->cr[0x07] & 0x10) << 4) |
990         ((s->cr[0x09] & 0x40) << 3);
991
992     if (line_offset != s->line_offset ||
993         start_addr != s->start_addr ||
994         line_compare != s->line_compare) {
995         s->line_offset = line_offset;
996         s->start_addr = start_addr;
997         s->line_compare = line_compare;
998         full_update = 1;
999     }
1000     return full_update;
1001 }
1002
1003 static inline int get_depth_index(int depth)
1004 {
1005     switch(depth) {
1006     default:
1007     case 8:
1008         return 0;
1009     case 15:
1010         return 1;
1011     case 16:
1012         return 2;
1013     case 32:
1014         return 3;
1015     }
1016 }
1017
1018 static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1019     vga_draw_glyph8_8,
1020     vga_draw_glyph8_16,
1021     vga_draw_glyph8_16,
1022     vga_draw_glyph8_32,
1023 };
1024
1025 static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1026     vga_draw_glyph16_8,
1027     vga_draw_glyph16_16,
1028     vga_draw_glyph16_16,
1029     vga_draw_glyph16_32,
1030 };
1031
1032 static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1033     vga_draw_glyph9_8,
1034     vga_draw_glyph9_16,
1035     vga_draw_glyph9_16,
1036     vga_draw_glyph9_32,
1037 };
1038     
1039 static const uint8_t cursor_glyph[32 * 4] = {
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     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1051     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1052     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1053     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1054     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1055     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1056 };    
1057
1058 /* 
1059  * Text mode update 
1060  * Missing:
1061  * - double scan
1062  * - double width 
1063  * - underline
1064  * - flashing
1065  */
1066 static void vga_draw_text(VGAState *s, int full_update)
1067 {
1068     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1069     int cx_min, cx_max, linesize, x_incr;
1070     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1071     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1072     const uint8_t *font_ptr, *font_base[2];
1073     int dup9, line_offset, depth_index;
1074     uint32_t *palette;
1075     uint32_t *ch_attr_ptr;
1076     vga_draw_glyph8_func *vga_draw_glyph8;
1077     vga_draw_glyph9_func *vga_draw_glyph9;
1078
1079     full_update |= update_palette16(s);
1080     palette = s->last_palette;
1081     
1082     /* compute font data address (in plane 2) */
1083     v = s->sr[3];
1084     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1085     if (offset != s->font_offsets[0]) {
1086         s->font_offsets[0] = offset;
1087         full_update = 1;
1088     }
1089     font_base[0] = s->vram_ptr + offset;
1090
1091     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1092     font_base[1] = s->vram_ptr + offset;
1093     if (offset != s->font_offsets[1]) {
1094         s->font_offsets[1] = offset;
1095         full_update = 1;
1096     }
1097     if (s->plane_updated & (1 << 2)) {
1098         /* if the plane 2 was modified since the last display, it
1099            indicates the font may have been modified */
1100         s->plane_updated = 0;
1101         full_update = 1;
1102     }
1103     full_update |= update_basic_params(s);
1104
1105     line_offset = s->line_offset;
1106     s1 = s->vram_ptr + (s->start_addr * 4);
1107
1108     /* total width & height */
1109     cheight = (s->cr[9] & 0x1f) + 1;
1110     cw = 8;
1111     if (!(s->sr[1] & 0x01))
1112         cw = 9;
1113     if (s->sr[1] & 0x08)
1114         cw = 16; /* NOTE: no 18 pixel wide */
1115     x_incr = cw * ((s->ds->depth + 7) >> 3);
1116     width = (s->cr[0x01] + 1);
1117     if (s->cr[0x06] == 100) {
1118         /* ugly hack for CGA 160x100x16 - explain me the logic */
1119         height = 100;
1120     } else {
1121         height = s->cr[0x12] | 
1122             ((s->cr[0x07] & 0x02) << 7) | 
1123             ((s->cr[0x07] & 0x40) << 3);
1124         height = (height + 1) / cheight;
1125     }
1126     if ((height * width) > CH_ATTR_SIZE) {
1127         /* better than nothing: exit if transient size is too big */
1128         return;
1129     }
1130
1131     if (width != s->last_width || height != s->last_height ||
1132         cw != s->last_cw || cheight != s->last_ch) {
1133         s->last_scr_width = width * cw;
1134         s->last_scr_height = height * cheight;
1135         dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1136         s->last_width = width;
1137         s->last_height = height;
1138         s->last_ch = cheight;
1139         s->last_cw = cw;
1140         full_update = 1;
1141     }
1142     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1143     if (cursor_offset != s->cursor_offset ||
1144         s->cr[0xa] != s->cursor_start ||
1145         s->cr[0xb] != s->cursor_end) {
1146       /* if the cursor position changed, we update the old and new
1147          chars */
1148         if (s->cursor_offset < CH_ATTR_SIZE)
1149             s->last_ch_attr[s->cursor_offset] = -1;
1150         if (cursor_offset < CH_ATTR_SIZE)
1151             s->last_ch_attr[cursor_offset] = -1;
1152         s->cursor_offset = cursor_offset;
1153         s->cursor_start = s->cr[0xa];
1154         s->cursor_end = s->cr[0xb];
1155     }
1156     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1157     
1158     depth_index = get_depth_index(s->ds->depth);
1159     if (cw == 16)
1160         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1161     else
1162         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1163     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1164     
1165     dest = s->ds->data;
1166     linesize = s->ds->linesize;
1167     ch_attr_ptr = s->last_ch_attr;
1168     for(cy = 0; cy < height; cy++) {
1169         d1 = dest;
1170         src = s1;
1171         cx_min = width;
1172         cx_max = -1;
1173         for(cx = 0; cx < width; cx++) {
1174             ch_attr = *(uint16_t *)src;
1175             if (full_update || ch_attr != *ch_attr_ptr) {
1176                 if (cx < cx_min)
1177                     cx_min = cx;
1178                 if (cx > cx_max)
1179                     cx_max = cx;
1180                 *ch_attr_ptr = ch_attr;
1181 #ifdef WORDS_BIGENDIAN
1182                 ch = ch_attr >> 8;
1183                 cattr = ch_attr & 0xff;
1184 #else
1185                 ch = ch_attr & 0xff;
1186                 cattr = ch_attr >> 8;
1187 #endif
1188                 font_ptr = font_base[(cattr >> 3) & 1];
1189                 font_ptr += 32 * 4 * ch;
1190                 bgcol = palette[cattr >> 4];
1191                 fgcol = palette[cattr & 0x0f];
1192                 if (cw != 9) {
1193                     vga_draw_glyph8(d1, linesize, 
1194                                     font_ptr, cheight, fgcol, bgcol);
1195                 } else {
1196                     dup9 = 0;
1197                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1198                         dup9 = 1;
1199                     vga_draw_glyph9(d1, linesize, 
1200                                     font_ptr, cheight, fgcol, bgcol, dup9);
1201                 }
1202                 if (src == cursor_ptr &&
1203                     !(s->cr[0x0a] & 0x20)) {
1204                     int line_start, line_last, h;
1205                     /* draw the cursor */
1206                     line_start = s->cr[0x0a] & 0x1f;
1207                     line_last = s->cr[0x0b] & 0x1f;
1208                     /* XXX: check that */
1209                     if (line_last > cheight - 1)
1210                         line_last = cheight - 1;
1211                     if (line_last >= line_start && line_start < cheight) {
1212                         h = line_last - line_start + 1;
1213                         d = d1 + linesize * line_start;
1214                         if (cw != 9) {
1215                             vga_draw_glyph8(d, linesize, 
1216                                             cursor_glyph, h, fgcol, bgcol);
1217                         } else {
1218                             vga_draw_glyph9(d, linesize, 
1219                                             cursor_glyph, h, fgcol, bgcol, 1);
1220                         }
1221                     }
1222                 }
1223             }
1224             d1 += x_incr;
1225             src += 4;
1226             ch_attr_ptr++;
1227         }
1228         if (cx_max != -1) {
1229             dpy_update(s->ds, cx_min * cw, cy * cheight, 
1230                        (cx_max - cx_min + 1) * cw, cheight);
1231         }
1232         dest += linesize * cheight;
1233         s1 += line_offset;
1234     }
1235 }
1236
1237 enum {
1238     VGA_DRAW_LINE2,
1239     VGA_DRAW_LINE2D2,
1240     VGA_DRAW_LINE4,
1241     VGA_DRAW_LINE4D2,
1242     VGA_DRAW_LINE8D2,
1243     VGA_DRAW_LINE8,
1244     VGA_DRAW_LINE15,
1245     VGA_DRAW_LINE16,
1246     VGA_DRAW_LINE24,
1247     VGA_DRAW_LINE32,
1248     VGA_DRAW_LINE_NB,
1249 };
1250
1251 static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1252     vga_draw_line2_8,
1253     vga_draw_line2_16,
1254     vga_draw_line2_16,
1255     vga_draw_line2_32,
1256
1257     vga_draw_line2d2_8,
1258     vga_draw_line2d2_16,
1259     vga_draw_line2d2_16,
1260     vga_draw_line2d2_32,
1261
1262     vga_draw_line4_8,
1263     vga_draw_line4_16,
1264     vga_draw_line4_16,
1265     vga_draw_line4_32,
1266
1267     vga_draw_line4d2_8,
1268     vga_draw_line4d2_16,
1269     vga_draw_line4d2_16,
1270     vga_draw_line4d2_32,
1271
1272     vga_draw_line8d2_8,
1273     vga_draw_line8d2_16,
1274     vga_draw_line8d2_16,
1275     vga_draw_line8d2_32,
1276
1277     vga_draw_line8_8,
1278     vga_draw_line8_16,
1279     vga_draw_line8_16,
1280     vga_draw_line8_32,
1281
1282     vga_draw_line15_8,
1283     vga_draw_line15_15,
1284     vga_draw_line15_16,
1285     vga_draw_line15_32,
1286
1287     vga_draw_line16_8,
1288     vga_draw_line16_15,
1289     vga_draw_line16_16,
1290     vga_draw_line16_32,
1291
1292     vga_draw_line24_8,
1293     vga_draw_line24_15,
1294     vga_draw_line24_16,
1295     vga_draw_line24_32,
1296
1297     vga_draw_line32_8,
1298     vga_draw_line32_15,
1299     vga_draw_line32_16,
1300     vga_draw_line32_32,
1301 };
1302
1303 static int vga_get_bpp(VGAState *s)
1304 {
1305     int ret;
1306 #ifdef CONFIG_BOCHS_VBE
1307     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1308         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1309     } else 
1310 #endif
1311     {
1312         ret = 0;
1313     }
1314     return ret;
1315 }
1316
1317 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1318 {
1319     int width, height;
1320     
1321     width = (s->cr[0x01] + 1) * 8;
1322     height = s->cr[0x12] | 
1323         ((s->cr[0x07] & 0x02) << 7) | 
1324         ((s->cr[0x07] & 0x40) << 3);
1325     height = (height + 1);
1326     *pwidth = width;
1327     *pheight = height;
1328 }
1329
1330 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1331 {
1332     int y;
1333     if (y1 >= VGA_MAX_HEIGHT)
1334         return;
1335     if (y2 >= VGA_MAX_HEIGHT)
1336         y2 = VGA_MAX_HEIGHT;
1337     for(y = y1; y < y2; y++) {
1338         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1339     }
1340 }
1341
1342 /* 
1343  * graphic modes
1344  */
1345 static void vga_draw_graphic(VGAState *s, int full_update)
1346 {
1347     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1348     int width, height, shift_control, line_offset, page0, page1, bwidth;
1349     int disp_width, multi_scan, multi_run;
1350     uint8_t *d;
1351     uint32_t v, addr1, addr;
1352     vga_draw_line_func *vga_draw_line;
1353     
1354     full_update |= update_basic_params(s);
1355
1356     s->get_resolution(s, &width, &height);
1357     disp_width = width;
1358
1359     shift_control = (s->gr[0x05] >> 5) & 3;
1360     double_scan = (s->cr[0x09] >> 7);
1361     if (shift_control != 1) {
1362         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1363     } else {
1364         /* in CGA modes, multi_scan is ignored */
1365         /* XXX: is it correct ? */
1366         multi_scan = double_scan;
1367     }
1368     multi_run = multi_scan;
1369     if (shift_control != s->shift_control ||
1370         double_scan != s->double_scan) {
1371         full_update = 1;
1372         s->shift_control = shift_control;
1373         s->double_scan = double_scan;
1374     }
1375     
1376     if (shift_control == 0) {
1377         full_update |= update_palette16(s);
1378         if (s->sr[0x01] & 8) {
1379             v = VGA_DRAW_LINE4D2;
1380             disp_width <<= 1;
1381         } else {
1382             v = VGA_DRAW_LINE4;
1383         }
1384     } else if (shift_control == 1) {
1385         full_update |= update_palette16(s);
1386         if (s->sr[0x01] & 8) {
1387             v = VGA_DRAW_LINE2D2;
1388             disp_width <<= 1;
1389         } else {
1390             v = VGA_DRAW_LINE2;
1391         }
1392     } else {
1393         switch(s->get_bpp(s)) {
1394         default:
1395         case 0:
1396             full_update |= update_palette256(s);
1397             v = VGA_DRAW_LINE8D2;
1398             break;
1399         case 8:
1400             full_update |= update_palette256(s);
1401             v = VGA_DRAW_LINE8;
1402             break;
1403         case 15:
1404             v = VGA_DRAW_LINE15;
1405             break;
1406         case 16:
1407             v = VGA_DRAW_LINE16;
1408             break;
1409         case 24:
1410             v = VGA_DRAW_LINE24;
1411             break;
1412         case 32:
1413             v = VGA_DRAW_LINE32;
1414             break;
1415         }
1416     }
1417     vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1418
1419     if (disp_width != s->last_width ||
1420         height != s->last_height) {
1421         dpy_resize(s->ds, disp_width, height);
1422         s->last_scr_width = disp_width;
1423         s->last_scr_height = height;
1424         s->last_width = disp_width;
1425         s->last_height = height;
1426         full_update = 1;
1427     }
1428     if (s->cursor_invalidate)
1429         s->cursor_invalidate(s);
1430     
1431     line_offset = s->line_offset;
1432 #if 0
1433     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",
1434            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1435 #endif
1436     addr1 = (s->start_addr * 4);
1437     bwidth = width * 4;
1438     y_start = -1;
1439     page_min = 0x7fffffff;
1440     page_max = -1;
1441     d = s->ds->data;
1442     linesize = s->ds->linesize;
1443     y1 = 0;
1444     for(y = 0; y < height; y++) {
1445         addr = addr1;
1446         if (!(s->cr[0x17] & 1)) {
1447             int shift;
1448             /* CGA compatibility handling */
1449             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1450             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1451         }
1452         if (!(s->cr[0x17] & 2)) {
1453             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1454         }
1455         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1456         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1457         update = full_update | 
1458             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1459             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1460         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1461             /* if wide line, can use another page */
1462             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE, 
1463                                                     VGA_DIRTY_FLAG);
1464         }
1465         /* explicit invalidation for the hardware cursor */
1466         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1467         if (update) {
1468             if (y_start < 0)
1469                 y_start = y;
1470             if (page0 < page_min)
1471                 page_min = page0;
1472             if (page1 > page_max)
1473                 page_max = page1;
1474             vga_draw_line(s, d, s->vram_ptr + addr, width);
1475             if (s->cursor_draw_line)
1476                 s->cursor_draw_line(s, d, y);
1477         } else {
1478             if (y_start >= 0) {
1479                 /* flush to display */
1480                 dpy_update(s->ds, 0, y_start, 
1481                            disp_width, y - y_start);
1482                 y_start = -1;
1483             }
1484         }
1485         if (!multi_run) {
1486             mask = (s->cr[0x17] & 3) ^ 3;
1487             if ((y1 & mask) == mask)
1488                 addr1 += line_offset;
1489             y1++;
1490             multi_run = multi_scan;
1491         } else {
1492             multi_run--;
1493         }
1494         /* line compare acts on the displayed lines */
1495         if (y == s->line_compare)
1496             addr1 = 0;
1497         d += linesize;
1498     }
1499     if (y_start >= 0) {
1500         /* flush to display */
1501         dpy_update(s->ds, 0, y_start, 
1502                    disp_width, y - y_start);
1503     }
1504     /* reset modified pages */
1505     if (page_max != -1) {
1506         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1507                                         VGA_DIRTY_FLAG);
1508     }
1509     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1510 }
1511
1512 static void vga_draw_blank(VGAState *s, int full_update)
1513 {
1514     int i, w, val;
1515     uint8_t *d;
1516
1517     if (!full_update)
1518         return;
1519     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1520         return;
1521     if (s->ds->depth == 8) 
1522         val = s->rgb_to_pixel(0, 0, 0);
1523     else
1524         val = 0;
1525     w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1526     d = s->ds->data;
1527     for(i = 0; i < s->last_scr_height; i++) {
1528         memset(d, val, w);
1529         d += s->ds->linesize;
1530     }
1531     dpy_update(s->ds, 0, 0, 
1532                s->last_scr_width, s->last_scr_height);
1533 }
1534
1535 #define GMODE_TEXT     0
1536 #define GMODE_GRAPH    1
1537 #define GMODE_BLANK 2 
1538
1539 void vga_update_display(void)
1540 {
1541     VGAState *s = vga_state;
1542     int full_update, graphic_mode;
1543
1544     if (s->ds->depth == 0) {
1545         /* nothing to do */
1546     } else {
1547         switch(s->ds->depth) {
1548         case 8:
1549             s->rgb_to_pixel = rgb_to_pixel8_dup;
1550             break;
1551         case 15:
1552             s->rgb_to_pixel = rgb_to_pixel15_dup;
1553             break;
1554         default:
1555         case 16:
1556             s->rgb_to_pixel = rgb_to_pixel16_dup;
1557             break;
1558         case 32:
1559             s->rgb_to_pixel = rgb_to_pixel32_dup;
1560             break;
1561         }
1562         
1563         full_update = 0;
1564         if (!(s->ar_index & 0x20)) {
1565             graphic_mode = GMODE_BLANK;
1566         } else {
1567             graphic_mode = s->gr[6] & 1;
1568         }
1569         if (graphic_mode != s->graphic_mode) {
1570             s->graphic_mode = graphic_mode;
1571             full_update = 1;
1572         }
1573         switch(graphic_mode) {
1574         case GMODE_TEXT:
1575             vga_draw_text(s, full_update);
1576             break;
1577         case GMODE_GRAPH:
1578             vga_draw_graphic(s, full_update);
1579             break;
1580         case GMODE_BLANK:
1581         default:
1582             vga_draw_blank(s, full_update);
1583             break;
1584         }
1585     }
1586 }
1587
1588 /* force a full display refresh */
1589 void vga_invalidate_display(void)
1590 {
1591     VGAState *s = vga_state;
1592     
1593     s->last_width = -1;
1594     s->last_height = -1;
1595 }
1596
1597 static void vga_reset(VGAState *s)
1598 {
1599     memset(s, 0, sizeof(VGAState));
1600 #ifdef CONFIG_S3VGA
1601     /* chip ID for 8c968 */
1602     s->cr[0x2d] = 0x88;
1603     s->cr[0x2e] = 0xb0;
1604     s->cr[0x2f] = 0x01; /* XXX: check revision code */
1605     s->cr[0x30] = 0xe1;
1606 #endif
1607     s->graphic_mode = -1; /* force full update */
1608 }
1609
1610 static CPUReadMemoryFunc *vga_mem_read[3] = {
1611     vga_mem_readb,
1612     vga_mem_readw,
1613     vga_mem_readl,
1614 };
1615
1616 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1617     vga_mem_writeb,
1618     vga_mem_writew,
1619     vga_mem_writel,
1620 };
1621
1622 static void vga_save(QEMUFile *f, void *opaque)
1623 {
1624     VGAState *s = opaque;
1625     int i;
1626
1627     qemu_put_be32s(f, &s->latch);
1628     qemu_put_8s(f, &s->sr_index);
1629     qemu_put_buffer(f, s->sr, 8);
1630     qemu_put_8s(f, &s->gr_index);
1631     qemu_put_buffer(f, s->gr, 16);
1632     qemu_put_8s(f, &s->ar_index);
1633     qemu_put_buffer(f, s->ar, 21);
1634     qemu_put_be32s(f, &s->ar_flip_flop);
1635     qemu_put_8s(f, &s->cr_index);
1636     qemu_put_buffer(f, s->cr, 256);
1637     qemu_put_8s(f, &s->msr);
1638     qemu_put_8s(f, &s->fcr);
1639     qemu_put_8s(f, &s->st00);
1640     qemu_put_8s(f, &s->st01);
1641
1642     qemu_put_8s(f, &s->dac_state);
1643     qemu_put_8s(f, &s->dac_sub_index);
1644     qemu_put_8s(f, &s->dac_read_index);
1645     qemu_put_8s(f, &s->dac_write_index);
1646     qemu_put_buffer(f, s->dac_cache, 3);
1647     qemu_put_buffer(f, s->palette, 768);
1648
1649     qemu_put_be32s(f, &s->bank_offset);
1650 #ifdef CONFIG_BOCHS_VBE
1651     qemu_put_byte(f, 1);
1652     qemu_put_be16s(f, &s->vbe_index);
1653     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1654         qemu_put_be16s(f, &s->vbe_regs[i]);
1655     qemu_put_be32s(f, &s->vbe_start_addr);
1656     qemu_put_be32s(f, &s->vbe_line_offset);
1657     qemu_put_be32s(f, &s->vbe_bank_mask);
1658 #else
1659     qemu_put_byte(f, 0);
1660 #endif
1661 }
1662
1663 static int vga_load(QEMUFile *f, void *opaque, int version_id)
1664 {
1665     VGAState *s = opaque;
1666     int is_vbe, i;
1667
1668     if (version_id != 1)
1669         return -EINVAL;
1670
1671     qemu_get_be32s(f, &s->latch);
1672     qemu_get_8s(f, &s->sr_index);
1673     qemu_get_buffer(f, s->sr, 8);
1674     qemu_get_8s(f, &s->gr_index);
1675     qemu_get_buffer(f, s->gr, 16);
1676     qemu_get_8s(f, &s->ar_index);
1677     qemu_get_buffer(f, s->ar, 21);
1678     qemu_get_be32s(f, &s->ar_flip_flop);
1679     qemu_get_8s(f, &s->cr_index);
1680     qemu_get_buffer(f, s->cr, 256);
1681     qemu_get_8s(f, &s->msr);
1682     qemu_get_8s(f, &s->fcr);
1683     qemu_get_8s(f, &s->st00);
1684     qemu_get_8s(f, &s->st01);
1685
1686     qemu_get_8s(f, &s->dac_state);
1687     qemu_get_8s(f, &s->dac_sub_index);
1688     qemu_get_8s(f, &s->dac_read_index);
1689     qemu_get_8s(f, &s->dac_write_index);
1690     qemu_get_buffer(f, s->dac_cache, 3);
1691     qemu_get_buffer(f, s->palette, 768);
1692
1693     qemu_get_be32s(f, &s->bank_offset);
1694     is_vbe = qemu_get_byte(f);
1695 #ifdef CONFIG_BOCHS_VBE
1696     if (!is_vbe)
1697         return -EINVAL;
1698     qemu_get_be16s(f, &s->vbe_index);
1699     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1700         qemu_get_be16s(f, &s->vbe_regs[i]);
1701     qemu_get_be32s(f, &s->vbe_start_addr);
1702     qemu_get_be32s(f, &s->vbe_line_offset);
1703     qemu_get_be32s(f, &s->vbe_bank_mask);
1704 #else
1705     if (is_vbe)
1706         return -EINVAL;
1707 #endif
1708
1709     /* force refresh */
1710     s->graphic_mode = -1;
1711     return 0;
1712 }
1713
1714 static void vga_map(PCIDevice *pci_dev, int region_num, 
1715                     uint32_t addr, uint32_t size, int type)
1716 {
1717     VGAState *s = vga_state;
1718
1719     cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1720 }
1721
1722 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1723                      unsigned long vga_ram_offset, int vga_ram_size)
1724 {
1725     int i, j, v, b;
1726
1727     for(i = 0;i < 256; i++) {
1728         v = 0;
1729         for(j = 0; j < 8; j++) {
1730             v |= ((i >> j) & 1) << (j * 4);
1731         }
1732         expand4[i] = v;
1733
1734         v = 0;
1735         for(j = 0; j < 4; j++) {
1736             v |= ((i >> (2 * j)) & 3) << (j * 4);
1737         }
1738         expand2[i] = v;
1739     }
1740     for(i = 0; i < 16; i++) {
1741         v = 0;
1742         for(j = 0; j < 4; j++) {
1743             b = ((i >> j) & 1);
1744             v |= b << (2 * j);
1745             v |= b << (2 * j + 1);
1746         }
1747         expand4to8[i] = v;
1748     }
1749
1750     vga_reset(s);
1751
1752     s->vram_ptr = vga_ram_base;
1753     s->vram_offset = vga_ram_offset;
1754     s->vram_size = vga_ram_size;
1755     s->ds = ds;
1756     s->get_bpp = vga_get_bpp;
1757     s->get_offsets = vga_get_offsets;
1758     s->get_resolution = vga_get_resolution;
1759     /* XXX: currently needed for display */
1760     vga_state = s;
1761 }
1762
1763
1764 int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1765                    unsigned long vga_ram_offset, int vga_ram_size)
1766 {
1767     VGAState *s;
1768
1769     s = qemu_mallocz(sizeof(VGAState));
1770     if (!s)
1771         return -1;
1772
1773     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1774
1775     register_savevm("vga", 0, 1, vga_save, vga_load, s);
1776
1777     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1778
1779     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1780     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1781     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1782     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1783
1784     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1785
1786     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1787     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1788     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1789     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1790     s->bank_offset = 0;
1791
1792 #ifdef CONFIG_BOCHS_VBE
1793     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1794     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1795 #if defined (TARGET_I386)
1796     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1797     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1798
1799     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1800     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1801
1802     /* old Bochs IO ports */
1803     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1804     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1805
1806     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1807     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1808 #else
1809     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1810     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1811
1812     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1813     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1814 #endif
1815 #endif /* CONFIG_BOCHS_VBE */
1816
1817     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1818     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1819                                  vga_io_memory);
1820
1821     if (bus) {
1822         PCIDevice *d;
1823         uint8_t *pci_conf;
1824
1825         d = pci_register_device(bus, "VGA", 
1826                                 sizeof(PCIDevice),
1827                                 -1, NULL, NULL);
1828         pci_conf = d->config;
1829         pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1830         pci_conf[0x01] = 0x12;
1831         pci_conf[0x02] = 0x11;
1832         pci_conf[0x03] = 0x11;
1833         pci_conf[0x0a] = 0x00; // VGA controller 
1834         pci_conf[0x0b] = 0x03;
1835         pci_conf[0x0e] = 0x00; // header_type
1836
1837         /* XXX: vga_ram_size must be a power of two */
1838         pci_register_io_region(d, 0, vga_ram_size, 
1839                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1840     } else {
1841 #ifdef CONFIG_BOCHS_VBE
1842         /* XXX: use optimized standard vga accesses */
1843         cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1844                                      vga_ram_size, vga_ram_offset);
1845 #endif
1846     }
1847     return 0;
1848 }
1849
1850 /********************************************************/
1851 /* vga screen dump */
1852
1853 static int vga_save_w, vga_save_h;
1854
1855 static void vga_save_dpy_update(DisplayState *s, 
1856                                 int x, int y, int w, int h)
1857 {
1858 }
1859
1860 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1861 {
1862     s->linesize = w * 4;
1863     s->data = qemu_malloc(h * s->linesize);
1864     vga_save_w = w;
1865     vga_save_h = h;
1866 }
1867
1868 static void vga_save_dpy_refresh(DisplayState *s)
1869 {
1870 }
1871
1872 static int ppm_save(const char *filename, uint8_t *data, 
1873                     int w, int h, int linesize)
1874 {
1875     FILE *f;
1876     uint8_t *d, *d1;
1877     unsigned int v;
1878     int y, x;
1879
1880     f = fopen(filename, "wb");
1881     if (!f)
1882         return -1;
1883     fprintf(f, "P6\n%d %d\n%d\n",
1884             w, h, 255);
1885     d1 = data;
1886     for(y = 0; y < h; y++) {
1887         d = d1;
1888         for(x = 0; x < w; x++) {
1889             v = *(uint32_t *)d;
1890             fputc((v >> 16) & 0xff, f);
1891             fputc((v >> 8) & 0xff, f);
1892             fputc((v) & 0xff, f);
1893             d += 4;
1894         }
1895         d1 += linesize;
1896     }
1897     fclose(f);
1898     return 0;
1899 }
1900
1901 /* save the vga display in a PPM image even if no display is
1902    available */
1903 void vga_screen_dump(const char *filename)
1904 {
1905     VGAState *s = vga_state;
1906     DisplayState *saved_ds, ds1, *ds = &ds1;
1907     
1908     /* XXX: this is a little hackish */
1909     vga_invalidate_display();
1910     saved_ds = s->ds;
1911
1912     memset(ds, 0, sizeof(DisplayState));
1913     ds->dpy_update = vga_save_dpy_update;
1914     ds->dpy_resize = vga_save_dpy_resize;
1915     ds->dpy_refresh = vga_save_dpy_refresh;
1916     ds->depth = 32;
1917
1918     s->ds = ds;
1919     s->graphic_mode = -1;
1920     vga_update_display();
1921     
1922     if (ds->data) {
1923         ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1924                  s->ds->linesize);
1925         qemu_free(ds->data);
1926     }
1927     s->ds = saved_ds;
1928 }