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