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