Statistics
| Branch: | Revision:

root / hw / vga.c @ 5414dec6

History | View | Annotate | Download (70.9 kB)

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