Statistics
| Branch: | Revision:

root / hw / vga.c @ fa2ddcb4

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