Statistics
| Branch: | Revision:

root / hw / vga.c @ 5bc89ef6

History | View | Annotate | Download (74.4 kB)

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