Statistics
| Branch: | Revision:

root / hw / vga.c @ 5fafdf24

History | View | Annotate | Download (59.9 kB)

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