Statistics
| Branch: | Revision:

root / hw / vga.c @ a8aa669b

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