Statistics
| Branch: | Revision:

root / hw / vga.c @ 9c02f1a2

History | View | Annotate | Download (56.5 kB)

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