Don't use "hz" in identifiers to make AIX happy.
[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 "hw.h"
25 #include "console.h"
26 #include "pc.h"
27 #include "pci.h"
28 #include "vga_int.h"
29 #include "pixel_ops.h"
30 #include "qemu-timer.h"
31
32 //#define DEBUG_VGA
33 //#define DEBUG_VGA_MEM
34 //#define DEBUG_VGA_REG
35
36 //#define DEBUG_BOCHS_VBE
37
38 /* force some bits to zero */
39 const uint8_t sr_mask[8] = {
40     (uint8_t)~0xfc,
41     (uint8_t)~0xc2,
42     (uint8_t)~0xf0,
43     (uint8_t)~0xc0,
44     (uint8_t)~0xf1,
45     (uint8_t)~0xff,
46     (uint8_t)~0xff,
47     (uint8_t)~0x00,
48 };
49
50 const uint8_t gr_mask[16] = {
51     (uint8_t)~0xf0, /* 0x00 */
52     (uint8_t)~0xf0, /* 0x01 */
53     (uint8_t)~0xf0, /* 0x02 */
54     (uint8_t)~0xe0, /* 0x03 */
55     (uint8_t)~0xfc, /* 0x04 */
56     (uint8_t)~0x84, /* 0x05 */
57     (uint8_t)~0xf0, /* 0x06 */
58     (uint8_t)~0xf0, /* 0x07 */
59     (uint8_t)~0x00, /* 0x08 */
60     (uint8_t)~0xff, /* 0x09 */
61     (uint8_t)~0xff, /* 0x0a */
62     (uint8_t)~0xff, /* 0x0b */
63     (uint8_t)~0xff, /* 0x0c */
64     (uint8_t)~0xff, /* 0x0d */
65     (uint8_t)~0xff, /* 0x0e */
66     (uint8_t)~0xff, /* 0x0f */
67 };
68
69 #define cbswap_32(__x) \
70 ((uint32_t)( \
71                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
72                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
73                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
74                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
75
76 #ifdef WORDS_BIGENDIAN
77 #define PAT(x) cbswap_32(x)
78 #else
79 #define PAT(x) (x)
80 #endif
81
82 #ifdef WORDS_BIGENDIAN
83 #define BIG 1
84 #else
85 #define BIG 0
86 #endif
87
88 #ifdef WORDS_BIGENDIAN
89 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
90 #else
91 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
92 #endif
93
94 static const uint32_t mask16[16] = {
95     PAT(0x00000000),
96     PAT(0x000000ff),
97     PAT(0x0000ff00),
98     PAT(0x0000ffff),
99     PAT(0x00ff0000),
100     PAT(0x00ff00ff),
101     PAT(0x00ffff00),
102     PAT(0x00ffffff),
103     PAT(0xff000000),
104     PAT(0xff0000ff),
105     PAT(0xff00ff00),
106     PAT(0xff00ffff),
107     PAT(0xffff0000),
108     PAT(0xffff00ff),
109     PAT(0xffffff00),
110     PAT(0xffffffff),
111 };
112
113 #undef PAT
114
115 #ifdef WORDS_BIGENDIAN
116 #define PAT(x) (x)
117 #else
118 #define PAT(x) cbswap_32(x)
119 #endif
120
121 static const uint32_t dmask16[16] = {
122     PAT(0x00000000),
123     PAT(0x000000ff),
124     PAT(0x0000ff00),
125     PAT(0x0000ffff),
126     PAT(0x00ff0000),
127     PAT(0x00ff00ff),
128     PAT(0x00ffff00),
129     PAT(0x00ffffff),
130     PAT(0xff000000),
131     PAT(0xff0000ff),
132     PAT(0xff00ff00),
133     PAT(0xff00ffff),
134     PAT(0xffff0000),
135     PAT(0xffff00ff),
136     PAT(0xffffff00),
137     PAT(0xffffffff),
138 };
139
140 static const uint32_t dmask4[4] = {
141     PAT(0x00000000),
142     PAT(0x0000ffff),
143     PAT(0xffff0000),
144     PAT(0xffffffff),
145 };
146
147 static uint32_t expand4[256];
148 static uint16_t expand2[256];
149 static uint8_t expand4to8[16];
150
151 static void vga_screen_dump(void *opaque, const char *filename);
152
153 static void vga_dumb_update_retrace_info(VGAState *s)
154 {
155     (void) s;
156 }
157
158 static void vga_precise_update_retrace_info(VGAState *s)
159 {
160     int htotal_chars;
161     int hretr_start_char;
162     int hretr_skew_chars;
163     int hretr_end_char;
164
165     int vtotal_lines;
166     int vretr_start_line;
167     int vretr_end_line;
168
169     int div2, sldiv2, dots;
170     int clocking_mode;
171     int clock_sel;
172     const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
173     int64_t chars_per_sec;
174     struct vga_precise_retrace *r = &s->retrace_info.precise;
175
176     htotal_chars = s->cr[0x00] + 5;
177     hretr_start_char = s->cr[0x04];
178     hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
179     hretr_end_char = s->cr[0x05] & 0x1f;
180
181     vtotal_lines = (s->cr[0x06]
182                     | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
183         ;
184     vretr_start_line = s->cr[0x10]
185         | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
186         ;
187     vretr_end_line = s->cr[0x11] & 0xf;
188
189
190     div2 = (s->cr[0x17] >> 2) & 1;
191     sldiv2 = (s->cr[0x17] >> 3) & 1;
192
193     clocking_mode = (s->sr[0x01] >> 3) & 1;
194     clock_sel = (s->msr >> 2) & 3;
195     dots = (s->msr & 1) ? 8 : 9;
196
197     chars_per_sec = clk_hz[clock_sel] / dots;
198
199     htotal_chars <<= clocking_mode;
200
201     r->total_chars = vtotal_lines * htotal_chars;
202     if (r->freq) {
203         r->ticks_per_char = ticks_per_sec / (r->total_chars * r->freq);
204     } else {
205         r->ticks_per_char = ticks_per_sec / chars_per_sec;
206     }
207
208     r->vstart = vretr_start_line;
209     r->vend = r->vstart + vretr_end_line + 1;
210
211     r->hstart = hretr_start_char + hretr_skew_chars;
212     r->hend = r->hstart + hretr_end_char + 1;
213     r->htotal = htotal_chars;
214
215 #if 0
216     printf (
217         "hz=%f\n"
218         "htotal = %d\n"
219         "hretr_start = %d\n"
220         "hretr_skew = %d\n"
221         "hretr_end = %d\n"
222         "vtotal = %d\n"
223         "vretr_start = %d\n"
224         "vretr_end = %d\n"
225         "div2 = %d sldiv2 = %d\n"
226         "clocking_mode = %d\n"
227         "clock_sel = %d %d\n"
228         "dots = %d\n"
229         "ticks/char = %lld\n"
230         "\n",
231         (double) ticks_per_sec / (r->ticks_per_char * r->total_chars),
232         htotal_chars,
233         hretr_start_char,
234         hretr_skew_chars,
235         hretr_end_char,
236         vtotal_lines,
237         vretr_start_line,
238         vretr_end_line,
239         div2, sldiv2,
240         clocking_mode,
241         clock_sel,
242         clk_hz[clock_sel],
243         dots,
244         r->ticks_per_char
245         );
246 #endif
247 }
248
249 static uint8_t vga_precise_retrace(VGAState *s)
250 {
251     struct vga_precise_retrace *r = &s->retrace_info.precise;
252     uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
253
254     if (r->total_chars) {
255         int cur_line, cur_line_char, cur_char;
256         int64_t cur_tick;
257
258         cur_tick = qemu_get_clock(vm_clock);
259
260         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
261         cur_line = cur_char / r->htotal;
262
263         if (cur_line >= r->vstart && cur_line <= r->vend) {
264             val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
265         } else {
266             cur_line_char = cur_char % r->htotal;
267             if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
268                 val |= ST01_DISP_ENABLE;
269             }
270         }
271
272         return val;
273     } else {
274         return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
275     }
276 }
277
278 static uint8_t vga_dumb_retrace(VGAState *s)
279 {
280     return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
281 }
282
283 static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
284 {
285     VGAState *s = opaque;
286     int val, index;
287
288     /* check port range access depending on color/monochrome mode */
289     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
290         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
291         val = 0xff;
292     } else {
293         switch(addr) {
294         case 0x3c0:
295             if (s->ar_flip_flop == 0) {
296                 val = s->ar_index;
297             } else {
298                 val = 0;
299             }
300             break;
301         case 0x3c1:
302             index = s->ar_index & 0x1f;
303             if (index < 21)
304                 val = s->ar[index];
305             else
306                 val = 0;
307             break;
308         case 0x3c2:
309             val = s->st00;
310             break;
311         case 0x3c4:
312             val = s->sr_index;
313             break;
314         case 0x3c5:
315             val = s->sr[s->sr_index];
316 #ifdef DEBUG_VGA_REG
317             printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
318 #endif
319             break;
320         case 0x3c7:
321             val = s->dac_state;
322             break;
323         case 0x3c8:
324             val = s->dac_write_index;
325             break;
326         case 0x3c9:
327             val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
328             if (++s->dac_sub_index == 3) {
329                 s->dac_sub_index = 0;
330                 s->dac_read_index++;
331             }
332             break;
333         case 0x3ca:
334             val = s->fcr;
335             break;
336         case 0x3cc:
337             val = s->msr;
338             break;
339         case 0x3ce:
340             val = s->gr_index;
341             break;
342         case 0x3cf:
343             val = s->gr[s->gr_index];
344 #ifdef DEBUG_VGA_REG
345             printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
346 #endif
347             break;
348         case 0x3b4:
349         case 0x3d4:
350             val = s->cr_index;
351             break;
352         case 0x3b5:
353         case 0x3d5:
354             val = s->cr[s->cr_index];
355 #ifdef DEBUG_VGA_REG
356             printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
357 #endif
358             break;
359         case 0x3ba:
360         case 0x3da:
361             /* just toggle to fool polling */
362             val = s->st01 = s->retrace(s);
363             s->ar_flip_flop = 0;
364             break;
365         default:
366             val = 0x00;
367             break;
368         }
369     }
370 #if defined(DEBUG_VGA)
371     printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
372 #endif
373     return val;
374 }
375
376 static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
377 {
378     VGAState *s = opaque;
379     int index;
380
381     /* check port range access depending on color/monochrome mode */
382     if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
383         (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
384         return;
385
386 #ifdef DEBUG_VGA
387     printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
388 #endif
389
390     switch(addr) {
391     case 0x3c0:
392         if (s->ar_flip_flop == 0) {
393             val &= 0x3f;
394             s->ar_index = val;
395         } else {
396             index = s->ar_index & 0x1f;
397             switch(index) {
398             case 0x00 ... 0x0f:
399                 s->ar[index] = val & 0x3f;
400                 break;
401             case 0x10:
402                 s->ar[index] = val & ~0x10;
403                 break;
404             case 0x11:
405                 s->ar[index] = val;
406                 break;
407             case 0x12:
408                 s->ar[index] = val & ~0xc0;
409                 break;
410             case 0x13:
411                 s->ar[index] = val & ~0xf0;
412                 break;
413             case 0x14:
414                 s->ar[index] = val & ~0xf0;
415                 break;
416             default:
417                 break;
418             }
419         }
420         s->ar_flip_flop ^= 1;
421         break;
422     case 0x3c2:
423         s->msr = val & ~0x10;
424         s->update_retrace_info(s);
425         break;
426     case 0x3c4:
427         s->sr_index = val & 7;
428         break;
429     case 0x3c5:
430 #ifdef DEBUG_VGA_REG
431         printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
432 #endif
433         s->sr[s->sr_index] = val & sr_mask[s->sr_index];
434         if (s->sr_index == 1) s->update_retrace_info(s);
435         break;
436     case 0x3c7:
437         s->dac_read_index = val;
438         s->dac_sub_index = 0;
439         s->dac_state = 3;
440         break;
441     case 0x3c8:
442         s->dac_write_index = val;
443         s->dac_sub_index = 0;
444         s->dac_state = 0;
445         break;
446     case 0x3c9:
447         s->dac_cache[s->dac_sub_index] = val;
448         if (++s->dac_sub_index == 3) {
449             memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
450             s->dac_sub_index = 0;
451             s->dac_write_index++;
452         }
453         break;
454     case 0x3ce:
455         s->gr_index = val & 0x0f;
456         break;
457     case 0x3cf:
458 #ifdef DEBUG_VGA_REG
459         printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
460 #endif
461         s->gr[s->gr_index] = val & gr_mask[s->gr_index];
462         break;
463     case 0x3b4:
464     case 0x3d4:
465         s->cr_index = val;
466         break;
467     case 0x3b5:
468     case 0x3d5:
469 #ifdef DEBUG_VGA_REG
470         printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
471 #endif
472         /* handle CR0-7 protection */
473         if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
474             /* can always write bit 4 of CR7 */
475             if (s->cr_index == 7)
476                 s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
477             return;
478         }
479         switch(s->cr_index) {
480         case 0x01: /* horizontal display end */
481         case 0x07:
482         case 0x09:
483         case 0x0c:
484         case 0x0d:
485         case 0x12: /* vertical display end */
486             s->cr[s->cr_index] = val;
487             break;
488         default:
489             s->cr[s->cr_index] = val;
490             break;
491         }
492
493         switch(s->cr_index) {
494         case 0x00:
495         case 0x04:
496         case 0x05:
497         case 0x06:
498         case 0x07:
499         case 0x11:
500         case 0x17:
501             s->update_retrace_info(s);
502             break;
503         }
504         break;
505     case 0x3ba:
506     case 0x3da:
507         s->fcr = val & 0x10;
508         break;
509     }
510 }
511
512 #ifdef CONFIG_BOCHS_VBE
513 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
514 {
515     VGAState *s = opaque;
516     uint32_t val;
517     val = s->vbe_index;
518     return val;
519 }
520
521 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
522 {
523     VGAState *s = opaque;
524     uint32_t val;
525
526     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
527         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
528             switch(s->vbe_index) {
529                 /* XXX: do not hardcode ? */
530             case VBE_DISPI_INDEX_XRES:
531                 val = VBE_DISPI_MAX_XRES;
532                 break;
533             case VBE_DISPI_INDEX_YRES:
534                 val = VBE_DISPI_MAX_YRES;
535                 break;
536             case VBE_DISPI_INDEX_BPP:
537                 val = VBE_DISPI_MAX_BPP;
538                 break;
539             default:
540                 val = s->vbe_regs[s->vbe_index];
541                 break;
542             }
543         } else {
544             val = s->vbe_regs[s->vbe_index];
545         }
546     } else {
547         val = 0;
548     }
549 #ifdef DEBUG_BOCHS_VBE
550     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
551 #endif
552     return val;
553 }
554
555 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
556 {
557     VGAState *s = opaque;
558     s->vbe_index = val;
559 }
560
561 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
562 {
563     VGAState *s = opaque;
564
565     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
566 #ifdef DEBUG_BOCHS_VBE
567         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
568 #endif
569         switch(s->vbe_index) {
570         case VBE_DISPI_INDEX_ID:
571             if (val == VBE_DISPI_ID0 ||
572                 val == VBE_DISPI_ID1 ||
573                 val == VBE_DISPI_ID2 ||
574                 val == VBE_DISPI_ID3 ||
575                 val == VBE_DISPI_ID4) {
576                 s->vbe_regs[s->vbe_index] = val;
577             }
578             break;
579         case VBE_DISPI_INDEX_XRES:
580             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
581                 s->vbe_regs[s->vbe_index] = val;
582             }
583             break;
584         case VBE_DISPI_INDEX_YRES:
585             if (val <= VBE_DISPI_MAX_YRES) {
586                 s->vbe_regs[s->vbe_index] = val;
587             }
588             break;
589         case VBE_DISPI_INDEX_BPP:
590             if (val == 0)
591                 val = 8;
592             if (val == 4 || val == 8 || val == 15 ||
593                 val == 16 || val == 24 || val == 32) {
594                 s->vbe_regs[s->vbe_index] = val;
595             }
596             break;
597         case VBE_DISPI_INDEX_BANK:
598             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
599               val &= (s->vbe_bank_mask >> 2);
600             } else {
601               val &= s->vbe_bank_mask;
602             }
603             s->vbe_regs[s->vbe_index] = val;
604             s->bank_offset = (val << 16);
605             break;
606         case VBE_DISPI_INDEX_ENABLE:
607             if ((val & VBE_DISPI_ENABLED) &&
608                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
609                 int h, shift_control;
610
611                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
612                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
613                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
614                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
615                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
616                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
617
618                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
619                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
620                 else
621                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
622                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
623                 s->vbe_start_addr = 0;
624
625                 /* clear the screen (should be done in BIOS) */
626                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
627                     memset(s->vram_ptr, 0,
628                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
629                 }
630
631                 /* we initialize the VGA graphic mode (should be done
632                    in BIOS) */
633                 s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
634                 s->cr[0x17] |= 3; /* no CGA modes */
635                 s->cr[0x13] = s->vbe_line_offset >> 3;
636                 /* width */
637                 s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
638                 /* height (only meaningful if < 1024) */
639                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
640                 s->cr[0x12] = h;
641                 s->cr[0x07] = (s->cr[0x07] & ~0x42) |
642                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
643                 /* line compare to 1023 */
644                 s->cr[0x18] = 0xff;
645                 s->cr[0x07] |= 0x10;
646                 s->cr[0x09] |= 0x40;
647
648                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
649                     shift_control = 0;
650                     s->sr[0x01] &= ~8; /* no double line */
651                 } else {
652                     shift_control = 2;
653                     s->sr[4] |= 0x08; /* set chain 4 mode */
654                     s->sr[2] |= 0x0f; /* activate all planes */
655                 }
656                 s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
657                 s->cr[0x09] &= ~0x9f; /* no double scan */
658             } else {
659                 /* XXX: the bios should do that */
660                 s->bank_offset = 0;
661             }
662             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
663             s->vbe_regs[s->vbe_index] = val;
664             break;
665         case VBE_DISPI_INDEX_VIRT_WIDTH:
666             {
667                 int w, h, line_offset;
668
669                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
670                     return;
671                 w = val;
672                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
673                     line_offset = w >> 1;
674                 else
675                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
676                 h = s->vram_size / line_offset;
677                 /* XXX: support weird bochs semantics ? */
678                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
679                     return;
680                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
681                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
682                 s->vbe_line_offset = line_offset;
683             }
684             break;
685         case VBE_DISPI_INDEX_X_OFFSET:
686         case VBE_DISPI_INDEX_Y_OFFSET:
687             {
688                 int x;
689                 s->vbe_regs[s->vbe_index] = val;
690                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
691                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
692                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
693                     s->vbe_start_addr += x >> 1;
694                 else
695                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
696                 s->vbe_start_addr >>= 2;
697             }
698             break;
699         default:
700             break;
701         }
702     }
703 }
704 #endif
705
706 /* called for accesses between 0xa0000 and 0xc0000 */
707 uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
708 {
709     VGAState *s = opaque;
710     int memory_map_mode, plane;
711     uint32_t ret;
712
713     /* convert to VGA memory offset */
714     memory_map_mode = (s->gr[6] >> 2) & 3;
715     addr &= 0x1ffff;
716     switch(memory_map_mode) {
717     case 0:
718         break;
719     case 1:
720         if (addr >= 0x10000)
721             return 0xff;
722         addr += s->bank_offset;
723         break;
724     case 2:
725         addr -= 0x10000;
726         if (addr >= 0x8000)
727             return 0xff;
728         break;
729     default:
730     case 3:
731         addr -= 0x18000;
732         if (addr >= 0x8000)
733             return 0xff;
734         break;
735     }
736
737     if (s->sr[4] & 0x08) {
738         /* chain 4 mode : simplest access */
739         ret = s->vram_ptr[addr];
740     } else if (s->gr[5] & 0x10) {
741         /* odd/even mode (aka text mode mapping) */
742         plane = (s->gr[4] & 2) | (addr & 1);
743         ret = s->vram_ptr[((addr & ~1) << 1) | plane];
744     } else {
745         /* standard VGA latched access */
746         s->latch = ((uint32_t *)s->vram_ptr)[addr];
747
748         if (!(s->gr[5] & 0x08)) {
749             /* read mode 0 */
750             plane = s->gr[4];
751             ret = GET_PLANE(s->latch, plane);
752         } else {
753             /* read mode 1 */
754             ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
755             ret |= ret >> 16;
756             ret |= ret >> 8;
757             ret = (~ret) & 0xff;
758         }
759     }
760     return ret;
761 }
762
763 static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
764 {
765     uint32_t v;
766 #ifdef TARGET_WORDS_BIGENDIAN
767     v = vga_mem_readb(opaque, addr) << 8;
768     v |= vga_mem_readb(opaque, addr + 1);
769 #else
770     v = vga_mem_readb(opaque, addr);
771     v |= vga_mem_readb(opaque, addr + 1) << 8;
772 #endif
773     return v;
774 }
775
776 static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
777 {
778     uint32_t v;
779 #ifdef TARGET_WORDS_BIGENDIAN
780     v = vga_mem_readb(opaque, addr) << 24;
781     v |= vga_mem_readb(opaque, addr + 1) << 16;
782     v |= vga_mem_readb(opaque, addr + 2) << 8;
783     v |= vga_mem_readb(opaque, addr + 3);
784 #else
785     v = vga_mem_readb(opaque, addr);
786     v |= vga_mem_readb(opaque, addr + 1) << 8;
787     v |= vga_mem_readb(opaque, addr + 2) << 16;
788     v |= vga_mem_readb(opaque, addr + 3) << 24;
789 #endif
790     return v;
791 }
792
793 /* called for accesses between 0xa0000 and 0xc0000 */
794 void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
795 {
796     VGAState *s = opaque;
797     int memory_map_mode, plane, write_mode, b, func_select, mask;
798     uint32_t write_mask, bit_mask, set_mask;
799
800 #ifdef DEBUG_VGA_MEM
801     printf("vga: [0x%x] = 0x%02x\n", addr, val);
802 #endif
803     /* convert to VGA memory offset */
804     memory_map_mode = (s->gr[6] >> 2) & 3;
805     addr &= 0x1ffff;
806     switch(memory_map_mode) {
807     case 0:
808         break;
809     case 1:
810         if (addr >= 0x10000)
811             return;
812         addr += s->bank_offset;
813         break;
814     case 2:
815         addr -= 0x10000;
816         if (addr >= 0x8000)
817             return;
818         break;
819     default:
820     case 3:
821         addr -= 0x18000;
822         if (addr >= 0x8000)
823             return;
824         break;
825     }
826
827     if (s->sr[4] & 0x08) {
828         /* chain 4 mode : simplest access */
829         plane = addr & 3;
830         mask = (1 << plane);
831         if (s->sr[2] & mask) {
832             s->vram_ptr[addr] = val;
833 #ifdef DEBUG_VGA_MEM
834             printf("vga: chain4: [0x%x]\n", addr);
835 #endif
836             s->plane_updated |= mask; /* only used to detect font change */
837             cpu_physical_memory_set_dirty(s->vram_offset + addr);
838         }
839     } else if (s->gr[5] & 0x10) {
840         /* odd/even mode (aka text mode mapping) */
841         plane = (s->gr[4] & 2) | (addr & 1);
842         mask = (1 << plane);
843         if (s->sr[2] & mask) {
844             addr = ((addr & ~1) << 1) | plane;
845             s->vram_ptr[addr] = val;
846 #ifdef DEBUG_VGA_MEM
847             printf("vga: odd/even: [0x%x]\n", addr);
848 #endif
849             s->plane_updated |= mask; /* only used to detect font change */
850             cpu_physical_memory_set_dirty(s->vram_offset + addr);
851         }
852     } else {
853         /* standard VGA latched access */
854         write_mode = s->gr[5] & 3;
855         switch(write_mode) {
856         default:
857         case 0:
858             /* rotate */
859             b = s->gr[3] & 7;
860             val = ((val >> b) | (val << (8 - b))) & 0xff;
861             val |= val << 8;
862             val |= val << 16;
863
864             /* apply set/reset mask */
865             set_mask = mask16[s->gr[1]];
866             val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
867             bit_mask = s->gr[8];
868             break;
869         case 1:
870             val = s->latch;
871             goto do_write;
872         case 2:
873             val = mask16[val & 0x0f];
874             bit_mask = s->gr[8];
875             break;
876         case 3:
877             /* rotate */
878             b = s->gr[3] & 7;
879             val = (val >> b) | (val << (8 - b));
880
881             bit_mask = s->gr[8] & val;
882             val = mask16[s->gr[0]];
883             break;
884         }
885
886         /* apply logical operation */
887         func_select = s->gr[3] >> 3;
888         switch(func_select) {
889         case 0:
890         default:
891             /* nothing to do */
892             break;
893         case 1:
894             /* and */
895             val &= s->latch;
896             break;
897         case 2:
898             /* or */
899             val |= s->latch;
900             break;
901         case 3:
902             /* xor */
903             val ^= s->latch;
904             break;
905         }
906
907         /* apply bit mask */
908         bit_mask |= bit_mask << 8;
909         bit_mask |= bit_mask << 16;
910         val = (val & bit_mask) | (s->latch & ~bit_mask);
911
912     do_write:
913         /* mask data according to sr[2] */
914         mask = s->sr[2];
915         s->plane_updated |= mask; /* only used to detect font change */
916         write_mask = mask16[mask];
917         ((uint32_t *)s->vram_ptr)[addr] =
918             (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
919             (val & write_mask);
920 #ifdef DEBUG_VGA_MEM
921             printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
922                    addr * 4, write_mask, val);
923 #endif
924             cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
925     }
926 }
927
928 static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
929 {
930 #ifdef TARGET_WORDS_BIGENDIAN
931     vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
932     vga_mem_writeb(opaque, addr + 1, val & 0xff);
933 #else
934     vga_mem_writeb(opaque, addr, val & 0xff);
935     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
936 #endif
937 }
938
939 static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
940 {
941 #ifdef TARGET_WORDS_BIGENDIAN
942     vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
943     vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
944     vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
945     vga_mem_writeb(opaque, addr + 3, val & 0xff);
946 #else
947     vga_mem_writeb(opaque, addr, val & 0xff);
948     vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
949     vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
950     vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
951 #endif
952 }
953
954 typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
955                              const uint8_t *font_ptr, int h,
956                              uint32_t fgcol, uint32_t bgcol);
957 typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
958                                   const uint8_t *font_ptr, int h,
959                                   uint32_t fgcol, uint32_t bgcol, int dup9);
960 typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
961                                 const uint8_t *s, int width);
962
963 #define DEPTH 8
964 #include "vga_template.h"
965
966 #define DEPTH 15
967 #include "vga_template.h"
968
969 #define BGR_FORMAT
970 #define DEPTH 15
971 #include "vga_template.h"
972
973 #define DEPTH 16
974 #include "vga_template.h"
975
976 #define BGR_FORMAT
977 #define DEPTH 16
978 #include "vga_template.h"
979
980 #define DEPTH 32
981 #include "vga_template.h"
982
983 #define BGR_FORMAT
984 #define DEPTH 32
985 #include "vga_template.h"
986
987 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
988 {
989     unsigned int col;
990     col = rgb_to_pixel8(r, g, b);
991     col |= col << 8;
992     col |= col << 16;
993     return col;
994 }
995
996 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
997 {
998     unsigned int col;
999     col = rgb_to_pixel15(r, g, b);
1000     col |= col << 16;
1001     return col;
1002 }
1003
1004 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1005                                           unsigned int b)
1006 {
1007     unsigned int col;
1008     col = rgb_to_pixel15bgr(r, g, b);
1009     col |= col << 16;
1010     return col;
1011 }
1012
1013 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1014 {
1015     unsigned int col;
1016     col = rgb_to_pixel16(r, g, b);
1017     col |= col << 16;
1018     return col;
1019 }
1020
1021 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1022                                           unsigned int b)
1023 {
1024     unsigned int col;
1025     col = rgb_to_pixel16bgr(r, g, b);
1026     col |= col << 16;
1027     return col;
1028 }
1029
1030 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1031 {
1032     unsigned int col;
1033     col = rgb_to_pixel32(r, g, b);
1034     return col;
1035 }
1036
1037 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1038 {
1039     unsigned int col;
1040     col = rgb_to_pixel32bgr(r, g, b);
1041     return col;
1042 }
1043
1044 /* return true if the palette was modified */
1045 static int update_palette16(VGAState *s)
1046 {
1047     int full_update, i;
1048     uint32_t v, col, *palette;
1049
1050     full_update = 0;
1051     palette = s->last_palette;
1052     for(i = 0; i < 16; i++) {
1053         v = s->ar[i];
1054         if (s->ar[0x10] & 0x80)
1055             v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1056         else
1057             v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1058         v = v * 3;
1059         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1060                               c6_to_8(s->palette[v + 1]),
1061                               c6_to_8(s->palette[v + 2]));
1062         if (col != palette[i]) {
1063             full_update = 1;
1064             palette[i] = col;
1065         }
1066     }
1067     return full_update;
1068 }
1069
1070 /* return true if the palette was modified */
1071 static int update_palette256(VGAState *s)
1072 {
1073     int full_update, i;
1074     uint32_t v, col, *palette;
1075
1076     full_update = 0;
1077     palette = s->last_palette;
1078     v = 0;
1079     for(i = 0; i < 256; i++) {
1080         if (s->dac_8bit) {
1081           col = s->rgb_to_pixel(s->palette[v],
1082                                 s->palette[v + 1],
1083                                 s->palette[v + 2]);
1084         } else {
1085           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1086                                 c6_to_8(s->palette[v + 1]),
1087                                 c6_to_8(s->palette[v + 2]));
1088         }
1089         if (col != palette[i]) {
1090             full_update = 1;
1091             palette[i] = col;
1092         }
1093         v += 3;
1094     }
1095     return full_update;
1096 }
1097
1098 static void vga_get_offsets(VGAState *s,
1099                             uint32_t *pline_offset,
1100                             uint32_t *pstart_addr,
1101                             uint32_t *pline_compare)
1102 {
1103     uint32_t start_addr, line_offset, line_compare;
1104 #ifdef CONFIG_BOCHS_VBE
1105     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1106         line_offset = s->vbe_line_offset;
1107         start_addr = s->vbe_start_addr;
1108         line_compare = 65535;
1109     } else
1110 #endif
1111     {
1112         /* compute line_offset in bytes */
1113         line_offset = s->cr[0x13];
1114         line_offset <<= 3;
1115
1116         /* starting address */
1117         start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1118
1119         /* line compare */
1120         line_compare = s->cr[0x18] |
1121             ((s->cr[0x07] & 0x10) << 4) |
1122             ((s->cr[0x09] & 0x40) << 3);
1123     }
1124     *pline_offset = line_offset;
1125     *pstart_addr = start_addr;
1126     *pline_compare = line_compare;
1127 }
1128
1129 /* update start_addr and line_offset. Return TRUE if modified */
1130 static int update_basic_params(VGAState *s)
1131 {
1132     int full_update;
1133     uint32_t start_addr, line_offset, line_compare;
1134
1135     full_update = 0;
1136
1137     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1138
1139     if (line_offset != s->line_offset ||
1140         start_addr != s->start_addr ||
1141         line_compare != s->line_compare) {
1142         s->line_offset = line_offset;
1143         s->start_addr = start_addr;
1144         s->line_compare = line_compare;
1145         full_update = 1;
1146     }
1147     return full_update;
1148 }
1149
1150 #define NB_DEPTHS 7
1151
1152 static inline int get_depth_index(DisplayState *s)
1153 {
1154     switch(s->depth) {
1155     default:
1156     case 8:
1157         return 0;
1158     case 15:
1159         if (s->bgr)
1160             return 5;
1161         else
1162             return 1;
1163     case 16:
1164         if (s->bgr)
1165             return 6;
1166         else
1167             return 2;
1168     case 32:
1169         if (s->bgr)
1170             return 4;
1171         else
1172             return 3;
1173     }
1174 }
1175
1176 static vga_draw_glyph8_func *vga_draw_glyph8_table[NB_DEPTHS] = {
1177     vga_draw_glyph8_8,
1178     vga_draw_glyph8_16,
1179     vga_draw_glyph8_16,
1180     vga_draw_glyph8_32,
1181     vga_draw_glyph8_32,
1182     vga_draw_glyph8_16,
1183     vga_draw_glyph8_16,
1184 };
1185
1186 static vga_draw_glyph8_func *vga_draw_glyph16_table[NB_DEPTHS] = {
1187     vga_draw_glyph16_8,
1188     vga_draw_glyph16_16,
1189     vga_draw_glyph16_16,
1190     vga_draw_glyph16_32,
1191     vga_draw_glyph16_32,
1192     vga_draw_glyph16_16,
1193     vga_draw_glyph16_16,
1194 };
1195
1196 static vga_draw_glyph9_func *vga_draw_glyph9_table[NB_DEPTHS] = {
1197     vga_draw_glyph9_8,
1198     vga_draw_glyph9_16,
1199     vga_draw_glyph9_16,
1200     vga_draw_glyph9_32,
1201     vga_draw_glyph9_32,
1202     vga_draw_glyph9_16,
1203     vga_draw_glyph9_16,
1204 };
1205
1206 static const uint8_t cursor_glyph[32 * 4] = {
1207     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1222     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1223 };
1224
1225 /*
1226  * Text mode update
1227  * Missing:
1228  * - double scan
1229  * - double width
1230  * - underline
1231  * - flashing
1232  */
1233 static void vga_draw_text(VGAState *s, int full_update)
1234 {
1235     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1236     int cx_min, cx_max, linesize, x_incr;
1237     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1238     uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1239     const uint8_t *font_ptr, *font_base[2];
1240     int dup9, line_offset, depth_index;
1241     uint32_t *palette;
1242     uint32_t *ch_attr_ptr;
1243     vga_draw_glyph8_func *vga_draw_glyph8;
1244     vga_draw_glyph9_func *vga_draw_glyph9;
1245
1246     full_update |= update_palette16(s);
1247     palette = s->last_palette;
1248
1249     /* compute font data address (in plane 2) */
1250     v = s->sr[3];
1251     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1252     if (offset != s->font_offsets[0]) {
1253         s->font_offsets[0] = offset;
1254         full_update = 1;
1255     }
1256     font_base[0] = s->vram_ptr + offset;
1257
1258     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1259     font_base[1] = s->vram_ptr + offset;
1260     if (offset != s->font_offsets[1]) {
1261         s->font_offsets[1] = offset;
1262         full_update = 1;
1263     }
1264     if (s->plane_updated & (1 << 2)) {
1265         /* if the plane 2 was modified since the last display, it
1266            indicates the font may have been modified */
1267         s->plane_updated = 0;
1268         full_update = 1;
1269     }
1270     full_update |= update_basic_params(s);
1271
1272     line_offset = s->line_offset;
1273     s1 = s->vram_ptr + (s->start_addr * 4);
1274
1275     /* total width & height */
1276     cheight = (s->cr[9] & 0x1f) + 1;
1277     cw = 8;
1278     if (!(s->sr[1] & 0x01))
1279         cw = 9;
1280     if (s->sr[1] & 0x08)
1281         cw = 16; /* NOTE: no 18 pixel wide */
1282     x_incr = cw * ((s->ds->depth + 7) >> 3);
1283     width = (s->cr[0x01] + 1);
1284     if (s->cr[0x06] == 100) {
1285         /* ugly hack for CGA 160x100x16 - explain me the logic */
1286         height = 100;
1287     } else {
1288         height = s->cr[0x12] |
1289             ((s->cr[0x07] & 0x02) << 7) |
1290             ((s->cr[0x07] & 0x40) << 3);
1291         height = (height + 1) / cheight;
1292     }
1293     if ((height * width) > CH_ATTR_SIZE) {
1294         /* better than nothing: exit if transient size is too big */
1295         return;
1296     }
1297
1298     if (width != s->last_width || height != s->last_height ||
1299         cw != s->last_cw || cheight != s->last_ch) {
1300         s->last_scr_width = width * cw;
1301         s->last_scr_height = height * cheight;
1302         qemu_console_resize(s->console, s->last_scr_width, s->last_scr_height);
1303         s->last_width = width;
1304         s->last_height = height;
1305         s->last_ch = cheight;
1306         s->last_cw = cw;
1307         full_update = 1;
1308     }
1309     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1310     if (cursor_offset != s->cursor_offset ||
1311         s->cr[0xa] != s->cursor_start ||
1312         s->cr[0xb] != s->cursor_end) {
1313       /* if the cursor position changed, we update the old and new
1314          chars */
1315         if (s->cursor_offset < CH_ATTR_SIZE)
1316             s->last_ch_attr[s->cursor_offset] = -1;
1317         if (cursor_offset < CH_ATTR_SIZE)
1318             s->last_ch_attr[cursor_offset] = -1;
1319         s->cursor_offset = cursor_offset;
1320         s->cursor_start = s->cr[0xa];
1321         s->cursor_end = s->cr[0xb];
1322     }
1323     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1324
1325     depth_index = get_depth_index(s->ds);
1326     if (cw == 16)
1327         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1328     else
1329         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1330     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1331
1332     dest = s->ds->data;
1333     linesize = s->ds->linesize;
1334     ch_attr_ptr = s->last_ch_attr;
1335     for(cy = 0; cy < height; cy++) {
1336         d1 = dest;
1337         src = s1;
1338         cx_min = width;
1339         cx_max = -1;
1340         for(cx = 0; cx < width; cx++) {
1341             ch_attr = *(uint16_t *)src;
1342             if (full_update || ch_attr != *ch_attr_ptr) {
1343                 if (cx < cx_min)
1344                     cx_min = cx;
1345                 if (cx > cx_max)
1346                     cx_max = cx;
1347                 *ch_attr_ptr = ch_attr;
1348 #ifdef WORDS_BIGENDIAN
1349                 ch = ch_attr >> 8;
1350                 cattr = ch_attr & 0xff;
1351 #else
1352                 ch = ch_attr & 0xff;
1353                 cattr = ch_attr >> 8;
1354 #endif
1355                 font_ptr = font_base[(cattr >> 3) & 1];
1356                 font_ptr += 32 * 4 * ch;
1357                 bgcol = palette[cattr >> 4];
1358                 fgcol = palette[cattr & 0x0f];
1359                 if (cw != 9) {
1360                     vga_draw_glyph8(d1, linesize,
1361                                     font_ptr, cheight, fgcol, bgcol);
1362                 } else {
1363                     dup9 = 0;
1364                     if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1365                         dup9 = 1;
1366                     vga_draw_glyph9(d1, linesize,
1367                                     font_ptr, cheight, fgcol, bgcol, dup9);
1368                 }
1369                 if (src == cursor_ptr &&
1370                     !(s->cr[0x0a] & 0x20)) {
1371                     int line_start, line_last, h;
1372                     /* draw the cursor */
1373                     line_start = s->cr[0x0a] & 0x1f;
1374                     line_last = s->cr[0x0b] & 0x1f;
1375                     /* XXX: check that */
1376                     if (line_last > cheight - 1)
1377                         line_last = cheight - 1;
1378                     if (line_last >= line_start && line_start < cheight) {
1379                         h = line_last - line_start + 1;
1380                         d = d1 + linesize * line_start;
1381                         if (cw != 9) {
1382                             vga_draw_glyph8(d, linesize,
1383                                             cursor_glyph, h, fgcol, bgcol);
1384                         } else {
1385                             vga_draw_glyph9(d, linesize,
1386                                             cursor_glyph, h, fgcol, bgcol, 1);
1387                         }
1388                     }
1389                 }
1390             }
1391             d1 += x_incr;
1392             src += 4;
1393             ch_attr_ptr++;
1394         }
1395         if (cx_max != -1) {
1396             dpy_update(s->ds, cx_min * cw, cy * cheight,
1397                        (cx_max - cx_min + 1) * cw, cheight);
1398         }
1399         dest += linesize * cheight;
1400         s1 += line_offset;
1401     }
1402 }
1403
1404 enum {
1405     VGA_DRAW_LINE2,
1406     VGA_DRAW_LINE2D2,
1407     VGA_DRAW_LINE4,
1408     VGA_DRAW_LINE4D2,
1409     VGA_DRAW_LINE8D2,
1410     VGA_DRAW_LINE8,
1411     VGA_DRAW_LINE15,
1412     VGA_DRAW_LINE16,
1413     VGA_DRAW_LINE24,
1414     VGA_DRAW_LINE32,
1415     VGA_DRAW_LINE_NB,
1416 };
1417
1418 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1419     vga_draw_line2_8,
1420     vga_draw_line2_16,
1421     vga_draw_line2_16,
1422     vga_draw_line2_32,
1423     vga_draw_line2_32,
1424     vga_draw_line2_16,
1425     vga_draw_line2_16,
1426
1427     vga_draw_line2d2_8,
1428     vga_draw_line2d2_16,
1429     vga_draw_line2d2_16,
1430     vga_draw_line2d2_32,
1431     vga_draw_line2d2_32,
1432     vga_draw_line2d2_16,
1433     vga_draw_line2d2_16,
1434
1435     vga_draw_line4_8,
1436     vga_draw_line4_16,
1437     vga_draw_line4_16,
1438     vga_draw_line4_32,
1439     vga_draw_line4_32,
1440     vga_draw_line4_16,
1441     vga_draw_line4_16,
1442
1443     vga_draw_line4d2_8,
1444     vga_draw_line4d2_16,
1445     vga_draw_line4d2_16,
1446     vga_draw_line4d2_32,
1447     vga_draw_line4d2_32,
1448     vga_draw_line4d2_16,
1449     vga_draw_line4d2_16,
1450
1451     vga_draw_line8d2_8,
1452     vga_draw_line8d2_16,
1453     vga_draw_line8d2_16,
1454     vga_draw_line8d2_32,
1455     vga_draw_line8d2_32,
1456     vga_draw_line8d2_16,
1457     vga_draw_line8d2_16,
1458
1459     vga_draw_line8_8,
1460     vga_draw_line8_16,
1461     vga_draw_line8_16,
1462     vga_draw_line8_32,
1463     vga_draw_line8_32,
1464     vga_draw_line8_16,
1465     vga_draw_line8_16,
1466
1467     vga_draw_line15_8,
1468     vga_draw_line15_15,
1469     vga_draw_line15_16,
1470     vga_draw_line15_32,
1471     vga_draw_line15_32bgr,
1472     vga_draw_line15_15bgr,
1473     vga_draw_line15_16bgr,
1474
1475     vga_draw_line16_8,
1476     vga_draw_line16_15,
1477     vga_draw_line16_16,
1478     vga_draw_line16_32,
1479     vga_draw_line16_32bgr,
1480     vga_draw_line16_15bgr,
1481     vga_draw_line16_16bgr,
1482
1483     vga_draw_line24_8,
1484     vga_draw_line24_15,
1485     vga_draw_line24_16,
1486     vga_draw_line24_32,
1487     vga_draw_line24_32bgr,
1488     vga_draw_line24_15bgr,
1489     vga_draw_line24_16bgr,
1490
1491     vga_draw_line32_8,
1492     vga_draw_line32_15,
1493     vga_draw_line32_16,
1494     vga_draw_line32_32,
1495     vga_draw_line32_32bgr,
1496     vga_draw_line32_15bgr,
1497     vga_draw_line32_16bgr,
1498 };
1499
1500 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1501
1502 static rgb_to_pixel_dup_func *rgb_to_pixel_dup_table[NB_DEPTHS] = {
1503     rgb_to_pixel8_dup,
1504     rgb_to_pixel15_dup,
1505     rgb_to_pixel16_dup,
1506     rgb_to_pixel32_dup,
1507     rgb_to_pixel32bgr_dup,
1508     rgb_to_pixel15bgr_dup,
1509     rgb_to_pixel16bgr_dup,
1510 };
1511
1512 static int vga_get_bpp(VGAState *s)
1513 {
1514     int ret;
1515 #ifdef CONFIG_BOCHS_VBE
1516     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1517         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1518     } else
1519 #endif
1520     {
1521         ret = 0;
1522     }
1523     return ret;
1524 }
1525
1526 static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1527 {
1528     int width, height;
1529
1530 #ifdef CONFIG_BOCHS_VBE
1531     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1532         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1533         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1534     } else
1535 #endif
1536     {
1537         width = (s->cr[0x01] + 1) * 8;
1538         height = s->cr[0x12] |
1539             ((s->cr[0x07] & 0x02) << 7) |
1540             ((s->cr[0x07] & 0x40) << 3);
1541         height = (height + 1);
1542     }
1543     *pwidth = width;
1544     *pheight = height;
1545 }
1546
1547 void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1548 {
1549     int y;
1550     if (y1 >= VGA_MAX_HEIGHT)
1551         return;
1552     if (y2 >= VGA_MAX_HEIGHT)
1553         y2 = VGA_MAX_HEIGHT;
1554     for(y = y1; y < y2; y++) {
1555         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1556     }
1557 }
1558
1559 /*
1560  * graphic modes
1561  */
1562 static void vga_draw_graphic(VGAState *s, int full_update)
1563 {
1564     int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1565     int width, height, shift_control, line_offset, page0, page1, bwidth, bits;
1566     int disp_width, multi_scan, multi_run;
1567     uint8_t *d;
1568     uint32_t v, addr1, addr;
1569     vga_draw_line_func *vga_draw_line;
1570
1571     full_update |= update_basic_params(s);
1572
1573     s->get_resolution(s, &width, &height);
1574     disp_width = width;
1575
1576     shift_control = (s->gr[0x05] >> 5) & 3;
1577     double_scan = (s->cr[0x09] >> 7);
1578     if (shift_control != 1) {
1579         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1580     } else {
1581         /* in CGA modes, multi_scan is ignored */
1582         /* XXX: is it correct ? */
1583         multi_scan = double_scan;
1584     }
1585     multi_run = multi_scan;
1586     if (shift_control != s->shift_control ||
1587         double_scan != s->double_scan) {
1588         full_update = 1;
1589         s->shift_control = shift_control;
1590         s->double_scan = double_scan;
1591     }
1592
1593     if (shift_control == 0) {
1594         full_update |= update_palette16(s);
1595         if (s->sr[0x01] & 8) {
1596             v = VGA_DRAW_LINE4D2;
1597             disp_width <<= 1;
1598         } else {
1599             v = VGA_DRAW_LINE4;
1600         }
1601         bits = 4;
1602     } else if (shift_control == 1) {
1603         full_update |= update_palette16(s);
1604         if (s->sr[0x01] & 8) {
1605             v = VGA_DRAW_LINE2D2;
1606             disp_width <<= 1;
1607         } else {
1608             v = VGA_DRAW_LINE2;
1609         }
1610         bits = 4;
1611     } else {
1612         switch(s->get_bpp(s)) {
1613         default:
1614         case 0:
1615             full_update |= update_palette256(s);
1616             v = VGA_DRAW_LINE8D2;
1617             bits = 4;
1618             break;
1619         case 8:
1620             full_update |= update_palette256(s);
1621             v = VGA_DRAW_LINE8;
1622             bits = 8;
1623             break;
1624         case 15:
1625             v = VGA_DRAW_LINE15;
1626             bits = 16;
1627             break;
1628         case 16:
1629             v = VGA_DRAW_LINE16;
1630             bits = 16;
1631             break;
1632         case 24:
1633             v = VGA_DRAW_LINE24;
1634             bits = 24;
1635             break;
1636         case 32:
1637             v = VGA_DRAW_LINE32;
1638             bits = 32;
1639             break;
1640         }
1641     }
1642     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1643
1644     if (disp_width != s->last_width ||
1645         height != s->last_height) {
1646         qemu_console_resize(s->console, disp_width, height);
1647         s->last_scr_width = disp_width;
1648         s->last_scr_height = height;
1649         s->last_width = disp_width;
1650         s->last_height = height;
1651         full_update = 1;
1652     }
1653     if (s->cursor_invalidate)
1654         s->cursor_invalidate(s);
1655
1656     line_offset = s->line_offset;
1657 #if 0
1658     printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1659            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1660 #endif
1661     addr1 = (s->start_addr * 4);
1662     bwidth = (width * bits + 7) / 8;
1663     y_start = -1;
1664     page_min = 0x7fffffff;
1665     page_max = -1;
1666     d = s->ds->data;
1667     linesize = s->ds->linesize;
1668     y1 = 0;
1669     for(y = 0; y < height; y++) {
1670         addr = addr1;
1671         if (!(s->cr[0x17] & 1)) {
1672             int shift;
1673             /* CGA compatibility handling */
1674             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1675             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1676         }
1677         if (!(s->cr[0x17] & 2)) {
1678             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1679         }
1680         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1681         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1682         update = full_update |
1683             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1684             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1685         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1686             /* if wide line, can use another page */
1687             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1688                                                     VGA_DIRTY_FLAG);
1689         }
1690         /* explicit invalidation for the hardware cursor */
1691         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1692         if (update) {
1693             if (y_start < 0)
1694                 y_start = y;
1695             if (page0 < page_min)
1696                 page_min = page0;
1697             if (page1 > page_max)
1698                 page_max = page1;
1699             vga_draw_line(s, d, s->vram_ptr + addr, width);
1700             if (s->cursor_draw_line)
1701                 s->cursor_draw_line(s, d, y);
1702         } else {
1703             if (y_start >= 0) {
1704                 /* flush to display */
1705                 dpy_update(s->ds, 0, y_start,
1706                            disp_width, y - y_start);
1707                 y_start = -1;
1708             }
1709         }
1710         if (!multi_run) {
1711             mask = (s->cr[0x17] & 3) ^ 3;
1712             if ((y1 & mask) == mask)
1713                 addr1 += line_offset;
1714             y1++;
1715             multi_run = multi_scan;
1716         } else {
1717             multi_run--;
1718         }
1719         /* line compare acts on the displayed lines */
1720         if (y == s->line_compare)
1721             addr1 = 0;
1722         d += linesize;
1723     }
1724     if (y_start >= 0) {
1725         /* flush to display */
1726         dpy_update(s->ds, 0, y_start,
1727                    disp_width, y - y_start);
1728     }
1729     /* reset modified pages */
1730     if (page_max != -1) {
1731         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1732                                         VGA_DIRTY_FLAG);
1733     }
1734     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1735 }
1736
1737 static void vga_draw_blank(VGAState *s, int full_update)
1738 {
1739     int i, w, val;
1740     uint8_t *d;
1741
1742     if (!full_update)
1743         return;
1744     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1745         return;
1746     if (s->ds->depth == 8)
1747         val = s->rgb_to_pixel(0, 0, 0);
1748     else
1749         val = 0;
1750     w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1751     d = s->ds->data;
1752     for(i = 0; i < s->last_scr_height; i++) {
1753         memset(d, val, w);
1754         d += s->ds->linesize;
1755     }
1756     dpy_update(s->ds, 0, 0,
1757                s->last_scr_width, s->last_scr_height);
1758 }
1759
1760 #define GMODE_TEXT     0
1761 #define GMODE_GRAPH    1
1762 #define GMODE_BLANK 2
1763
1764 static void vga_update_display(void *opaque)
1765 {
1766     VGAState *s = (VGAState *)opaque;
1767     int full_update, graphic_mode;
1768
1769     if (s->ds->depth == 0) {
1770         /* nothing to do */
1771     } else {
1772         s->rgb_to_pixel =
1773             rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1774
1775         full_update = 0;
1776         if (!(s->ar_index & 0x20)) {
1777             graphic_mode = GMODE_BLANK;
1778         } else {
1779             graphic_mode = s->gr[6] & 1;
1780         }
1781         if (graphic_mode != s->graphic_mode) {
1782             s->graphic_mode = graphic_mode;
1783             full_update = 1;
1784         }
1785         switch(graphic_mode) {
1786         case GMODE_TEXT:
1787             vga_draw_text(s, full_update);
1788             break;
1789         case GMODE_GRAPH:
1790             vga_draw_graphic(s, full_update);
1791             break;
1792         case GMODE_BLANK:
1793         default:
1794             vga_draw_blank(s, full_update);
1795             break;
1796         }
1797     }
1798 }
1799
1800 /* force a full display refresh */
1801 static void vga_invalidate_display(void *opaque)
1802 {
1803     VGAState *s = (VGAState *)opaque;
1804
1805     s->last_width = -1;
1806     s->last_height = -1;
1807 }
1808
1809 static void vga_reset(VGAState *s)
1810 {
1811     memset(s, 0, sizeof(VGAState));
1812     s->graphic_mode = -1; /* force full update */
1813 }
1814
1815 #define TEXTMODE_X(x)   ((x) % width)
1816 #define TEXTMODE_Y(x)   ((x) / width)
1817 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1818         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1819 /* relay text rendering to the display driver
1820  * instead of doing a full vga_update_display() */
1821 static void vga_update_text(void *opaque, console_ch_t *chardata)
1822 {
1823     VGAState *s = (VGAState *) opaque;
1824     int graphic_mode, i, cursor_offset, cursor_visible;
1825     int cw, cheight, width, height, size, c_min, c_max;
1826     uint32_t *src;
1827     console_ch_t *dst, val;
1828     char msg_buffer[80];
1829     int full_update = 0;
1830
1831     if (!(s->ar_index & 0x20)) {
1832         graphic_mode = GMODE_BLANK;
1833     } else {
1834         graphic_mode = s->gr[6] & 1;
1835     }
1836     if (graphic_mode != s->graphic_mode) {
1837         s->graphic_mode = graphic_mode;
1838         full_update = 1;
1839     }
1840     if (s->last_width == -1) {
1841         s->last_width = 0;
1842         full_update = 1;
1843     }
1844
1845     switch (graphic_mode) {
1846     case GMODE_TEXT:
1847         /* TODO: update palette */
1848         full_update |= update_basic_params(s);
1849
1850         /* total width & height */
1851         cheight = (s->cr[9] & 0x1f) + 1;
1852         cw = 8;
1853         if (!(s->sr[1] & 0x01))
1854             cw = 9;
1855         if (s->sr[1] & 0x08)
1856             cw = 16; /* NOTE: no 18 pixel wide */
1857         width = (s->cr[0x01] + 1);
1858         if (s->cr[0x06] == 100) {
1859             /* ugly hack for CGA 160x100x16 - explain me the logic */
1860             height = 100;
1861         } else {
1862             height = s->cr[0x12] | 
1863                 ((s->cr[0x07] & 0x02) << 7) | 
1864                 ((s->cr[0x07] & 0x40) << 3);
1865             height = (height + 1) / cheight;
1866         }
1867
1868         size = (height * width);
1869         if (size > CH_ATTR_SIZE) {
1870             if (!full_update)
1871                 return;
1872
1873             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1874                      width, height);
1875             break;
1876         }
1877
1878         if (width != s->last_width || height != s->last_height ||
1879             cw != s->last_cw || cheight != s->last_ch) {
1880             s->last_scr_width = width * cw;
1881             s->last_scr_height = height * cheight;
1882             qemu_console_resize(s->console, width, height);
1883             s->last_width = width;
1884             s->last_height = height;
1885             s->last_ch = cheight;
1886             s->last_cw = cw;
1887             full_update = 1;
1888         }
1889
1890         /* Update "hardware" cursor */
1891         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1892         if (cursor_offset != s->cursor_offset ||
1893             s->cr[0xa] != s->cursor_start ||
1894             s->cr[0xb] != s->cursor_end || full_update) {
1895             cursor_visible = !(s->cr[0xa] & 0x20);
1896             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1897                 dpy_cursor(s->ds,
1898                            TEXTMODE_X(cursor_offset),
1899                            TEXTMODE_Y(cursor_offset));
1900             else
1901                 dpy_cursor(s->ds, -1, -1);
1902             s->cursor_offset = cursor_offset;
1903             s->cursor_start = s->cr[0xa];
1904             s->cursor_end = s->cr[0xb];
1905         }
1906
1907         src = (uint32_t *) s->vram_ptr + s->start_addr;
1908         dst = chardata;
1909
1910         if (full_update) {
1911             for (i = 0; i < size; src ++, dst ++, i ++)
1912                 console_write_ch(dst, VMEM2CHTYPE(*src));
1913
1914             dpy_update(s->ds, 0, 0, width, height);
1915         } else {
1916             c_max = 0;
1917
1918             for (i = 0; i < size; src ++, dst ++, i ++) {
1919                 console_write_ch(&val, VMEM2CHTYPE(*src));
1920                 if (*dst != val) {
1921                     *dst = val;
1922                     c_max = i;
1923                     break;
1924                 }
1925             }
1926             c_min = i;
1927             for (; i < size; src ++, dst ++, i ++) {
1928                 console_write_ch(&val, VMEM2CHTYPE(*src));
1929                 if (*dst != val) {
1930                     *dst = val;
1931                     c_max = i;
1932                 }
1933             }
1934
1935             if (c_min <= c_max) {
1936                 i = TEXTMODE_Y(c_min);
1937                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1938             }
1939         }
1940
1941         return;
1942     case GMODE_GRAPH:
1943         if (!full_update)
1944             return;
1945
1946         s->get_resolution(s, &width, &height);
1947         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
1948                  width, height);
1949         break;
1950     case GMODE_BLANK:
1951     default:
1952         if (!full_update)
1953             return;
1954
1955         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
1956         break;
1957     }
1958
1959     /* Display a message */
1960     s->last_width = 60;
1961     s->last_height = height = 3;
1962     dpy_cursor(s->ds, -1, -1);
1963     qemu_console_resize(s->console, s->last_width, height);
1964
1965     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
1966         console_write_ch(dst ++, ' ');
1967
1968     size = strlen(msg_buffer);
1969     width = (s->last_width - size) / 2;
1970     dst = chardata + s->last_width + width;
1971     for (i = 0; i < size; i ++)
1972         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
1973
1974     dpy_update(s->ds, 0, 0, s->last_width, height);
1975 }
1976
1977 static CPUReadMemoryFunc *vga_mem_read[3] = {
1978     vga_mem_readb,
1979     vga_mem_readw,
1980     vga_mem_readl,
1981 };
1982
1983 static CPUWriteMemoryFunc *vga_mem_write[3] = {
1984     vga_mem_writeb,
1985     vga_mem_writew,
1986     vga_mem_writel,
1987 };
1988
1989 static void vga_save(QEMUFile *f, void *opaque)
1990 {
1991     VGAState *s = opaque;
1992     int i;
1993
1994     if (s->pci_dev)
1995         pci_device_save(s->pci_dev, f);
1996
1997     qemu_put_be32s(f, &s->latch);
1998     qemu_put_8s(f, &s->sr_index);
1999     qemu_put_buffer(f, s->sr, 8);
2000     qemu_put_8s(f, &s->gr_index);
2001     qemu_put_buffer(f, s->gr, 16);
2002     qemu_put_8s(f, &s->ar_index);
2003     qemu_put_buffer(f, s->ar, 21);
2004     qemu_put_be32(f, s->ar_flip_flop);
2005     qemu_put_8s(f, &s->cr_index);
2006     qemu_put_buffer(f, s->cr, 256);
2007     qemu_put_8s(f, &s->msr);
2008     qemu_put_8s(f, &s->fcr);
2009     qemu_put_byte(f, s->st00);
2010     qemu_put_8s(f, &s->st01);
2011
2012     qemu_put_8s(f, &s->dac_state);
2013     qemu_put_8s(f, &s->dac_sub_index);
2014     qemu_put_8s(f, &s->dac_read_index);
2015     qemu_put_8s(f, &s->dac_write_index);
2016     qemu_put_buffer(f, s->dac_cache, 3);
2017     qemu_put_buffer(f, s->palette, 768);
2018
2019     qemu_put_be32(f, s->bank_offset);
2020 #ifdef CONFIG_BOCHS_VBE
2021     qemu_put_byte(f, 1);
2022     qemu_put_be16s(f, &s->vbe_index);
2023     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2024         qemu_put_be16s(f, &s->vbe_regs[i]);
2025     qemu_put_be32s(f, &s->vbe_start_addr);
2026     qemu_put_be32s(f, &s->vbe_line_offset);
2027     qemu_put_be32s(f, &s->vbe_bank_mask);
2028 #else
2029     qemu_put_byte(f, 0);
2030 #endif
2031 }
2032
2033 static int vga_load(QEMUFile *f, void *opaque, int version_id)
2034 {
2035     VGAState *s = opaque;
2036     int is_vbe, i, ret;
2037
2038     if (version_id > 2)
2039         return -EINVAL;
2040
2041     if (s->pci_dev && version_id >= 2) {
2042         ret = pci_device_load(s->pci_dev, f);
2043         if (ret < 0)
2044             return ret;
2045     }
2046
2047     qemu_get_be32s(f, &s->latch);
2048     qemu_get_8s(f, &s->sr_index);
2049     qemu_get_buffer(f, s->sr, 8);
2050     qemu_get_8s(f, &s->gr_index);
2051     qemu_get_buffer(f, s->gr, 16);
2052     qemu_get_8s(f, &s->ar_index);
2053     qemu_get_buffer(f, s->ar, 21);
2054     s->ar_flip_flop=qemu_get_be32(f);
2055     qemu_get_8s(f, &s->cr_index);
2056     qemu_get_buffer(f, s->cr, 256);
2057     qemu_get_8s(f, &s->msr);
2058     qemu_get_8s(f, &s->fcr);
2059     qemu_get_8s(f, &s->st00);
2060     qemu_get_8s(f, &s->st01);
2061
2062     qemu_get_8s(f, &s->dac_state);
2063     qemu_get_8s(f, &s->dac_sub_index);
2064     qemu_get_8s(f, &s->dac_read_index);
2065     qemu_get_8s(f, &s->dac_write_index);
2066     qemu_get_buffer(f, s->dac_cache, 3);
2067     qemu_get_buffer(f, s->palette, 768);
2068
2069     s->bank_offset=qemu_get_be32(f);
2070     is_vbe = qemu_get_byte(f);
2071 #ifdef CONFIG_BOCHS_VBE
2072     if (!is_vbe)
2073         return -EINVAL;
2074     qemu_get_be16s(f, &s->vbe_index);
2075     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2076         qemu_get_be16s(f, &s->vbe_regs[i]);
2077     qemu_get_be32s(f, &s->vbe_start_addr);
2078     qemu_get_be32s(f, &s->vbe_line_offset);
2079     qemu_get_be32s(f, &s->vbe_bank_mask);
2080 #else
2081     if (is_vbe)
2082         return -EINVAL;
2083 #endif
2084
2085     /* force refresh */
2086     s->graphic_mode = -1;
2087     return 0;
2088 }
2089
2090 typedef struct PCIVGAState {
2091     PCIDevice dev;
2092     VGAState vga_state;
2093 } PCIVGAState;
2094
2095 static void vga_map(PCIDevice *pci_dev, int region_num,
2096                     uint32_t addr, uint32_t size, int type)
2097 {
2098     PCIVGAState *d = (PCIVGAState *)pci_dev;
2099     VGAState *s = &d->vga_state;
2100     if (region_num == PCI_ROM_SLOT) {
2101         cpu_register_physical_memory(addr, s->bios_size, s->bios_offset);
2102     } else {
2103         cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
2104     }
2105 }
2106
2107 void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
2108                      unsigned long vga_ram_offset, int vga_ram_size)
2109 {
2110     int i, j, v, b;
2111
2112     for(i = 0;i < 256; i++) {
2113         v = 0;
2114         for(j = 0; j < 8; j++) {
2115             v |= ((i >> j) & 1) << (j * 4);
2116         }
2117         expand4[i] = v;
2118
2119         v = 0;
2120         for(j = 0; j < 4; j++) {
2121             v |= ((i >> (2 * j)) & 3) << (j * 4);
2122         }
2123         expand2[i] = v;
2124     }
2125     for(i = 0; i < 16; i++) {
2126         v = 0;
2127         for(j = 0; j < 4; j++) {
2128             b = ((i >> j) & 1);
2129             v |= b << (2 * j);
2130             v |= b << (2 * j + 1);
2131         }
2132         expand4to8[i] = v;
2133     }
2134
2135     vga_reset(s);
2136
2137     s->vram_ptr = vga_ram_base;
2138     s->vram_offset = vga_ram_offset;
2139     s->vram_size = vga_ram_size;
2140     s->ds = ds;
2141     s->get_bpp = vga_get_bpp;
2142     s->get_offsets = vga_get_offsets;
2143     s->get_resolution = vga_get_resolution;
2144     s->update = vga_update_display;
2145     s->invalidate = vga_invalidate_display;
2146     s->screen_dump = vga_screen_dump;
2147     s->text_update = vga_update_text;
2148     switch (vga_retrace_method) {
2149     case VGA_RETRACE_DUMB:
2150         s->retrace = vga_dumb_retrace;
2151         s->update_retrace_info = vga_dumb_update_retrace_info;
2152         break;
2153
2154     case VGA_RETRACE_PRECISE:
2155         s->retrace = vga_precise_retrace;
2156         s->update_retrace_info = vga_precise_update_retrace_info;
2157         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
2158         break;
2159     }
2160 }
2161
2162 /* used by both ISA and PCI */
2163 void vga_init(VGAState *s)
2164 {
2165     int vga_io_memory;
2166
2167     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2168
2169     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2170
2171     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2172     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2173     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2174     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2175
2176     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2177
2178     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2179     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2180     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2181     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2182     s->bank_offset = 0;
2183
2184 #ifdef CONFIG_BOCHS_VBE
2185     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
2186     s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
2187 #if defined (TARGET_I386)
2188     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2189     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2190
2191     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2192     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2193
2194     /* old Bochs IO ports */
2195     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2196     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2197
2198     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2199     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2200 #else
2201     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2202     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2203
2204     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2205     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2206 #endif
2207 #endif /* CONFIG_BOCHS_VBE */
2208
2209     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2210     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2211                                  vga_io_memory);
2212 }
2213
2214 /* Memory mapped interface */
2215 static uint32_t vga_mm_readb (void *opaque, target_phys_addr_t addr)
2216 {
2217     VGAState *s = opaque;
2218
2219     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xff;
2220 }
2221
2222 static void vga_mm_writeb (void *opaque,
2223                            target_phys_addr_t addr, uint32_t value)
2224 {
2225     VGAState *s = opaque;
2226
2227     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xff);
2228 }
2229
2230 static uint32_t vga_mm_readw (void *opaque, target_phys_addr_t addr)
2231 {
2232     VGAState *s = opaque;
2233
2234     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift) & 0xffff;
2235 }
2236
2237 static void vga_mm_writew (void *opaque,
2238                            target_phys_addr_t addr, uint32_t value)
2239 {
2240     VGAState *s = opaque;
2241
2242     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value & 0xffff);
2243 }
2244
2245 static uint32_t vga_mm_readl (void *opaque, target_phys_addr_t addr)
2246 {
2247     VGAState *s = opaque;
2248
2249     return vga_ioport_read(s, (addr - s->base_ctrl) >> s->it_shift);
2250 }
2251
2252 static void vga_mm_writel (void *opaque,
2253                            target_phys_addr_t addr, uint32_t value)
2254 {
2255     VGAState *s = opaque;
2256
2257     vga_ioport_write(s, (addr - s->base_ctrl) >> s->it_shift, value);
2258 }
2259
2260 static CPUReadMemoryFunc *vga_mm_read_ctrl[] = {
2261     &vga_mm_readb,
2262     &vga_mm_readw,
2263     &vga_mm_readl,
2264 };
2265
2266 static CPUWriteMemoryFunc *vga_mm_write_ctrl[] = {
2267     &vga_mm_writeb,
2268     &vga_mm_writew,
2269     &vga_mm_writel,
2270 };
2271
2272 static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base,
2273                         target_phys_addr_t ctrl_base, int it_shift)
2274 {
2275     int s_ioport_ctrl, vga_io_memory;
2276
2277     s->base_ctrl = ctrl_base;
2278     s->it_shift = it_shift;
2279     s_ioport_ctrl = cpu_register_io_memory(0, vga_mm_read_ctrl, vga_mm_write_ctrl, s);
2280     vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
2281
2282     register_savevm("vga", 0, 2, vga_save, vga_load, s);
2283
2284     cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl);
2285     s->bank_offset = 0;
2286     cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory);
2287 }
2288
2289 int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
2290                  unsigned long vga_ram_offset, int vga_ram_size)
2291 {
2292     VGAState *s;
2293
2294     s = qemu_mallocz(sizeof(VGAState));
2295     if (!s)
2296         return -1;
2297
2298     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2299     vga_init(s);
2300
2301     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2302                                       s->screen_dump, s->text_update, s);
2303
2304 #ifdef CONFIG_BOCHS_VBE
2305     /* XXX: use optimized standard vga accesses */
2306     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2307                                  vga_ram_size, vga_ram_offset);
2308 #endif
2309     return 0;
2310 }
2311
2312 int isa_vga_mm_init(DisplayState *ds, uint8_t *vga_ram_base,
2313                     unsigned long vga_ram_offset, int vga_ram_size,
2314                     target_phys_addr_t vram_base, target_phys_addr_t ctrl_base,
2315                     int it_shift)
2316 {
2317     VGAState *s;
2318
2319     s = qemu_mallocz(sizeof(VGAState));
2320     if (!s)
2321         return -1;
2322
2323     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2324     vga_mm_init(s, vram_base, ctrl_base, it_shift);
2325
2326     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2327                                       s->screen_dump, s->text_update, s);
2328
2329 #ifdef CONFIG_BOCHS_VBE
2330     /* XXX: use optimized standard vga accesses */
2331     cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2332                                  vga_ram_size, vga_ram_offset);
2333 #endif
2334     return 0;
2335 }
2336
2337 int pci_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
2338                  unsigned long vga_ram_offset, int vga_ram_size,
2339                  unsigned long vga_bios_offset, int vga_bios_size)
2340 {
2341     PCIVGAState *d;
2342     VGAState *s;
2343     uint8_t *pci_conf;
2344
2345     d = (PCIVGAState *)pci_register_device(bus, "VGA",
2346                                            sizeof(PCIVGAState),
2347                                            -1, NULL, NULL);
2348     if (!d)
2349         return -1;
2350     s = &d->vga_state;
2351
2352     vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
2353     vga_init(s);
2354
2355     s->console = graphic_console_init(s->ds, s->update, s->invalidate,
2356                                       s->screen_dump, s->text_update, s);
2357
2358     s->pci_dev = &d->dev;
2359
2360     pci_conf = d->dev.config;
2361     pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
2362     pci_conf[0x01] = 0x12;
2363     pci_conf[0x02] = 0x11;
2364     pci_conf[0x03] = 0x11;
2365     pci_conf[0x0a] = 0x00; // VGA controller
2366     pci_conf[0x0b] = 0x03;
2367     pci_conf[0x0e] = 0x00; // header_type
2368
2369     /* XXX: vga_ram_size must be a power of two */
2370     pci_register_io_region(&d->dev, 0, vga_ram_size,
2371                            PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2372     if (vga_bios_size != 0) {
2373         unsigned int bios_total_size;
2374         s->bios_offset = vga_bios_offset;
2375         s->bios_size = vga_bios_size;
2376         /* must be a power of two */
2377         bios_total_size = 1;
2378         while (bios_total_size < vga_bios_size)
2379             bios_total_size <<= 1;
2380         pci_register_io_region(&d->dev, PCI_ROM_SLOT, bios_total_size,
2381                                PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
2382     }
2383     return 0;
2384 }
2385
2386 /********************************************************/
2387 /* vga screen dump */
2388
2389 static int vga_save_w, vga_save_h;
2390
2391 static void vga_save_dpy_update(DisplayState *s,
2392                                 int x, int y, int w, int h)
2393 {
2394 }
2395
2396 static void vga_save_dpy_resize(DisplayState *s, int w, int h)
2397 {
2398     s->linesize = w * 4;
2399     s->data = qemu_mallocz(h * s->linesize);
2400     vga_save_w = w;
2401     vga_save_h = h;
2402 }
2403
2404 static void vga_save_dpy_refresh(DisplayState *s)
2405 {
2406 }
2407
2408 int ppm_save(const char *filename, uint8_t *data,
2409              int w, int h, int linesize)
2410 {
2411     FILE *f;
2412     uint8_t *d, *d1;
2413     unsigned int v;
2414     int y, x;
2415
2416     f = fopen(filename, "wb");
2417     if (!f)
2418         return -1;
2419     fprintf(f, "P6\n%d %d\n%d\n",
2420             w, h, 255);
2421     d1 = data;
2422     for(y = 0; y < h; y++) {
2423         d = d1;
2424         for(x = 0; x < w; x++) {
2425             v = *(uint32_t *)d;
2426             fputc((v >> 16) & 0xff, f);
2427             fputc((v >> 8) & 0xff, f);
2428             fputc((v) & 0xff, f);
2429             d += 4;
2430         }
2431         d1 += linesize;
2432     }
2433     fclose(f);
2434     return 0;
2435 }
2436
2437 /* save the vga display in a PPM image even if no display is
2438    available */
2439 static void vga_screen_dump(void *opaque, const char *filename)
2440 {
2441     VGAState *s = (VGAState *)opaque;
2442     DisplayState *saved_ds, ds1, *ds = &ds1;
2443
2444     /* XXX: this is a little hackish */
2445     vga_invalidate_display(s);
2446     saved_ds = s->ds;
2447
2448     memset(ds, 0, sizeof(DisplayState));
2449     ds->dpy_update = vga_save_dpy_update;
2450     ds->dpy_resize = vga_save_dpy_resize;
2451     ds->dpy_refresh = vga_save_dpy_refresh;
2452     ds->depth = 32;
2453
2454     s->ds = ds;
2455     s->graphic_mode = -1;
2456     vga_update_display(s);
2457
2458     if (ds->data) {
2459         ppm_save(filename, ds->data, vga_save_w, vga_save_h,
2460                  s->ds->linesize);
2461         qemu_free(ds->data);
2462     }
2463     s->ds = saved_ds;
2464 }