Statistics
| Branch: | Revision:

root / hw / vga.c @ ed9873bf

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