Statistics
| Branch: | Revision:

root / hw / vga.c @ 59369b08

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