Statistics
| Branch: | Revision:

root / hw / vga.c @ a130a41e

History | View | Annotate | Download (53.5 kB)

1 e89f66ec bellard
/*
2 4fa0f5d2 bellard
 * QEMU VGA Emulator.
3 e89f66ec bellard
 * 
4 e89f66ec bellard
 * Copyright (c) 2003 Fabrice Bellard
5 e89f66ec bellard
 * 
6 e89f66ec bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e89f66ec bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e89f66ec bellard
 * in the Software without restriction, including without limitation the rights
9 e89f66ec bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e89f66ec bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e89f66ec bellard
 * furnished to do so, subject to the following conditions:
12 e89f66ec bellard
 *
13 e89f66ec bellard
 * The above copyright notice and this permission notice shall be included in
14 e89f66ec bellard
 * all copies or substantial portions of the Software.
15 e89f66ec bellard
 *
16 e89f66ec bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e89f66ec bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e89f66ec bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e89f66ec bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e89f66ec bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e89f66ec bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e89f66ec bellard
 * THE SOFTWARE.
23 e89f66ec bellard
 */
24 e89f66ec bellard
#include "vl.h"
25 798b0c25 bellard
#include "vga_int.h"
26 e89f66ec bellard
27 e89f66ec bellard
//#define DEBUG_VGA
28 17b0018b bellard
//#define DEBUG_VGA_MEM
29 a41bc9af bellard
//#define DEBUG_VGA_REG
30 a41bc9af bellard
31 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 a130a41e bellard
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1305 a130a41e bellard
{
1306 a130a41e bellard
    int width, height;
1307 a130a41e bellard
    
1308 a130a41e bellard
    width = (s->cr[0x01] + 1) * 8;
1309 a130a41e bellard
    height = s->cr[0x12] | 
1310 a130a41e bellard
        ((s->cr[0x07] & 0x02) << 7) | 
1311 a130a41e bellard
        ((s->cr[0x07] & 0x40) << 3);
1312 a130a41e bellard
    height = (height + 1);
1313 a130a41e bellard
    *pwidth = width;
1314 a130a41e bellard
    *pheight = height;
1315 a130a41e bellard
}
1316 a130a41e bellard
1317 a8aa669b bellard
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1318 a8aa669b bellard
{
1319 a8aa669b bellard
    int y;
1320 a8aa669b bellard
    if (y1 >= VGA_MAX_HEIGHT)
1321 a8aa669b bellard
        return;
1322 a8aa669b bellard
    if (y2 >= VGA_MAX_HEIGHT)
1323 a8aa669b bellard
        y2 = VGA_MAX_HEIGHT;
1324 a8aa669b bellard
    for(y = y1; y < y2; y++) {
1325 a8aa669b bellard
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1326 a8aa669b bellard
    }
1327 a8aa669b bellard
}
1328 a8aa669b bellard
1329 e89f66ec bellard
/* 
1330 e89f66ec bellard
 * graphic modes
1331 e89f66ec bellard
 */
1332 e89f66ec bellard
static void vga_draw_graphic(VGAState *s, int full_update)
1333 e89f66ec bellard
{
1334 17b0018b bellard
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1335 39cf7803 bellard
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1336 a07cf92a bellard
    int disp_width, multi_scan, multi_run;
1337 e89f66ec bellard
    uint8_t *d;
1338 39cf7803 bellard
    uint32_t v, addr1, addr;
1339 e89f66ec bellard
    vga_draw_line_func *vga_draw_line;
1340 17b0018b bellard
    
1341 e89f66ec bellard
    full_update |= update_basic_params(s);
1342 e89f66ec bellard
1343 a130a41e bellard
    s->get_resolution(s, &width, &height);
1344 17b0018b bellard
    disp_width = width;
1345 09a79b49 bellard
1346 e89f66ec bellard
    shift_control = (s->gr[0x05] >> 5) & 3;
1347 a07cf92a bellard
    double_scan = (s->cr[0x09] & 0x80);
1348 a07cf92a bellard
    if (shift_control > 1) {
1349 a07cf92a bellard
        multi_scan = (s->cr[0x09] & 0x1f);
1350 a07cf92a bellard
    } else {
1351 a07cf92a bellard
        multi_scan = 0;
1352 a07cf92a bellard
    }
1353 a07cf92a bellard
    multi_run = multi_scan;
1354 17b0018b bellard
    if (shift_control != s->shift_control ||
1355 17b0018b bellard
        double_scan != s->double_scan) {
1356 e89f66ec bellard
        full_update = 1;
1357 e89f66ec bellard
        s->shift_control = shift_control;
1358 17b0018b bellard
        s->double_scan = double_scan;
1359 e89f66ec bellard
    }
1360 e89f66ec bellard
    
1361 17b0018b bellard
    if (shift_control == 0) {
1362 17b0018b bellard
        full_update |= update_palette16(s);
1363 17b0018b bellard
        if (s->sr[0x01] & 8) {
1364 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1365 17b0018b bellard
            disp_width <<= 1;
1366 17b0018b bellard
        } else {
1367 17b0018b bellard
            v = VGA_DRAW_LINE4;
1368 17b0018b bellard
        }
1369 17b0018b bellard
    } else if (shift_control == 1) {
1370 17b0018b bellard
        full_update |= update_palette16(s);
1371 17b0018b bellard
        if (s->sr[0x01] & 8) {
1372 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1373 17b0018b bellard
            disp_width <<= 1;
1374 17b0018b bellard
        } else {
1375 17b0018b bellard
            v = VGA_DRAW_LINE2;
1376 17b0018b bellard
        }
1377 17b0018b bellard
    } else {
1378 798b0c25 bellard
        switch(s->get_bpp(s)) {
1379 798b0c25 bellard
        default:
1380 798b0c25 bellard
        case 0:
1381 4fa0f5d2 bellard
            full_update |= update_palette256(s);
1382 4fa0f5d2 bellard
            v = VGA_DRAW_LINE8D2;
1383 798b0c25 bellard
            break;
1384 798b0c25 bellard
        case 8:
1385 798b0c25 bellard
            full_update |= update_palette256(s);
1386 798b0c25 bellard
            v = VGA_DRAW_LINE8;
1387 798b0c25 bellard
            break;
1388 798b0c25 bellard
        case 15:
1389 798b0c25 bellard
            v = VGA_DRAW_LINE15;
1390 798b0c25 bellard
            break;
1391 798b0c25 bellard
        case 16:
1392 798b0c25 bellard
            v = VGA_DRAW_LINE16;
1393 798b0c25 bellard
            break;
1394 798b0c25 bellard
        case 24:
1395 798b0c25 bellard
            v = VGA_DRAW_LINE24;
1396 798b0c25 bellard
            break;
1397 798b0c25 bellard
        case 32:
1398 798b0c25 bellard
            v = VGA_DRAW_LINE32;
1399 798b0c25 bellard
            break;
1400 4fa0f5d2 bellard
        }
1401 17b0018b bellard
    }
1402 e89f66ec bellard
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1403 17b0018b bellard
1404 17b0018b bellard
    if (disp_width != s->last_width ||
1405 17b0018b bellard
        height != s->last_height) {
1406 17b0018b bellard
        dpy_resize(s->ds, disp_width, height);
1407 2aebb3eb bellard
        s->last_scr_width = disp_width;
1408 2aebb3eb bellard
        s->last_scr_height = height;
1409 17b0018b bellard
        s->last_width = disp_width;
1410 17b0018b bellard
        s->last_height = height;
1411 17b0018b bellard
        full_update = 1;
1412 17b0018b bellard
    }
1413 a8aa669b bellard
    if (s->cursor_invalidate)
1414 a8aa669b bellard
        s->cursor_invalidate(s);
1415 a8aa669b bellard
    
1416 e89f66ec bellard
    line_offset = s->line_offset;
1417 17b0018b bellard
#if 0
1418 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",
1419 17b0018b bellard
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1420 17b0018b bellard
#endif
1421 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1422 39cf7803 bellard
    bwidth = width * 4;
1423 39cf7803 bellard
    y_start = -1;
1424 e89f66ec bellard
    page_min = 0x7fffffff;
1425 e89f66ec bellard
    page_max = -1;
1426 e89f66ec bellard
    d = s->ds->data;
1427 e89f66ec bellard
    linesize = s->ds->linesize;
1428 17b0018b bellard
    y1 = 0;
1429 e89f66ec bellard
    for(y = 0; y < height; y++) {
1430 e89f66ec bellard
        addr = addr1;
1431 39cf7803 bellard
        if (!(s->cr[0x17] & 1)) {
1432 17b0018b bellard
            int shift;
1433 e89f66ec bellard
            /* CGA compatibility handling */
1434 17b0018b bellard
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1435 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1436 e89f66ec bellard
        }
1437 39cf7803 bellard
        if (!(s->cr[0x17] & 2)) {
1438 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1439 e89f66ec bellard
        }
1440 4fa0f5d2 bellard
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1441 4fa0f5d2 bellard
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1442 4fa0f5d2 bellard
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1443 4fa0f5d2 bellard
            cpu_physical_memory_is_dirty(page1);
1444 4fa0f5d2 bellard
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1445 39cf7803 bellard
            /* if wide line, can use another page */
1446 4fa0f5d2 bellard
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1447 39cf7803 bellard
        }
1448 a8aa669b bellard
        /* explicit invalidation for the hardware cursor */
1449 a8aa669b bellard
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1450 e89f66ec bellard
        if (update) {
1451 39cf7803 bellard
            if (y_start < 0)
1452 39cf7803 bellard
                y_start = y;
1453 e89f66ec bellard
            if (page0 < page_min)
1454 e89f66ec bellard
                page_min = page0;
1455 e89f66ec bellard
            if (page1 > page_max)
1456 e89f66ec bellard
                page_max = page1;
1457 e89f66ec bellard
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1458 a8aa669b bellard
            if (s->cursor_draw_line)
1459 a8aa669b bellard
                s->cursor_draw_line(s, d, y);
1460 39cf7803 bellard
        } else {
1461 39cf7803 bellard
            if (y_start >= 0) {
1462 39cf7803 bellard
                /* flush to display */
1463 39cf7803 bellard
                dpy_update(s->ds, 0, y_start, 
1464 17b0018b bellard
                           disp_width, y - y_start);
1465 39cf7803 bellard
                y_start = -1;
1466 39cf7803 bellard
            }
1467 e89f66ec bellard
        }
1468 a07cf92a bellard
        if (!multi_run) {
1469 a07cf92a bellard
            if (!double_scan || (y & 1) != 0) {
1470 a07cf92a bellard
                if (y1 == s->line_compare) {
1471 a07cf92a bellard
                    addr1 = 0;
1472 a07cf92a bellard
                } else {
1473 a07cf92a bellard
                    mask = (s->cr[0x17] & 3) ^ 3;
1474 a07cf92a bellard
                    if ((y1 & mask) == mask)
1475 a07cf92a bellard
                        addr1 += line_offset;
1476 a07cf92a bellard
                }
1477 a07cf92a bellard
                y1++;
1478 17b0018b bellard
            }
1479 a07cf92a bellard
            multi_run = multi_scan;
1480 a07cf92a bellard
        } else {
1481 a07cf92a bellard
            multi_run--;
1482 17b0018b bellard
            y1++;
1483 e89f66ec bellard
        }
1484 e89f66ec bellard
        d += linesize;
1485 e89f66ec bellard
    }
1486 39cf7803 bellard
    if (y_start >= 0) {
1487 39cf7803 bellard
        /* flush to display */
1488 39cf7803 bellard
        dpy_update(s->ds, 0, y_start, 
1489 17b0018b bellard
                   disp_width, y - y_start);
1490 39cf7803 bellard
    }
1491 e89f66ec bellard
    /* reset modified pages */
1492 e89f66ec bellard
    if (page_max != -1) {
1493 4fa0f5d2 bellard
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1494 e89f66ec bellard
    }
1495 a8aa669b bellard
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1496 e89f66ec bellard
}
1497 e89f66ec bellard
1498 2aebb3eb bellard
static void vga_draw_blank(VGAState *s, int full_update)
1499 2aebb3eb bellard
{
1500 2aebb3eb bellard
    int i, w, val;
1501 2aebb3eb bellard
    uint8_t *d;
1502 2aebb3eb bellard
1503 2aebb3eb bellard
    if (!full_update)
1504 2aebb3eb bellard
        return;
1505 2aebb3eb bellard
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1506 2aebb3eb bellard
        return;
1507 2aebb3eb bellard
    if (s->ds->depth == 8) 
1508 2aebb3eb bellard
        val = s->rgb_to_pixel(0, 0, 0);
1509 2aebb3eb bellard
    else
1510 2aebb3eb bellard
        val = 0;
1511 2aebb3eb bellard
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1512 2aebb3eb bellard
    d = s->ds->data;
1513 2aebb3eb bellard
    for(i = 0; i < s->last_scr_height; i++) {
1514 2aebb3eb bellard
        memset(d, val, w);
1515 2aebb3eb bellard
        d += s->ds->linesize;
1516 2aebb3eb bellard
    }
1517 2aebb3eb bellard
    dpy_update(s->ds, 0, 0, 
1518 2aebb3eb bellard
               s->last_scr_width, s->last_scr_height);
1519 2aebb3eb bellard
}
1520 2aebb3eb bellard
1521 2aebb3eb bellard
#define GMODE_TEXT     0
1522 2aebb3eb bellard
#define GMODE_GRAPH    1
1523 2aebb3eb bellard
#define GMODE_BLANK 2 
1524 2aebb3eb bellard
1525 e89f66ec bellard
void vga_update_display(void)
1526 e89f66ec bellard
{
1527 7b17d41e bellard
    VGAState *s = vga_state;
1528 e89f66ec bellard
    int full_update, graphic_mode;
1529 e89f66ec bellard
1530 e89f66ec bellard
    if (s->ds->depth == 0) {
1531 0f35920c bellard
        /* nothing to do */
1532 59a983b9 bellard
    } else {
1533 59a983b9 bellard
        switch(s->ds->depth) {
1534 59a983b9 bellard
        case 8:
1535 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel8_dup;
1536 59a983b9 bellard
            break;
1537 59a983b9 bellard
        case 15:
1538 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel15_dup;
1539 59a983b9 bellard
            break;
1540 59a983b9 bellard
        default:
1541 59a983b9 bellard
        case 16:
1542 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel16_dup;
1543 59a983b9 bellard
            break;
1544 59a983b9 bellard
        case 32:
1545 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel32_dup;
1546 59a983b9 bellard
            break;
1547 59a983b9 bellard
        }
1548 59a983b9 bellard
        
1549 e89f66ec bellard
        full_update = 0;
1550 2aebb3eb bellard
        if (!(s->ar_index & 0x20)) {
1551 2aebb3eb bellard
            graphic_mode = GMODE_BLANK;
1552 2aebb3eb bellard
        } else {
1553 2aebb3eb bellard
            graphic_mode = s->gr[6] & 1;
1554 2aebb3eb bellard
        }
1555 e89f66ec bellard
        if (graphic_mode != s->graphic_mode) {
1556 e89f66ec bellard
            s->graphic_mode = graphic_mode;
1557 e89f66ec bellard
            full_update = 1;
1558 e89f66ec bellard
        }
1559 2aebb3eb bellard
        switch(graphic_mode) {
1560 2aebb3eb bellard
        case GMODE_TEXT:
1561 e89f66ec bellard
            vga_draw_text(s, full_update);
1562 2aebb3eb bellard
            break;
1563 2aebb3eb bellard
        case GMODE_GRAPH:
1564 2aebb3eb bellard
            vga_draw_graphic(s, full_update);
1565 2aebb3eb bellard
            break;
1566 2aebb3eb bellard
        case GMODE_BLANK:
1567 2aebb3eb bellard
        default:
1568 2aebb3eb bellard
            vga_draw_blank(s, full_update);
1569 2aebb3eb bellard
            break;
1570 2aebb3eb bellard
        }
1571 e89f66ec bellard
    }
1572 e89f66ec bellard
}
1573 e89f66ec bellard
1574 a130a41e bellard
/* force a full display refresh */
1575 a130a41e bellard
void vga_invalidate_display(void)
1576 a130a41e bellard
{
1577 a130a41e bellard
    VGAState *s = vga_state;
1578 a130a41e bellard
    
1579 a130a41e bellard
    s->last_width = -1;
1580 a130a41e bellard
    s->last_height = -1;
1581 a130a41e bellard
}
1582 a130a41e bellard
1583 59a983b9 bellard
static void vga_reset(VGAState *s)
1584 e89f66ec bellard
{
1585 e89f66ec bellard
    memset(s, 0, sizeof(VGAState));
1586 a41bc9af bellard
#ifdef CONFIG_S3VGA
1587 e89f66ec bellard
    /* chip ID for 8c968 */
1588 e89f66ec bellard
    s->cr[0x2d] = 0x88;
1589 e89f66ec bellard
    s->cr[0x2e] = 0xb0;
1590 e89f66ec bellard
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1591 e89f66ec bellard
    s->cr[0x30] = 0xe1;
1592 a41bc9af bellard
#endif
1593 e89f66ec bellard
    s->graphic_mode = -1; /* force full update */
1594 e89f66ec bellard
}
1595 e89f66ec bellard
1596 59a983b9 bellard
static CPUReadMemoryFunc *vga_mem_read[3] = {
1597 e89f66ec bellard
    vga_mem_readb,
1598 e89f66ec bellard
    vga_mem_readw,
1599 e89f66ec bellard
    vga_mem_readl,
1600 e89f66ec bellard
};
1601 e89f66ec bellard
1602 59a983b9 bellard
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1603 e89f66ec bellard
    vga_mem_writeb,
1604 e89f66ec bellard
    vga_mem_writew,
1605 e89f66ec bellard
    vga_mem_writel,
1606 e89f66ec bellard
};
1607 e89f66ec bellard
1608 b0a21b53 bellard
static void vga_save(QEMUFile *f, void *opaque)
1609 b0a21b53 bellard
{
1610 b0a21b53 bellard
    VGAState *s = opaque;
1611 b0a21b53 bellard
    int i;
1612 b0a21b53 bellard
1613 b0a21b53 bellard
    qemu_put_be32s(f, &s->latch);
1614 b0a21b53 bellard
    qemu_put_8s(f, &s->sr_index);
1615 b0a21b53 bellard
    qemu_put_buffer(f, s->sr, 8);
1616 b0a21b53 bellard
    qemu_put_8s(f, &s->gr_index);
1617 b0a21b53 bellard
    qemu_put_buffer(f, s->gr, 16);
1618 b0a21b53 bellard
    qemu_put_8s(f, &s->ar_index);
1619 b0a21b53 bellard
    qemu_put_buffer(f, s->ar, 21);
1620 b0a21b53 bellard
    qemu_put_be32s(f, &s->ar_flip_flop);
1621 b0a21b53 bellard
    qemu_put_8s(f, &s->cr_index);
1622 b0a21b53 bellard
    qemu_put_buffer(f, s->cr, 256);
1623 b0a21b53 bellard
    qemu_put_8s(f, &s->msr);
1624 b0a21b53 bellard
    qemu_put_8s(f, &s->fcr);
1625 b0a21b53 bellard
    qemu_put_8s(f, &s->st00);
1626 b0a21b53 bellard
    qemu_put_8s(f, &s->st01);
1627 b0a21b53 bellard
1628 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_state);
1629 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_sub_index);
1630 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_read_index);
1631 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_write_index);
1632 b0a21b53 bellard
    qemu_put_buffer(f, s->dac_cache, 3);
1633 b0a21b53 bellard
    qemu_put_buffer(f, s->palette, 768);
1634 b0a21b53 bellard
1635 b0a21b53 bellard
    qemu_put_be32s(f, &s->bank_offset);
1636 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
1637 b0a21b53 bellard
    qemu_put_byte(f, 1);
1638 b0a21b53 bellard
    qemu_put_be16s(f, &s->vbe_index);
1639 b0a21b53 bellard
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1640 b0a21b53 bellard
        qemu_put_be16s(f, &s->vbe_regs[i]);
1641 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_start_addr);
1642 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_line_offset);
1643 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_bank_mask);
1644 b0a21b53 bellard
#else
1645 b0a21b53 bellard
    qemu_put_byte(f, 0);
1646 b0a21b53 bellard
#endif
1647 b0a21b53 bellard
}
1648 b0a21b53 bellard
1649 b0a21b53 bellard
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1650 b0a21b53 bellard
{
1651 b0a21b53 bellard
    VGAState *s = opaque;
1652 b0a21b53 bellard
    int is_vbe, i;
1653 b0a21b53 bellard
1654 b0a21b53 bellard
    if (version_id != 1)
1655 b0a21b53 bellard
        return -EINVAL;
1656 b0a21b53 bellard
1657 b0a21b53 bellard
    qemu_get_be32s(f, &s->latch);
1658 b0a21b53 bellard
    qemu_get_8s(f, &s->sr_index);
1659 b0a21b53 bellard
    qemu_get_buffer(f, s->sr, 8);
1660 b0a21b53 bellard
    qemu_get_8s(f, &s->gr_index);
1661 b0a21b53 bellard
    qemu_get_buffer(f, s->gr, 16);
1662 b0a21b53 bellard
    qemu_get_8s(f, &s->ar_index);
1663 b0a21b53 bellard
    qemu_get_buffer(f, s->ar, 21);
1664 b0a21b53 bellard
    qemu_get_be32s(f, &s->ar_flip_flop);
1665 b0a21b53 bellard
    qemu_get_8s(f, &s->cr_index);
1666 b0a21b53 bellard
    qemu_get_buffer(f, s->cr, 256);
1667 b0a21b53 bellard
    qemu_get_8s(f, &s->msr);
1668 b0a21b53 bellard
    qemu_get_8s(f, &s->fcr);
1669 b0a21b53 bellard
    qemu_get_8s(f, &s->st00);
1670 b0a21b53 bellard
    qemu_get_8s(f, &s->st01);
1671 b0a21b53 bellard
1672 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_state);
1673 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_sub_index);
1674 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_read_index);
1675 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_write_index);
1676 b0a21b53 bellard
    qemu_get_buffer(f, s->dac_cache, 3);
1677 b0a21b53 bellard
    qemu_get_buffer(f, s->palette, 768);
1678 b0a21b53 bellard
1679 b0a21b53 bellard
    qemu_get_be32s(f, &s->bank_offset);
1680 b0a21b53 bellard
    is_vbe = qemu_get_byte(f);
1681 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
1682 b0a21b53 bellard
    if (!is_vbe)
1683 b0a21b53 bellard
        return -EINVAL;
1684 b0a21b53 bellard
    qemu_get_be16s(f, &s->vbe_index);
1685 b0a21b53 bellard
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1686 b0a21b53 bellard
        qemu_get_be16s(f, &s->vbe_regs[i]);
1687 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_start_addr);
1688 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_line_offset);
1689 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_bank_mask);
1690 b0a21b53 bellard
#else
1691 b0a21b53 bellard
    if (is_vbe)
1692 b0a21b53 bellard
        return -EINVAL;
1693 b0a21b53 bellard
#endif
1694 b0a21b53 bellard
1695 b0a21b53 bellard
    /* force refresh */
1696 b0a21b53 bellard
    s->graphic_mode = -1;
1697 b0a21b53 bellard
    return 0;
1698 b0a21b53 bellard
}
1699 b0a21b53 bellard
1700 1078f663 bellard
static void vga_map(PCIDevice *pci_dev, int region_num, 
1701 1078f663 bellard
                    uint32_t addr, uint32_t size, int type)
1702 1078f663 bellard
{
1703 7b17d41e bellard
    VGAState *s = vga_state;
1704 1078f663 bellard
1705 1078f663 bellard
    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1706 1078f663 bellard
}
1707 1078f663 bellard
1708 798b0c25 bellard
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1709 798b0c25 bellard
                     unsigned long vga_ram_offset, int vga_ram_size)
1710 e89f66ec bellard
{
1711 17b0018b bellard
    int i, j, v, b;
1712 e89f66ec bellard
1713 e89f66ec bellard
    for(i = 0;i < 256; i++) {
1714 e89f66ec bellard
        v = 0;
1715 e89f66ec bellard
        for(j = 0; j < 8; j++) {
1716 e89f66ec bellard
            v |= ((i >> j) & 1) << (j * 4);
1717 e89f66ec bellard
        }
1718 e89f66ec bellard
        expand4[i] = v;
1719 e89f66ec bellard
1720 e89f66ec bellard
        v = 0;
1721 e89f66ec bellard
        for(j = 0; j < 4; j++) {
1722 e89f66ec bellard
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1723 e89f66ec bellard
        }
1724 e89f66ec bellard
        expand2[i] = v;
1725 e89f66ec bellard
    }
1726 17b0018b bellard
    for(i = 0; i < 16; i++) {
1727 17b0018b bellard
        v = 0;
1728 17b0018b bellard
        for(j = 0; j < 4; j++) {
1729 17b0018b bellard
            b = ((i >> j) & 1);
1730 17b0018b bellard
            v |= b << (2 * j);
1731 17b0018b bellard
            v |= b << (2 * j + 1);
1732 17b0018b bellard
        }
1733 17b0018b bellard
        expand4to8[i] = v;
1734 17b0018b bellard
    }
1735 e89f66ec bellard
1736 e89f66ec bellard
    vga_reset(s);
1737 e89f66ec bellard
1738 e89f66ec bellard
    s->vram_ptr = vga_ram_base;
1739 e89f66ec bellard
    s->vram_offset = vga_ram_offset;
1740 e89f66ec bellard
    s->vram_size = vga_ram_size;
1741 e89f66ec bellard
    s->ds = ds;
1742 798b0c25 bellard
    s->get_bpp = vga_get_bpp;
1743 798b0c25 bellard
    s->get_offsets = vga_get_offsets;
1744 a130a41e bellard
    s->get_resolution = vga_get_resolution;
1745 7b17d41e bellard
    /* XXX: currently needed for display */
1746 7b17d41e bellard
    vga_state = s;
1747 798b0c25 bellard
}
1748 798b0c25 bellard
1749 798b0c25 bellard
1750 798b0c25 bellard
int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, 
1751 798b0c25 bellard
                   unsigned long vga_ram_offset, int vga_ram_size, 
1752 798b0c25 bellard
                   int is_pci)
1753 798b0c25 bellard
{
1754 7b17d41e bellard
    VGAState *s;
1755 7b17d41e bellard
1756 7b17d41e bellard
    s = qemu_mallocz(sizeof(VGAState));
1757 7b17d41e bellard
    if (!s)
1758 7b17d41e bellard
        return -1;
1759 798b0c25 bellard
1760 798b0c25 bellard
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1761 e89f66ec bellard
1762 b0a21b53 bellard
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1763 b0a21b53 bellard
1764 0f35920c bellard
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1765 e89f66ec bellard
1766 0f35920c bellard
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1767 0f35920c bellard
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1768 0f35920c bellard
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1769 0f35920c bellard
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1770 e89f66ec bellard
1771 0f35920c bellard
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1772 e89f66ec bellard
1773 0f35920c bellard
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1774 0f35920c bellard
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1775 0f35920c bellard
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1776 0f35920c bellard
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1777 26aa7d72 bellard
    s->bank_offset = 0;
1778 e89f66ec bellard
1779 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1780 4fa0f5d2 bellard
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1781 cae61cef bellard
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1782 09a79b49 bellard
#if defined (TARGET_I386)
1783 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1784 09a79b49 bellard
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1785 4fa0f5d2 bellard
1786 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1787 09a79b49 bellard
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1788 646be93b bellard
1789 646be93b bellard
    /* old Bochs IO ports */
1790 09a79b49 bellard
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1791 09a79b49 bellard
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1792 646be93b bellard
1793 09a79b49 bellard
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1794 09a79b49 bellard
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1795 09a79b49 bellard
#else
1796 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1797 09a79b49 bellard
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1798 09a79b49 bellard
1799 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1800 09a79b49 bellard
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1801 4fa0f5d2 bellard
#endif
1802 09a79b49 bellard
#endif /* CONFIG_BOCHS_VBE */
1803 4fa0f5d2 bellard
1804 a4193c8a bellard
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1805 26aa7d72 bellard
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1806 26aa7d72 bellard
                                 vga_io_memory);
1807 1078f663 bellard
1808 1078f663 bellard
    if (is_pci) {
1809 1078f663 bellard
        PCIDevice *d;
1810 1078f663 bellard
        uint8_t *pci_conf;
1811 1078f663 bellard
1812 1078f663 bellard
        d = pci_register_device("VGA", 
1813 1078f663 bellard
                                sizeof(PCIDevice),
1814 1078f663 bellard
                                0, -1, 
1815 1078f663 bellard
                                NULL, NULL);
1816 1078f663 bellard
        pci_conf = d->config;
1817 1078f663 bellard
        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1818 1078f663 bellard
        pci_conf[0x01] = 0x12;
1819 1078f663 bellard
        pci_conf[0x02] = 0x11;
1820 1078f663 bellard
        pci_conf[0x03] = 0x11;
1821 1078f663 bellard
        pci_conf[0x0a] = 0x00; // VGA controller 
1822 1078f663 bellard
        pci_conf[0x0b] = 0x03;
1823 1078f663 bellard
        pci_conf[0x0e] = 0x00; // header_type
1824 1078f663 bellard
1825 1078f663 bellard
        /* XXX: vga_ram_size must be a power of two */
1826 1078f663 bellard
        pci_register_io_region(d, 0, vga_ram_size, 
1827 1078f663 bellard
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1828 1078f663 bellard
    } else {
1829 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1830 1078f663 bellard
        /* XXX: use optimized standard vga accesses */
1831 1078f663 bellard
        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1832 1078f663 bellard
                                     vga_ram_size, vga_ram_offset);
1833 4fa0f5d2 bellard
#endif
1834 1078f663 bellard
    }
1835 e89f66ec bellard
    return 0;
1836 e89f66ec bellard
}
1837 59a983b9 bellard
1838 59a983b9 bellard
/********************************************************/
1839 59a983b9 bellard
/* vga screen dump */
1840 59a983b9 bellard
1841 59a983b9 bellard
static int vga_save_w, vga_save_h;
1842 59a983b9 bellard
1843 59a983b9 bellard
static void vga_save_dpy_update(DisplayState *s, 
1844 59a983b9 bellard
                                int x, int y, int w, int h)
1845 59a983b9 bellard
{
1846 59a983b9 bellard
}
1847 59a983b9 bellard
1848 59a983b9 bellard
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1849 59a983b9 bellard
{
1850 59a983b9 bellard
    s->linesize = w * 4;
1851 59a983b9 bellard
    s->data = qemu_malloc(h * s->linesize);
1852 59a983b9 bellard
    vga_save_w = w;
1853 59a983b9 bellard
    vga_save_h = h;
1854 59a983b9 bellard
}
1855 59a983b9 bellard
1856 59a983b9 bellard
static void vga_save_dpy_refresh(DisplayState *s)
1857 59a983b9 bellard
{
1858 59a983b9 bellard
}
1859 59a983b9 bellard
1860 59a983b9 bellard
static int ppm_save(const char *filename, uint8_t *data, 
1861 59a983b9 bellard
                    int w, int h, int linesize)
1862 59a983b9 bellard
{
1863 59a983b9 bellard
    FILE *f;
1864 59a983b9 bellard
    uint8_t *d, *d1;
1865 59a983b9 bellard
    unsigned int v;
1866 59a983b9 bellard
    int y, x;
1867 59a983b9 bellard
1868 59a983b9 bellard
    f = fopen(filename, "wb");
1869 59a983b9 bellard
    if (!f)
1870 59a983b9 bellard
        return -1;
1871 59a983b9 bellard
    fprintf(f, "P6\n%d %d\n%d\n",
1872 59a983b9 bellard
            w, h, 255);
1873 59a983b9 bellard
    d1 = data;
1874 59a983b9 bellard
    for(y = 0; y < h; y++) {
1875 59a983b9 bellard
        d = d1;
1876 59a983b9 bellard
        for(x = 0; x < w; x++) {
1877 59a983b9 bellard
            v = *(uint32_t *)d;
1878 59a983b9 bellard
            fputc((v >> 16) & 0xff, f);
1879 59a983b9 bellard
            fputc((v >> 8) & 0xff, f);
1880 59a983b9 bellard
            fputc((v) & 0xff, f);
1881 59a983b9 bellard
            d += 4;
1882 59a983b9 bellard
        }
1883 59a983b9 bellard
        d1 += linesize;
1884 59a983b9 bellard
    }
1885 59a983b9 bellard
    fclose(f);
1886 59a983b9 bellard
    return 0;
1887 59a983b9 bellard
}
1888 59a983b9 bellard
1889 59a983b9 bellard
/* save the vga display in a PPM image even if no display is
1890 59a983b9 bellard
   available */
1891 59a983b9 bellard
void vga_screen_dump(const char *filename)
1892 59a983b9 bellard
{
1893 7b17d41e bellard
    VGAState *s = vga_state;
1894 59a983b9 bellard
    DisplayState *saved_ds, ds1, *ds = &ds1;
1895 59a983b9 bellard
    
1896 59a983b9 bellard
    /* XXX: this is a little hackish */
1897 a130a41e bellard
    vga_invalidate_display();
1898 59a983b9 bellard
    saved_ds = s->ds;
1899 59a983b9 bellard
1900 59a983b9 bellard
    memset(ds, 0, sizeof(DisplayState));
1901 59a983b9 bellard
    ds->dpy_update = vga_save_dpy_update;
1902 59a983b9 bellard
    ds->dpy_resize = vga_save_dpy_resize;
1903 59a983b9 bellard
    ds->dpy_refresh = vga_save_dpy_refresh;
1904 59a983b9 bellard
    ds->depth = 32;
1905 59a983b9 bellard
1906 59a983b9 bellard
    s->ds = ds;
1907 59a983b9 bellard
    s->graphic_mode = -1;
1908 59a983b9 bellard
    vga_update_display();
1909 59a983b9 bellard
    
1910 59a983b9 bellard
    if (ds->data) {
1911 59a983b9 bellard
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1912 59a983b9 bellard
                 s->ds->linesize);
1913 59a983b9 bellard
        qemu_free(ds->data);
1914 59a983b9 bellard
    }
1915 59a983b9 bellard
    s->ds = saved_ds;
1916 59a983b9 bellard
}