Statistics
| Branch: | Revision:

root / hw / vga.c @ e59fb374

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