Statistics
| Branch: | Revision:

root / hw / vga.c @ 0647b949

History | View | Annotate | Download (67.9 kB)

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