Statistics
| Branch: | Revision:

root / hw / vga.c @ 0b7ade1d

History | View | Annotate | Download (70.5 kB)

1 e89f66ec bellard
/*
2 4fa0f5d2 bellard
 * QEMU VGA Emulator.
3 5fafdf24 ths
 *
4 e89f66ec bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5fafdf24 ths
 *
6 e89f66ec bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e89f66ec bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e89f66ec bellard
 * in the Software without restriction, including without limitation the rights
9 e89f66ec bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e89f66ec bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e89f66ec bellard
 * furnished to do so, subject to the following conditions:
12 e89f66ec bellard
 *
13 e89f66ec bellard
 * The above copyright notice and this permission notice shall be included in
14 e89f66ec bellard
 * all copies or substantial portions of the Software.
15 e89f66ec bellard
 *
16 e89f66ec bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e89f66ec bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e89f66ec bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e89f66ec bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e89f66ec bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e89f66ec bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e89f66ec bellard
 * THE SOFTWARE.
23 e89f66ec bellard
 */
24 87ecb68b pbrook
#include "hw.h"
25 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 3294b949 bellard
    if ((height * width) > CH_ATTR_SIZE) {
1331 3294b949 bellard
        /* better than nothing: exit if transient size is too big */
1332 3294b949 bellard
        return;
1333 3294b949 bellard
    }
1334 3294b949 bellard
1335 799e709b aliguori
    if (width != s->last_width || height != s->last_height ||
1336 799e709b aliguori
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1337 799e709b aliguori
        s->last_scr_width = width * cw;
1338 799e709b aliguori
        s->last_scr_height = height * cheight;
1339 799e709b aliguori
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1340 799e709b aliguori
        s->last_depth = 0;
1341 799e709b aliguori
        s->last_width = width;
1342 799e709b aliguori
        s->last_height = height;
1343 799e709b aliguori
        s->last_ch = cheight;
1344 799e709b aliguori
        s->last_cw = cw;
1345 799e709b aliguori
        full_update = 1;
1346 799e709b aliguori
    }
1347 7d957bd8 aliguori
    s->rgb_to_pixel =
1348 7d957bd8 aliguori
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1349 7d957bd8 aliguori
    full_update |= update_palette16(s);
1350 7d957bd8 aliguori
    palette = s->last_palette;
1351 7d957bd8 aliguori
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1352 7d957bd8 aliguori
1353 5e55efc9 Blue Swirl
    cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
1354 5e55efc9 Blue Swirl
                     s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
1355 e89f66ec bellard
    if (cursor_offset != s->cursor_offset ||
1356 5e55efc9 Blue Swirl
        s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
1357 5e55efc9 Blue Swirl
        s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end) {
1358 e89f66ec bellard
      /* if the cursor position changed, we update the old and new
1359 e89f66ec bellard
         chars */
1360 e89f66ec bellard
        if (s->cursor_offset < CH_ATTR_SIZE)
1361 e89f66ec bellard
            s->last_ch_attr[s->cursor_offset] = -1;
1362 e89f66ec bellard
        if (cursor_offset < CH_ATTR_SIZE)
1363 e89f66ec bellard
            s->last_ch_attr[cursor_offset] = -1;
1364 e89f66ec bellard
        s->cursor_offset = cursor_offset;
1365 5e55efc9 Blue Swirl
        s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
1366 5e55efc9 Blue Swirl
        s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
1367 e89f66ec bellard
    }
1368 39cf7803 bellard
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1369 3b46e624 ths
1370 d3079cd2 bellard
    depth_index = get_depth_index(s->ds);
1371 17b0018b bellard
    if (cw == 16)
1372 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1373 17b0018b bellard
    else
1374 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1375 e89f66ec bellard
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1376 3b46e624 ths
1377 0e1f5a0c aliguori
    dest = ds_get_data(s->ds);
1378 0e1f5a0c aliguori
    linesize = ds_get_linesize(s->ds);
1379 e89f66ec bellard
    ch_attr_ptr = s->last_ch_attr;
1380 d1984194 malc
    line = 0;
1381 d1984194 malc
    offset = s->start_addr * 4;
1382 e89f66ec bellard
    for(cy = 0; cy < height; cy++) {
1383 e89f66ec bellard
        d1 = dest;
1384 d1984194 malc
        src = s->vram_ptr + offset;
1385 e89f66ec bellard
        cx_min = width;
1386 e89f66ec bellard
        cx_max = -1;
1387 e89f66ec bellard
        for(cx = 0; cx < width; cx++) {
1388 e89f66ec bellard
            ch_attr = *(uint16_t *)src;
1389 e89f66ec bellard
            if (full_update || ch_attr != *ch_attr_ptr) {
1390 e89f66ec bellard
                if (cx < cx_min)
1391 e89f66ec bellard
                    cx_min = cx;
1392 e89f66ec bellard
                if (cx > cx_max)
1393 e89f66ec bellard
                    cx_max = cx;
1394 e89f66ec bellard
                *ch_attr_ptr = ch_attr;
1395 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
1396 e89f66ec bellard
                ch = ch_attr >> 8;
1397 e89f66ec bellard
                cattr = ch_attr & 0xff;
1398 e89f66ec bellard
#else
1399 e89f66ec bellard
                ch = ch_attr & 0xff;
1400 e89f66ec bellard
                cattr = ch_attr >> 8;
1401 e89f66ec bellard
#endif
1402 e89f66ec bellard
                font_ptr = font_base[(cattr >> 3) & 1];
1403 e89f66ec bellard
                font_ptr += 32 * 4 * ch;
1404 e89f66ec bellard
                bgcol = palette[cattr >> 4];
1405 e89f66ec bellard
                fgcol = palette[cattr & 0x0f];
1406 17b0018b bellard
                if (cw != 9) {
1407 5fafdf24 ths
                    vga_draw_glyph8(d1, linesize,
1408 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol);
1409 e89f66ec bellard
                } else {
1410 e89f66ec bellard
                    dup9 = 0;
1411 5e55efc9 Blue Swirl
                    if (ch >= 0xb0 && ch <= 0xdf &&
1412 5e55efc9 Blue Swirl
                        (s->ar[VGA_ATC_MODE] & 0x04)) {
1413 e89f66ec bellard
                        dup9 = 1;
1414 5e55efc9 Blue Swirl
                    }
1415 5fafdf24 ths
                    vga_draw_glyph9(d1, linesize,
1416 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1417 e89f66ec bellard
                }
1418 e89f66ec bellard
                if (src == cursor_ptr &&
1419 5e55efc9 Blue Swirl
                    !(s->cr[VGA_CRTC_CURSOR_START] & 0x20)) {
1420 e89f66ec bellard
                    int line_start, line_last, h;
1421 e89f66ec bellard
                    /* draw the cursor */
1422 5e55efc9 Blue Swirl
                    line_start = s->cr[VGA_CRTC_CURSOR_START] & 0x1f;
1423 5e55efc9 Blue Swirl
                    line_last = s->cr[VGA_CRTC_CURSOR_END] & 0x1f;
1424 e89f66ec bellard
                    /* XXX: check that */
1425 e89f66ec bellard
                    if (line_last > cheight - 1)
1426 e89f66ec bellard
                        line_last = cheight - 1;
1427 e89f66ec bellard
                    if (line_last >= line_start && line_start < cheight) {
1428 e89f66ec bellard
                        h = line_last - line_start + 1;
1429 e89f66ec bellard
                        d = d1 + linesize * line_start;
1430 17b0018b bellard
                        if (cw != 9) {
1431 5fafdf24 ths
                            vga_draw_glyph8(d, linesize,
1432 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol);
1433 e89f66ec bellard
                        } else {
1434 5fafdf24 ths
                            vga_draw_glyph9(d, linesize,
1435 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol, 1);
1436 e89f66ec bellard
                        }
1437 e89f66ec bellard
                    }
1438 e89f66ec bellard
                }
1439 e89f66ec bellard
            }
1440 e89f66ec bellard
            d1 += x_incr;
1441 e89f66ec bellard
            src += 4;
1442 e89f66ec bellard
            ch_attr_ptr++;
1443 e89f66ec bellard
        }
1444 e89f66ec bellard
        if (cx_max != -1) {
1445 5fafdf24 ths
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1446 e89f66ec bellard
                       (cx_max - cx_min + 1) * cw, cheight);
1447 e89f66ec bellard
        }
1448 e89f66ec bellard
        dest += linesize * cheight;
1449 cae334cd malc
        line1 = line + cheight;
1450 cae334cd malc
        offset += line_offset;
1451 cae334cd malc
        if (line < s->line_compare && line1 >= s->line_compare) {
1452 d1984194 malc
            offset = 0;
1453 d1984194 malc
        }
1454 cae334cd malc
        line = line1;
1455 e89f66ec bellard
    }
1456 e89f66ec bellard
}
1457 e89f66ec bellard
1458 17b0018b bellard
enum {
1459 17b0018b bellard
    VGA_DRAW_LINE2,
1460 17b0018b bellard
    VGA_DRAW_LINE2D2,
1461 17b0018b bellard
    VGA_DRAW_LINE4,
1462 17b0018b bellard
    VGA_DRAW_LINE4D2,
1463 17b0018b bellard
    VGA_DRAW_LINE8D2,
1464 17b0018b bellard
    VGA_DRAW_LINE8,
1465 17b0018b bellard
    VGA_DRAW_LINE15,
1466 17b0018b bellard
    VGA_DRAW_LINE16,
1467 4fa0f5d2 bellard
    VGA_DRAW_LINE24,
1468 17b0018b bellard
    VGA_DRAW_LINE32,
1469 17b0018b bellard
    VGA_DRAW_LINE_NB,
1470 17b0018b bellard
};
1471 17b0018b bellard
1472 68f04a3c Blue Swirl
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1473 e89f66ec bellard
    vga_draw_line2_8,
1474 e89f66ec bellard
    vga_draw_line2_16,
1475 e89f66ec bellard
    vga_draw_line2_16,
1476 e89f66ec bellard
    vga_draw_line2_32,
1477 d3079cd2 bellard
    vga_draw_line2_32,
1478 b29169d2 blueswir1
    vga_draw_line2_16,
1479 b29169d2 blueswir1
    vga_draw_line2_16,
1480 e89f66ec bellard
1481 17b0018b bellard
    vga_draw_line2d2_8,
1482 17b0018b bellard
    vga_draw_line2d2_16,
1483 17b0018b bellard
    vga_draw_line2d2_16,
1484 17b0018b bellard
    vga_draw_line2d2_32,
1485 d3079cd2 bellard
    vga_draw_line2d2_32,
1486 b29169d2 blueswir1
    vga_draw_line2d2_16,
1487 b29169d2 blueswir1
    vga_draw_line2d2_16,
1488 17b0018b bellard
1489 e89f66ec bellard
    vga_draw_line4_8,
1490 e89f66ec bellard
    vga_draw_line4_16,
1491 e89f66ec bellard
    vga_draw_line4_16,
1492 e89f66ec bellard
    vga_draw_line4_32,
1493 d3079cd2 bellard
    vga_draw_line4_32,
1494 b29169d2 blueswir1
    vga_draw_line4_16,
1495 b29169d2 blueswir1
    vga_draw_line4_16,
1496 e89f66ec bellard
1497 17b0018b bellard
    vga_draw_line4d2_8,
1498 17b0018b bellard
    vga_draw_line4d2_16,
1499 17b0018b bellard
    vga_draw_line4d2_16,
1500 17b0018b bellard
    vga_draw_line4d2_32,
1501 d3079cd2 bellard
    vga_draw_line4d2_32,
1502 b29169d2 blueswir1
    vga_draw_line4d2_16,
1503 b29169d2 blueswir1
    vga_draw_line4d2_16,
1504 17b0018b bellard
1505 17b0018b bellard
    vga_draw_line8d2_8,
1506 17b0018b bellard
    vga_draw_line8d2_16,
1507 17b0018b bellard
    vga_draw_line8d2_16,
1508 17b0018b bellard
    vga_draw_line8d2_32,
1509 d3079cd2 bellard
    vga_draw_line8d2_32,
1510 b29169d2 blueswir1
    vga_draw_line8d2_16,
1511 b29169d2 blueswir1
    vga_draw_line8d2_16,
1512 17b0018b bellard
1513 e89f66ec bellard
    vga_draw_line8_8,
1514 e89f66ec bellard
    vga_draw_line8_16,
1515 e89f66ec bellard
    vga_draw_line8_16,
1516 e89f66ec bellard
    vga_draw_line8_32,
1517 d3079cd2 bellard
    vga_draw_line8_32,
1518 b29169d2 blueswir1
    vga_draw_line8_16,
1519 b29169d2 blueswir1
    vga_draw_line8_16,
1520 e89f66ec bellard
1521 e89f66ec bellard
    vga_draw_line15_8,
1522 e89f66ec bellard
    vga_draw_line15_15,
1523 e89f66ec bellard
    vga_draw_line15_16,
1524 e89f66ec bellard
    vga_draw_line15_32,
1525 d3079cd2 bellard
    vga_draw_line15_32bgr,
1526 b29169d2 blueswir1
    vga_draw_line15_15bgr,
1527 b29169d2 blueswir1
    vga_draw_line15_16bgr,
1528 e89f66ec bellard
1529 e89f66ec bellard
    vga_draw_line16_8,
1530 e89f66ec bellard
    vga_draw_line16_15,
1531 e89f66ec bellard
    vga_draw_line16_16,
1532 e89f66ec bellard
    vga_draw_line16_32,
1533 d3079cd2 bellard
    vga_draw_line16_32bgr,
1534 b29169d2 blueswir1
    vga_draw_line16_15bgr,
1535 b29169d2 blueswir1
    vga_draw_line16_16bgr,
1536 e89f66ec bellard
1537 4fa0f5d2 bellard
    vga_draw_line24_8,
1538 4fa0f5d2 bellard
    vga_draw_line24_15,
1539 4fa0f5d2 bellard
    vga_draw_line24_16,
1540 4fa0f5d2 bellard
    vga_draw_line24_32,
1541 d3079cd2 bellard
    vga_draw_line24_32bgr,
1542 b29169d2 blueswir1
    vga_draw_line24_15bgr,
1543 b29169d2 blueswir1
    vga_draw_line24_16bgr,
1544 4fa0f5d2 bellard
1545 e89f66ec bellard
    vga_draw_line32_8,
1546 e89f66ec bellard
    vga_draw_line32_15,
1547 e89f66ec bellard
    vga_draw_line32_16,
1548 e89f66ec bellard
    vga_draw_line32_32,
1549 d3079cd2 bellard
    vga_draw_line32_32bgr,
1550 b29169d2 blueswir1
    vga_draw_line32_15bgr,
1551 b29169d2 blueswir1
    vga_draw_line32_16bgr,
1552 d3079cd2 bellard
};
1553 d3079cd2 bellard
1554 cedd91d2 Juan Quintela
static int vga_get_bpp(VGACommonState *s)
1555 798b0c25 bellard
{
1556 798b0c25 bellard
    int ret;
1557 798b0c25 bellard
#ifdef CONFIG_BOCHS_VBE
1558 798b0c25 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1559 798b0c25 bellard
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1560 5fafdf24 ths
    } else
1561 798b0c25 bellard
#endif
1562 798b0c25 bellard
    {
1563 798b0c25 bellard
        ret = 0;
1564 798b0c25 bellard
    }
1565 798b0c25 bellard
    return ret;
1566 798b0c25 bellard
}
1567 798b0c25 bellard
1568 cedd91d2 Juan Quintela
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1569 a130a41e bellard
{
1570 a130a41e bellard
    int width, height;
1571 3b46e624 ths
1572 8454df8b bellard
#ifdef CONFIG_BOCHS_VBE
1573 8454df8b bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1574 8454df8b bellard
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1575 8454df8b bellard
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1576 5fafdf24 ths
    } else
1577 8454df8b bellard
#endif
1578 8454df8b bellard
    {
1579 5e55efc9 Blue Swirl
        width = (s->cr[VGA_CRTC_H_DISP] + 1) * 8;
1580 5e55efc9 Blue Swirl
        height = s->cr[VGA_CRTC_V_DISP_END] |
1581 5e55efc9 Blue Swirl
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
1582 5e55efc9 Blue Swirl
            ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
1583 8454df8b bellard
        height = (height + 1);
1584 8454df8b bellard
    }
1585 a130a41e bellard
    *pwidth = width;
1586 a130a41e bellard
    *pheight = height;
1587 a130a41e bellard
}
1588 a130a41e bellard
1589 cedd91d2 Juan Quintela
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1590 a8aa669b bellard
{
1591 a8aa669b bellard
    int y;
1592 a8aa669b bellard
    if (y1 >= VGA_MAX_HEIGHT)
1593 a8aa669b bellard
        return;
1594 a8aa669b bellard
    if (y2 >= VGA_MAX_HEIGHT)
1595 a8aa669b bellard
        y2 = VGA_MAX_HEIGHT;
1596 a8aa669b bellard
    for(y = y1; y < y2; y++) {
1597 a8aa669b bellard
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1598 a8aa669b bellard
    }
1599 a8aa669b bellard
}
1600 a8aa669b bellard
1601 cedd91d2 Juan Quintela
static void vga_sync_dirty_bitmap(VGACommonState *s)
1602 2bec46dc aliguori
{
1603 b1950430 Avi Kivity
    memory_region_sync_dirty_bitmap(&s->vram);
1604 2bec46dc aliguori
}
1605 2bec46dc aliguori
1606 50af3246 Juan Quintela
void vga_dirty_log_start(VGACommonState *s)
1607 50af3246 Juan Quintela
{
1608 b1950430 Avi Kivity
    memory_region_set_log(&s->vram, true, DIRTY_MEMORY_VGA);
1609 b5cc6e32 Anthony Liguori
}
1610 b5cc6e32 Anthony Liguori
1611 b5cc6e32 Anthony Liguori
void vga_dirty_log_stop(VGACommonState *s)
1612 b5cc6e32 Anthony Liguori
{
1613 b1950430 Avi Kivity
    memory_region_set_log(&s->vram, false, DIRTY_MEMORY_VGA);
1614 b5cc6e32 Anthony Liguori
}
1615 b5cc6e32 Anthony Liguori
1616 799e709b aliguori
/*
1617 799e709b aliguori
 * graphic modes
1618 799e709b aliguori
 */
1619 cedd91d2 Juan Quintela
static void vga_draw_graphic(VGACommonState *s, int full_update)
1620 e89f66ec bellard
{
1621 12c7e75a Avi Kivity
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1622 12c7e75a Avi Kivity
    int width, height, shift_control, line_offset, bwidth, bits;
1623 c227f099 Anthony Liguori
    ram_addr_t page0, page1, page_min, page_max;
1624 a07cf92a bellard
    int disp_width, multi_scan, multi_run;
1625 799e709b aliguori
    uint8_t *d;
1626 799e709b aliguori
    uint32_t v, addr1, addr;
1627 799e709b aliguori
    vga_draw_line_func *vga_draw_line;
1628 799e709b aliguori
1629 799e709b aliguori
    full_update |= update_basic_params(s);
1630 799e709b aliguori
1631 799e709b aliguori
    if (!full_update)
1632 799e709b aliguori
        vga_sync_dirty_bitmap(s);
1633 2bec46dc aliguori
1634 a130a41e bellard
    s->get_resolution(s, &width, &height);
1635 17b0018b bellard
    disp_width = width;
1636 09a79b49 bellard
1637 5e55efc9 Blue Swirl
    shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3;
1638 5e55efc9 Blue Swirl
    double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7);
1639 799e709b aliguori
    if (shift_control != 1) {
1640 5e55efc9 Blue Swirl
        multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan)
1641 5e55efc9 Blue Swirl
            - 1;
1642 799e709b aliguori
    } else {
1643 799e709b aliguori
        /* in CGA modes, multi_scan is ignored */
1644 799e709b aliguori
        /* XXX: is it correct ? */
1645 799e709b aliguori
        multi_scan = double_scan;
1646 799e709b aliguori
    }
1647 799e709b aliguori
    multi_run = multi_scan;
1648 17b0018b bellard
    if (shift_control != s->shift_control ||
1649 17b0018b bellard
        double_scan != s->double_scan) {
1650 799e709b aliguori
        full_update = 1;
1651 e89f66ec bellard
        s->shift_control = shift_control;
1652 17b0018b bellard
        s->double_scan = double_scan;
1653 e89f66ec bellard
    }
1654 3b46e624 ths
1655 aba35a6c malc
    if (shift_control == 0) {
1656 5e55efc9 Blue Swirl
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1657 aba35a6c malc
            disp_width <<= 1;
1658 aba35a6c malc
        }
1659 aba35a6c malc
    } else if (shift_control == 1) {
1660 5e55efc9 Blue Swirl
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1661 aba35a6c malc
            disp_width <<= 1;
1662 aba35a6c malc
        }
1663 aba35a6c malc
    }
1664 aba35a6c malc
1665 799e709b aliguori
    depth = s->get_bpp(s);
1666 e3697092 aurel32
    if (s->line_offset != s->last_line_offset ||
1667 e3697092 aurel32
        disp_width != s->last_width ||
1668 e3697092 aurel32
        height != s->last_height ||
1669 799e709b aliguori
        s->last_depth != depth) {
1670 e2542fe2 Juan Quintela
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1671 e3697092 aurel32
        if (depth == 16 || depth == 32) {
1672 0da2ea1b malc
#else
1673 0da2ea1b malc
        if (depth == 32) {
1674 0da2ea1b malc
#endif
1675 b8c18e4c aliguori
            qemu_free_displaysurface(s->ds);
1676 b8c18e4c aliguori
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1677 b8c18e4c aliguori
                    s->line_offset,
1678 b8c18e4c aliguori
                    s->vram_ptr + (s->start_addr * 4));
1679 e2542fe2 Juan Quintela
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1680 b8c18e4c aliguori
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1681 0da2ea1b malc
#endif
1682 b8c18e4c aliguori
            dpy_resize(s->ds);
1683 e3697092 aurel32
        } else {
1684 e3697092 aurel32
            qemu_console_resize(s->ds, disp_width, height);
1685 e3697092 aurel32
        }
1686 e3697092 aurel32
        s->last_scr_width = disp_width;
1687 e3697092 aurel32
        s->last_scr_height = height;
1688 e3697092 aurel32
        s->last_width = disp_width;
1689 e3697092 aurel32
        s->last_height = height;
1690 e3697092 aurel32
        s->last_line_offset = s->line_offset;
1691 e3697092 aurel32
        s->last_depth = depth;
1692 799e709b aliguori
        full_update = 1;
1693 799e709b aliguori
    } else if (is_buffer_shared(s->ds->surface) &&
1694 e3697092 aurel32
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1695 e3697092 aurel32
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1696 e3697092 aurel32
        dpy_setdata(s->ds);
1697 e3697092 aurel32
    }
1698 e3697092 aurel32
1699 e3697092 aurel32
    s->rgb_to_pixel =
1700 e3697092 aurel32
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1701 e3697092 aurel32
1702 799e709b aliguori
    if (shift_control == 0) {
1703 17b0018b bellard
        full_update |= update_palette16(s);
1704 5e55efc9 Blue Swirl
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1705 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1706 17b0018b bellard
        } else {
1707 17b0018b bellard
            v = VGA_DRAW_LINE4;
1708 17b0018b bellard
        }
1709 15342721 aurel32
        bits = 4;
1710 799e709b aliguori
    } else if (shift_control == 1) {
1711 17b0018b bellard
        full_update |= update_palette16(s);
1712 5e55efc9 Blue Swirl
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 8) {
1713 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1714 17b0018b bellard
        } else {
1715 17b0018b bellard
            v = VGA_DRAW_LINE2;
1716 17b0018b bellard
        }
1717 15342721 aurel32
        bits = 4;
1718 17b0018b bellard
    } else {
1719 798b0c25 bellard
        switch(s->get_bpp(s)) {
1720 798b0c25 bellard
        default:
1721 798b0c25 bellard
        case 0:
1722 4fa0f5d2 bellard
            full_update |= update_palette256(s);
1723 4fa0f5d2 bellard
            v = VGA_DRAW_LINE8D2;
1724 15342721 aurel32
            bits = 4;
1725 798b0c25 bellard
            break;
1726 798b0c25 bellard
        case 8:
1727 798b0c25 bellard
            full_update |= update_palette256(s);
1728 798b0c25 bellard
            v = VGA_DRAW_LINE8;
1729 15342721 aurel32
            bits = 8;
1730 798b0c25 bellard
            break;
1731 798b0c25 bellard
        case 15:
1732 798b0c25 bellard
            v = VGA_DRAW_LINE15;
1733 15342721 aurel32
            bits = 16;
1734 798b0c25 bellard
            break;
1735 798b0c25 bellard
        case 16:
1736 798b0c25 bellard
            v = VGA_DRAW_LINE16;
1737 15342721 aurel32
            bits = 16;
1738 798b0c25 bellard
            break;
1739 798b0c25 bellard
        case 24:
1740 798b0c25 bellard
            v = VGA_DRAW_LINE24;
1741 15342721 aurel32
            bits = 24;
1742 798b0c25 bellard
            break;
1743 798b0c25 bellard
        case 32:
1744 798b0c25 bellard
            v = VGA_DRAW_LINE32;
1745 15342721 aurel32
            bits = 32;
1746 798b0c25 bellard
            break;
1747 4fa0f5d2 bellard
        }
1748 17b0018b bellard
    }
1749 d3079cd2 bellard
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1750 17b0018b bellard
1751 7d957bd8 aliguori
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1752 a8aa669b bellard
        s->cursor_invalidate(s);
1753 3b46e624 ths
1754 e89f66ec bellard
    line_offset = s->line_offset;
1755 17b0018b bellard
#if 0
1756 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",
1757 5e55efc9 Blue Swirl
           width, height, v, line_offset, s->cr[9], s->cr[VGA_CRTC_MODE],
1758 5e55efc9 Blue Swirl
           s->line_compare, s->sr[VGA_SEQ_CLOCK_MODE]);
1759 17b0018b bellard
#endif
1760 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1761 15342721 aurel32
    bwidth = (width * bits + 7) / 8;
1762 39cf7803 bellard
    y_start = -1;
1763 12c7e75a Avi Kivity
    page_min = -1;
1764 12c7e75a Avi Kivity
    page_max = 0;
1765 0e1f5a0c aliguori
    d = ds_get_data(s->ds);
1766 0e1f5a0c aliguori
    linesize = ds_get_linesize(s->ds);
1767 17b0018b bellard
    y1 = 0;
1768 e89f66ec bellard
    for(y = 0; y < height; y++) {
1769 e89f66ec bellard
        addr = addr1;
1770 5e55efc9 Blue Swirl
        if (!(s->cr[VGA_CRTC_MODE] & 1)) {
1771 17b0018b bellard
            int shift;
1772 e89f66ec bellard
            /* CGA compatibility handling */
1773 5e55efc9 Blue Swirl
            shift = 14 + ((s->cr[VGA_CRTC_MODE] >> 6) & 1);
1774 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1775 e89f66ec bellard
        }
1776 5e55efc9 Blue Swirl
        if (!(s->cr[VGA_CRTC_MODE] & 2)) {
1777 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1778 e89f66ec bellard
        }
1779 734781c9 Jan Kiszka
        update = full_update;
1780 cd7a45c9 Blue Swirl
        page0 = addr;
1781 cd7a45c9 Blue Swirl
        page1 = addr + bwidth - 1;
1782 734781c9 Jan Kiszka
        update |= memory_region_get_dirty(&s->vram, page0, page1 - page0,
1783 734781c9 Jan Kiszka
                                          DIRTY_MEMORY_VGA);
1784 a8aa669b bellard
        /* explicit invalidation for the hardware cursor */
1785 a8aa669b bellard
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1786 e89f66ec bellard
        if (update) {
1787 39cf7803 bellard
            if (y_start < 0)
1788 39cf7803 bellard
                y_start = y;
1789 e89f66ec bellard
            if (page0 < page_min)
1790 e89f66ec bellard
                page_min = page0;
1791 e89f66ec bellard
            if (page1 > page_max)
1792 e89f66ec bellard
                page_max = page1;
1793 7d957bd8 aliguori
            if (!(is_buffer_shared(s->ds->surface))) {
1794 7d957bd8 aliguori
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1795 7d957bd8 aliguori
                if (s->cursor_draw_line)
1796 7d957bd8 aliguori
                    s->cursor_draw_line(s, d, y);
1797 7d957bd8 aliguori
            }
1798 39cf7803 bellard
        } else {
1799 39cf7803 bellard
            if (y_start >= 0) {
1800 39cf7803 bellard
                /* flush to display */
1801 5fafdf24 ths
                dpy_update(s->ds, 0, y_start,
1802 799e709b aliguori
                           disp_width, y - y_start);
1803 39cf7803 bellard
                y_start = -1;
1804 39cf7803 bellard
            }
1805 e89f66ec bellard
        }
1806 a07cf92a bellard
        if (!multi_run) {
1807 5e55efc9 Blue Swirl
            mask = (s->cr[VGA_CRTC_MODE] & 3) ^ 3;
1808 f6c958c8 bellard
            if ((y1 & mask) == mask)
1809 f6c958c8 bellard
                addr1 += line_offset;
1810 f6c958c8 bellard
            y1++;
1811 799e709b aliguori
            multi_run = multi_scan;
1812 a07cf92a bellard
        } else {
1813 a07cf92a bellard
            multi_run--;
1814 e89f66ec bellard
        }
1815 f6c958c8 bellard
        /* line compare acts on the displayed lines */
1816 f6c958c8 bellard
        if (y == s->line_compare)
1817 f6c958c8 bellard
            addr1 = 0;
1818 e89f66ec bellard
        d += linesize;
1819 e89f66ec bellard
    }
1820 39cf7803 bellard
    if (y_start >= 0) {
1821 39cf7803 bellard
        /* flush to display */
1822 5fafdf24 ths
        dpy_update(s->ds, 0, y_start,
1823 799e709b aliguori
                   disp_width, y - y_start);
1824 39cf7803 bellard
    }
1825 e89f66ec bellard
    /* reset modified pages */
1826 12c7e75a Avi Kivity
    if (page_max >= page_min) {
1827 b1950430 Avi Kivity
        memory_region_reset_dirty(&s->vram,
1828 b1950430 Avi Kivity
                                  page_min,
1829 cd7a45c9 Blue Swirl
                                  page_max - page_min,
1830 b1950430 Avi Kivity
                                  DIRTY_MEMORY_VGA);
1831 e89f66ec bellard
    }
1832 a8aa669b bellard
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1833 e89f66ec bellard
}
1834 e89f66ec bellard
1835 cedd91d2 Juan Quintela
static void vga_draw_blank(VGACommonState *s, int full_update)
1836 2aebb3eb bellard
{
1837 2aebb3eb bellard
    int i, w, val;
1838 2aebb3eb bellard
    uint8_t *d;
1839 2aebb3eb bellard
1840 2aebb3eb bellard
    if (!full_update)
1841 2aebb3eb bellard
        return;
1842 2aebb3eb bellard
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1843 2aebb3eb bellard
        return;
1844 2bec46dc aliguori
1845 7d957bd8 aliguori
    s->rgb_to_pixel =
1846 7d957bd8 aliguori
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1847 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(s->ds) == 8)
1848 2aebb3eb bellard
        val = s->rgb_to_pixel(0, 0, 0);
1849 2aebb3eb bellard
    else
1850 2aebb3eb bellard
        val = 0;
1851 0e1f5a0c aliguori
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1852 0e1f5a0c aliguori
    d = ds_get_data(s->ds);
1853 2aebb3eb bellard
    for(i = 0; i < s->last_scr_height; i++) {
1854 2aebb3eb bellard
        memset(d, val, w);
1855 0e1f5a0c aliguori
        d += ds_get_linesize(s->ds);
1856 2aebb3eb bellard
    }
1857 5fafdf24 ths
    dpy_update(s->ds, 0, 0,
1858 2aebb3eb bellard
               s->last_scr_width, s->last_scr_height);
1859 2aebb3eb bellard
}
1860 2aebb3eb bellard
1861 799e709b aliguori
#define GMODE_TEXT     0
1862 799e709b aliguori
#define GMODE_GRAPH    1
1863 799e709b aliguori
#define GMODE_BLANK 2
1864 799e709b aliguori
1865 95219897 pbrook
static void vga_update_display(void *opaque)
1866 e89f66ec bellard
{
1867 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
1868 799e709b aliguori
    int full_update, graphic_mode;
1869 e89f66ec bellard
1870 e9a07334 Jan Kiszka
    qemu_flush_coalesced_mmio_buffer();
1871 e9a07334 Jan Kiszka
1872 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1873 0f35920c bellard
        /* nothing to do */
1874 59a983b9 bellard
    } else {
1875 3098b9fd Aurelien Jarno
        full_update = 0;
1876 799e709b aliguori
        if (!(s->ar_index & 0x20)) {
1877 799e709b aliguori
            graphic_mode = GMODE_BLANK;
1878 799e709b aliguori
        } else {
1879 5e55efc9 Blue Swirl
            graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1880 799e709b aliguori
        }
1881 799e709b aliguori
        if (graphic_mode != s->graphic_mode) {
1882 799e709b aliguori
            s->graphic_mode = graphic_mode;
1883 799e709b aliguori
            full_update = 1;
1884 799e709b aliguori
        }
1885 799e709b aliguori
        switch(graphic_mode) {
1886 2aebb3eb bellard
        case GMODE_TEXT:
1887 e89f66ec bellard
            vga_draw_text(s, full_update);
1888 2aebb3eb bellard
            break;
1889 2aebb3eb bellard
        case GMODE_GRAPH:
1890 2aebb3eb bellard
            vga_draw_graphic(s, full_update);
1891 2aebb3eb bellard
            break;
1892 2aebb3eb bellard
        case GMODE_BLANK:
1893 2aebb3eb bellard
        default:
1894 2aebb3eb bellard
            vga_draw_blank(s, full_update);
1895 2aebb3eb bellard
            break;
1896 2aebb3eb bellard
        }
1897 e89f66ec bellard
    }
1898 e89f66ec bellard
}
1899 e89f66ec bellard
1900 a130a41e bellard
/* force a full display refresh */
1901 95219897 pbrook
static void vga_invalidate_display(void *opaque)
1902 a130a41e bellard
{
1903 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
1904 3b46e624 ths
1905 3098b9fd Aurelien Jarno
    s->last_width = -1;
1906 3098b9fd Aurelien Jarno
    s->last_height = -1;
1907 a130a41e bellard
}
1908 a130a41e bellard
1909 03a3e7ba Juan Quintela
void vga_common_reset(VGACommonState *s)
1910 e89f66ec bellard
{
1911 6e6b7363 blueswir1
    s->sr_index = 0;
1912 6e6b7363 blueswir1
    memset(s->sr, '\0', sizeof(s->sr));
1913 6e6b7363 blueswir1
    s->gr_index = 0;
1914 6e6b7363 blueswir1
    memset(s->gr, '\0', sizeof(s->gr));
1915 6e6b7363 blueswir1
    s->ar_index = 0;
1916 6e6b7363 blueswir1
    memset(s->ar, '\0', sizeof(s->ar));
1917 6e6b7363 blueswir1
    s->ar_flip_flop = 0;
1918 6e6b7363 blueswir1
    s->cr_index = 0;
1919 6e6b7363 blueswir1
    memset(s->cr, '\0', sizeof(s->cr));
1920 6e6b7363 blueswir1
    s->msr = 0;
1921 6e6b7363 blueswir1
    s->fcr = 0;
1922 6e6b7363 blueswir1
    s->st00 = 0;
1923 6e6b7363 blueswir1
    s->st01 = 0;
1924 6e6b7363 blueswir1
    s->dac_state = 0;
1925 6e6b7363 blueswir1
    s->dac_sub_index = 0;
1926 6e6b7363 blueswir1
    s->dac_read_index = 0;
1927 6e6b7363 blueswir1
    s->dac_write_index = 0;
1928 6e6b7363 blueswir1
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1929 6e6b7363 blueswir1
    s->dac_8bit = 0;
1930 6e6b7363 blueswir1
    memset(s->palette, '\0', sizeof(s->palette));
1931 6e6b7363 blueswir1
    s->bank_offset = 0;
1932 6e6b7363 blueswir1
#ifdef CONFIG_BOCHS_VBE
1933 6e6b7363 blueswir1
    s->vbe_index = 0;
1934 6e6b7363 blueswir1
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1935 af92284b Gerd Hoffmann
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1936 6e6b7363 blueswir1
    s->vbe_start_addr = 0;
1937 6e6b7363 blueswir1
    s->vbe_line_offset = 0;
1938 6e6b7363 blueswir1
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1939 6e6b7363 blueswir1
#endif
1940 6e6b7363 blueswir1
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1941 799e709b aliguori
    s->graphic_mode = -1; /* force full update */
1942 6e6b7363 blueswir1
    s->shift_control = 0;
1943 6e6b7363 blueswir1
    s->double_scan = 0;
1944 6e6b7363 blueswir1
    s->line_offset = 0;
1945 6e6b7363 blueswir1
    s->line_compare = 0;
1946 6e6b7363 blueswir1
    s->start_addr = 0;
1947 6e6b7363 blueswir1
    s->plane_updated = 0;
1948 6e6b7363 blueswir1
    s->last_cw = 0;
1949 6e6b7363 blueswir1
    s->last_ch = 0;
1950 6e6b7363 blueswir1
    s->last_width = 0;
1951 6e6b7363 blueswir1
    s->last_height = 0;
1952 6e6b7363 blueswir1
    s->last_scr_width = 0;
1953 6e6b7363 blueswir1
    s->last_scr_height = 0;
1954 6e6b7363 blueswir1
    s->cursor_start = 0;
1955 6e6b7363 blueswir1
    s->cursor_end = 0;
1956 6e6b7363 blueswir1
    s->cursor_offset = 0;
1957 6e6b7363 blueswir1
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1958 6e6b7363 blueswir1
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1959 6e6b7363 blueswir1
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1960 6e6b7363 blueswir1
    switch (vga_retrace_method) {
1961 6e6b7363 blueswir1
    case VGA_RETRACE_DUMB:
1962 6e6b7363 blueswir1
        break;
1963 6e6b7363 blueswir1
    case VGA_RETRACE_PRECISE:
1964 6e6b7363 blueswir1
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1965 6e6b7363 blueswir1
        break;
1966 6e6b7363 blueswir1
    }
1967 80763888 Jan Kiszka
    vga_update_memory_access(s);
1968 e89f66ec bellard
}
1969 e89f66ec bellard
1970 03a3e7ba Juan Quintela
static void vga_reset(void *opaque)
1971 03a3e7ba Juan Quintela
{
1972 cedd91d2 Juan Quintela
    VGACommonState *s =  opaque;
1973 03a3e7ba Juan Quintela
    vga_common_reset(s);
1974 03a3e7ba Juan Quintela
}
1975 03a3e7ba Juan Quintela
1976 4d3b6f6e balrog
#define TEXTMODE_X(x)        ((x) % width)
1977 4d3b6f6e balrog
#define TEXTMODE_Y(x)        ((x) / width)
1978 4d3b6f6e balrog
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
1979 4d3b6f6e balrog
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
1980 4d3b6f6e balrog
/* relay text rendering to the display driver
1981 4d3b6f6e balrog
 * instead of doing a full vga_update_display() */
1982 c227f099 Anthony Liguori
static void vga_update_text(void *opaque, console_ch_t *chardata)
1983 4d3b6f6e balrog
{
1984 cedd91d2 Juan Quintela
    VGACommonState *s =  opaque;
1985 799e709b aliguori
    int graphic_mode, i, cursor_offset, cursor_visible;
1986 4d3b6f6e balrog
    int cw, cheight, width, height, size, c_min, c_max;
1987 4d3b6f6e balrog
    uint32_t *src;
1988 c227f099 Anthony Liguori
    console_ch_t *dst, val;
1989 4d3b6f6e balrog
    char msg_buffer[80];
1990 799e709b aliguori
    int full_update = 0;
1991 799e709b aliguori
1992 e9a07334 Jan Kiszka
    qemu_flush_coalesced_mmio_buffer();
1993 e9a07334 Jan Kiszka
1994 799e709b aliguori
    if (!(s->ar_index & 0x20)) {
1995 799e709b aliguori
        graphic_mode = GMODE_BLANK;
1996 799e709b aliguori
    } else {
1997 5e55efc9 Blue Swirl
        graphic_mode = s->gr[VGA_GFX_MISC] & VGA_GR06_GRAPHICS_MODE;
1998 799e709b aliguori
    }
1999 799e709b aliguori
    if (graphic_mode != s->graphic_mode) {
2000 799e709b aliguori
        s->graphic_mode = graphic_mode;
2001 799e709b aliguori
        full_update = 1;
2002 799e709b aliguori
    }
2003 799e709b aliguori
    if (s->last_width == -1) {
2004 799e709b aliguori
        s->last_width = 0;
2005 799e709b aliguori
        full_update = 1;
2006 799e709b aliguori
    }
2007 4d3b6f6e balrog
2008 799e709b aliguori
    switch (graphic_mode) {
2009 4d3b6f6e balrog
    case GMODE_TEXT:
2010 4d3b6f6e balrog
        /* TODO: update palette */
2011 799e709b aliguori
        full_update |= update_basic_params(s);
2012 4d3b6f6e balrog
2013 799e709b aliguori
        /* total width & height */
2014 5e55efc9 Blue Swirl
        cheight = (s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1;
2015 799e709b aliguori
        cw = 8;
2016 5e55efc9 Blue Swirl
        if (!(s->sr[VGA_SEQ_CLOCK_MODE] & VGA_SR01_CHAR_CLK_8DOTS)) {
2017 799e709b aliguori
            cw = 9;
2018 5e55efc9 Blue Swirl
        }
2019 5e55efc9 Blue Swirl
        if (s->sr[VGA_SEQ_CLOCK_MODE] & 0x08) {
2020 799e709b aliguori
            cw = 16; /* NOTE: no 18 pixel wide */
2021 5e55efc9 Blue Swirl
        }
2022 5e55efc9 Blue Swirl
        width = (s->cr[VGA_CRTC_H_DISP] + 1);
2023 5e55efc9 Blue Swirl
        if (s->cr[VGA_CRTC_V_TOTAL] == 100) {
2024 799e709b aliguori
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2025 799e709b aliguori
            height = 100;
2026 799e709b aliguori
        } else {
2027 5e55efc9 Blue Swirl
            height = s->cr[VGA_CRTC_V_DISP_END] |
2028 5e55efc9 Blue Swirl
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x02) << 7) |
2029 5e55efc9 Blue Swirl
                ((s->cr[VGA_CRTC_OVERFLOW] & 0x40) << 3);
2030 799e709b aliguori
            height = (height + 1) / cheight;
2031 4d3b6f6e balrog
        }
2032 4d3b6f6e balrog
2033 4d3b6f6e balrog
        size = (height * width);
2034 4d3b6f6e balrog
        if (size > CH_ATTR_SIZE) {
2035 4d3b6f6e balrog
            if (!full_update)
2036 4d3b6f6e balrog
                return;
2037 4d3b6f6e balrog
2038 363a37d5 blueswir1
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2039 363a37d5 blueswir1
                     width, height);
2040 4d3b6f6e balrog
            break;
2041 4d3b6f6e balrog
        }
2042 4d3b6f6e balrog
2043 799e709b aliguori
        if (width != s->last_width || height != s->last_height ||
2044 799e709b aliguori
            cw != s->last_cw || cheight != s->last_ch) {
2045 799e709b aliguori
            s->last_scr_width = width * cw;
2046 799e709b aliguori
            s->last_scr_height = height * cheight;
2047 799e709b aliguori
            s->ds->surface->width = width;
2048 799e709b aliguori
            s->ds->surface->height = height;
2049 799e709b aliguori
            dpy_resize(s->ds);
2050 799e709b aliguori
            s->last_width = width;
2051 799e709b aliguori
            s->last_height = height;
2052 799e709b aliguori
            s->last_ch = cheight;
2053 799e709b aliguori
            s->last_cw = cw;
2054 799e709b aliguori
            full_update = 1;
2055 799e709b aliguori
        }
2056 799e709b aliguori
2057 4d3b6f6e balrog
        /* Update "hardware" cursor */
2058 5e55efc9 Blue Swirl
        cursor_offset = ((s->cr[VGA_CRTC_CURSOR_HI] << 8) |
2059 5e55efc9 Blue Swirl
                         s->cr[VGA_CRTC_CURSOR_LO]) - s->start_addr;
2060 4d3b6f6e balrog
        if (cursor_offset != s->cursor_offset ||
2061 5e55efc9 Blue Swirl
            s->cr[VGA_CRTC_CURSOR_START] != s->cursor_start ||
2062 5e55efc9 Blue Swirl
            s->cr[VGA_CRTC_CURSOR_END] != s->cursor_end || full_update) {
2063 5e55efc9 Blue Swirl
            cursor_visible = !(s->cr[VGA_CRTC_CURSOR_START] & 0x20);
2064 4d3b6f6e balrog
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2065 4d3b6f6e balrog
                dpy_cursor(s->ds,
2066 4d3b6f6e balrog
                           TEXTMODE_X(cursor_offset),
2067 4d3b6f6e balrog
                           TEXTMODE_Y(cursor_offset));
2068 4d3b6f6e balrog
            else
2069 4d3b6f6e balrog
                dpy_cursor(s->ds, -1, -1);
2070 4d3b6f6e balrog
            s->cursor_offset = cursor_offset;
2071 5e55efc9 Blue Swirl
            s->cursor_start = s->cr[VGA_CRTC_CURSOR_START];
2072 5e55efc9 Blue Swirl
            s->cursor_end = s->cr[VGA_CRTC_CURSOR_END];
2073 4d3b6f6e balrog
        }
2074 4d3b6f6e balrog
2075 4d3b6f6e balrog
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2076 4d3b6f6e balrog
        dst = chardata;
2077 4d3b6f6e balrog
2078 4d3b6f6e balrog
        if (full_update) {
2079 4d3b6f6e balrog
            for (i = 0; i < size; src ++, dst ++, i ++)
2080 9ae19b65 Aurelien Jarno
                console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
2081 4d3b6f6e balrog
2082 4d3b6f6e balrog
            dpy_update(s->ds, 0, 0, width, height);
2083 4d3b6f6e balrog
        } else {
2084 4d3b6f6e balrog
            c_max = 0;
2085 4d3b6f6e balrog
2086 4d3b6f6e balrog
            for (i = 0; i < size; src ++, dst ++, i ++) {
2087 9ae19b65 Aurelien Jarno
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2088 4d3b6f6e balrog
                if (*dst != val) {
2089 4d3b6f6e balrog
                    *dst = val;
2090 4d3b6f6e balrog
                    c_max = i;
2091 4d3b6f6e balrog
                    break;
2092 4d3b6f6e balrog
                }
2093 4d3b6f6e balrog
            }
2094 4d3b6f6e balrog
            c_min = i;
2095 4d3b6f6e balrog
            for (; i < size; src ++, dst ++, i ++) {
2096 9ae19b65 Aurelien Jarno
                console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
2097 4d3b6f6e balrog
                if (*dst != val) {
2098 4d3b6f6e balrog
                    *dst = val;
2099 4d3b6f6e balrog
                    c_max = i;
2100 4d3b6f6e balrog
                }
2101 4d3b6f6e balrog
            }
2102 4d3b6f6e balrog
2103 4d3b6f6e balrog
            if (c_min <= c_max) {
2104 4d3b6f6e balrog
                i = TEXTMODE_Y(c_min);
2105 4d3b6f6e balrog
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2106 4d3b6f6e balrog
            }
2107 4d3b6f6e balrog
        }
2108 4d3b6f6e balrog
2109 4d3b6f6e balrog
        return;
2110 4d3b6f6e balrog
    case GMODE_GRAPH:
2111 4d3b6f6e balrog
        if (!full_update)
2112 4d3b6f6e balrog
            return;
2113 4d3b6f6e balrog
2114 4d3b6f6e balrog
        s->get_resolution(s, &width, &height);
2115 363a37d5 blueswir1
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2116 363a37d5 blueswir1
                 width, height);
2117 4d3b6f6e balrog
        break;
2118 4d3b6f6e balrog
    case GMODE_BLANK:
2119 4d3b6f6e balrog
    default:
2120 4d3b6f6e balrog
        if (!full_update)
2121 4d3b6f6e balrog
            return;
2122 4d3b6f6e balrog
2123 363a37d5 blueswir1
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2124 4d3b6f6e balrog
        break;
2125 4d3b6f6e balrog
    }
2126 4d3b6f6e balrog
2127 4d3b6f6e balrog
    /* Display a message */
2128 5228c2d3 balrog
    s->last_width = 60;
2129 5228c2d3 balrog
    s->last_height = height = 3;
2130 4d3b6f6e balrog
    dpy_cursor(s->ds, -1, -1);
2131 7d957bd8 aliguori
    s->ds->surface->width = s->last_width;
2132 7d957bd8 aliguori
    s->ds->surface->height = height;
2133 7d957bd8 aliguori
    dpy_resize(s->ds);
2134 4d3b6f6e balrog
2135 5228c2d3 balrog
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2136 4d3b6f6e balrog
        console_write_ch(dst ++, ' ');
2137 4d3b6f6e balrog
2138 4d3b6f6e balrog
    size = strlen(msg_buffer);
2139 5228c2d3 balrog
    width = (s->last_width - size) / 2;
2140 5228c2d3 balrog
    dst = chardata + s->last_width + width;
2141 4d3b6f6e balrog
    for (i = 0; i < size; i ++)
2142 4d3b6f6e balrog
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2143 4d3b6f6e balrog
2144 5228c2d3 balrog
    dpy_update(s->ds, 0, 0, s->last_width, height);
2145 4d3b6f6e balrog
}
2146 4d3b6f6e balrog
2147 b1950430 Avi Kivity
static uint64_t vga_mem_read(void *opaque, target_phys_addr_t addr,
2148 b1950430 Avi Kivity
                             unsigned size)
2149 b1950430 Avi Kivity
{
2150 b1950430 Avi Kivity
    VGACommonState *s = opaque;
2151 b1950430 Avi Kivity
2152 b2a5e761 Avi Kivity
    return vga_mem_readb(s, addr);
2153 b1950430 Avi Kivity
}
2154 e89f66ec bellard
2155 b1950430 Avi Kivity
static void vga_mem_write(void *opaque, target_phys_addr_t addr,
2156 b1950430 Avi Kivity
                          uint64_t data, unsigned size)
2157 b1950430 Avi Kivity
{
2158 b1950430 Avi Kivity
    VGACommonState *s = opaque;
2159 b1950430 Avi Kivity
2160 b2a5e761 Avi Kivity
    return vga_mem_writeb(s, addr, data);
2161 b1950430 Avi Kivity
}
2162 b1950430 Avi Kivity
2163 b1950430 Avi Kivity
const MemoryRegionOps vga_mem_ops = {
2164 b1950430 Avi Kivity
    .read = vga_mem_read,
2165 b1950430 Avi Kivity
    .write = vga_mem_write,
2166 b1950430 Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
2167 b2a5e761 Avi Kivity
    .impl = {
2168 b2a5e761 Avi Kivity
        .min_access_size = 1,
2169 b2a5e761 Avi Kivity
        .max_access_size = 1,
2170 b2a5e761 Avi Kivity
    },
2171 e89f66ec bellard
};
2172 e89f66ec bellard
2173 11b6b345 Juan Quintela
static int vga_common_post_load(void *opaque, int version_id)
2174 b0a21b53 bellard
{
2175 0d65ddc3 Juan Quintela
    VGACommonState *s = opaque;
2176 11b6b345 Juan Quintela
2177 11b6b345 Juan Quintela
    /* force refresh */
2178 11b6b345 Juan Quintela
    s->graphic_mode = -1;
2179 11b6b345 Juan Quintela
    return 0;
2180 11b6b345 Juan Quintela
}
2181 11b6b345 Juan Quintela
2182 11b6b345 Juan Quintela
const VMStateDescription vmstate_vga_common = {
2183 11b6b345 Juan Quintela
    .name = "vga",
2184 11b6b345 Juan Quintela
    .version_id = 2,
2185 11b6b345 Juan Quintela
    .minimum_version_id = 2,
2186 11b6b345 Juan Quintela
    .minimum_version_id_old = 2,
2187 11b6b345 Juan Quintela
    .post_load = vga_common_post_load,
2188 11b6b345 Juan Quintela
    .fields      = (VMStateField []) {
2189 11b6b345 Juan Quintela
        VMSTATE_UINT32(latch, VGACommonState),
2190 11b6b345 Juan Quintela
        VMSTATE_UINT8(sr_index, VGACommonState),
2191 11b6b345 Juan Quintela
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2192 11b6b345 Juan Quintela
        VMSTATE_UINT8(gr_index, VGACommonState),
2193 11b6b345 Juan Quintela
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2194 11b6b345 Juan Quintela
        VMSTATE_UINT8(ar_index, VGACommonState),
2195 11b6b345 Juan Quintela
        VMSTATE_BUFFER(ar, VGACommonState),
2196 11b6b345 Juan Quintela
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2197 11b6b345 Juan Quintela
        VMSTATE_UINT8(cr_index, VGACommonState),
2198 11b6b345 Juan Quintela
        VMSTATE_BUFFER(cr, VGACommonState),
2199 11b6b345 Juan Quintela
        VMSTATE_UINT8(msr, VGACommonState),
2200 11b6b345 Juan Quintela
        VMSTATE_UINT8(fcr, VGACommonState),
2201 11b6b345 Juan Quintela
        VMSTATE_UINT8(st00, VGACommonState),
2202 11b6b345 Juan Quintela
        VMSTATE_UINT8(st01, VGACommonState),
2203 11b6b345 Juan Quintela
2204 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_state, VGACommonState),
2205 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2206 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2207 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2208 11b6b345 Juan Quintela
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2209 11b6b345 Juan Quintela
        VMSTATE_BUFFER(palette, VGACommonState),
2210 11b6b345 Juan Quintela
2211 11b6b345 Juan Quintela
        VMSTATE_INT32(bank_offset, VGACommonState),
2212 11b6b345 Juan Quintela
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2213 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
2214 11b6b345 Juan Quintela
        VMSTATE_UINT16(vbe_index, VGACommonState),
2215 11b6b345 Juan Quintela
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2216 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2217 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2218 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2219 b0a21b53 bellard
#endif
2220 11b6b345 Juan Quintela
        VMSTATE_END_OF_LIST()
2221 11b6b345 Juan Quintela
    }
2222 11b6b345 Juan Quintela
};
2223 11b6b345 Juan Quintela
2224 a4a2f59c Juan Quintela
void vga_common_init(VGACommonState *s, int vga_ram_size)
2225 e89f66ec bellard
{
2226 17b0018b bellard
    int i, j, v, b;
2227 e89f66ec bellard
2228 e89f66ec bellard
    for(i = 0;i < 256; i++) {
2229 e89f66ec bellard
        v = 0;
2230 e89f66ec bellard
        for(j = 0; j < 8; j++) {
2231 e89f66ec bellard
            v |= ((i >> j) & 1) << (j * 4);
2232 e89f66ec bellard
        }
2233 e89f66ec bellard
        expand4[i] = v;
2234 e89f66ec bellard
2235 e89f66ec bellard
        v = 0;
2236 e89f66ec bellard
        for(j = 0; j < 4; j++) {
2237 e89f66ec bellard
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2238 e89f66ec bellard
        }
2239 e89f66ec bellard
        expand2[i] = v;
2240 e89f66ec bellard
    }
2241 17b0018b bellard
    for(i = 0; i < 16; i++) {
2242 17b0018b bellard
        v = 0;
2243 17b0018b bellard
        for(j = 0; j < 4; j++) {
2244 17b0018b bellard
            b = ((i >> j) & 1);
2245 17b0018b bellard
            v |= b << (2 * j);
2246 17b0018b bellard
            v |= b << (2 * j + 1);
2247 17b0018b bellard
        }
2248 17b0018b bellard
        expand4to8[i] = v;
2249 17b0018b bellard
    }
2250 e89f66ec bellard
2251 2a3138ab Juan Quintela
#ifdef CONFIG_BOCHS_VBE
2252 2a3138ab Juan Quintela
    s->is_vbe_vmstate = 1;
2253 2a3138ab Juan Quintela
#else
2254 2a3138ab Juan Quintela
    s->is_vbe_vmstate = 0;
2255 2a3138ab Juan Quintela
#endif
2256 c5705a77 Avi Kivity
    memory_region_init_ram(&s->vram, "vga.vram", vga_ram_size);
2257 c5705a77 Avi Kivity
    vmstate_register_ram_global(&s->vram);
2258 c65adf9b Avi Kivity
    xen_register_framebuffer(&s->vram);
2259 b1950430 Avi Kivity
    s->vram_ptr = memory_region_get_ram_ptr(&s->vram);
2260 e89f66ec bellard
    s->vram_size = vga_ram_size;
2261 798b0c25 bellard
    s->get_bpp = vga_get_bpp;
2262 798b0c25 bellard
    s->get_offsets = vga_get_offsets;
2263 a130a41e bellard
    s->get_resolution = vga_get_resolution;
2264 d34cab9f ths
    s->update = vga_update_display;
2265 d34cab9f ths
    s->invalidate = vga_invalidate_display;
2266 d34cab9f ths
    s->screen_dump = vga_screen_dump;
2267 4d3b6f6e balrog
    s->text_update = vga_update_text;
2268 cb5a7aa8 malc
    switch (vga_retrace_method) {
2269 cb5a7aa8 malc
    case VGA_RETRACE_DUMB:
2270 cb5a7aa8 malc
        s->retrace = vga_dumb_retrace;
2271 cb5a7aa8 malc
        s->update_retrace_info = vga_dumb_update_retrace_info;
2272 cb5a7aa8 malc
        break;
2273 cb5a7aa8 malc
2274 cb5a7aa8 malc
    case VGA_RETRACE_PRECISE:
2275 cb5a7aa8 malc
        s->retrace = vga_precise_retrace;
2276 cb5a7aa8 malc
        s->update_retrace_info = vga_precise_update_retrace_info;
2277 cb5a7aa8 malc
        break;
2278 cb5a7aa8 malc
    }
2279 b1950430 Avi Kivity
    vga_dirty_log_start(s);
2280 798b0c25 bellard
}
2281 798b0c25 bellard
2282 0a039dc7 Richard Henderson
static const MemoryRegionPortio vga_portio_list[] = {
2283 0a039dc7 Richard Henderson
    { 0x04,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3b4 */
2284 0a039dc7 Richard Henderson
    { 0x0a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3ba */
2285 0a039dc7 Richard Henderson
    { 0x10, 16, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3c0 */
2286 0a039dc7 Richard Henderson
    { 0x24,  2, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3d4 */
2287 0a039dc7 Richard Henderson
    { 0x2a,  1, 1, .read = vga_ioport_read, .write = vga_ioport_write }, /* 3da */
2288 0a039dc7 Richard Henderson
    PORTIO_END_OF_LIST(),
2289 0a039dc7 Richard Henderson
};
2290 e89f66ec bellard
2291 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
2292 0a039dc7 Richard Henderson
static const MemoryRegionPortio vbe_portio_list[] = {
2293 0a039dc7 Richard Henderson
    { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
2294 0a039dc7 Richard Henderson
# ifdef TARGET_I386
2295 0a039dc7 Richard Henderson
    { 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2296 0a039dc7 Richard Henderson
# else
2297 0a039dc7 Richard Henderson
    { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
2298 0a039dc7 Richard Henderson
# endif
2299 0a039dc7 Richard Henderson
    PORTIO_END_OF_LIST(),
2300 0a039dc7 Richard Henderson
};
2301 0a039dc7 Richard Henderson
#endif /* CONFIG_BOCHS_VBE */
2302 4fa0f5d2 bellard
2303 0a039dc7 Richard Henderson
/* Used by both ISA and PCI */
2304 0a039dc7 Richard Henderson
MemoryRegion *vga_init_io(VGACommonState *s,
2305 0a039dc7 Richard Henderson
                          const MemoryRegionPortio **vga_ports,
2306 0a039dc7 Richard Henderson
                          const MemoryRegionPortio **vbe_ports)
2307 0a039dc7 Richard Henderson
{
2308 0a039dc7 Richard Henderson
    MemoryRegion *vga_mem;
2309 09a79b49 bellard
2310 0a039dc7 Richard Henderson
    *vga_ports = vga_portio_list;
2311 0a039dc7 Richard Henderson
    *vbe_ports = NULL;
2312 0a039dc7 Richard Henderson
#ifdef CONFIG_BOCHS_VBE
2313 0a039dc7 Richard Henderson
    *vbe_ports = vbe_portio_list;
2314 4fa0f5d2 bellard
#endif
2315 4fa0f5d2 bellard
2316 7267c094 Anthony Liguori
    vga_mem = g_malloc(sizeof(*vga_mem));
2317 b1950430 Avi Kivity
    memory_region_init_io(vga_mem, &vga_mem_ops, s,
2318 b1950430 Avi Kivity
                          "vga-lowmem", 0x20000);
2319 b1950430 Avi Kivity
2320 b1950430 Avi Kivity
    return vga_mem;
2321 7435b791 Blue Swirl
}
2322 7435b791 Blue Swirl
2323 0a039dc7 Richard Henderson
void vga_init(VGACommonState *s, MemoryRegion *address_space,
2324 0a039dc7 Richard Henderson
              MemoryRegion *address_space_io, bool init_vga_ports)
2325 7435b791 Blue Swirl
{
2326 b1950430 Avi Kivity
    MemoryRegion *vga_io_memory;
2327 0a039dc7 Richard Henderson
    const MemoryRegionPortio *vga_ports, *vbe_ports;
2328 0a039dc7 Richard Henderson
    PortioList *vga_port_list = g_new(PortioList, 1);
2329 0a039dc7 Richard Henderson
    PortioList *vbe_port_list = g_new(PortioList, 1);
2330 7435b791 Blue Swirl
2331 7435b791 Blue Swirl
    qemu_register_reset(vga_reset, s);
2332 7435b791 Blue Swirl
2333 7435b791 Blue Swirl
    s->bank_offset = 0;
2334 7435b791 Blue Swirl
2335 80763888 Jan Kiszka
    s->legacy_address_space = address_space;
2336 80763888 Jan Kiszka
2337 0a039dc7 Richard Henderson
    vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports);
2338 be20f9e9 Avi Kivity
    memory_region_add_subregion_overlap(address_space,
2339 b1950430 Avi Kivity
                                        isa_mem_base + 0x000a0000,
2340 b1950430 Avi Kivity
                                        vga_io_memory,
2341 b1950430 Avi Kivity
                                        1);
2342 b1950430 Avi Kivity
    memory_region_set_coalescing(vga_io_memory);
2343 0a039dc7 Richard Henderson
    if (init_vga_ports) {
2344 0a039dc7 Richard Henderson
        portio_list_init(vga_port_list, vga_ports, s, "vga");
2345 0a039dc7 Richard Henderson
        portio_list_add(vga_port_list, address_space_io, 0x3b0);
2346 0a039dc7 Richard Henderson
    }
2347 0a039dc7 Richard Henderson
    if (vbe_ports) {
2348 0a039dc7 Richard Henderson
        portio_list_init(vbe_port_list, vbe_ports, s, "vbe");
2349 0a039dc7 Richard Henderson
        portio_list_add(vbe_port_list, address_space_io, 0x1ce);
2350 0a039dc7 Richard Henderson
    }
2351 d2269f6f bellard
}
2352 d2269f6f bellard
2353 be20f9e9 Avi Kivity
void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory)
2354 f0138a63 Anthony Liguori
{
2355 f0138a63 Anthony Liguori
#ifdef CONFIG_BOCHS_VBE
2356 f0138a63 Anthony Liguori
    /* XXX: use optimized standard vga accesses */
2357 be20f9e9 Avi Kivity
    memory_region_add_subregion(system_memory,
2358 b1950430 Avi Kivity
                                VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2359 b1950430 Avi Kivity
                                &s->vram);
2360 f0138a63 Anthony Liguori
    s->vbe_mapped = 1;
2361 f0138a63 Anthony Liguori
#endif 
2362 f0138a63 Anthony Liguori
}
2363 59a983b9 bellard
/********************************************************/
2364 59a983b9 bellard
/* vga screen dump */
2365 59a983b9 bellard
2366 e07d630a aliguori
int ppm_save(const char *filename, struct DisplaySurface *ds)
2367 59a983b9 bellard
{
2368 59a983b9 bellard
    FILE *f;
2369 59a983b9 bellard
    uint8_t *d, *d1;
2370 e07d630a aliguori
    uint32_t v;
2371 59a983b9 bellard
    int y, x;
2372 e07d630a aliguori
    uint8_t r, g, b;
2373 f8e378f2 Avi Kivity
    int ret;
2374 f8e378f2 Avi Kivity
    char *linebuf, *pbuf;
2375 59a983b9 bellard
2376 72750018 Alon Levy
    trace_ppm_save(filename, ds);
2377 59a983b9 bellard
    f = fopen(filename, "wb");
2378 59a983b9 bellard
    if (!f)
2379 59a983b9 bellard
        return -1;
2380 59a983b9 bellard
    fprintf(f, "P6\n%d %d\n%d\n",
2381 e07d630a aliguori
            ds->width, ds->height, 255);
2382 7267c094 Anthony Liguori
    linebuf = g_malloc(ds->width * 3);
2383 e07d630a aliguori
    d1 = ds->data;
2384 e07d630a aliguori
    for(y = 0; y < ds->height; y++) {
2385 59a983b9 bellard
        d = d1;
2386 f8e378f2 Avi Kivity
        pbuf = linebuf;
2387 e07d630a aliguori
        for(x = 0; x < ds->width; x++) {
2388 e07d630a aliguori
            if (ds->pf.bits_per_pixel == 32)
2389 e07d630a aliguori
                v = *(uint32_t *)d;
2390 e07d630a aliguori
            else
2391 e07d630a aliguori
                v = (uint32_t) (*(uint16_t *)d);
2392 a0f42610 Avi Kivity
            /* Limited to 8 or fewer bits per channel: */
2393 a0f42610 Avi Kivity
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) << (8 - ds->pf.rbits);
2394 a0f42610 Avi Kivity
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) << (8 - ds->pf.gbits);
2395 a0f42610 Avi Kivity
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) << (8 - ds->pf.bbits);
2396 f8e378f2 Avi Kivity
            *pbuf++ = r;
2397 f8e378f2 Avi Kivity
            *pbuf++ = g;
2398 f8e378f2 Avi Kivity
            *pbuf++ = b;
2399 e07d630a aliguori
            d += ds->pf.bytes_per_pixel;
2400 59a983b9 bellard
        }
2401 e07d630a aliguori
        d1 += ds->linesize;
2402 f8e378f2 Avi Kivity
        ret = fwrite(linebuf, 1, pbuf - linebuf, f);
2403 f8e378f2 Avi Kivity
        (void)ret;
2404 59a983b9 bellard
    }
2405 7267c094 Anthony Liguori
    g_free(linebuf);
2406 59a983b9 bellard
    fclose(f);
2407 59a983b9 bellard
    return 0;
2408 59a983b9 bellard
}
2409 59a983b9 bellard
2410 4c5e8c5c blueswir1
/* save the vga display in a PPM image even if no display is
2411 4c5e8c5c blueswir1
   available */
2412 45efb161 Gerd Hoffmann
static void vga_screen_dump(void *opaque, const char *filename, bool cswitch)
2413 4c5e8c5c blueswir1
{
2414 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
2415 4c5e8c5c blueswir1
2416 45efb161 Gerd Hoffmann
    if (cswitch) {
2417 45efb161 Gerd Hoffmann
        vga_invalidate_display(s);
2418 45efb161 Gerd Hoffmann
        vga_hw_update();
2419 45efb161 Gerd Hoffmann
    }
2420 9a51f5b0 Gerd Hoffmann
    ppm_save(filename, s->ds->surface);
2421 4c5e8c5c blueswir1
}