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