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