Statistics
| Branch: | Revision:

root / hw / vga.c @ 1f163b14

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