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