update source for tizen_2.1
[sdk/emulator/qemu.git] / tizen / src / hw / maru_vga.c
1 /*
2  * Maru vga device
3  * Based on qemu/hw/vga.c
4  *
5  * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
6  *
7  * Contact:
8  * GiWoong Kim <giwoong.kim@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  * HyunJun Son
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31
32 #include "maru_common.h"
33
34 #include "hw.h"
35 #include "vga.h"
36 #include "console.h"
37 #include "pc.h"
38 #include "pci.h"
39 #include "vga_int.h"
40 #include "pixel_ops.h"
41 #include "qemu-timer.h"
42 #include "xen.h"
43 #include "trace.h"
44
45 #include "maru_vga_int.h"
46 #include "maru_brightness.h"
47 #include "maru_overlay.h"
48 #include "maru_display.h"
49 #include "emul_state.h"
50 #include "debug_ch.h"
51 #include <pthread.h>
52
53 #ifdef CONFIG_USE_SHM
54 #include "emulator.h"
55 #include <sys/types.h>
56 #include <sys/ipc.h>
57 #include <sys/shm.h>
58 #include "maru_err_table.h"
59 #include "emul_state.h"
60 #endif
61
62 #ifdef CONFIG_USE_SHM
63 void *shared_memory = (void*) 0;
64 int skin_shmid;
65 #endif
66
67
68 MULTI_DEBUG_CHANNEL(qemu, maru_vga);
69
70 extern pthread_mutex_t mutex_screenshot;
71 extern pthread_cond_t cond_screenshot;
72
73 //#define DEBUG_VGA
74 //#define DEBUG_VGA_MEM
75 //#define DEBUG_VGA_REG
76
77 //#define DEBUG_BOCHS_VBE
78
79 /* 16 state changes per vertical frame @60 Hz */
80 #define VGA_TEXT_CURSOR_PERIOD_MS       (1000 * 2 * 16 / 60)
81
82 #define cbswap_32(__x) \
83 ((uint32_t)( \
84         (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
85         (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
86         (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
87         (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
88
89 #ifdef HOST_WORDS_BIGENDIAN
90 #define PAT(x) cbswap_32(x)
91 #else
92 #define PAT(x) (x)
93 #endif
94
95 #ifdef HOST_WORDS_BIGENDIAN
96 #define BIG 1
97 #else
98 #define BIG 0
99 #endif
100
101 #ifdef HOST_WORDS_BIGENDIAN
102 #define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
103 #else
104 #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
105 #endif
106
107 #define MARU_VGA
108
109 static const uint32_t mask16[16] = {
110     PAT(0x00000000),
111     PAT(0x000000ff),
112     PAT(0x0000ff00),
113     PAT(0x0000ffff),
114     PAT(0x00ff0000),
115     PAT(0x00ff00ff),
116     PAT(0x00ffff00),
117     PAT(0x00ffffff),
118     PAT(0xff000000),
119     PAT(0xff0000ff),
120     PAT(0xff00ff00),
121     PAT(0xff00ffff),
122     PAT(0xffff0000),
123     PAT(0xffff00ff),
124     PAT(0xffffff00),
125     PAT(0xffffffff),
126 };
127
128 #undef PAT
129
130 #ifdef HOST_WORDS_BIGENDIAN
131 #define PAT(x) (x)
132 #else
133 #define PAT(x) cbswap_32(x)
134 #endif
135
136 static const uint32_t dmask16[16] = {
137     PAT(0x00000000),
138     PAT(0x000000ff),
139     PAT(0x0000ff00),
140     PAT(0x0000ffff),
141     PAT(0x00ff0000),
142     PAT(0x00ff00ff),
143     PAT(0x00ffff00),
144     PAT(0x00ffffff),
145     PAT(0xff000000),
146     PAT(0xff0000ff),
147     PAT(0xff00ff00),
148     PAT(0xff00ffff),
149     PAT(0xffff0000),
150     PAT(0xffff00ff),
151     PAT(0xffffff00),
152     PAT(0xffffffff),
153 };
154
155 static const uint32_t dmask4[4] = {
156     PAT(0x00000000),
157     PAT(0x0000ffff),
158     PAT(0xffff0000),
159     PAT(0xffffffff),
160 };
161
162 static uint32_t expand4[256];
163 static uint16_t expand2[256];
164 static uint8_t expand4to8[16];
165
166 static void vga_screen_dump(void *opaque, const char *filename, bool cswitch);
167
168 static void vga_update_memory_access(VGACommonState *s)
169 {
170     MemoryRegion *region, *old_region = s->chain4_alias;
171     target_phys_addr_t base, offset, size;
172
173     s->chain4_alias = NULL;
174
175     if ((s->sr[VGA_SEQ_PLANE_WRITE] & VGA_SR02_ALL_PLANES) ==
176         VGA_SR02_ALL_PLANES && s->sr[VGA_SEQ_MEMORY_MODE] & VGA_SR04_CHN_4M) {
177         offset = 0;
178         switch ((s->gr[VGA_GFX_MISC] >> 2) & 3) {
179         case 0:
180             base = 0xa0000;
181             size = 0x20000;
182             break;
183         case 1:
184             base = 0xa0000;
185             size = 0x10000;
186             offset = s->bank_offset;
187             break;
188         case 2:
189             base = 0xb0000;
190             size = 0x8000;
191             break;
192         case 3:
193         default:
194             base = 0xb8000;
195             size = 0x8000;
196             break;
197         }
198         base += isa_mem_base;
199         region = g_malloc(sizeof(*region));
200         memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size);
201         memory_region_add_subregion_overlap(s->legacy_address_space, base,
202                                             region, 2);
203         s->chain4_alias = region;
204     }
205     if (old_region) {
206         memory_region_del_subregion(s->legacy_address_space, old_region);
207         memory_region_destroy(old_region);
208         g_free(old_region);
209         s->plane_updated = 0xf;
210     }
211 }
212
213 static void vga_dumb_update_retrace_info(VGACommonState *s)
214 {
215     (void) s;
216 }
217
218 static void vga_precise_update_retrace_info(VGACommonState *s)
219 {
220     int htotal_chars;
221     int hretr_start_char;
222     int hretr_skew_chars;
223     int hretr_end_char;
224
225     int vtotal_lines;
226     int vretr_start_line;
227     int vretr_end_line;
228
229     int dots;
230 #if 0
231     int div2, sldiv2;
232 #endif
233     int clocking_mode;
234     int clock_sel;
235     const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
236     int64_t chars_per_sec;
237     struct vga_precise_retrace *r = &s->retrace_info.precise;
238
239     htotal_chars = s->cr[VGA_CRTC_H_TOTAL] + 5;
240     hretr_start_char = s->cr[VGA_CRTC_H_SYNC_START];
241     hretr_skew_chars = (s->cr[VGA_CRTC_H_SYNC_END] >> 5) & 3;
242     hretr_end_char = s->cr[VGA_CRTC_H_SYNC_END] & 0x1f;
243
244     vtotal_lines = (s->cr[VGA_CRTC_V_TOTAL] |
245                     (((s->cr[VGA_CRTC_OVERFLOW] & 1) |
246                       ((s->cr[VGA_CRTC_OVERFLOW] >> 4) & 2)) << 8)) + 2;
247     vretr_start_line = s->cr[VGA_CRTC_V_SYNC_START] |
248         ((((s->cr[VGA_CRTC_OVERFLOW] >> 2) & 1) |
249           ((s->cr[VGA_CRTC_OVERFLOW] >> 6) & 2)) << 8);
250     vretr_end_line = s->cr[VGA_CRTC_V_SYNC_END] & 0xf;
251
252     clocking_mode = (s->sr[VGA_SEQ_CLOCK_MODE] >> 3) & 1;
253     clock_sel = (s->msr >> 2) & 3;
254     dots = (s->msr & 1) ? 8 : 9;
255
256     chars_per_sec = clk_hz[clock_sel] / dots;
257
258     htotal_chars <<= clocking_mode;
259
260     r->total_chars = vtotal_lines * htotal_chars;
261     if (r->freq) {
262         r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
263     } else {
264         r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
265     }
266
267     r->vstart = vretr_start_line;
268     r->vend = r->vstart + vretr_end_line + 1;
269
270     r->hstart = hretr_start_char + hretr_skew_chars;
271     r->hend = r->hstart + hretr_end_char + 1;
272     r->htotal = htotal_chars;
273
274 #if 0
275     div2 = (s->cr[VGA_CRTC_MODE] >> 2) & 1;
276     sldiv2 = (s->cr[VGA_CRTC_MODE] >> 3) & 1;
277     printf (
278         "hz=%f\n"
279         "htotal = %d\n"
280         "hretr_start = %d\n"
281         "hretr_skew = %d\n"
282         "hretr_end = %d\n"
283         "vtotal = %d\n"
284         "vretr_start = %d\n"
285         "vretr_end = %d\n"
286         "div2 = %d sldiv2 = %d\n"
287         "clocking_mode = %d\n"
288         "clock_sel = %d %d\n"
289         "dots = %d\n"
290         "ticks/char = %" PRId64 "\n"
291         "\n",
292         (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
293         htotal_chars,
294         hretr_start_char,
295         hretr_skew_chars,
296         hretr_end_char,
297         vtotal_lines,
298         vretr_start_line,
299         vretr_end_line,
300         div2, sldiv2,
301         clocking_mode,
302         clock_sel,
303         clk_hz[clock_sel],
304         dots,
305         r->ticks_per_char
306         );
307 #endif
308 }
309
310 static uint8_t vga_precise_retrace(VGACommonState *s)
311 {
312     struct vga_precise_retrace *r = &s->retrace_info.precise;
313     uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
314
315     if (r->total_chars) {
316         int cur_line, cur_line_char, cur_char;
317         int64_t cur_tick;
318
319         cur_tick = qemu_get_clock_ns(vm_clock);
320
321         cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
322         cur_line = cur_char / r->htotal;
323
324         if (cur_line >= r->vstart && cur_line <= r->vend) {
325             val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
326         } else {
327             cur_line_char = cur_char % r->htotal;
328             if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
329                 val |= ST01_DISP_ENABLE;
330             }
331         }
332
333         return val;
334     } else {
335         return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
336     }
337 }
338
339 static uint8_t vga_dumb_retrace(VGACommonState *s)
340 {
341     return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
342 }
343
344 #ifdef CONFIG_BOCHS_VBE
345 static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
346 {
347     VGACommonState *s = opaque;
348     uint32_t val;
349     val = s->vbe_index;
350     return val;
351 }
352
353 static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
354 {
355     VGACommonState *s = opaque;
356     uint32_t val;
357
358     if (s->vbe_index < VBE_DISPI_INDEX_NB) {
359         if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
360             switch(s->vbe_index) {
361                 /* XXX: do not hardcode ? */
362             case VBE_DISPI_INDEX_XRES:
363                 val = VBE_DISPI_MAX_XRES;
364                 break;
365             case VBE_DISPI_INDEX_YRES:
366                 val = VBE_DISPI_MAX_YRES;
367                 break;
368             case VBE_DISPI_INDEX_BPP:
369                 val = VBE_DISPI_MAX_BPP;
370                 break;
371             default:
372                 val = s->vbe_regs[s->vbe_index];
373                 break;
374             }
375         } else {
376             val = s->vbe_regs[s->vbe_index];
377         }
378     } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
379         val = s->vram_size / (64 * 1024);
380     } else {
381         val = 0;
382     }
383 #ifdef DEBUG_BOCHS_VBE
384     printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
385 #endif
386     return val;
387 }
388
389 static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
390 {
391     VGACommonState *s = opaque;
392     s->vbe_index = val;
393 }
394
395 static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
396 {
397     VGACommonState *s = opaque;
398
399     if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
400 #ifdef DEBUG_BOCHS_VBE
401         printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
402 #endif
403         switch(s->vbe_index) {
404         case VBE_DISPI_INDEX_ID:
405             if (val == VBE_DISPI_ID0 ||
406                 val == VBE_DISPI_ID1 ||
407                 val == VBE_DISPI_ID2 ||
408                 val == VBE_DISPI_ID3 ||
409                 val == VBE_DISPI_ID4) {
410                 s->vbe_regs[s->vbe_index] = val;
411             }
412             break;
413         case VBE_DISPI_INDEX_XRES:
414             if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
415                 s->vbe_regs[s->vbe_index] = val;
416             }
417             break;
418         case VBE_DISPI_INDEX_YRES:
419             if (val <= VBE_DISPI_MAX_YRES) {
420                 s->vbe_regs[s->vbe_index] = val;
421             }
422             break;
423         case VBE_DISPI_INDEX_BPP:
424             if (val == 0)
425                 val = 8;
426             if (val == 4 || val == 8 || val == 15 ||
427                 val == 16 || val == 24 || val == 32) {
428                 s->vbe_regs[s->vbe_index] = val;
429             }
430             break;
431         case VBE_DISPI_INDEX_BANK:
432             if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
433               val &= (s->vbe_bank_mask >> 2);
434             } else {
435               val &= s->vbe_bank_mask;
436             }
437             s->vbe_regs[s->vbe_index] = val;
438             s->bank_offset = (val << 16);
439             vga_update_memory_access(s);
440             break;
441         case VBE_DISPI_INDEX_ENABLE:
442             if ((val & VBE_DISPI_ENABLED) &&
443                 !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
444                 int h, shift_control;
445
446                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
447                     s->vbe_regs[VBE_DISPI_INDEX_XRES];
448                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
449                     s->vbe_regs[VBE_DISPI_INDEX_YRES];
450                 s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
451                 s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
452
453                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
454                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
455                 else
456                     s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
457                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
458                 s->vbe_start_addr = 0;
459
460                 /* clear the screen (should be done in BIOS) */
461                 if (!(val & VBE_DISPI_NOCLEARMEM)) {
462                     memset(s->vram_ptr, 0,
463                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
464                 }
465
466                 /* we initialize the VGA graphic mode (should be done
467                    in BIOS) */
468                 /* graphic mode + memory map 1 */
469                 s->gr[VGA_GFX_MISC] = (s->gr[VGA_GFX_MISC] & ~0x0c) | 0x04 |
470                     VGA_GR06_GRAPHICS_MODE;
471                 s->cr[VGA_CRTC_MODE] |= 3; /* no CGA modes */
472                 s->cr[VGA_CRTC_OFFSET] = s->vbe_line_offset >> 3;
473                 /* width */
474                 s->cr[VGA_CRTC_H_DISP] =
475                     (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
476                 /* height (only meaningful if < 1024) */
477                 h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
478                 s->cr[VGA_CRTC_V_DISP_END] = h;
479                 s->cr[VGA_CRTC_OVERFLOW] = (s->cr[VGA_CRTC_OVERFLOW] & ~0x42) |
480                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
481                 /* line compare to 1023 */
482                 s->cr[VGA_CRTC_LINE_COMPARE] = 0xff;
483                 s->cr[VGA_CRTC_OVERFLOW] |= 0x10;
484                 s->cr[VGA_CRTC_MAX_SCAN] |= 0x40;
485
486                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
487                     shift_control = 0;
488                     s->sr[VGA_SEQ_CLOCK_MODE] &= ~8; /* no double line */
489                 } else {
490                     shift_control = 2;
491                     /* set chain 4 mode */
492                     s->sr[VGA_SEQ_MEMORY_MODE] |= VGA_SR04_CHN_4M;
493                     /* activate all planes */
494                     s->sr[VGA_SEQ_PLANE_WRITE] |= VGA_SR02_ALL_PLANES;
495                 }
496                 s->gr[VGA_GFX_MODE] = (s->gr[VGA_GFX_MODE] & ~0x60) |
497                     (shift_control << 5);
498                 s->cr[VGA_CRTC_MAX_SCAN] &= ~0x9f; /* no double scan */
499             } else {
500                 /* XXX: the bios should do that */
501                 s->bank_offset = 0;
502             }
503             s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
504             s->vbe_regs[s->vbe_index] = val;
505             vga_update_memory_access(s);
506             break;
507         case VBE_DISPI_INDEX_VIRT_WIDTH:
508             {
509                 int w, h, line_offset;
510
511                 if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
512                     return;
513                 w = val;
514                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
515                     line_offset = w >> 1;
516                 else
517                     line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
518                 h = s->vram_size / line_offset;
519                 /* XXX: support weird bochs semantics ? */
520                 if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
521                     return;
522                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
523                 s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
524                 s->vbe_line_offset = line_offset;
525             }
526             break;
527         case VBE_DISPI_INDEX_X_OFFSET:
528         case VBE_DISPI_INDEX_Y_OFFSET:
529             {
530                 int x;
531                 s->vbe_regs[s->vbe_index] = val;
532                 s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
533                 x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
534                 if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
535                     s->vbe_start_addr += x >> 1;
536                 else
537                     s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
538                 s->vbe_start_addr >>= 2;
539             }
540             break;
541         default:
542             break;
543         }
544     }
545 }
546 #endif
547
548 typedef void maru_vga_draw_glyph8_func(uint8_t *d, int linesize,
549                              const uint8_t *font_ptr, int h,
550                              uint32_t fgcol, uint32_t bgcol);
551 typedef void maru_vga_draw_glyph9_func(uint8_t *d, int linesize,
552                                   const uint8_t *font_ptr, int h,
553                                   uint32_t fgcol, uint32_t bgcol, int dup9);
554 typedef void maru_vga_draw_line_func(VGACommonState *s1, uint8_t *d,
555                                 const uint8_t *s, int width);
556
557 #define DEPTH 8
558 #include "maru_vga_template.h"
559
560 #define DEPTH 15
561 #include "maru_vga_template.h"
562
563 #define BGR_FORMAT
564 #define DEPTH 15
565 #include "maru_vga_template.h"
566
567 #define DEPTH 16
568 #include "maru_vga_template.h"
569
570 #define BGR_FORMAT
571 #define DEPTH 16
572 #include "maru_vga_template.h"
573
574 #define DEPTH 32
575 #include "maru_vga_template.h"
576
577 #define BGR_FORMAT
578 #define DEPTH 32
579 #include "maru_vga_template.h"
580
581 static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
582 {
583     unsigned int col;
584     col = rgb_to_pixel8(r, g, b);
585     col |= col << 8;
586     col |= col << 16;
587     return col;
588 }
589
590 static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
591 {
592     unsigned int col;
593     col = rgb_to_pixel15(r, g, b);
594     col |= col << 16;
595     return col;
596 }
597
598 static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
599                                           unsigned int b)
600 {
601     unsigned int col;
602     col = rgb_to_pixel15bgr(r, g, b);
603     col |= col << 16;
604     return col;
605 }
606
607 static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
608 {
609     unsigned int col;
610     col = rgb_to_pixel16(r, g, b);
611     col |= col << 16;
612     return col;
613 }
614
615 static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
616                                           unsigned int b)
617 {
618     unsigned int col;
619     col = rgb_to_pixel16bgr(r, g, b);
620     col |= col << 16;
621     return col;
622 }
623
624 static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
625 {
626     unsigned int col;
627     col = rgb_to_pixel32(r, g, b);
628     return col;
629 }
630
631 static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
632 {
633     unsigned int col;
634     col = rgb_to_pixel32bgr(r, g, b);
635     return col;
636 }
637
638 /* return true if the palette was modified */
639 static int update_palette16(VGACommonState *s)
640 {
641     int full_update, i;
642     uint32_t v, col, *palette;
643
644     full_update = 0;
645     palette = s->last_palette;
646     for(i = 0; i < 16; i++) {
647         v = s->ar[i];
648         if (s->ar[VGA_ATC_MODE] & 0x80) {
649             v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xf) << 4) | (v & 0xf);
650         } else {
651             v = ((s->ar[VGA_ATC_COLOR_PAGE] & 0xc) << 4) | (v & 0x3f);
652         }
653         v = v * 3;
654         col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
655                               c6_to_8(s->palette[v + 1]),
656                               c6_to_8(s->palette[v + 2]));
657         if (col != palette[i]) {
658             full_update = 1;
659             palette[i] = col;
660         }
661     }
662     return full_update;
663 }
664
665 /* return true if the palette was modified */
666 static int update_palette256(VGACommonState *s)
667 {
668     int full_update, i;
669     uint32_t v, col, *palette;
670
671     full_update = 0;
672     palette = s->last_palette;
673     v = 0;
674     for(i = 0; i < 256; i++) {
675         if (s->dac_8bit) {
676           col = s->rgb_to_pixel(s->palette[v],
677                                 s->palette[v + 1],
678                                 s->palette[v + 2]);
679         } else {
680           col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
681                                 c6_to_8(s->palette[v + 1]),
682                                 c6_to_8(s->palette[v + 2]));
683         }
684         if (col != palette[i]) {
685             full_update = 1;
686             palette[i] = col;
687         }
688         v += 3;
689     }
690     return full_update;
691 }
692
693 static void vga_get_offsets(VGACommonState *s,
694                             uint32_t *pline_offset,
695                             uint32_t *pstart_addr,
696                             uint32_t *pline_compare)
697 {
698     uint32_t start_addr, line_offset, line_compare;
699 #ifdef CONFIG_BOCHS_VBE
700     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
701         line_offset = s->vbe_line_offset;
702         start_addr = s->vbe_start_addr;
703         line_compare = 65535;
704     } else
705 #endif
706     {
707         /* compute line_offset in bytes */
708         line_offset = s->cr[VGA_CRTC_OFFSET];
709         line_offset <<= 3;
710
711         /* starting address */
712         start_addr = s->cr[VGA_CRTC_START_LO] |
713             (s->cr[VGA_CRTC_START_HI] << 8);
714
715         /* line compare */
716         line_compare = s->cr[VGA_CRTC_LINE_COMPARE] |
717             ((s->cr[VGA_CRTC_OVERFLOW] & 0x10) << 4) |
718             ((s->cr[VGA_CRTC_MAX_SCAN] & 0x40) << 3);
719     }
720     *pline_offset = line_offset;
721     *pstart_addr = start_addr;
722     *pline_compare = line_compare;
723 }
724
725 /* update start_addr and line_offset. Return TRUE if modified */
726 static int update_basic_params(VGACommonState *s)
727 {
728     int full_update;
729     uint32_t start_addr, line_offset, line_compare;
730
731     full_update = 0;
732
733     s->get_offsets(s, &line_offset, &start_addr, &line_compare);
734
735     if (line_offset != s->line_offset ||
736         start_addr != s->start_addr ||
737         line_compare != s->line_compare) {
738         s->line_offset = line_offset;
739         s->start_addr = start_addr;
740         s->line_compare = line_compare;
741         full_update = 1;
742     }
743     return full_update;
744 }
745
746 #define NB_DEPTHS 7
747
748 static inline int get_depth_index(DisplayState *s)
749 {
750     switch(ds_get_bits_per_pixel(s)) {
751     default:
752     case 8:
753         return 0;
754     case 15:
755         return 1;
756     case 16:
757         return 2;
758     case 32:
759         if (is_surface_bgr(s->surface))
760             return 4;
761         else
762             return 3;
763     }
764 }
765
766 static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph8_table[NB_DEPTHS] = {
767     maru_vga_draw_glyph8_8,
768     maru_vga_draw_glyph8_16,
769     maru_vga_draw_glyph8_16,
770     maru_vga_draw_glyph8_32,
771     maru_vga_draw_glyph8_32,
772     maru_vga_draw_glyph8_16,
773     maru_vga_draw_glyph8_16,
774 };
775
776 static maru_vga_draw_glyph8_func * const maru_vga_draw_glyph16_table[NB_DEPTHS] = {
777     maru_vga_draw_glyph16_8,
778     maru_vga_draw_glyph16_16,
779     maru_vga_draw_glyph16_16,
780     maru_vga_draw_glyph16_32,
781     maru_vga_draw_glyph16_32,
782     maru_vga_draw_glyph16_16,
783     maru_vga_draw_glyph16_16,
784 };
785
786 static maru_vga_draw_glyph9_func * const maru_vga_draw_glyph9_table[NB_DEPTHS] = {
787     maru_vga_draw_glyph9_8,
788     maru_vga_draw_glyph9_16,
789     maru_vga_draw_glyph9_16,
790     maru_vga_draw_glyph9_32,
791     maru_vga_draw_glyph9_32,
792     maru_vga_draw_glyph9_16,
793     maru_vga_draw_glyph9_16,
794 };
795
796 static const uint8_t cursor_glyph[32 * 4] = {
797     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
798     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
799     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
800     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
801     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
802     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
803     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
804     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
805     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
806     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
807     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
808     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
809     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
810     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
811     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
812     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
813 };
814
815 static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
816                                     int *pcwidth, int *pcheight)
817 {
818     int width, cwidth, height, cheight;
819
820     /* total width & height */
821     cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
822     cwidth = 8;
823     if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
824         cwidth = 9;
825     }
826     if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
827         cwidth = 16; /* NOTE: no 18 pixel wide */
828     }
829     width = (s->cr[VGA_CRTC_H_DISP] + 1);
830     if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
831         /* ugly hack for CGA 160x100x16 - explain me the logic */
832         height = 100;
833     } else {
834         height = s->cr[VGA_CRTC_V_DISP_END] |
835             ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
836             ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
837         height = (height + 1) / cheight;
838     }
839
840     *pwidth = width;
841     *pheight = height;
842     *pcwidth = cwidth;
843     *pcheight = cheight;
844 }
845
846 typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
847
848 static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
849     rgb_to_pixel8_dup,
850     rgb_to_pixel15_dup,
851     rgb_to_pixel16_dup,
852     rgb_to_pixel32_dup,
853     rgb_to_pixel32bgr_dup,
854     rgb_to_pixel15bgr_dup,
855     rgb_to_pixel16bgr_dup,
856 };
857
858 /*
859  * Text mode update
860  * Missing:
861  * - double scan
862  * - double width
863  * - underline
864  * - flashing
865  */
866 static void vga_draw_text(VGACommonState *s, int full_update)
867 {
868     int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
869     int cx_min, cx_max, linesize, x_incr, line, line1;
870     uint32_t offset, fgcol, bgcol, v, cursor_offset;
871     uint8_t *d1, *d, *src, *dest, *cursor_ptr;
872     const uint8_t *font_ptr, *font_base[2];
873     int dup9, line_offset, depth_index;
874     uint32_t *palette;
875     uint32_t *ch_attr_ptr;
876     maru_vga_draw_glyph8_func *maru_vga_draw_glyph8;
877     maru_vga_draw_glyph9_func *maru_vga_draw_glyph9;
878     int64_t now = qemu_get_clock_ms(vm_clock);
879
880     /* compute font data address (in plane 2) */
881     v = s->sr[VGA_SEQ_CHARACTER_MAP];
882     offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
883     if (offset != s->font_offsets[0]) {
884         s->font_offsets[0] = offset;
885         full_update = 1;
886     }
887     font_base[0] = s->vram_ptr + offset;
888
889     offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
890     font_base[1] = s->vram_ptr + offset;
891     if (offset != s->font_offsets[1]) {
892         s->font_offsets[1] = offset;
893         full_update = 1;
894     }
895     if (s->plane_updated & (1 << 2) || s->chain4_alias) {
896         /* if the plane 2 was modified since the last display, it
897            indicates the font may have been modified */
898         s->plane_updated = 0;
899         full_update = 1;
900     }
901     full_update |= update_basic_params(s);
902
903     line_offset = s->line_offset;
904
905     vga_get_text_resolution(s, &width, &height, &cw, &cheight);
906     if ((height * width) <= 1) {
907         /* better than nothing: exit if transient size is too small */
908         return;
909     }
910     if ((height * width) > CH_ATTR_SIZE) {
911         /* better than nothing: exit if transient size is too big */
912         return;
913     }
914
915     if (width != s->last_width || height != s->last_height ||
916         cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
917         s->last_scr_width = width * cw;
918         s->last_scr_height = height * cheight;
919         qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
920         s->last_depth = 0;
921         s->last_width = width;
922         s->last_height = height;
923         s->last_ch = cheight;
924         s->last_cw = cw;
925         full_update = 1;
926     }
927     s->rgb_to_pixel =
928         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
929     full_update |= update_palette16(s);
930     palette = s->last_palette;
931     x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
932
933     cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
934                      s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
935     if (cursor_offset != s->cursor_offset ||
936         s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
937         s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
938       /* if the cursor position changed, we update the old and new
939          chars */
940         if (s->cursor_offset < CH_ATTR_SIZE)
941             s->last_ch_attr[s->cursor_offset] = -1;
942         if (cursor_offset < CH_ATTR_SIZE)
943             s->last_ch_attr[cursor_offset] = -1;
944         s->cursor_offset = cursor_offset;
945         s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
946         s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
947     }
948     cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
949     if (now >= s->cursor_blink_time) {
950         s->cursor_blink_time = now + VGA_TEXT_CURSOR_PERIOD_MS / 2;
951         s->cursor_visible_phase = !s->cursor_visible_phase;
952     }
953
954     depth_index = get_depth_index(s->ds);
955     if (cw == 16)
956         maru_vga_draw_glyph8 = maru_vga_draw_glyph16_table[depth_index];
957     else
958         maru_vga_draw_glyph8 = maru_vga_draw_glyph8_table[depth_index];
959     maru_vga_draw_glyph9 = maru_vga_draw_glyph9_table[depth_index];
960
961     dest = ds_get_data(s->ds);
962     linesize = ds_get_linesize(s->ds);
963     ch_attr_ptr = s->last_ch_attr;
964     line = 0;
965     offset = s->start_addr * 4;
966     for(cy = 0; cy < height; cy++) {
967         d1 = dest;
968         src = s->vram_ptr + offset;
969         cx_min = width;
970         cx_max = -1;
971         for(cx = 0; cx < width; cx++) {
972             ch_attr = *(uint16_t *)src;
973             if (full_update || ch_attr != *ch_attr_ptr || src == cursor_ptr) {
974                 if (cx < cx_min)
975                     cx_min = cx;
976                 if (cx > cx_max)
977                     cx_max = cx;
978                 *ch_attr_ptr = ch_attr;
979 #ifdef HOST_WORDS_BIGENDIAN
980                 ch = ch_attr >> 8;
981                 cattr = ch_attr & 0xff;
982 #else
983                 ch = ch_attr & 0xff;
984                 cattr = ch_attr >> 8;
985 #endif
986                 font_ptr = font_base[(cattr >> 3) & 1];
987                 font_ptr += 32 * 4 * ch;
988                 bgcol = palette[cattr >> 4];
989                 fgcol = palette[cattr & 0x0f];
990                 if (cw != 9) {
991                     maru_vga_draw_glyph8(d1, linesize,
992                                     font_ptr, cheight, fgcol, bgcol);
993                 } else {
994                     dup9 = 0;
995                     if (ch >= 0xb0 && ch <= 0xdf &&
996                         (s->ar[VGA_ATC_MODE] & 0x04)) {
997                         dup9 = 1;
998                     }
999                     maru_vga_draw_glyph9(d1, linesize,
1000                                     font_ptr, cheight, fgcol, bgcol, dup9);
1001                 }
1002                 if (src == cursor_ptr &&
1003                     !(s->cr[VGA_CRTC_CURSOR_START] & 0x20) &&
1004                     s->cursor_visible_phase) {
1005                     int line_start, line_last, h;
1006                     /* draw the cursor */
1007                     line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1008                     line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1009                     /* XXX: check that */
1010                     if (line_last > cheight - 1)
1011                         line_last = cheight - 1;
1012                     if (line_last >= line_start && line_start < cheight) {
1013                         h = line_last - line_start + 1;
1014                         d = d1 + linesize * line_start;
1015                         if (cw != 9) {
1016                             maru_vga_draw_glyph8(d, linesize,
1017                                             cursor_glyph, h, fgcol, bgcol);
1018                         } else {
1019                             maru_vga_draw_glyph9(d, linesize,
1020                                             cursor_glyph, h, fgcol, bgcol, 1);
1021                         }
1022                     }
1023                 }
1024             }
1025             d1 += x_incr;
1026             src += 4;
1027             ch_attr_ptr++;
1028         }
1029         if (cx_max != -1) {
1030             dpy_update(s->ds, cx_min * cw, cy * cheight,
1031                        (cx_max - cx_min + 1) * cw, cheight);
1032         }
1033         dest += linesize * cheight;
1034         line1 = line + cheight;
1035         offset += line_offset;
1036         if (line < s->line_compare && line1 >= s->line_compare) {
1037             offset = 0;
1038         }
1039         line = line1;
1040     }
1041 }
1042
1043 enum {
1044     maru_vga_draw_line2,
1045     maru_vga_draw_line2D2,
1046     maru_vga_draw_line4,
1047     maru_vga_draw_line4D2,
1048     maru_vga_draw_line8D2,
1049     maru_vga_draw_line8,
1050     maru_vga_draw_line15,
1051     maru_vga_draw_line16,
1052     maru_vga_draw_line24,
1053     maru_vga_draw_line32,
1054     maru_vga_draw_line_NB,
1055 };
1056
1057 static maru_vga_draw_line_func * const maru_vga_draw_line_table[NB_DEPTHS * maru_vga_draw_line_NB] = {
1058     maru_vga_draw_line2_8,
1059     maru_vga_draw_line2_16,
1060     maru_vga_draw_line2_16,
1061     maru_vga_draw_line2_32,
1062     maru_vga_draw_line2_32,
1063     maru_vga_draw_line2_16,
1064     maru_vga_draw_line2_16,
1065
1066     maru_vga_draw_line2d2_8,
1067     maru_vga_draw_line2d2_16,
1068     maru_vga_draw_line2d2_16,
1069     maru_vga_draw_line2d2_32,
1070     maru_vga_draw_line2d2_32,
1071     maru_vga_draw_line2d2_16,
1072     maru_vga_draw_line2d2_16,
1073
1074     maru_vga_draw_line4_8,
1075     maru_vga_draw_line4_16,
1076     maru_vga_draw_line4_16,
1077     maru_vga_draw_line4_32,
1078     maru_vga_draw_line4_32,
1079     maru_vga_draw_line4_16,
1080     maru_vga_draw_line4_16,
1081
1082     maru_vga_draw_line4d2_8,
1083     maru_vga_draw_line4d2_16,
1084     maru_vga_draw_line4d2_16,
1085     maru_vga_draw_line4d2_32,
1086     maru_vga_draw_line4d2_32,
1087     maru_vga_draw_line4d2_16,
1088     maru_vga_draw_line4d2_16,
1089
1090     maru_vga_draw_line8d2_8,
1091     maru_vga_draw_line8d2_16,
1092     maru_vga_draw_line8d2_16,
1093     maru_vga_draw_line8d2_32,
1094     maru_vga_draw_line8d2_32,
1095     maru_vga_draw_line8d2_16,
1096     maru_vga_draw_line8d2_16,
1097
1098     maru_vga_draw_line8_8,
1099     maru_vga_draw_line8_16,
1100     maru_vga_draw_line8_16,
1101     maru_vga_draw_line8_32,
1102     maru_vga_draw_line8_32,
1103     maru_vga_draw_line8_16,
1104     maru_vga_draw_line8_16,
1105
1106     maru_vga_draw_line15_8,
1107     maru_vga_draw_line15_15,
1108     maru_vga_draw_line15_16,
1109     maru_vga_draw_line15_32,
1110     maru_vga_draw_line15_32bgr,
1111     maru_vga_draw_line15_15bgr,
1112     maru_vga_draw_line15_16bgr,
1113
1114     maru_vga_draw_line16_8,
1115     maru_vga_draw_line16_15,
1116     maru_vga_draw_line16_16,
1117     maru_vga_draw_line16_32,
1118     maru_vga_draw_line16_32bgr,
1119     maru_vga_draw_line16_15bgr,
1120     maru_vga_draw_line16_16bgr,
1121
1122     maru_vga_draw_line24_8,
1123     maru_vga_draw_line24_15,
1124     maru_vga_draw_line24_16,
1125     maru_vga_draw_line24_32,
1126     maru_vga_draw_line24_32bgr,
1127     maru_vga_draw_line24_15bgr,
1128     maru_vga_draw_line24_16bgr,
1129
1130     maru_vga_draw_line32_8,
1131     maru_vga_draw_line32_15,
1132     maru_vga_draw_line32_16,
1133     maru_vga_draw_line32_32,
1134     maru_vga_draw_line32_32bgr,
1135     maru_vga_draw_line32_15bgr,
1136     maru_vga_draw_line32_16bgr,
1137 };
1138
1139 static int vga_get_bpp(VGACommonState *s)
1140 {
1141     int ret;
1142 #ifdef CONFIG_BOCHS_VBE
1143     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1144         ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1145     } else
1146 #endif
1147     {
1148         ret = 0;
1149     }
1150     return ret;
1151 }
1152
1153 static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1154 {
1155     int width, height;
1156
1157 #ifdef CONFIG_BOCHS_VBE
1158     if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1159         width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1160         height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1161     } else
1162 #endif
1163     {
1164         width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1165         height = s->cr[VGA_CRTC_V_DISP_END] |
1166             ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1167             ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1168         height = (height + 1);
1169     }
1170     *pwidth = width;
1171     *pheight = height;
1172 }
1173
1174 static void vga_sync_dirty_bitmap(VGACommonState *s)
1175 {
1176     memory_region_sync_dirty_bitmap(&s->vram);
1177 }
1178
1179 /*
1180  * graphic modes
1181  */
1182 static void vga_draw_graphic(VGACommonState *s, int full_update)
1183 {
1184     int y1, y, update, linesize, y_start, double_scan, mask, depth;
1185     int width, height, shift_control, line_offset, bwidth, bits;
1186     ram_addr_t page0, page1, page_min, page_max;
1187     int disp_width, multi_scan, multi_run;
1188     uint8_t *d;
1189     uint32_t v, addr1, addr;
1190     maru_vga_draw_line_func *maru_vga_draw_line;
1191
1192     full_update |= update_basic_params(s);
1193
1194     if (!full_update)
1195         vga_sync_dirty_bitmap(s);
1196
1197     s->get_resolution(s, &width, &height);
1198
1199     disp_width = width;
1200
1201     shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1202     double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1203     if (shift_control != 1) {
1204         multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1205             - 1;
1206     } else {
1207         /* in CGA modes, multi_scan is ignored */
1208         /* XXX: is it correct ? */
1209         multi_scan = double_scan;
1210     }
1211     multi_run = multi_scan;
1212     if (shift_control != s->shift_control ||
1213         double_scan != s->double_scan) {
1214         full_update = 1;
1215         s->shift_control = shift_control;
1216         s->double_scan = double_scan;
1217     }
1218
1219     if (shift_control == 0) {
1220         if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1221             disp_width <<= 1;
1222         }
1223     } else if (shift_control == 1) {
1224         if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1225             disp_width <<= 1;
1226         }
1227     }
1228
1229     depth = s->get_bpp(s);
1230     if (s->line_offset != s->last_line_offset ||
1231         disp_width != s->last_width ||
1232         height != s->last_height ||
1233         s->last_depth != depth) {
1234 #if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1235         if (depth == 16 || depth == 32) {
1236 #else
1237         if (depth == 32) {
1238 #endif
1239             qemu_free_displaysurface(s->ds);
1240
1241 #ifdef MARU_VGA // create new sufrace by malloc in MARU VGA
1242
1243             /* s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1244                     disp_width * 4, (uint8_t*)shared_memory); */
1245             s->ds->surface = qemu_create_displaysurface(s->ds, disp_width, height);
1246
1247
1248 #else //MARU_VGA
1249             s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1250                     s->line_offset,
1251                     s->vram_ptr + (s->start_addr * 4));
1252 #endif //MARU_VGA
1253
1254 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1255             s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1256 #endif
1257             dpy_resize(s->ds);
1258         } else {
1259             qemu_console_resize(s->ds, disp_width, height);
1260         }
1261         s->last_scr_width = disp_width;
1262         s->last_scr_height = height;
1263         s->last_width = disp_width;
1264         s->last_height = height;
1265         s->last_line_offset = s->line_offset;
1266         s->last_depth = depth;
1267         full_update = 1;
1268     } else if (is_buffer_shared(s->ds->surface) &&
1269                (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1270         s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1271         dpy_setdata(s->ds);
1272     }
1273
1274     s->rgb_to_pixel =
1275         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1276
1277     if (shift_control == 0) {
1278         full_update |= update_palette16(s);
1279         if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1280             v = maru_vga_draw_line4D2;
1281         } else {
1282             v = maru_vga_draw_line4;
1283         }
1284         bits = 4;
1285     } else if (shift_control == 1) {
1286         full_update |= update_palette16(s);
1287         if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1288             v = maru_vga_draw_line2D2;
1289         } else {
1290             v = maru_vga_draw_line2;
1291         }
1292         bits = 4;
1293     } else {
1294         switch(s->get_bpp(s)) {
1295         default:
1296         case 0:
1297             full_update |= update_palette256(s);
1298             v = maru_vga_draw_line8D2;
1299             bits = 4;
1300             break;
1301         case 8:
1302             full_update |= update_palette256(s);
1303             v = maru_vga_draw_line8;
1304             bits = 8;
1305             break;
1306         case 15:
1307             v = maru_vga_draw_line15;
1308             bits = 16;
1309             break;
1310         case 16:
1311             v = maru_vga_draw_line16;
1312             bits = 16;
1313             break;
1314         case 24:
1315             v = maru_vga_draw_line24;
1316             bits = 24;
1317             break;
1318         case 32:
1319             v = maru_vga_draw_line32;
1320             bits = 32;
1321             break;
1322         }
1323     }
1324     maru_vga_draw_line = maru_vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1325
1326     if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate) {
1327         s->cursor_invalidate(s);
1328     }
1329
1330     line_offset = s->line_offset;
1331 #if 0
1332     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",
1333            width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1334            s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
1335 #endif
1336     addr1 = (s->start_addr * 4);
1337     bwidth = (width * bits + 7) / 8;
1338     y_start = -1;
1339     page_min = -1;
1340     page_max = 0;
1341     d = ds_get_data(s->ds);
1342     linesize = ds_get_linesize(s->ds);
1343     y1 = 0;
1344     for(y = 0; y < height; y++) {
1345         addr = addr1;
1346         if (!(s->cr[0x17] & 1)) {
1347             int shift;
1348             /* CGA compatibility handling */
1349             shift = 14 + ((s->cr[0x17] >> 6) & 1);
1350             addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1351         }
1352         if (!(s->cr[0x17] & 2)) {
1353             addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1354         }
1355         update = full_update;
1356         page0 = addr;
1357         page1 = addr + bwidth - 1;
1358         update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
1359                                           DIRTY_MEMORY_VGA);
1360         /* explicit invalidation for the hardware cursor */
1361         update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1362
1363 #ifdef MARU_VGA // needs full update
1364         update |= 1;
1365 #endif
1366
1367         if (update) {
1368             if (y_start < 0)
1369                 y_start = y;
1370             if (page0 < page_min)
1371                 page_min = page0;
1372             if (page1 > page_max)
1373                 page_max = page1;
1374
1375             if (!(is_buffer_shared(s->ds->surface))) {
1376                 maru_vga_draw_line(s, d, s->vram_ptr + addr, width);
1377                 if (s->cursor_draw_line)
1378                     s->cursor_draw_line(s, d, y);
1379             }
1380
1381 #ifdef MARU_VGA
1382
1383             int i;
1384             uint8_t *fb_sub;
1385             uint8_t *over_sub;
1386             uint8_t *dst_sub;
1387             uint8_t alpha, c_alpha;
1388             uint32_t *dst;
1389             uint16_t overlay_bottom;
1390
1391             if ( overlay0_power ) {
1392
1393                 overlay_bottom = overlay0_top + overlay0_height;
1394
1395                 if ( overlay0_top <= y && y < overlay_bottom ) {
1396
1397                     fb_sub = s->vram_ptr + addr + overlay0_left * 4;
1398                     over_sub = overlay_ptr + ( y - overlay0_top ) * overlay0_width * 4;
1399                     dst = (uint32_t*) ( s->ds->surface->data + addr + overlay0_left * 4 );
1400
1401                     for ( i = 0; i < overlay0_width; i++, fb_sub += 4, over_sub += 4, dst++ ) {
1402
1403                         alpha = fb_sub[3];
1404                         c_alpha = 0xff - alpha;
1405
1406                         *dst = ( ( c_alpha * over_sub[0] + alpha * fb_sub[0] ) >> 8 )
1407                             | ( ( c_alpha * over_sub[1] + alpha * fb_sub[1] ) & 0xFF00 )
1408                             | ( ( ( c_alpha * over_sub[2] + alpha * fb_sub[2] ) & 0xFF00 ) << 8 );
1409                     }
1410
1411                 }
1412
1413             }
1414
1415             if ( overlay1_power ) {
1416
1417                 overlay_bottom = overlay1_top + overlay1_height;
1418
1419                 if ( overlay1_top <= y && y < overlay_bottom ) {
1420
1421                     fb_sub = s->vram_ptr + addr + overlay1_left * 4;
1422                     over_sub = overlay_ptr + ( y - overlay1_top ) * overlay1_width * 4 + 0x00400000;
1423                     dst = (uint32_t*) ( s->ds->surface->data + addr + overlay1_left * 4 );
1424
1425                     for ( i = 0; i < overlay1_width; i++, fb_sub += 4, over_sub += 4, dst++ ) {
1426
1427                         alpha = fb_sub[3];
1428                         c_alpha = 0xff - alpha;
1429
1430                         *dst = ( ( c_alpha * over_sub[0] + alpha * fb_sub[0] ) >> 8 )
1431                             | ( ( c_alpha * over_sub[1] + alpha * fb_sub[1] ) & 0xFF00 )
1432                             | ( ( ( c_alpha * over_sub[2] + alpha * fb_sub[2] ) & 0xFF00 ) << 8 );
1433                     }
1434
1435                 }
1436
1437             }
1438
1439             if ( brightness_off ) {
1440
1441                 dst_sub = s->ds->surface->data + addr;
1442                 dst = (uint32_t*) ( s->ds->surface->data + addr );
1443
1444                 for ( i = 0; i < disp_width; i++, dst_sub += 4, dst++ ) {
1445                     *dst = 0xFF000000; // black
1446                 }
1447
1448             } else  {
1449
1450                 if ( brightness_level < BRIGHTNESS_MAX ) {
1451
1452                     alpha = brightness_tbl[brightness_level];
1453
1454                     dst_sub = s->ds->surface->data + addr;
1455                     dst = (uint32_t*) ( s->ds->surface->data + addr );
1456
1457                     for ( i = 0; i < disp_width; i++, dst_sub += 4, dst++ ) {
1458                         *dst = ( ( alpha * dst_sub[0] ) >> 8 )
1459                                 | ( ( alpha * dst_sub[1] ) & 0xFF00 )
1460                                 | ( ( ( alpha * dst_sub[2] ) & 0xFF00 ) << 8 );
1461                     }
1462                 }
1463
1464             }
1465
1466 #endif /* MARU_VGA */
1467
1468         } else {
1469             if (y_start >= 0) {
1470                 /* flush to display */
1471                 dpy_update(s->ds, 0, y_start,
1472                            disp_width, y - y_start);
1473                 y_start = -1;
1474             }
1475         }
1476         if (!multi_run) {
1477             mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1478             if ((y1 & mask) == mask)
1479                 addr1 += line_offset;
1480             y1++;
1481             multi_run = multi_scan;
1482         } else {
1483             multi_run--;
1484         }
1485         /* line compare acts on the displayed lines */
1486         if (y == s->line_compare)
1487             addr1 = 0;
1488         d += linesize;
1489     }
1490
1491     /* for screenshot */
1492     pthread_mutex_lock(&mutex_screenshot);
1493     MaruScreenshot* maru_screenshot = get_maru_screenshot();
1494     if (maru_screenshot) {
1495         maru_screenshot->isReady = 1;
1496         if (maru_screenshot->request_screenshot == 1) {
1497             memcpy(maru_screenshot->pixel_data, s->ds->surface->data, 
1498                 s->ds->surface->linesize * s->ds->surface->height);
1499             maru_screenshot->request_screenshot = 0;
1500             pthread_cond_signal(&cond_screenshot);
1501         }
1502     }
1503     pthread_mutex_unlock(&mutex_screenshot);
1504
1505 #ifdef CONFIG_USE_SHM
1506     memcpy(shared_memory, s->ds->surface->data,
1507         s->ds->surface->linesize * s->ds->surface->height);
1508 #endif
1509
1510     if (y_start >= 0) {
1511         /* flush to display */
1512         dpy_update(s->ds, 0, y_start,
1513                    disp_width, y - y_start);
1514     }
1515
1516     /* reset modified pages */
1517     if (page_max >= page_min) {
1518         memory_region_reset_dirty(&s->vram,
1519                                   page_min,
1520                                   page_max - page_min,
1521                                   DIRTY_MEMORY_VGA);
1522     }
1523     memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1524 }
1525
1526 static void vga_draw_blank(VGACommonState *s, int full_update)
1527 {
1528     int i, w, val;
1529     uint8_t *d;
1530
1531     if (!full_update)
1532         return;
1533     if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1534         return;
1535
1536     s->rgb_to_pixel =
1537         rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1538     if (ds_get_bits_per_pixel(s->ds) == 8)
1539         val = s->rgb_to_pixel(0, 0, 0);
1540     else
1541         val = 0;
1542     w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1543     d = ds_get_data(s->ds);
1544     for(i = 0; i < s->last_scr_height; i++) {
1545         memset(d, val, w);
1546         d += ds_get_linesize(s->ds);
1547     }
1548     dpy_update(s->ds, 0, 0,
1549                s->last_scr_width, s->last_scr_height);
1550 }
1551
1552 #define GMODE_TEXT     0
1553 #define GMODE_GRAPH    1
1554 #define GMODE_BLANK 2
1555
1556 static void vga_update_display(void *opaque)
1557 {
1558     VGACommonState *s = opaque;
1559     int full_update, graphic_mode;
1560
1561     qemu_flush_coalesced_mmio_buffer();
1562
1563     if (ds_get_bits_per_pixel(s->ds) == 0) {
1564         /* nothing to do */
1565     } else {
1566         full_update = 0;
1567         if (!(s->ar_index & 0x20)) {
1568             graphic_mode = GMODE_BLANK;
1569         } else {
1570             graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1571         }
1572         if (graphic_mode != s->graphic_mode) {
1573             s->graphic_mode = graphic_mode;
1574             s->cursor_blink_time = qemu_get_clock_ms(vm_clock);
1575             full_update = 1;
1576         }
1577         switch(graphic_mode) {
1578         case GMODE_TEXT:
1579             vga_draw_text(s, full_update);
1580             break;
1581         case GMODE_GRAPH:
1582             vga_draw_graphic(s, full_update);
1583             break;
1584         case GMODE_BLANK:
1585         default:
1586             vga_draw_blank(s, full_update);
1587             break;
1588         }
1589     }
1590 }
1591
1592 /* force a full display refresh */
1593 static void vga_invalidate_display(void *opaque)
1594 {
1595     VGACommonState *s = opaque;
1596
1597     s->last_width = -1;
1598     s->last_height = -1;
1599 }
1600
1601 #define TEXTMODE_X(x)   ((x) % width)
1602 #define TEXTMODE_Y(x)   ((x) / width)
1603 #define VMEM2CHTYPE(v)  ((v & 0xff0007ff) | \
1604         ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1605 /* relay text rendering to the display driver
1606  * instead of doing a full vga_update_display() */
1607 static void vga_update_text(void *opaque, console_ch_t *chardata)
1608 {
1609     VGACommonState *s =  opaque;
1610     int graphic_mode, i, cursor_offset, cursor_visible;
1611     int cw, cheight, width, height, size, c_min, c_max;
1612     uint32_t *src;
1613     console_ch_t *dst, val;
1614     char msg_buffer[80];
1615     int full_update = 0;
1616
1617     qemu_flush_coalesced_mmio_buffer();
1618
1619     if (!(s->ar_index & 0x20)) {
1620         graphic_mode = GMODE_BLANK;
1621     } else {
1622         graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1623     }
1624     if (graphic_mode != s->graphic_mode) {
1625         s->graphic_mode = graphic_mode;
1626         full_update = 1;
1627     }
1628     if (s->last_width == -1) {
1629         s->last_width = 0;
1630         full_update = 1;
1631     }
1632
1633     switch (graphic_mode) {
1634     case GMODE_TEXT:
1635         /* TODO: update palette */
1636         full_update |= update_basic_params(s);
1637
1638         /* total width & height */
1639         cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
1640         cw = 8;
1641         if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
1642             cw = 9;
1643         }
1644         if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
1645             cw = 16; /* NOTE: no 18 pixel wide */
1646         }
1647         width = (s->cr[VGA_CRTC_H_DISP] + 1);
1648         if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
1649             /* ugly hack for CGA 160x100x16 - explain me the logic */
1650             height = 100;
1651         } else {
1652             height = s->cr[VGA_CRTC_V_DISP_END] |
1653                 ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1654                 ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1655             height = (height + 1) / cheight;
1656         }
1657
1658         size = (height * width);
1659         if (size > CH_ATTR_SIZE) {
1660             if (!full_update)
1661                 return;
1662
1663             snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
1664                      width, height);
1665             break;
1666         }
1667
1668         if (width != s->last_width || height != s->last_height ||
1669             cw != s->last_cw || cheight != s->last_ch) {
1670             s->last_scr_width = width * cw;
1671             s->last_scr_height = height * cheight;
1672             s->ds->surface->width = width;
1673             s->ds->surface->height = height;
1674             dpy_resize(s->ds);
1675             s->last_width = width;
1676             s->last_height = height;
1677             s->last_ch = cheight;
1678             s->last_cw = cw;
1679             full_update = 1;
1680         }
1681
1682         /* Update "hardware" cursor */
1683         cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1684                          s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1685         if (cursor_offset != s->cursor_offset ||
1686             s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1687             s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
1688             cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
1689             if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
1690                 dpy_cursor(s->ds,
1691                            TEXTMODE_X(cursor_offset),
1692                            TEXTMODE_Y(cursor_offset));
1693             else
1694                 dpy_cursor(s->ds, -1, -1);
1695             s->cursor_offset = cursor_offset;
1696             s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1697             s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1698         }
1699
1700         src = (uint32_t *) s->vram_ptr + s->start_addr;
1701         dst = chardata;
1702
1703         if (full_update) {
1704             for (i = 0; i < size; src ++, dst ++, i ++) {
1705                 console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
1706             }
1707
1708             dpy_update(s->ds, 0, 0, width, height);
1709         } else {
1710             c_max = 0;
1711
1712             for (i = 0; i < size; src ++, dst ++, i ++) {
1713                 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1714                 if (*dst != val) {
1715                     *dst = val;
1716                     c_max = i;
1717                     break;
1718                 }
1719             }
1720             c_min = i;
1721             for (; i < size; src ++, dst ++, i ++) {
1722                 console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
1723                 if (*dst != val) {
1724                     *dst = val;
1725                     c_max = i;
1726                 }
1727             }
1728
1729             if (c_min <= c_max) {
1730                 i = TEXTMODE_Y(c_min);
1731                 dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
1732             }
1733         }
1734
1735         return;
1736     case GMODE_GRAPH:
1737         if (!full_update)
1738             return;
1739
1740         s->get_resolution(s, &width, &height);
1741         snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
1742                  width, height);
1743         break;
1744     case GMODE_BLANK:
1745     default:
1746         if (!full_update)
1747             return;
1748
1749         snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
1750         break;
1751     }
1752
1753     /* Display a message */
1754     s->last_width = 60;
1755     s->last_height = height = 3;
1756     dpy_cursor(s->ds, -1, -1);
1757     s->ds->surface->width = s->last_width;
1758     s->ds->surface->height = height;
1759     dpy_resize(s->ds);
1760
1761     for (dst = chardata, i = 0; i < s->last_width * height; i ++) {
1762         console_write_ch(dst ++, ' ');
1763     }
1764
1765     size = strlen(msg_buffer);
1766     width = (s->last_width - size) / 2;
1767     dst = chardata + s->last_width + width;
1768     for (i = 0; i < size; i ++) {
1769         console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
1770     }
1771
1772     dpy_update(s->ds, 0, 0, s->last_width, height);
1773 }
1774
1775
1776 #if 0
1777 static void vga_reset(void *opaque)
1778 {
1779     VGACommonState *s =  opaque;
1780     vga_common_reset(s);
1781 }
1782
1783 static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
1784                              unsigned size)
1785 {
1786     VGACommonState *s = opaque;
1787
1788     return vga_mem_readb(s, addr);
1789 }
1790
1791 static void vga_mem_write(void *opaque, target_phys_addr_t addr,
1792                           uint64_t data, unsigned size)
1793 {
1794     VGACommonState *s = opaque;
1795
1796     return vga_mem_writeb(s, addr, data);
1797 }
1798
1799 static int vga_common_post_load(void *opaque, int version_id)
1800 {
1801     VGACommonState *s = opaque;
1802
1803     /* force refresh */
1804     s->graphic_mode = -1;
1805     return 0;
1806 }
1807 #endif
1808
1809 void maru_vga_common_init(VGACommonState *s)
1810 {
1811     int i, j, v, b;
1812
1813     for(i = 0;i < 256; i++) {
1814         v = 0;
1815         for(j = 0; j < 8; j++) {
1816             v |= ((i >> j) & 1) << (j * 4);
1817         }
1818         expand4[i] = v;
1819
1820         v = 0;
1821         for(j = 0; j < 4; j++) {
1822             v |= ((i >> (2 * j)) & 3) << (j * 4);
1823         }
1824         expand2[i] = v;
1825     }
1826     for(i = 0; i < 16; i++) {
1827         v = 0;
1828         for(j = 0; j < 4; j++) {
1829             b = ((i >> j) & 1);
1830             v |= b << (2 * j);
1831             v |= b << (2 * j + 1);
1832         }
1833         expand4to8[i] = v;
1834     }
1835
1836     /* valid range: 1 MB -> 256 MB */
1837     s->vram_size = 1024 * 1024;
1838     while (s->vram_size < (s->vram_size_mb << 20) &&
1839            s->vram_size < (256 << 20)) {
1840         s->vram_size <<= 1;
1841     }
1842     s->vram_size_mb = s->vram_size >> 20;
1843
1844 #ifdef CONFIG_BOCHS_VBE
1845     s->is_vbe_vmstate = 1;
1846 #else
1847     s->is_vbe_vmstate = 0;
1848 #endif
1849     memory_region_init_ram(&s->vram, "maru_vga.vram", s->vram_size);
1850     vmstate_register_ram_global(&s->vram);
1851     xen_register_framebuffer(&s->vram);
1852     s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
1853     s->get_bpp = vga_get_bpp;
1854     s->get_offsets = vga_get_offsets;
1855     s->get_resolution = vga_get_resolution;
1856     s->update = vga_update_display;
1857     s->invalidate = vga_invalidate_display;
1858     s->screen_dump = vga_screen_dump;
1859     s->text_update = vga_update_text;
1860     switch (vga_retrace_method) {
1861     case VGA_RETRACE_DUMB:
1862         s->retrace = vga_dumb_retrace;
1863         s->update_retrace_info = vga_dumb_update_retrace_info;
1864         break;
1865
1866     case VGA_RETRACE_PRECISE:
1867         s->retrace = vga_precise_retrace;
1868         s->update_retrace_info = vga_precise_update_retrace_info;
1869         break;
1870     default:
1871         break;
1872     }
1873     vga_dirty_log_start(s);
1874
1875 #ifdef CONFIG_USE_SHM
1876     /* base + 1 = sdb port */
1877     /* base + 2 = shared memory key */
1878     int mykey = get_emul_vm_base_port() + 2;
1879
1880     INFO("shared memory key: %d, vga ram_size : %d\n", mykey, s->vram_size);
1881
1882     skin_shmid = shmget((key_t)mykey, (size_t)s->vram_size, 0666 | IPC_CREAT);
1883     if (skin_shmid == -1) {
1884         ERR("shmget failed\n");
1885         perror("maru_vga: ");
1886         maru_register_exit_msg(MARU_EXIT_UNKNOWN,
1887             (char*) "Cannot launch this VM.\n"
1888             "Shared memory is not enough.");
1889         exit(0);
1890     }
1891
1892     shared_memory = shmat(skin_shmid, (void*)0, 0);
1893     if (shared_memory == (void *)-1) {
1894         ERR("shmat failed\n");
1895         perror("maru_vga: ");
1896         exit(1);
1897     }
1898
1899     memset(shared_memory, 0x00, (size_t)s->vram_size);
1900     printf("Memory attached at %X\n", (int)shared_memory);
1901 #endif
1902
1903 }
1904
1905 #ifdef CONFIG_USE_SHM
1906 void maru_vga_common_fini(void)
1907 {
1908     if (shmdt(shared_memory) == -1) {
1909         ERR("shmdt failed\n");
1910         perror("maru_vga: ");
1911     }
1912
1913     if (shmctl(skin_shmid, IPC_RMID, 0) == -1) {
1914         ERR("shmctl failed\n");
1915         perror("maru_vga: ");
1916     }
1917 }
1918 #endif
1919
1920 static const MemoryRegionPortio vga_portio_list[] = {
1921     { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
1922     { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
1923     { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
1924     { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
1925     { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
1926     PORTIO_END_OF_LIST(),
1927 };
1928
1929 #ifdef CONFIG_BOCHS_VBE
1930 static const MemoryRegionPortio vbe_portio_list[] = {
1931     { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
1932 # ifdef TARGET_I386
1933     { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
1934 # else
1935     { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
1936 # endif
1937     PORTIO_END_OF_LIST(),
1938 };
1939 #endif /* CONFIG_BOCHS_VBE */
1940
1941 /********************************************************/
1942 /* vga screen dump */
1943
1944 #if 0
1945 static int maru_ppm_save(const char *filename, struct DisplaySurface *ds)
1946 {
1947     FILE *f;
1948     uint8_t *d, *d1;
1949     uint32_t v;
1950     int y, x;
1951     uint8_t r, g, b;
1952     int ret;
1953     char *linebuf, *pbuf;
1954
1955     trace_ppm_save(filename, ds);
1956     f = fopen(filename, "wb");
1957     if (!f)
1958         return -1;
1959     fprintf(f, "P6\n%d %d\n%d\n",
1960             ds->width, ds->height, 255);
1961     linebuf = g_malloc(ds->width * 3);
1962     d1 = ds->data;
1963     for(y = 0; y < ds->height; y++) {
1964         d = d1;
1965         pbuf = linebuf;
1966         for(x = 0; x < ds->width; x++) {
1967             if (ds->pf.bits_per_pixel == 32)
1968                 v = *(uint32_t *)d;
1969             else
1970                 v = (uint32_t) (*(uint16_t *)d);
1971             /* Limited to 8 or fewer bits per channel: */
1972             r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
1973             g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
1974             b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
1975             *pbuf++ = r;
1976             *pbuf++ = g;
1977             *pbuf++ = b;
1978             d += ds->pf.bytes_per_pixel;
1979         }
1980         d1 += ds->linesize;
1981         ret = fwrite(linebuf, 1, pbuf - linebuf, f);
1982         (void)ret;
1983     }
1984     g_free(linebuf);
1985     fclose(f);
1986     return 0;
1987 }
1988 #endif
1989
1990 /* save the vga display in a PPM image even if no display is
1991    available */
1992 static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
1993 {
1994     VGACommonState *s = opaque;
1995
1996     if (cswitch) {
1997         vga_invalidate_display(s);
1998     }
1999     vga_hw_update();
2000     ppm_save(filename, s->ds->surface);
2001 }