Statistics
| Branch: | Revision:

root / hw / vga.c @ 0200db65

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