]> Git Repo - qemu.git/blob - hw/vga.c
ide: port pci ide to vmstate
[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;
1271     uint32_t offset, fgcol, bgcol, v, cursor_offset;
1272     uint8_t *d1, *d, *src, *s1, *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     s1 = s->vram_ptr + (s->start_addr * 4);
1305
1306     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1307     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1308     if ((height * width) > CH_ATTR_SIZE) {
1309         /* better than nothing: exit if transient size is too big */
1310         return;
1311     }
1312
1313     if (width != s->last_width || height != s->last_height ||
1314         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1315         s->last_scr_width = width * cw;
1316         s->last_scr_height = height * cheight;
1317         qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1318         s->last_depth = 0;
1319         s->last_width = width;
1320         s->last_height = height;
1321         s->last_ch = cheight;
1322         s->last_cw = cw;
1323         full_update = 1;
1324     }
1325     s->rgb_to_pixel =
1326         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1327     full_update |= update_palette16(s);
1328     palette = s->last_palette;
1329     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1330
1331     cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1332     if (cursor_offset != s->cursor_offset ||
1333         s->cr[0xa] != s->cursor_start ||
1334         s->cr[0xb] != s->cursor_end) {
1335       /* if the cursor position changed, we update the old and new
1336          chars */
1337         if (s->cursor_offset < CH_ATTR_SIZE)
1338             s->last_ch_attr[s->cursor_offset] = -1;
1339         if (cursor_offset < CH_ATTR_SIZE)
1340             s->last_ch_attr[cursor_offset] = -1;
1341         s->cursor_offset = cursor_offset;
1342         s->cursor_start = s->cr[0xa];
1343         s->cursor_end = s->cr[0xb];
1344     }
1345     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1346
1347     depth_index = get_depth_index(s->ds);
1348     if (cw == 16)
1349         vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1350     else
1351         vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1352     vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1353
1354     dest = ds_get_data(s->ds);
1355     linesize = ds_get_linesize(s->ds);
1356     ch_attr_ptr = s->last_ch_attr;
1357     for(cy = 0; cy < height; cy++) {
1358         d1 = dest;
1359         src = s1;
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         s1 += line_offset;
1423     }
1424 }
1425
1426 enum {
1427     VGA_DRAW_LINE2,
1428     VGA_DRAW_LINE2D2,
1429     VGA_DRAW_LINE4,
1430     VGA_DRAW_LINE4D2,
1431     VGA_DRAW_LINE8D2,
1432     VGA_DRAW_LINE8,
1433     VGA_DRAW_LINE15,
1434     VGA_DRAW_LINE16,
1435     VGA_DRAW_LINE24,
1436     VGA_DRAW_LINE32,
1437     VGA_DRAW_LINE_NB,
1438 };
1439
1440 static vga_draw_line_func *vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1441     vga_draw_line2_8,
1442     vga_draw_line2_16,
1443     vga_draw_line2_16,
1444     vga_draw_line2_32,
1445     vga_draw_line2_32,
1446     vga_draw_line2_16,
1447     vga_draw_line2_16,
1448
1449     vga_draw_line2d2_8,
1450     vga_draw_line2d2_16,
1451     vga_draw_line2d2_16,
1452     vga_draw_line2d2_32,
1453     vga_draw_line2d2_32,
1454     vga_draw_line2d2_16,
1455     vga_draw_line2d2_16,
1456
1457     vga_draw_line4_8,
1458     vga_draw_line4_16,
1459     vga_draw_line4_16,
1460     vga_draw_line4_32,
1461     vga_draw_line4_32,
1462     vga_draw_line4_16,
1463     vga_draw_line4_16,
1464
1465     vga_draw_line4d2_8,
1466     vga_draw_line4d2_16,
1467     vga_draw_line4d2_16,
1468     vga_draw_line4d2_32,
1469     vga_draw_line4d2_32,
1470     vga_draw_line4d2_16,
1471     vga_draw_line4d2_16,
1472
1473     vga_draw_line8d2_8,
1474     vga_draw_line8d2_16,
1475     vga_draw_line8d2_16,
1476     vga_draw_line8d2_32,
1477     vga_draw_line8d2_32,
1478     vga_draw_line8d2_16,
1479     vga_draw_line8d2_16,
1480
1481     vga_draw_line8_8,
1482     vga_draw_line8_16,
1483     vga_draw_line8_16,
1484     vga_draw_line8_32,
1485     vga_draw_line8_32,
1486     vga_draw_line8_16,
1487     vga_draw_line8_16,
1488
1489     vga_draw_line15_8,
1490     vga_draw_line15_15,
1491     vga_draw_line15_16,
1492     vga_draw_line15_32,
1493     vga_draw_line15_32bgr,
1494     vga_draw_line15_15bgr,
1495     vga_draw_line15_16bgr,
1496
1497     vga_draw_line16_8,
1498     vga_draw_line16_15,
1499     vga_draw_line16_16,
1500     vga_draw_line16_32,
1501     vga_draw_line16_32bgr,
1502     vga_draw_line16_15bgr,
1503     vga_draw_line16_16bgr,
1504
1505     vga_draw_line24_8,
1506     vga_draw_line24_15,
1507     vga_draw_line24_16,
1508     vga_draw_line24_32,
1509     vga_draw_line24_32bgr,
1510     vga_draw_line24_15bgr,
1511     vga_draw_line24_16bgr,
1512
1513     vga_draw_line32_8,
1514     vga_draw_line32_15,
1515     vga_draw_line32_16,
1516     vga_draw_line32_32,
1517     vga_draw_line32_32bgr,
1518     vga_draw_line32_15bgr,
1519     vga_draw_line32_16bgr,
1520 };
1521
1522 static int vga_get_bpp(VGACommonState *s)
1523 {
1524     int ret;
1525 #ifdef CONFIG_BOCHS_VBE
1526     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1527         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1528     } else
1529 #endif
1530     {
1531         ret = 0;
1532     }
1533     return ret;
1534 }
1535
1536 static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1537 {
1538     int width, height;
1539
1540 #ifdef CONFIG_BOCHS_VBE
1541     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1542         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1543         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1544     } else
1545 #endif
1546     {
1547         width = (s->cr[0x01] + 1) * 8;
1548         height = s->cr[0x12] |
1549             ((s->cr[0x07] & 0x02) << 7) |
1550             ((s->cr[0x07] & 0x40) << 3);
1551         height = (height + 1);
1552     }
1553     *pwidth = width;
1554     *pheight = height;
1555 }
1556
1557 void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1558 {
1559     int y;
1560     if (y1 >= VGA_MAX_HEIGHT)
1561         return;
1562     if (y2 >= VGA_MAX_HEIGHT)
1563         y2 = VGA_MAX_HEIGHT;
1564     for(y = y1; y < y2; y++) {
1565         s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1566     }
1567 }
1568
1569 static void vga_sync_dirty_bitmap(VGACommonState *s)
1570 {
1571     if (s->map_addr)
1572         cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1573
1574     if (s->lfb_vram_mapped) {
1575         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1576         cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1577     }
1578 }
1579
1580 void vga_dirty_log_start(VGACommonState *s)
1581 {
1582     if (kvm_enabled() && s->map_addr)
1583         kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1584
1585     if (kvm_enabled() && s->lfb_vram_mapped) {
1586         kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1587         kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1588     }
1589 }
1590
1591 /*
1592  * graphic modes
1593  */
1594 static void vga_draw_graphic(VGACommonState *s, int full_update)
1595 {
1596     int y1, y, update, linesize, y_start, double_scan, mask, depth;
1597     int width, height, shift_control, line_offset, bwidth, bits;
1598     ram_addr_t page0, page1, page_min, page_max;
1599     int disp_width, multi_scan, multi_run;
1600     uint8_t *d;
1601     uint32_t v, addr1, addr;
1602     vga_draw_line_func *vga_draw_line;
1603
1604     full_update |= update_basic_params(s);
1605
1606     if (!full_update)
1607         vga_sync_dirty_bitmap(s);
1608
1609     s->get_resolution(s, &width, &height);
1610     disp_width = width;
1611
1612     shift_control = (s->gr[0x05] >> 5) & 3;
1613     double_scan = (s->cr[0x09] >> 7);
1614     if (shift_control != 1) {
1615         multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1616     } else {
1617         /* in CGA modes, multi_scan is ignored */
1618         /* XXX: is it correct ? */
1619         multi_scan = double_scan;
1620     }
1621     multi_run = multi_scan;
1622     if (shift_control != s->shift_control ||
1623         double_scan != s->double_scan) {
1624         full_update = 1;
1625         s->shift_control = shift_control;
1626         s->double_scan = double_scan;
1627     }
1628
1629     if (shift_control == 0) {
1630         if (s->sr[0x01] & 8) {
1631             disp_width <<= 1;
1632         }
1633     } else if (shift_control == 1) {
1634         if (s->sr[0x01] & 8) {
1635             disp_width <<= 1;
1636         }
1637     }
1638
1639     depth = s->get_bpp(s);
1640     if (s->line_offset != s->last_line_offset ||
1641         disp_width != s->last_width ||
1642         height != s->last_height ||
1643         s->last_depth != depth) {
1644 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1645         if (depth == 16 || depth == 32) {
1646 #else
1647         if (depth == 32) {
1648 #endif
1649             qemu_free_displaysurface(s->ds);
1650             s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1651                     s->line_offset,
1652                     s->vram_ptr + (s->start_addr * 4));
1653 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1654             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1655 #endif
1656             dpy_resize(s->ds);
1657         } else {
1658             qemu_console_resize(s->ds, disp_width, height);
1659         }
1660         s->last_scr_width = disp_width;
1661         s->last_scr_height = height;
1662         s->last_width = disp_width;
1663         s->last_height = height;
1664         s->last_line_offset = s->line_offset;
1665         s->last_depth = depth;
1666         full_update = 1;
1667     } else if (is_buffer_shared(s->ds->surface) &&
1668                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1669         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1670         dpy_setdata(s->ds);
1671     }
1672
1673     s->rgb_to_pixel =
1674         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1675
1676     if (shift_control == 0) {
1677         full_update |= update_palette16(s);
1678         if (s->sr[0x01] & 8) {
1679             v = VGA_DRAW_LINE4D2;
1680         } else {
1681             v = VGA_DRAW_LINE4;
1682         }
1683         bits = 4;
1684     } else if (shift_control == 1) {
1685         full_update |= update_palette16(s);
1686         if (s->sr[0x01] & 8) {
1687             v = VGA_DRAW_LINE2D2;
1688         } else {
1689             v = VGA_DRAW_LINE2;
1690         }
1691         bits = 4;
1692     } else {
1693         switch(s->get_bpp(s)) {
1694         default:
1695         case 0:
1696             full_update |= update_palette256(s);
1697             v = VGA_DRAW_LINE8D2;
1698             bits = 4;
1699             break;
1700         case 8:
1701             full_update |= update_palette256(s);
1702             v = VGA_DRAW_LINE8;
1703             bits = 8;
1704             break;
1705         case 15:
1706             v = VGA_DRAW_LINE15;
1707             bits = 16;
1708             break;
1709         case 16:
1710             v = VGA_DRAW_LINE16;
1711             bits = 16;
1712             break;
1713         case 24:
1714             v = VGA_DRAW_LINE24;
1715             bits = 24;
1716             break;
1717         case 32:
1718             v = VGA_DRAW_LINE32;
1719             bits = 32;
1720             break;
1721         }
1722     }
1723     vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1724
1725     if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1726         s->cursor_invalidate(s);
1727
1728     line_offset = s->line_offset;
1729 #if 0
1730     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",
1731            width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1732 #endif
1733     addr1 = (s->start_addr * 4);
1734     bwidth = (width * bits + 7) / 8;
1735     y_start = -1;
1736     page_min = -1;
1737     page_max = 0;
1738     d = ds_get_data(s->ds);
1739     linesize = ds_get_linesize(s->ds);
1740     y1 = 0;
1741     for(y = 0; y < height; y++) {
1742         addr = addr1;
1743         if (!(s->cr[0x17] & 1)) {
1744             int shift;
1745             /* CGA compatibility handling */
1746             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1747             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1748         }
1749         if (!(s->cr[0x17] & 2)) {
1750             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1751         }
1752         page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1753         page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1754         update = full_update |
1755             cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1756             cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1757         if ((page1 - page0) > TARGET_PAGE_SIZE) {
1758             /* if wide line, can use another page */
1759             update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1760                                                     VGA_DIRTY_FLAG);
1761         }
1762         /* explicit invalidation for the hardware cursor */
1763         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1764         if (update) {
1765             if (y_start < 0)
1766                 y_start = y;
1767             if (page0 < page_min)
1768                 page_min = page0;
1769             if (page1 > page_max)
1770                 page_max = page1;
1771             if (!(is_buffer_shared(s->ds->surface))) {
1772                 vga_draw_line(s, d, s->vram_ptr + addr, width);
1773                 if (s->cursor_draw_line)
1774                     s->cursor_draw_line(s, d, y);
1775             }
1776         } else {
1777             if (y_start >= 0) {
1778                 /* flush to display */
1779                 dpy_update(s->ds, 0, y_start,
1780                            disp_width, y - y_start);
1781                 y_start = -1;
1782             }
1783         }
1784         if (!multi_run) {
1785             mask = (s->cr[0x17] & 3) ^ 3;
1786             if ((y1 & mask) == mask)
1787                 addr1 += line_offset;
1788             y1++;
1789             multi_run = multi_scan;
1790         } else {
1791             multi_run--;
1792         }
1793         /* line compare acts on the displayed lines */
1794         if (y == s->line_compare)
1795             addr1 = 0;
1796         d += linesize;
1797     }
1798     if (y_start >= 0) {
1799         /* flush to display */
1800         dpy_update(s->ds, 0, y_start,
1801                    disp_width, y - y_start);
1802     }
1803     /* reset modified pages */
1804     if (page_max >= page_min) {
1805         cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1806                                         VGA_DIRTY_FLAG);
1807     }
1808     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1809 }
1810
1811 static void vga_draw_blank(VGACommonState *s, int full_update)
1812 {
1813     int i, w, val;
1814     uint8_t *d;
1815
1816     if (!full_update)
1817         return;
1818     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1819         return;
1820
1821     s->rgb_to_pixel =
1822         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1823     if (ds_get_bits_per_pixel(s->ds) == 8)
1824         val = s->rgb_to_pixel(0, 0, 0);
1825     else
1826         val = 0;
1827     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1828     d = ds_get_data(s->ds);
1829     for(i = 0; i < s->last_scr_height; i++) {
1830         memset(d, val, w);
1831         d += ds_get_linesize(s->ds);
1832     }
1833     dpy_update(s->ds, 0, 0,
1834                s->last_scr_width, s->last_scr_height);
1835 }
1836
1837 #define GMODE_TEXT     0
1838 #define GMODE_GRAPH    1
1839 #define GMODE_BLANK 2
1840
1841 static void vga_update_display(void *opaque)
1842 {
1843     VGACommonState *s = opaque;
1844     int full_update, graphic_mode;
1845
1846     if (ds_get_bits_per_pixel(s->ds) == 0) {
1847         /* nothing to do */
1848     } else {
1849         full_update = s->full_update;
1850         s->full_update = 0;
1851         if (!(s->ar_index & 0x20)) {
1852             graphic_mode = GMODE_BLANK;
1853         } else {
1854             graphic_mode = s->gr[6] & 1;
1855         }
1856         if (graphic_mode != s->graphic_mode) {
1857             s->graphic_mode = graphic_mode;
1858             full_update = 1;
1859         }
1860         switch(graphic_mode) {
1861         case GMODE_TEXT:
1862             vga_draw_text(s, full_update);
1863             break;
1864         case GMODE_GRAPH:
1865             vga_draw_graphic(s, full_update);
1866             break;
1867         case GMODE_BLANK:
1868         default:
1869             vga_draw_blank(s, full_update);
1870             break;
1871         }
1872     }
1873 }
1874
1875 /* force a full display refresh */
1876 static void vga_invalidate_display(void *opaque)
1877 {
1878     VGACommonState *s = opaque;
1879
1880     s->full_update = 1;
1881 }
1882
1883 void vga_common_reset(VGACommonState *s)
1884 {
1885     s->lfb_addr = 0;
1886     s->lfb_end = 0;
1887     s->map_addr = 0;
1888     s->map_end = 0;
1889     s->lfb_vram_mapped = 0;
1890     s->bios_offset = 0;
1891     s->bios_size = 0;
1892     s->sr_index = 0;
1893     memset(s->sr, '\0', sizeof(s->sr));
1894     s->gr_index = 0;
1895     memset(s->gr, '\0', sizeof(s->gr));
1896     s->ar_index = 0;
1897     memset(s->ar, '\0', sizeof(s->ar));
1898     s->ar_flip_flop = 0;
1899     s->cr_index = 0;
1900     memset(s->cr, '\0', sizeof(s->cr));
1901     s->msr = 0;
1902     s->fcr = 0;
1903     s->st00 = 0;
1904     s->st01 = 0;
1905     s->dac_state = 0;
1906     s->dac_sub_index = 0;
1907     s->dac_read_index = 0;
1908     s->dac_write_index = 0;
1909     memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1910     s->dac_8bit = 0;
1911     memset(s->palette, '\0', sizeof(s->palette));
1912     s->bank_offset = 0;
1913 #ifdef CONFIG_BOCHS_VBE
1914     s->vbe_index = 0;
1915     memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1916     s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1917     s->vbe_start_addr = 0;
1918     s->vbe_line_offset = 0;
1919     s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1920 #endif
1921     memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1922     s->graphic_mode = -1; /* force full update */
1923     s->shift_control = 0;
1924     s->double_scan = 0;
1925     s->line_offset = 0;
1926     s->line_compare = 0;
1927     s->start_addr = 0;
1928     s->plane_updated = 0;
1929     s->last_cw = 0;
1930     s->last_ch = 0;
1931     s->last_width = 0;
1932     s->last_height = 0;
1933     s->last_scr_width = 0;
1934     s->last_scr_height = 0;
1935     s->cursor_start = 0;
1936     s->cursor_end = 0;
1937     s->cursor_offset = 0;
1938     memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1939     memset(s->last_palette, '\0', sizeof(s->last_palette));
1940     memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1941     switch (vga_retrace_method) {
1942     case VGA_RETRACE_DUMB:
1943         break;
1944     case VGA_RETRACE_PRECISE:
1945         memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1946         break;
1947     }
1948 }
1949
1950 static void vga_reset(void *opaque)
1951 {
1952     VGACommonState *s =  opaque;
1953     vga_common_reset(s);
1954 }
1955
1956 #define TEXTMODE_X(x)   ((x) % width)
1957 #define TEXTMODE_Y(x)   ((x) / width)
1958 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1959         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1960 /* relay text rendering to the display driver
1961  * instead of doing a full vga_update_display() */
1962 static void vga_update_text(void *opaque, console_ch_t *chardata)
1963 {
1964     VGACommonState *s =  opaque;
1965     int graphic_mode, i, cursor_offset, cursor_visible;
1966     int cw, cheight, width, height, size, c_min, c_max;
1967     uint32_t *src;
1968     console_ch_t *dst, val;
1969     char msg_buffer[80];
1970     int full_update = 0;
1971
1972     if (!(s->ar_index & 0x20)) {
1973         graphic_mode = GMODE_BLANK;
1974     } else {
1975         graphic_mode = s->gr[6] & 1;
1976     }
1977     if (graphic_mode != s->graphic_mode) {
1978         s->graphic_mode = graphic_mode;
1979         full_update = 1;
1980     }
1981     if (s->last_width == -1) {
1982         s->last_width = 0;
1983         full_update = 1;
1984     }
1985
1986     switch (graphic_mode) {
1987     case GMODE_TEXT:
1988         /* TODO: update palette */
1989         full_update |= update_basic_params(s);
1990
1991         /* total width & height */
1992         cheight = (s->cr[9] & 0x1f) + 1;
1993         cw = 8;
1994         if (!(s->sr[1] & 0x01))
1995             cw = 9;
1996         if (s->sr[1] & 0x08)
1997             cw = 16; /* NOTE: no 18 pixel wide */
1998         width = (s->cr[0x01] + 1);
1999         if (s->cr[0x06] == 100) {
2000             /* ugly hack for CGA 160x100x16 - explain me the logic */
2001             height = 100;
2002         } else {
2003             height = s->cr[0x12] | 
2004                 ((s->cr[0x07] & 0x02) << 7) | 
2005                 ((s->cr[0x07] & 0x40) << 3);
2006             height = (height + 1) / cheight;
2007         }
2008
2009         size = (height * width);
2010         if (size > CH_ATTR_SIZE) {
2011             if (!full_update)
2012                 return;
2013
2014             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2015                      width, height);
2016             break;
2017         }
2018
2019         if (width != s->last_width || height != s->last_height ||
2020             cw != s->last_cw || cheight != s->last_ch) {
2021             s->last_scr_width = width * cw;
2022             s->last_scr_height = height * cheight;
2023             s->ds->surface->width = width;
2024             s->ds->surface->height = height;
2025             dpy_resize(s->ds);
2026             s->last_width = width;
2027             s->last_height = height;
2028             s->last_ch = cheight;
2029             s->last_cw = cw;
2030             full_update = 1;
2031         }
2032
2033         /* Update "hardware" cursor */
2034         cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2035         if (cursor_offset != s->cursor_offset ||
2036             s->cr[0xa] != s->cursor_start ||
2037             s->cr[0xb] != s->cursor_end || full_update) {
2038             cursor_visible = !(s->cr[0xa] & 0x20);
2039             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2040                 dpy_cursor(s->ds,
2041                            TEXTMODE_X(cursor_offset),
2042                            TEXTMODE_Y(cursor_offset));
2043             else
2044                 dpy_cursor(s->ds, -1, -1);
2045             s->cursor_offset = cursor_offset;
2046             s->cursor_start = s->cr[0xa];
2047             s->cursor_end = s->cr[0xb];
2048         }
2049
2050         src = (uint32_t *) s->vram_ptr + s->start_addr;
2051         dst = chardata;
2052
2053         if (full_update) {
2054             for (i = 0; i < size; src ++, dst ++, i ++)
2055                 console_write_ch(dst, VMEM2CHTYPE(*src));
2056
2057             dpy_update(s->ds, 0, 0, width, height);
2058         } else {
2059             c_max = 0;
2060
2061             for (i = 0; i < size; src ++, dst ++, i ++) {
2062                 console_write_ch(&val, VMEM2CHTYPE(*src));
2063                 if (*dst != val) {
2064                     *dst = val;
2065                     c_max = i;
2066                     break;
2067                 }
2068             }
2069             c_min = i;
2070             for (; i < size; src ++, dst ++, i ++) {
2071                 console_write_ch(&val, VMEM2CHTYPE(*src));
2072                 if (*dst != val) {
2073                     *dst = val;
2074                     c_max = i;
2075                 }
2076             }
2077
2078             if (c_min <= c_max) {
2079                 i = TEXTMODE_Y(c_min);
2080                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2081             }
2082         }
2083
2084         return;
2085     case GMODE_GRAPH:
2086         if (!full_update)
2087             return;
2088
2089         s->get_resolution(s, &width, &height);
2090         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2091                  width, height);
2092         break;
2093     case GMODE_BLANK:
2094     default:
2095         if (!full_update)
2096             return;
2097
2098         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2099         break;
2100     }
2101
2102     /* Display a message */
2103     s->last_width = 60;
2104     s->last_height = height = 3;
2105     dpy_cursor(s->ds, -1, -1);
2106     s->ds->surface->width = s->last_width;
2107     s->ds->surface->height = height;
2108     dpy_resize(s->ds);
2109
2110     for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2111         console_write_ch(dst ++, ' ');
2112
2113     size = strlen(msg_buffer);
2114     width = (s->last_width - size) / 2;
2115     dst = chardata + s->last_width + width;
2116     for (i = 0; i < size; i ++)
2117         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2118
2119     dpy_update(s->ds, 0, 0, s->last_width, height);
2120 }
2121
2122 CPUReadMemoryFunc * const vga_mem_read[3] = {
2123     vga_mem_readb,
2124     vga_mem_readw,
2125     vga_mem_readl,
2126 };
2127
2128 CPUWriteMemoryFunc * const vga_mem_write[3] = {
2129     vga_mem_writeb,
2130     vga_mem_writew,
2131     vga_mem_writel,
2132 };
2133
2134 void vga_common_save(QEMUFile *f, void *opaque)
2135 {
2136     VGACommonState *s = opaque;
2137     int i;
2138
2139     qemu_put_be32s(f, &s->latch);
2140     qemu_put_8s(f, &s->sr_index);
2141     qemu_put_buffer(f, s->sr, 8);
2142     qemu_put_8s(f, &s->gr_index);
2143     qemu_put_buffer(f, s->gr, 16);
2144     qemu_put_8s(f, &s->ar_index);
2145     qemu_put_buffer(f, s->ar, 21);
2146     qemu_put_be32(f, s->ar_flip_flop);
2147     qemu_put_8s(f, &s->cr_index);
2148     qemu_put_buffer(f, s->cr, 256);
2149     qemu_put_8s(f, &s->msr);
2150     qemu_put_8s(f, &s->fcr);
2151     qemu_put_byte(f, s->st00);
2152     qemu_put_8s(f, &s->st01);
2153
2154     qemu_put_8s(f, &s->dac_state);
2155     qemu_put_8s(f, &s->dac_sub_index);
2156     qemu_put_8s(f, &s->dac_read_index);
2157     qemu_put_8s(f, &s->dac_write_index);
2158     qemu_put_buffer(f, s->dac_cache, 3);
2159     qemu_put_buffer(f, s->palette, 768);
2160
2161     qemu_put_be32(f, s->bank_offset);
2162 #ifdef CONFIG_BOCHS_VBE
2163     qemu_put_byte(f, 1);
2164     qemu_put_be16s(f, &s->vbe_index);
2165     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2166         qemu_put_be16s(f, &s->vbe_regs[i]);
2167     qemu_put_be32s(f, &s->vbe_start_addr);
2168     qemu_put_be32s(f, &s->vbe_line_offset);
2169     qemu_put_be32s(f, &s->vbe_bank_mask);
2170 #else
2171     qemu_put_byte(f, 0);
2172 #endif
2173 }
2174
2175 int vga_common_load(QEMUFile *f, void *opaque, int version_id)
2176 {
2177     VGACommonState *s = opaque;
2178     int is_vbe, i;
2179
2180     if (version_id > 2)
2181         return -EINVAL;
2182
2183     qemu_get_be32s(f, &s->latch);
2184     qemu_get_8s(f, &s->sr_index);
2185     qemu_get_buffer(f, s->sr, 8);
2186     qemu_get_8s(f, &s->gr_index);
2187     qemu_get_buffer(f, s->gr, 16);
2188     qemu_get_8s(f, &s->ar_index);
2189     qemu_get_buffer(f, s->ar, 21);
2190     s->ar_flip_flop=qemu_get_be32(f);
2191     qemu_get_8s(f, &s->cr_index);
2192     qemu_get_buffer(f, s->cr, 256);
2193     qemu_get_8s(f, &s->msr);
2194     qemu_get_8s(f, &s->fcr);
2195     qemu_get_8s(f, &s->st00);
2196     qemu_get_8s(f, &s->st01);
2197
2198     qemu_get_8s(f, &s->dac_state);
2199     qemu_get_8s(f, &s->dac_sub_index);
2200     qemu_get_8s(f, &s->dac_read_index);
2201     qemu_get_8s(f, &s->dac_write_index);
2202     qemu_get_buffer(f, s->dac_cache, 3);
2203     qemu_get_buffer(f, s->palette, 768);
2204
2205     s->bank_offset=qemu_get_be32(f);
2206     is_vbe = qemu_get_byte(f);
2207 #ifdef CONFIG_BOCHS_VBE
2208     if (!is_vbe)
2209         return -EINVAL;
2210     qemu_get_be16s(f, &s->vbe_index);
2211     for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
2212         qemu_get_be16s(f, &s->vbe_regs[i]);
2213     qemu_get_be32s(f, &s->vbe_start_addr);
2214     qemu_get_be32s(f, &s->vbe_line_offset);
2215     qemu_get_be32s(f, &s->vbe_bank_mask);
2216 #else
2217     if (is_vbe)
2218         return -EINVAL;
2219 #endif
2220
2221     /* force refresh */
2222     s->graphic_mode = -1;
2223     return 0;
2224 }
2225
2226 void vga_common_init(VGACommonState *s, int vga_ram_size)
2227 {
2228     int i, j, v, b;
2229
2230     for(i = 0;i < 256; i++) {
2231         v = 0;
2232         for(j = 0; j < 8; j++) {
2233             v |= ((i >> j) & 1) << (j * 4);
2234         }
2235         expand4[i] = v;
2236
2237         v = 0;
2238         for(j = 0; j < 4; j++) {
2239             v |= ((i >> (2 * j)) & 3) << (j * 4);
2240         }
2241         expand2[i] = v;
2242     }
2243     for(i = 0; i < 16; i++) {
2244         v = 0;
2245         for(j = 0; j < 4; j++) {
2246             b = ((i >> j) & 1);
2247             v |= b << (2 * j);
2248             v |= b << (2 * j + 1);
2249         }
2250         expand4to8[i] = v;
2251     }
2252
2253     s->vram_offset = qemu_ram_alloc(vga_ram_size);
2254     s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2255     s->vram_size = vga_ram_size;
2256     s->get_bpp = vga_get_bpp;
2257     s->get_offsets = vga_get_offsets;
2258     s->get_resolution = vga_get_resolution;
2259     s->update = vga_update_display;
2260     s->invalidate = vga_invalidate_display;
2261     s->screen_dump = vga_screen_dump;
2262     s->text_update = vga_update_text;
2263     switch (vga_retrace_method) {
2264     case VGA_RETRACE_DUMB:
2265         s->retrace = vga_dumb_retrace;
2266         s->update_retrace_info = vga_dumb_update_retrace_info;
2267         break;
2268
2269     case VGA_RETRACE_PRECISE:
2270         s->retrace = vga_precise_retrace;
2271         s->update_retrace_info = vga_precise_update_retrace_info;
2272         break;
2273     }
2274     vga_reset(s);
2275 }
2276
2277 /* used by both ISA and PCI */
2278 void vga_init(VGACommonState *s)
2279 {
2280     int vga_io_memory;
2281
2282     qemu_register_reset(vga_reset, s);
2283
2284     register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2285
2286     register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2287     register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2288     register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2289     register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2290
2291     register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2292
2293     register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2294     register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2295     register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2296     register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2297     s->bank_offset = 0;
2298
2299 #ifdef CONFIG_BOCHS_VBE
2300 #if defined (TARGET_I386)
2301     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2302     register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2303
2304     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2305     register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2306
2307     /* old Bochs IO ports */
2308     register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
2309     register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
2310
2311     register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
2312     register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
2313 #else
2314     register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2315     register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2316
2317     register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2318     register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2319 #endif
2320 #endif /* CONFIG_BOCHS_VBE */
2321
2322     vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2323     cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2324                                  vga_io_memory);
2325     qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2326 }
2327
2328 /********************************************************/
2329 /* vga screen dump */
2330
2331 static void vga_save_dpy_update(DisplayState *ds,
2332                                 int x, int y, int w, int h)
2333 {
2334     if (screen_dump_filename) {
2335         ppm_save(screen_dump_filename, ds->surface);
2336         screen_dump_filename = NULL;
2337     }
2338 }
2339
2340 static void vga_save_dpy_resize(DisplayState *s)
2341 {
2342 }
2343
2344 static void vga_save_dpy_refresh(DisplayState *s)
2345 {
2346 }
2347
2348 int ppm_save(const char *filename, struct DisplaySurface *ds)
2349 {
2350     FILE *f;
2351     uint8_t *d, *d1;
2352     uint32_t v;
2353     int y, x;
2354     uint8_t r, g, b;
2355
2356     f = fopen(filename, "wb");
2357     if (!f)
2358         return -1;
2359     fprintf(f, "P6\n%d %d\n%d\n",
2360             ds->width, ds->height, 255);
2361     d1 = ds->data;
2362     for(y = 0; y < ds->height; y++) {
2363         d = d1;
2364         for(x = 0; x < ds->width; x++) {
2365             if (ds->pf.bits_per_pixel == 32)
2366                 v = *(uint32_t *)d;
2367             else
2368                 v = (uint32_t) (*(uint16_t *)d);
2369             r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2370                 (ds->pf.rmax + 1);
2371             g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2372                 (ds->pf.gmax + 1);
2373             b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2374                 (ds->pf.bmax + 1);
2375             fputc(r, f);
2376             fputc(g, f);
2377             fputc(b, f);
2378             d += ds->pf.bytes_per_pixel;
2379         }
2380         d1 += ds->linesize;
2381     }
2382     fclose(f);
2383     return 0;
2384 }
2385
2386 static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2387 {
2388     DisplayChangeListener *dcl;
2389
2390     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2391     dcl->dpy_update = vga_save_dpy_update;
2392     dcl->dpy_resize = vga_save_dpy_resize;
2393     dcl->dpy_refresh = vga_save_dpy_refresh;
2394     register_displaychangelistener(ds, dcl);
2395     return dcl;
2396 }
2397
2398 /* save the vga display in a PPM image even if no display is
2399    available */
2400 static void vga_screen_dump(void *opaque, const char *filename)
2401 {
2402     VGACommonState *s = opaque;
2403
2404     if (!screen_dump_dcl)
2405         screen_dump_dcl = vga_screen_dump_init(s->ds);
2406
2407     screen_dump_filename = (char *)filename;
2408     vga_invalidate_display(s);
2409     vga_hw_update();
2410 }
2411
This page took 0.152317 seconds and 4 git commands to generate.