Statistics
| Branch: | Revision:

root / hw / vga.c @ aba35a6c

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