Statistics
| Branch: | Revision:

root / hw / vga.c @ cedd91d2

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