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