Statistics
| Branch: | Revision:

root / hw / vga.c @ 1f51470d

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