Statistics
| Branch: | Revision:

root / hw / vga.c @ f6c958c8

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 e6eccb38 bellard
        case 0x3c8:
194 e6eccb38 bellard
            val = s->dac_write_index;
195 e6eccb38 bellard
            break;
196 e89f66ec bellard
        case 0x3c9:
197 e89f66ec bellard
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
198 e89f66ec bellard
            if (++s->dac_sub_index == 3) {
199 e89f66ec bellard
                s->dac_sub_index = 0;
200 e89f66ec bellard
                s->dac_read_index++;
201 e89f66ec bellard
            }
202 e89f66ec bellard
            break;
203 e89f66ec bellard
        case 0x3ca:
204 e89f66ec bellard
            val = s->fcr;
205 e89f66ec bellard
            break;
206 e89f66ec bellard
        case 0x3cc:
207 e89f66ec bellard
            val = s->msr;
208 e89f66ec bellard
            break;
209 e89f66ec bellard
        case 0x3ce:
210 e89f66ec bellard
            val = s->gr_index;
211 e89f66ec bellard
            break;
212 e89f66ec bellard
        case 0x3cf:
213 e89f66ec bellard
            val = s->gr[s->gr_index];
214 a41bc9af bellard
#ifdef DEBUG_VGA_REG
215 a41bc9af bellard
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
216 a41bc9af bellard
#endif
217 e89f66ec bellard
            break;
218 e89f66ec bellard
        case 0x3b4:
219 e89f66ec bellard
        case 0x3d4:
220 e89f66ec bellard
            val = s->cr_index;
221 e89f66ec bellard
            break;
222 e89f66ec bellard
        case 0x3b5:
223 e89f66ec bellard
        case 0x3d5:
224 e89f66ec bellard
            val = s->cr[s->cr_index];
225 a41bc9af bellard
#ifdef DEBUG_VGA_REG
226 a41bc9af bellard
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
227 a41bc9af bellard
#endif
228 a41bc9af bellard
#ifdef DEBUG_S3
229 a41bc9af bellard
            if (s->cr_index >= 0x20)
230 a41bc9af bellard
                printf("S3: CR read index=0x%x val=0x%x\n",
231 a41bc9af bellard
                       s->cr_index, val);
232 a41bc9af bellard
#endif
233 e89f66ec bellard
            break;
234 e89f66ec bellard
        case 0x3ba:
235 e89f66ec bellard
        case 0x3da:
236 e89f66ec bellard
            /* just toggle to fool polling */
237 e89f66ec bellard
            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
238 e89f66ec bellard
            val = s->st01;
239 e89f66ec bellard
            s->ar_flip_flop = 0;
240 e89f66ec bellard
            break;
241 e89f66ec bellard
        default:
242 e89f66ec bellard
            val = 0x00;
243 e89f66ec bellard
            break;
244 e89f66ec bellard
        }
245 e89f66ec bellard
    }
246 4fa0f5d2 bellard
#if defined(DEBUG_VGA)
247 e89f66ec bellard
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
248 e89f66ec bellard
#endif
249 e89f66ec bellard
    return val;
250 e89f66ec bellard
}
251 e89f66ec bellard
252 0f35920c bellard
static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
253 e89f66ec bellard
{
254 0f35920c bellard
    VGAState *s = opaque;
255 5467a722 bellard
    int index;
256 e89f66ec bellard
257 e89f66ec bellard
    /* check port range access depending on color/monochrome mode */
258 e89f66ec bellard
    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
259 e89f66ec bellard
        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
260 e89f66ec bellard
        return;
261 e89f66ec bellard
262 e89f66ec bellard
#ifdef DEBUG_VGA
263 e89f66ec bellard
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
264 e89f66ec bellard
#endif
265 e89f66ec bellard
266 e89f66ec bellard
    switch(addr) {
267 e89f66ec bellard
    case 0x3c0:
268 e89f66ec bellard
        if (s->ar_flip_flop == 0) {
269 e89f66ec bellard
            val &= 0x3f;
270 e89f66ec bellard
            s->ar_index = val;
271 e89f66ec bellard
        } else {
272 e89f66ec bellard
            index = s->ar_index & 0x1f;
273 e89f66ec bellard
            switch(index) {
274 e89f66ec bellard
            case 0x00 ... 0x0f:
275 e89f66ec bellard
                s->ar[index] = val & 0x3f;
276 e89f66ec bellard
                break;
277 e89f66ec bellard
            case 0x10:
278 e89f66ec bellard
                s->ar[index] = val & ~0x10;
279 e89f66ec bellard
                break;
280 e89f66ec bellard
            case 0x11:
281 e89f66ec bellard
                s->ar[index] = val;
282 e89f66ec bellard
                break;
283 e89f66ec bellard
            case 0x12:
284 e89f66ec bellard
                s->ar[index] = val & ~0xc0;
285 e89f66ec bellard
                break;
286 e89f66ec bellard
            case 0x13:
287 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
288 e89f66ec bellard
                break;
289 e89f66ec bellard
            case 0x14:
290 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
291 e89f66ec bellard
                break;
292 e89f66ec bellard
            default:
293 e89f66ec bellard
                break;
294 e89f66ec bellard
            }
295 e89f66ec bellard
        }
296 e89f66ec bellard
        s->ar_flip_flop ^= 1;
297 e89f66ec bellard
        break;
298 e89f66ec bellard
    case 0x3c2:
299 e89f66ec bellard
        s->msr = val & ~0x10;
300 e89f66ec bellard
        break;
301 e89f66ec bellard
    case 0x3c4:
302 e89f66ec bellard
        s->sr_index = val & 7;
303 e89f66ec bellard
        break;
304 e89f66ec bellard
    case 0x3c5:
305 a41bc9af bellard
#ifdef DEBUG_VGA_REG
306 a41bc9af bellard
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
307 a41bc9af bellard
#endif
308 e89f66ec bellard
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
309 e89f66ec bellard
        break;
310 e89f66ec bellard
    case 0x3c7:
311 e89f66ec bellard
        s->dac_read_index = val;
312 e89f66ec bellard
        s->dac_sub_index = 0;
313 e89f66ec bellard
        s->dac_state = 3;
314 e89f66ec bellard
        break;
315 e89f66ec bellard
    case 0x3c8:
316 e89f66ec bellard
        s->dac_write_index = val;
317 e89f66ec bellard
        s->dac_sub_index = 0;
318 e89f66ec bellard
        s->dac_state = 0;
319 e89f66ec bellard
        break;
320 e89f66ec bellard
    case 0x3c9:
321 e89f66ec bellard
        s->dac_cache[s->dac_sub_index] = val;
322 e89f66ec bellard
        if (++s->dac_sub_index == 3) {
323 e89f66ec bellard
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
324 e89f66ec bellard
            s->dac_sub_index = 0;
325 e89f66ec bellard
            s->dac_write_index++;
326 e89f66ec bellard
        }
327 e89f66ec bellard
        break;
328 e89f66ec bellard
    case 0x3ce:
329 e89f66ec bellard
        s->gr_index = val & 0x0f;
330 e89f66ec bellard
        break;
331 e89f66ec bellard
    case 0x3cf:
332 a41bc9af bellard
#ifdef DEBUG_VGA_REG
333 a41bc9af bellard
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
334 a41bc9af bellard
#endif
335 e89f66ec bellard
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
336 e89f66ec bellard
        break;
337 e89f66ec bellard
    case 0x3b4:
338 e89f66ec bellard
    case 0x3d4:
339 e89f66ec bellard
        s->cr_index = val;
340 e89f66ec bellard
        break;
341 e89f66ec bellard
    case 0x3b5:
342 e89f66ec bellard
    case 0x3d5:
343 a41bc9af bellard
#ifdef DEBUG_VGA_REG
344 a41bc9af bellard
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
345 a41bc9af bellard
#endif
346 e89f66ec bellard
        /* handle CR0-7 protection */
347 f6c958c8 bellard
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
348 e89f66ec bellard
            /* can always write bit 4 of CR7 */
349 e89f66ec bellard
            if (s->cr_index == 7)
350 e89f66ec bellard
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
351 e89f66ec bellard
            return;
352 e89f66ec bellard
        }
353 e89f66ec bellard
        switch(s->cr_index) {
354 e89f66ec bellard
        case 0x01: /* horizontal display end */
355 e89f66ec bellard
        case 0x07:
356 e89f66ec bellard
        case 0x09:
357 e89f66ec bellard
        case 0x0c:
358 e89f66ec bellard
        case 0x0d:
359 e89f66ec bellard
        case 0x12: /* veritcal display end */
360 e89f66ec bellard
            s->cr[s->cr_index] = val;
361 e89f66ec bellard
            break;
362 e89f66ec bellard
363 a41bc9af bellard
#ifdef CONFIG_S3VGA
364 e89f66ec bellard
            /* S3 registers */
365 e89f66ec bellard
        case 0x2d:
366 e89f66ec bellard
        case 0x2e:
367 e89f66ec bellard
        case 0x2f:
368 e89f66ec bellard
        case 0x30:
369 e89f66ec bellard
            /* chip ID, cannot write */
370 e89f66ec bellard
            break;
371 e89f66ec bellard
        case 0x31:
372 e89f66ec bellard
            /* update start address */
373 5467a722 bellard
            {
374 5467a722 bellard
                int v;
375 5467a722 bellard
                s->cr[s->cr_index] = val;
376 5467a722 bellard
                v = (val >> 4) & 3;
377 5467a722 bellard
                s->cr[0x69] = (s->cr[69] & ~0x03) | v;
378 5467a722 bellard
            }
379 e89f66ec bellard
            break;
380 e89f66ec bellard
        case 0x51:
381 e89f66ec bellard
            /* update start address */
382 5467a722 bellard
            {
383 5467a722 bellard
                int v;
384 5467a722 bellard
                s->cr[s->cr_index] = val;
385 5467a722 bellard
                v = val & 3;
386 5467a722 bellard
                s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
387 5467a722 bellard
            }
388 e89f66ec bellard
            break;
389 a41bc9af bellard
#endif
390 e89f66ec bellard
        default:
391 e89f66ec bellard
            s->cr[s->cr_index] = val;
392 e89f66ec bellard
            break;
393 e89f66ec bellard
        }
394 a41bc9af bellard
#ifdef DEBUG_S3
395 a41bc9af bellard
        if (s->cr_index >= 0x20)
396 a41bc9af bellard
            printf("S3: CR write index=0x%x val=0x%x\n",
397 a41bc9af bellard
                   s->cr_index, val);
398 a41bc9af bellard
#endif
399 e89f66ec bellard
        break;
400 e89f66ec bellard
    case 0x3ba:
401 e89f66ec bellard
    case 0x3da:
402 e89f66ec bellard
        s->fcr = val & 0x10;
403 e89f66ec bellard
        break;
404 e89f66ec bellard
    }
405 e89f66ec bellard
}
406 e89f66ec bellard
407 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
408 09a79b49 bellard
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
409 4fa0f5d2 bellard
{
410 0f35920c bellard
    VGAState *s = opaque;
411 4fa0f5d2 bellard
    uint32_t val;
412 09a79b49 bellard
    val = s->vbe_index;
413 09a79b49 bellard
    return val;
414 09a79b49 bellard
}
415 4fa0f5d2 bellard
416 09a79b49 bellard
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
417 09a79b49 bellard
{
418 09a79b49 bellard
    VGAState *s = opaque;
419 09a79b49 bellard
    uint32_t val;
420 09a79b49 bellard
421 09a79b49 bellard
    if (s->vbe_index <= VBE_DISPI_INDEX_NB)
422 09a79b49 bellard
        val = s->vbe_regs[s->vbe_index];
423 09a79b49 bellard
    else
424 09a79b49 bellard
        val = 0;
425 4fa0f5d2 bellard
#ifdef DEBUG_BOCHS_VBE
426 09a79b49 bellard
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
427 4fa0f5d2 bellard
#endif
428 4fa0f5d2 bellard
    return val;
429 4fa0f5d2 bellard
}
430 4fa0f5d2 bellard
431 09a79b49 bellard
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
432 09a79b49 bellard
{
433 09a79b49 bellard
    VGAState *s = opaque;
434 09a79b49 bellard
    s->vbe_index = val;
435 09a79b49 bellard
}
436 09a79b49 bellard
437 09a79b49 bellard
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
438 4fa0f5d2 bellard
{
439 0f35920c bellard
    VGAState *s = opaque;
440 4fa0f5d2 bellard
441 09a79b49 bellard
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
442 4fa0f5d2 bellard
#ifdef DEBUG_BOCHS_VBE
443 4fa0f5d2 bellard
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
444 4fa0f5d2 bellard
#endif
445 4fa0f5d2 bellard
        switch(s->vbe_index) {
446 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_ID:
447 cae61cef bellard
            if (val == VBE_DISPI_ID0 ||
448 cae61cef bellard
                val == VBE_DISPI_ID1 ||
449 cae61cef bellard
                val == VBE_DISPI_ID2) {
450 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
451 cae61cef bellard
            }
452 4fa0f5d2 bellard
            break;
453 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_XRES:
454 cae61cef bellard
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
455 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
456 cae61cef bellard
            }
457 4fa0f5d2 bellard
            break;
458 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_YRES:
459 cae61cef bellard
            if (val <= VBE_DISPI_MAX_YRES) {
460 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
461 cae61cef bellard
            }
462 4fa0f5d2 bellard
            break;
463 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_BPP:
464 4fa0f5d2 bellard
            if (val == 0)
465 4fa0f5d2 bellard
                val = 8;
466 cae61cef bellard
            if (val == 4 || val == 8 || val == 15 || 
467 cae61cef bellard
                val == 16 || val == 24 || val == 32) {
468 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
469 cae61cef bellard
            }
470 4fa0f5d2 bellard
            break;
471 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_BANK:
472 cae61cef bellard
            val &= s->vbe_bank_mask;
473 cae61cef bellard
            s->vbe_regs[s->vbe_index] = val;
474 26aa7d72 bellard
            s->bank_offset = (val << 16);
475 4fa0f5d2 bellard
            break;
476 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_ENABLE:
477 4fa0f5d2 bellard
            if (val & VBE_DISPI_ENABLED) {
478 4fa0f5d2 bellard
                int h, shift_control;
479 4fa0f5d2 bellard
480 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = 
481 4fa0f5d2 bellard
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
482 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = 
483 4fa0f5d2 bellard
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
484 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
485 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
486 4fa0f5d2 bellard
                
487 4fa0f5d2 bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
488 4fa0f5d2 bellard
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
489 4fa0f5d2 bellard
                else
490 4fa0f5d2 bellard
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * 
491 4fa0f5d2 bellard
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
492 4fa0f5d2 bellard
                s->vbe_start_addr = 0;
493 4fa0f5d2 bellard
                
494 4fa0f5d2 bellard
                /* clear the screen (should be done in BIOS) */
495 4fa0f5d2 bellard
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
496 4fa0f5d2 bellard
                    memset(s->vram_ptr, 0, 
497 4fa0f5d2 bellard
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
498 4fa0f5d2 bellard
                }
499 4fa0f5d2 bellard
                
500 cae61cef bellard
                /* we initialize the VGA graphic mode (should be done
501 cae61cef bellard
                   in BIOS) */
502 cae61cef bellard
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
503 4fa0f5d2 bellard
                s->cr[0x17] |= 3; /* no CGA modes */
504 4fa0f5d2 bellard
                s->cr[0x13] = s->vbe_line_offset >> 3;
505 4fa0f5d2 bellard
                /* width */
506 4fa0f5d2 bellard
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
507 4fa0f5d2 bellard
                /* height */
508 4fa0f5d2 bellard
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
509 4fa0f5d2 bellard
                s->cr[0x12] = h;
510 4fa0f5d2 bellard
                s->cr[0x07] = (s->cr[0x07] & ~0x42) | 
511 4fa0f5d2 bellard
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
512 4fa0f5d2 bellard
                /* line compare to 1023 */
513 4fa0f5d2 bellard
                s->cr[0x18] = 0xff;
514 4fa0f5d2 bellard
                s->cr[0x07] |= 0x10;
515 4fa0f5d2 bellard
                s->cr[0x09] |= 0x40;
516 4fa0f5d2 bellard
                
517 4fa0f5d2 bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
518 4fa0f5d2 bellard
                    shift_control = 0;
519 4fa0f5d2 bellard
                    s->sr[0x01] &= ~8; /* no double line */
520 4fa0f5d2 bellard
                } else {
521 4fa0f5d2 bellard
                    shift_control = 2;
522 646be93b bellard
                    s->sr[4] |= 0x08; /* set chain 4 mode */
523 141253b2 bellard
                    s->sr[2] |= 0x0f; /* activate all planes */
524 4fa0f5d2 bellard
                }
525 4fa0f5d2 bellard
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
526 4fa0f5d2 bellard
                s->cr[0x09] &= ~0x9f; /* no double scan */
527 cae61cef bellard
            } else {
528 cae61cef bellard
                /* XXX: the bios should do that */
529 26aa7d72 bellard
                s->bank_offset = 0;
530 cae61cef bellard
            }
531 141253b2 bellard
            s->vbe_regs[s->vbe_index] = val;
532 cae61cef bellard
            break;
533 cae61cef bellard
        case VBE_DISPI_INDEX_VIRT_WIDTH:
534 cae61cef bellard
            {
535 cae61cef bellard
                int w, h, line_offset;
536 cae61cef bellard
537 cae61cef bellard
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
538 cae61cef bellard
                    return;
539 cae61cef bellard
                w = val;
540 cae61cef bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
541 cae61cef bellard
                    line_offset = w >> 1;
542 cae61cef bellard
                else
543 cae61cef bellard
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
544 cae61cef bellard
                h = s->vram_size / line_offset;
545 cae61cef bellard
                /* XXX: support weird bochs semantics ? */
546 cae61cef bellard
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
547 cae61cef bellard
                    return;
548 cae61cef bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
549 cae61cef bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
550 cae61cef bellard
                s->vbe_line_offset = line_offset;
551 cae61cef bellard
            }
552 cae61cef bellard
            break;
553 cae61cef bellard
        case VBE_DISPI_INDEX_X_OFFSET:
554 cae61cef bellard
        case VBE_DISPI_INDEX_Y_OFFSET:
555 cae61cef bellard
            {
556 cae61cef bellard
                int x;
557 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
558 cae61cef bellard
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
559 cae61cef bellard
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
560 cae61cef bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
561 cae61cef bellard
                    s->vbe_start_addr += x >> 1;
562 cae61cef bellard
                else
563 cae61cef bellard
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
564 cae61cef bellard
                s->vbe_start_addr >>= 2;
565 4fa0f5d2 bellard
            }
566 4fa0f5d2 bellard
            break;
567 4fa0f5d2 bellard
        default:
568 4fa0f5d2 bellard
            break;
569 4fa0f5d2 bellard
        }
570 4fa0f5d2 bellard
    }
571 4fa0f5d2 bellard
}
572 4fa0f5d2 bellard
#endif
573 4fa0f5d2 bellard
574 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
575 798b0c25 bellard
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
576 e89f66ec bellard
{
577 a4193c8a bellard
    VGAState *s = opaque;
578 e89f66ec bellard
    int memory_map_mode, plane;
579 e89f66ec bellard
    uint32_t ret;
580 e89f66ec bellard
    
581 e89f66ec bellard
    /* convert to VGA memory offset */
582 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
583 26aa7d72 bellard
    addr &= 0x1ffff;
584 e89f66ec bellard
    switch(memory_map_mode) {
585 e89f66ec bellard
    case 0:
586 e89f66ec bellard
        break;
587 e89f66ec bellard
    case 1:
588 26aa7d72 bellard
        if (addr >= 0x10000)
589 e89f66ec bellard
            return 0xff;
590 cae61cef bellard
        addr += s->bank_offset;
591 e89f66ec bellard
        break;
592 e89f66ec bellard
    case 2:
593 26aa7d72 bellard
        addr -= 0x10000;
594 e89f66ec bellard
        if (addr >= 0x8000)
595 e89f66ec bellard
            return 0xff;
596 e89f66ec bellard
        break;
597 e89f66ec bellard
    default:
598 e89f66ec bellard
    case 3:
599 26aa7d72 bellard
        addr -= 0x18000;
600 c92b2e84 bellard
        if (addr >= 0x8000)
601 c92b2e84 bellard
            return 0xff;
602 e89f66ec bellard
        break;
603 e89f66ec bellard
    }
604 e89f66ec bellard
    
605 e89f66ec bellard
    if (s->sr[4] & 0x08) {
606 e89f66ec bellard
        /* chain 4 mode : simplest access */
607 e89f66ec bellard
        ret = s->vram_ptr[addr];
608 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
609 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
610 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
611 e89f66ec bellard
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
612 e89f66ec bellard
    } else {
613 e89f66ec bellard
        /* standard VGA latched access */
614 e89f66ec bellard
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
615 e89f66ec bellard
616 e89f66ec bellard
        if (!(s->gr[5] & 0x08)) {
617 e89f66ec bellard
            /* read mode 0 */
618 e89f66ec bellard
            plane = s->gr[4];
619 b8ed223b bellard
            ret = GET_PLANE(s->latch, plane);
620 e89f66ec bellard
        } else {
621 e89f66ec bellard
            /* read mode 1 */
622 e89f66ec bellard
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
623 e89f66ec bellard
            ret |= ret >> 16;
624 e89f66ec bellard
            ret |= ret >> 8;
625 e89f66ec bellard
            ret = (~ret) & 0xff;
626 e89f66ec bellard
        }
627 e89f66ec bellard
    }
628 e89f66ec bellard
    return ret;
629 e89f66ec bellard
}
630 e89f66ec bellard
631 a4193c8a bellard
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
632 e89f66ec bellard
{
633 e89f66ec bellard
    uint32_t v;
634 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
635 a4193c8a bellard
    v = vga_mem_readb(opaque, addr) << 8;
636 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1);
637 09a79b49 bellard
#else
638 a4193c8a bellard
    v = vga_mem_readb(opaque, addr);
639 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 8;
640 09a79b49 bellard
#endif
641 e89f66ec bellard
    return v;
642 e89f66ec bellard
}
643 e89f66ec bellard
644 a4193c8a bellard
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
645 e89f66ec bellard
{
646 e89f66ec bellard
    uint32_t v;
647 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
648 a4193c8a bellard
    v = vga_mem_readb(opaque, addr) << 24;
649 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 16;
650 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 2) << 8;
651 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 3);
652 09a79b49 bellard
#else
653 a4193c8a bellard
    v = vga_mem_readb(opaque, addr);
654 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 8;
655 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 2) << 16;
656 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 3) << 24;
657 09a79b49 bellard
#endif
658 e89f66ec bellard
    return v;
659 e89f66ec bellard
}
660 e89f66ec bellard
661 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
662 798b0c25 bellard
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
663 e89f66ec bellard
{
664 a4193c8a bellard
    VGAState *s = opaque;
665 e89f66ec bellard
    int memory_map_mode, plane, write_mode, b, func_select;
666 e89f66ec bellard
    uint32_t write_mask, bit_mask, set_mask;
667 e89f66ec bellard
668 17b0018b bellard
#ifdef DEBUG_VGA_MEM
669 e89f66ec bellard
    printf("vga: [0x%x] = 0x%02x\n", addr, val);
670 e89f66ec bellard
#endif
671 e89f66ec bellard
    /* convert to VGA memory offset */
672 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
673 26aa7d72 bellard
    addr &= 0x1ffff;
674 e89f66ec bellard
    switch(memory_map_mode) {
675 e89f66ec bellard
    case 0:
676 e89f66ec bellard
        break;
677 e89f66ec bellard
    case 1:
678 26aa7d72 bellard
        if (addr >= 0x10000)
679 e89f66ec bellard
            return;
680 cae61cef bellard
        addr += s->bank_offset;
681 e89f66ec bellard
        break;
682 e89f66ec bellard
    case 2:
683 26aa7d72 bellard
        addr -= 0x10000;
684 e89f66ec bellard
        if (addr >= 0x8000)
685 e89f66ec bellard
            return;
686 e89f66ec bellard
        break;
687 e89f66ec bellard
    default:
688 e89f66ec bellard
    case 3:
689 26aa7d72 bellard
        addr -= 0x18000;
690 c92b2e84 bellard
        if (addr >= 0x8000)
691 c92b2e84 bellard
            return;
692 e89f66ec bellard
        break;
693 e89f66ec bellard
    }
694 e89f66ec bellard
    
695 e89f66ec bellard
    if (s->sr[4] & 0x08) {
696 e89f66ec bellard
        /* chain 4 mode : simplest access */
697 e89f66ec bellard
        plane = addr & 3;
698 e89f66ec bellard
        if (s->sr[2] & (1 << plane)) {
699 e89f66ec bellard
            s->vram_ptr[addr] = val;
700 17b0018b bellard
#ifdef DEBUG_VGA_MEM
701 e89f66ec bellard
            printf("vga: chain4: [0x%x]\n", addr);
702 e89f66ec bellard
#endif
703 4fa0f5d2 bellard
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
704 e89f66ec bellard
        }
705 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
706 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
707 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
708 e89f66ec bellard
        if (s->sr[2] & (1 << plane)) {
709 e89f66ec bellard
            addr = ((addr & ~1) << 1) | plane;
710 e89f66ec bellard
            s->vram_ptr[addr] = val;
711 17b0018b bellard
#ifdef DEBUG_VGA_MEM
712 e89f66ec bellard
            printf("vga: odd/even: [0x%x]\n", addr);
713 e89f66ec bellard
#endif
714 4fa0f5d2 bellard
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
715 e89f66ec bellard
        }
716 e89f66ec bellard
    } else {
717 e89f66ec bellard
        /* standard VGA latched access */
718 e89f66ec bellard
        write_mode = s->gr[5] & 3;
719 e89f66ec bellard
        switch(write_mode) {
720 e89f66ec bellard
        default:
721 e89f66ec bellard
        case 0:
722 e89f66ec bellard
            /* rotate */
723 e89f66ec bellard
            b = s->gr[3] & 7;
724 e89f66ec bellard
            val = ((val >> b) | (val << (8 - b))) & 0xff;
725 e89f66ec bellard
            val |= val << 8;
726 e89f66ec bellard
            val |= val << 16;
727 e89f66ec bellard
728 e89f66ec bellard
            /* apply set/reset mask */
729 e89f66ec bellard
            set_mask = mask16[s->gr[1]];
730 e89f66ec bellard
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
731 e89f66ec bellard
            bit_mask = s->gr[8];
732 e89f66ec bellard
            break;
733 e89f66ec bellard
        case 1:
734 e89f66ec bellard
            val = s->latch;
735 e89f66ec bellard
            goto do_write;
736 e89f66ec bellard
        case 2:
737 e89f66ec bellard
            val = mask16[val & 0x0f];
738 e89f66ec bellard
            bit_mask = s->gr[8];
739 e89f66ec bellard
            break;
740 e89f66ec bellard
        case 3:
741 e89f66ec bellard
            /* rotate */
742 e89f66ec bellard
            b = s->gr[3] & 7;
743 a41bc9af bellard
            val = (val >> b) | (val << (8 - b));
744 e89f66ec bellard
745 e89f66ec bellard
            bit_mask = s->gr[8] & val;
746 e89f66ec bellard
            val = mask16[s->gr[0]];
747 e89f66ec bellard
            break;
748 e89f66ec bellard
        }
749 e89f66ec bellard
750 e89f66ec bellard
        /* apply logical operation */
751 e89f66ec bellard
        func_select = s->gr[3] >> 3;
752 e89f66ec bellard
        switch(func_select) {
753 e89f66ec bellard
        case 0:
754 e89f66ec bellard
        default:
755 e89f66ec bellard
            /* nothing to do */
756 e89f66ec bellard
            break;
757 e89f66ec bellard
        case 1:
758 e89f66ec bellard
            /* and */
759 e89f66ec bellard
            val &= s->latch;
760 e89f66ec bellard
            break;
761 e89f66ec bellard
        case 2:
762 e89f66ec bellard
            /* or */
763 e89f66ec bellard
            val |= s->latch;
764 e89f66ec bellard
            break;
765 e89f66ec bellard
        case 3:
766 e89f66ec bellard
            /* xor */
767 e89f66ec bellard
            val ^= s->latch;
768 e89f66ec bellard
            break;
769 e89f66ec bellard
        }
770 e89f66ec bellard
771 e89f66ec bellard
        /* apply bit mask */
772 e89f66ec bellard
        bit_mask |= bit_mask << 8;
773 e89f66ec bellard
        bit_mask |= bit_mask << 16;
774 e89f66ec bellard
        val = (val & bit_mask) | (s->latch & ~bit_mask);
775 e89f66ec bellard
776 e89f66ec bellard
    do_write:
777 e89f66ec bellard
        /* mask data according to sr[2] */
778 e89f66ec bellard
        write_mask = mask16[s->sr[2]];
779 e89f66ec bellard
        ((uint32_t *)s->vram_ptr)[addr] = 
780 e89f66ec bellard
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | 
781 e89f66ec bellard
            (val & write_mask);
782 17b0018b bellard
#ifdef DEBUG_VGA_MEM
783 e89f66ec bellard
            printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", 
784 e89f66ec bellard
                   addr * 4, write_mask, val);
785 e89f66ec bellard
#endif
786 4fa0f5d2 bellard
            cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
787 e89f66ec bellard
    }
788 e89f66ec bellard
}
789 e89f66ec bellard
790 a4193c8a bellard
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
791 e89f66ec bellard
{
792 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
793 a4193c8a bellard
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
794 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
795 09a79b49 bellard
#else
796 a4193c8a bellard
    vga_mem_writeb(opaque, addr, val & 0xff);
797 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
798 09a79b49 bellard
#endif
799 e89f66ec bellard
}
800 e89f66ec bellard
801 a4193c8a bellard
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
802 e89f66ec bellard
{
803 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
804 a4193c8a bellard
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
805 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
806 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
807 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
808 09a79b49 bellard
#else
809 a4193c8a bellard
    vga_mem_writeb(opaque, addr, val & 0xff);
810 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
811 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
812 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
813 09a79b49 bellard
#endif
814 e89f66ec bellard
}
815 e89f66ec bellard
816 e89f66ec bellard
typedef void vga_draw_glyph8_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);
819 e89f66ec bellard
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
820 e89f66ec bellard
                                  const uint8_t *font_ptr, int h, 
821 e89f66ec bellard
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
822 e89f66ec bellard
typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, 
823 e89f66ec bellard
                                const uint8_t *s, int width);
824 e89f66ec bellard
825 e89f66ec bellard
static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
826 e89f66ec bellard
{
827 188d8579 bellard
    return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
828 e89f66ec bellard
}
829 e89f66ec bellard
830 e89f66ec bellard
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
831 e89f66ec bellard
{
832 e89f66ec bellard
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
833 e89f66ec bellard
}
834 e89f66ec bellard
835 e89f66ec bellard
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
836 e89f66ec bellard
{
837 e89f66ec bellard
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
838 e89f66ec bellard
}
839 e89f66ec bellard
840 e89f66ec bellard
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
841 e89f66ec bellard
{
842 e89f66ec bellard
    return (r << 16) | (g << 8) | b;
843 e89f66ec bellard
}
844 e89f66ec bellard
845 e89f66ec bellard
#define DEPTH 8
846 e89f66ec bellard
#include "vga_template.h"
847 e89f66ec bellard
848 e89f66ec bellard
#define DEPTH 15
849 e89f66ec bellard
#include "vga_template.h"
850 e89f66ec bellard
851 e89f66ec bellard
#define DEPTH 16
852 e89f66ec bellard
#include "vga_template.h"
853 e89f66ec bellard
854 e89f66ec bellard
#define DEPTH 32
855 e89f66ec bellard
#include "vga_template.h"
856 e89f66ec bellard
857 17b0018b bellard
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
858 17b0018b bellard
{
859 17b0018b bellard
    unsigned int col;
860 17b0018b bellard
    col = rgb_to_pixel8(r, g, b);
861 17b0018b bellard
    col |= col << 8;
862 17b0018b bellard
    col |= col << 16;
863 17b0018b bellard
    return col;
864 17b0018b bellard
}
865 17b0018b bellard
866 17b0018b bellard
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
867 17b0018b bellard
{
868 17b0018b bellard
    unsigned int col;
869 17b0018b bellard
    col = rgb_to_pixel15(r, g, b);
870 17b0018b bellard
    col |= col << 16;
871 17b0018b bellard
    return col;
872 17b0018b bellard
}
873 17b0018b bellard
874 17b0018b bellard
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
875 17b0018b bellard
{
876 17b0018b bellard
    unsigned int col;
877 17b0018b bellard
    col = rgb_to_pixel16(r, g, b);
878 17b0018b bellard
    col |= col << 16;
879 17b0018b bellard
    return col;
880 17b0018b bellard
}
881 17b0018b bellard
882 17b0018b bellard
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
883 17b0018b bellard
{
884 17b0018b bellard
    unsigned int col;
885 17b0018b bellard
    col = rgb_to_pixel32(r, g, b);
886 17b0018b bellard
    return col;
887 17b0018b bellard
}
888 17b0018b bellard
889 e89f66ec bellard
/* return true if the palette was modified */
890 e89f66ec bellard
static int update_palette16(VGAState *s)
891 e89f66ec bellard
{
892 17b0018b bellard
    int full_update, i;
893 e89f66ec bellard
    uint32_t v, col, *palette;
894 e89f66ec bellard
895 e89f66ec bellard
    full_update = 0;
896 e89f66ec bellard
    palette = s->last_palette;
897 e89f66ec bellard
    for(i = 0; i < 16; i++) {
898 e89f66ec bellard
        v = s->ar[i];
899 e89f66ec bellard
        if (s->ar[0x10] & 0x80)
900 e89f66ec bellard
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
901 e89f66ec bellard
        else
902 e89f66ec bellard
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
903 e89f66ec bellard
        v = v * 3;
904 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
905 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
906 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
907 17b0018b bellard
        if (col != palette[i]) {
908 17b0018b bellard
            full_update = 1;
909 17b0018b bellard
            palette[i] = col;
910 e89f66ec bellard
        }
911 17b0018b bellard
    }
912 17b0018b bellard
    return full_update;
913 17b0018b bellard
}
914 17b0018b bellard
915 17b0018b bellard
/* return true if the palette was modified */
916 17b0018b bellard
static int update_palette256(VGAState *s)
917 17b0018b bellard
{
918 17b0018b bellard
    int full_update, i;
919 17b0018b bellard
    uint32_t v, col, *palette;
920 17b0018b bellard
921 17b0018b bellard
    full_update = 0;
922 17b0018b bellard
    palette = s->last_palette;
923 17b0018b bellard
    v = 0;
924 17b0018b bellard
    for(i = 0; i < 256; i++) {
925 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
926 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
927 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
928 e89f66ec bellard
        if (col != palette[i]) {
929 e89f66ec bellard
            full_update = 1;
930 e89f66ec bellard
            palette[i] = col;
931 e89f66ec bellard
        }
932 17b0018b bellard
        v += 3;
933 e89f66ec bellard
    }
934 e89f66ec bellard
    return full_update;
935 e89f66ec bellard
}
936 e89f66ec bellard
937 798b0c25 bellard
static void vga_get_offsets(VGAState *s, 
938 798b0c25 bellard
                            uint32_t *pline_offset, 
939 798b0c25 bellard
                            uint32_t *pstart_addr)
940 e89f66ec bellard
{
941 798b0c25 bellard
    uint32_t start_addr, line_offset;
942 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
943 4fa0f5d2 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
944 4fa0f5d2 bellard
        line_offset = s->vbe_line_offset;
945 4fa0f5d2 bellard
        start_addr = s->vbe_start_addr;
946 4fa0f5d2 bellard
    } else
947 4fa0f5d2 bellard
#endif
948 4fa0f5d2 bellard
    {  
949 4fa0f5d2 bellard
        /* compute line_offset in bytes */
950 4fa0f5d2 bellard
        line_offset = s->cr[0x13];
951 a41bc9af bellard
#ifdef CONFIG_S3VGA
952 5467a722 bellard
        {
953 5467a722 bellard
            uinr32_t v;
954 5467a722 bellard
            v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
955 5467a722 bellard
            if (v == 0)
956 5467a722 bellard
                v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
957 5467a722 bellard
            line_offset |= (v << 8);
958 5467a722 bellard
        }
959 a41bc9af bellard
#endif
960 4fa0f5d2 bellard
        line_offset <<= 3;
961 4fa0f5d2 bellard
        
962 4fa0f5d2 bellard
        /* starting address */
963 4fa0f5d2 bellard
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
964 a41bc9af bellard
#ifdef CONFIG_S3VGA
965 4fa0f5d2 bellard
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
966 a41bc9af bellard
#endif
967 4fa0f5d2 bellard
    }
968 798b0c25 bellard
    *pline_offset = line_offset;
969 798b0c25 bellard
    *pstart_addr = start_addr;
970 798b0c25 bellard
}
971 798b0c25 bellard
972 798b0c25 bellard
/* update start_addr and line_offset. Return TRUE if modified */
973 798b0c25 bellard
static int update_basic_params(VGAState *s)
974 798b0c25 bellard
{
975 798b0c25 bellard
    int full_update;
976 798b0c25 bellard
    uint32_t start_addr, line_offset, line_compare;
977 4fa0f5d2 bellard
    
978 798b0c25 bellard
    full_update = 0;
979 798b0c25 bellard
980 798b0c25 bellard
    s->get_offsets(s, &line_offset, &start_addr);
981 e89f66ec bellard
    /* line compare */
982 e89f66ec bellard
    line_compare = s->cr[0x18] | 
983 e89f66ec bellard
        ((s->cr[0x07] & 0x10) << 4) |
984 e89f66ec bellard
        ((s->cr[0x09] & 0x40) << 3);
985 e89f66ec bellard
986 e89f66ec bellard
    if (line_offset != s->line_offset ||
987 e89f66ec bellard
        start_addr != s->start_addr ||
988 e89f66ec bellard
        line_compare != s->line_compare) {
989 e89f66ec bellard
        s->line_offset = line_offset;
990 e89f66ec bellard
        s->start_addr = start_addr;
991 e89f66ec bellard
        s->line_compare = line_compare;
992 e89f66ec bellard
        full_update = 1;
993 e89f66ec bellard
    }
994 e89f66ec bellard
    return full_update;
995 e89f66ec bellard
}
996 e89f66ec bellard
997 e89f66ec bellard
static inline int get_depth_index(int depth)
998 e89f66ec bellard
{
999 e89f66ec bellard
    switch(depth) {
1000 e89f66ec bellard
    default:
1001 e89f66ec bellard
    case 8:
1002 e89f66ec bellard
        return 0;
1003 e89f66ec bellard
    case 15:
1004 e89f66ec bellard
        return 1;
1005 e89f66ec bellard
    case 16:
1006 e89f66ec bellard
        return 2;
1007 e89f66ec bellard
    case 32:
1008 e89f66ec bellard
        return 3;
1009 e89f66ec bellard
    }
1010 e89f66ec bellard
}
1011 e89f66ec bellard
1012 e89f66ec bellard
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1013 e89f66ec bellard
    vga_draw_glyph8_8,
1014 e89f66ec bellard
    vga_draw_glyph8_16,
1015 e89f66ec bellard
    vga_draw_glyph8_16,
1016 e89f66ec bellard
    vga_draw_glyph8_32,
1017 e89f66ec bellard
};
1018 e89f66ec bellard
1019 17b0018b bellard
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1020 17b0018b bellard
    vga_draw_glyph16_8,
1021 17b0018b bellard
    vga_draw_glyph16_16,
1022 17b0018b bellard
    vga_draw_glyph16_16,
1023 17b0018b bellard
    vga_draw_glyph16_32,
1024 17b0018b bellard
};
1025 17b0018b bellard
1026 e89f66ec bellard
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1027 e89f66ec bellard
    vga_draw_glyph9_8,
1028 e89f66ec bellard
    vga_draw_glyph9_16,
1029 e89f66ec bellard
    vga_draw_glyph9_16,
1030 e89f66ec bellard
    vga_draw_glyph9_32,
1031 e89f66ec bellard
};
1032 e89f66ec bellard
    
1033 e89f66ec bellard
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1049 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1050 e89f66ec bellard
};    
1051 e89f66ec bellard
1052 e89f66ec bellard
/* 
1053 e89f66ec bellard
 * Text mode update 
1054 e89f66ec bellard
 * Missing:
1055 e89f66ec bellard
 * - double scan
1056 e89f66ec bellard
 * - double width 
1057 e89f66ec bellard
 * - underline
1058 e89f66ec bellard
 * - flashing
1059 e89f66ec bellard
 */
1060 e89f66ec bellard
static void vga_draw_text(VGAState *s, int full_update)
1061 e89f66ec bellard
{
1062 e89f66ec bellard
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1063 e89f66ec bellard
    int cx_min, cx_max, linesize, x_incr;
1064 e89f66ec bellard
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1065 e89f66ec bellard
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1066 e89f66ec bellard
    const uint8_t *font_ptr, *font_base[2];
1067 e89f66ec bellard
    int dup9, line_offset, depth_index;
1068 e89f66ec bellard
    uint32_t *palette;
1069 e89f66ec bellard
    uint32_t *ch_attr_ptr;
1070 e89f66ec bellard
    vga_draw_glyph8_func *vga_draw_glyph8;
1071 e89f66ec bellard
    vga_draw_glyph9_func *vga_draw_glyph9;
1072 e89f66ec bellard
1073 e89f66ec bellard
    full_update |= update_palette16(s);
1074 e89f66ec bellard
    palette = s->last_palette;
1075 e89f66ec bellard
    
1076 e89f66ec bellard
    /* compute font data address (in plane 2) */
1077 e89f66ec bellard
    v = s->sr[3];
1078 1078f663 bellard
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1079 e89f66ec bellard
    if (offset != s->font_offsets[0]) {
1080 e89f66ec bellard
        s->font_offsets[0] = offset;
1081 e89f66ec bellard
        full_update = 1;
1082 e89f66ec bellard
    }
1083 e89f66ec bellard
    font_base[0] = s->vram_ptr + offset;
1084 e89f66ec bellard
1085 1078f663 bellard
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1086 e89f66ec bellard
    font_base[1] = s->vram_ptr + offset;
1087 e89f66ec bellard
    if (offset != s->font_offsets[1]) {
1088 e89f66ec bellard
        s->font_offsets[1] = offset;
1089 e89f66ec bellard
        full_update = 1;
1090 e89f66ec bellard
    }
1091 e89f66ec bellard
1092 e89f66ec bellard
    full_update |= update_basic_params(s);
1093 e89f66ec bellard
1094 e89f66ec bellard
    line_offset = s->line_offset;
1095 e89f66ec bellard
    s1 = s->vram_ptr + (s->start_addr * 4);
1096 e89f66ec bellard
1097 e89f66ec bellard
    /* total width & height */
1098 e89f66ec bellard
    cheight = (s->cr[9] & 0x1f) + 1;
1099 e89f66ec bellard
    cw = 8;
1100 eccabc6e bellard
    if (!(s->sr[1] & 0x01))
1101 e89f66ec bellard
        cw = 9;
1102 17b0018b bellard
    if (s->sr[1] & 0x08)
1103 17b0018b bellard
        cw = 16; /* NOTE: no 18 pixel wide */
1104 e89f66ec bellard
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1105 e89f66ec bellard
    width = (s->cr[0x01] + 1);
1106 17b0018b bellard
    if (s->cr[0x06] == 100) {
1107 17b0018b bellard
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1108 17b0018b bellard
        height = 100;
1109 17b0018b bellard
    } else {
1110 17b0018b bellard
        height = s->cr[0x12] | 
1111 17b0018b bellard
            ((s->cr[0x07] & 0x02) << 7) | 
1112 17b0018b bellard
            ((s->cr[0x07] & 0x40) << 3);
1113 17b0018b bellard
        height = (height + 1) / cheight;
1114 17b0018b bellard
    }
1115 3294b949 bellard
    if ((height * width) > CH_ATTR_SIZE) {
1116 3294b949 bellard
        /* better than nothing: exit if transient size is too big */
1117 3294b949 bellard
        return;
1118 3294b949 bellard
    }
1119 3294b949 bellard
1120 e89f66ec bellard
    if (width != s->last_width || height != s->last_height ||
1121 eccabc6e bellard
        cw != s->last_cw || cheight != s->last_ch) {
1122 2aebb3eb bellard
        s->last_scr_width = width * cw;
1123 2aebb3eb bellard
        s->last_scr_height = height * cheight;
1124 2aebb3eb bellard
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1125 e89f66ec bellard
        s->last_width = width;
1126 e89f66ec bellard
        s->last_height = height;
1127 e89f66ec bellard
        s->last_ch = cheight;
1128 e89f66ec bellard
        s->last_cw = cw;
1129 e89f66ec bellard
        full_update = 1;
1130 e89f66ec bellard
    }
1131 e89f66ec bellard
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1132 e89f66ec bellard
    if (cursor_offset != s->cursor_offset ||
1133 e89f66ec bellard
        s->cr[0xa] != s->cursor_start ||
1134 e89f66ec bellard
        s->cr[0xb] != s->cursor_end) {
1135 e89f66ec bellard
      /* if the cursor position changed, we update the old and new
1136 e89f66ec bellard
         chars */
1137 e89f66ec bellard
        if (s->cursor_offset < CH_ATTR_SIZE)
1138 e89f66ec bellard
            s->last_ch_attr[s->cursor_offset] = -1;
1139 e89f66ec bellard
        if (cursor_offset < CH_ATTR_SIZE)
1140 e89f66ec bellard
            s->last_ch_attr[cursor_offset] = -1;
1141 e89f66ec bellard
        s->cursor_offset = cursor_offset;
1142 e89f66ec bellard
        s->cursor_start = s->cr[0xa];
1143 e89f66ec bellard
        s->cursor_end = s->cr[0xb];
1144 e89f66ec bellard
    }
1145 39cf7803 bellard
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1146 e89f66ec bellard
    
1147 e89f66ec bellard
    depth_index = get_depth_index(s->ds->depth);
1148 17b0018b bellard
    if (cw == 16)
1149 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1150 17b0018b bellard
    else
1151 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1152 e89f66ec bellard
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1153 e89f66ec bellard
    
1154 e89f66ec bellard
    dest = s->ds->data;
1155 e89f66ec bellard
    linesize = s->ds->linesize;
1156 e89f66ec bellard
    ch_attr_ptr = s->last_ch_attr;
1157 e89f66ec bellard
    for(cy = 0; cy < height; cy++) {
1158 e89f66ec bellard
        d1 = dest;
1159 e89f66ec bellard
        src = s1;
1160 e89f66ec bellard
        cx_min = width;
1161 e89f66ec bellard
        cx_max = -1;
1162 e89f66ec bellard
        for(cx = 0; cx < width; cx++) {
1163 e89f66ec bellard
            ch_attr = *(uint16_t *)src;
1164 e89f66ec bellard
            if (full_update || ch_attr != *ch_attr_ptr) {
1165 e89f66ec bellard
                if (cx < cx_min)
1166 e89f66ec bellard
                    cx_min = cx;
1167 e89f66ec bellard
                if (cx > cx_max)
1168 e89f66ec bellard
                    cx_max = cx;
1169 e89f66ec bellard
                *ch_attr_ptr = ch_attr;
1170 e89f66ec bellard
#ifdef WORDS_BIGENDIAN
1171 e89f66ec bellard
                ch = ch_attr >> 8;
1172 e89f66ec bellard
                cattr = ch_attr & 0xff;
1173 e89f66ec bellard
#else
1174 e89f66ec bellard
                ch = ch_attr & 0xff;
1175 e89f66ec bellard
                cattr = ch_attr >> 8;
1176 e89f66ec bellard
#endif
1177 e89f66ec bellard
                font_ptr = font_base[(cattr >> 3) & 1];
1178 e89f66ec bellard
                font_ptr += 32 * 4 * ch;
1179 e89f66ec bellard
                bgcol = palette[cattr >> 4];
1180 e89f66ec bellard
                fgcol = palette[cattr & 0x0f];
1181 17b0018b bellard
                if (cw != 9) {
1182 e89f66ec bellard
                    vga_draw_glyph8(d1, linesize, 
1183 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol);
1184 e89f66ec bellard
                } else {
1185 e89f66ec bellard
                    dup9 = 0;
1186 e89f66ec bellard
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1187 e89f66ec bellard
                        dup9 = 1;
1188 e89f66ec bellard
                    vga_draw_glyph9(d1, linesize, 
1189 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1190 e89f66ec bellard
                }
1191 e89f66ec bellard
                if (src == cursor_ptr &&
1192 e89f66ec bellard
                    !(s->cr[0x0a] & 0x20)) {
1193 e89f66ec bellard
                    int line_start, line_last, h;
1194 e89f66ec bellard
                    /* draw the cursor */
1195 e89f66ec bellard
                    line_start = s->cr[0x0a] & 0x1f;
1196 e89f66ec bellard
                    line_last = s->cr[0x0b] & 0x1f;
1197 e89f66ec bellard
                    /* XXX: check that */
1198 e89f66ec bellard
                    if (line_last > cheight - 1)
1199 e89f66ec bellard
                        line_last = cheight - 1;
1200 e89f66ec bellard
                    if (line_last >= line_start && line_start < cheight) {
1201 e89f66ec bellard
                        h = line_last - line_start + 1;
1202 e89f66ec bellard
                        d = d1 + linesize * line_start;
1203 17b0018b bellard
                        if (cw != 9) {
1204 e89f66ec bellard
                            vga_draw_glyph8(d, linesize, 
1205 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol);
1206 e89f66ec bellard
                        } else {
1207 e89f66ec bellard
                            vga_draw_glyph9(d, linesize, 
1208 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol, 1);
1209 e89f66ec bellard
                        }
1210 e89f66ec bellard
                    }
1211 e89f66ec bellard
                }
1212 e89f66ec bellard
            }
1213 e89f66ec bellard
            d1 += x_incr;
1214 e89f66ec bellard
            src += 4;
1215 e89f66ec bellard
            ch_attr_ptr++;
1216 e89f66ec bellard
        }
1217 e89f66ec bellard
        if (cx_max != -1) {
1218 e89f66ec bellard
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1219 e89f66ec bellard
                       (cx_max - cx_min + 1) * cw, cheight);
1220 e89f66ec bellard
        }
1221 e89f66ec bellard
        dest += linesize * cheight;
1222 e89f66ec bellard
        s1 += line_offset;
1223 e89f66ec bellard
    }
1224 e89f66ec bellard
}
1225 e89f66ec bellard
1226 17b0018b bellard
enum {
1227 17b0018b bellard
    VGA_DRAW_LINE2,
1228 17b0018b bellard
    VGA_DRAW_LINE2D2,
1229 17b0018b bellard
    VGA_DRAW_LINE4,
1230 17b0018b bellard
    VGA_DRAW_LINE4D2,
1231 17b0018b bellard
    VGA_DRAW_LINE8D2,
1232 17b0018b bellard
    VGA_DRAW_LINE8,
1233 17b0018b bellard
    VGA_DRAW_LINE15,
1234 17b0018b bellard
    VGA_DRAW_LINE16,
1235 4fa0f5d2 bellard
    VGA_DRAW_LINE24,
1236 17b0018b bellard
    VGA_DRAW_LINE32,
1237 17b0018b bellard
    VGA_DRAW_LINE_NB,
1238 17b0018b bellard
};
1239 17b0018b bellard
1240 17b0018b bellard
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1241 e89f66ec bellard
    vga_draw_line2_8,
1242 e89f66ec bellard
    vga_draw_line2_16,
1243 e89f66ec bellard
    vga_draw_line2_16,
1244 e89f66ec bellard
    vga_draw_line2_32,
1245 e89f66ec bellard
1246 17b0018b bellard
    vga_draw_line2d2_8,
1247 17b0018b bellard
    vga_draw_line2d2_16,
1248 17b0018b bellard
    vga_draw_line2d2_16,
1249 17b0018b bellard
    vga_draw_line2d2_32,
1250 17b0018b bellard
1251 e89f66ec bellard
    vga_draw_line4_8,
1252 e89f66ec bellard
    vga_draw_line4_16,
1253 e89f66ec bellard
    vga_draw_line4_16,
1254 e89f66ec bellard
    vga_draw_line4_32,
1255 e89f66ec bellard
1256 17b0018b bellard
    vga_draw_line4d2_8,
1257 17b0018b bellard
    vga_draw_line4d2_16,
1258 17b0018b bellard
    vga_draw_line4d2_16,
1259 17b0018b bellard
    vga_draw_line4d2_32,
1260 17b0018b bellard
1261 17b0018b bellard
    vga_draw_line8d2_8,
1262 17b0018b bellard
    vga_draw_line8d2_16,
1263 17b0018b bellard
    vga_draw_line8d2_16,
1264 17b0018b bellard
    vga_draw_line8d2_32,
1265 17b0018b bellard
1266 e89f66ec bellard
    vga_draw_line8_8,
1267 e89f66ec bellard
    vga_draw_line8_16,
1268 e89f66ec bellard
    vga_draw_line8_16,
1269 e89f66ec bellard
    vga_draw_line8_32,
1270 e89f66ec bellard
1271 e89f66ec bellard
    vga_draw_line15_8,
1272 e89f66ec bellard
    vga_draw_line15_15,
1273 e89f66ec bellard
    vga_draw_line15_16,
1274 e89f66ec bellard
    vga_draw_line15_32,
1275 e89f66ec bellard
1276 e89f66ec bellard
    vga_draw_line16_8,
1277 e89f66ec bellard
    vga_draw_line16_15,
1278 e89f66ec bellard
    vga_draw_line16_16,
1279 e89f66ec bellard
    vga_draw_line16_32,
1280 e89f66ec bellard
1281 4fa0f5d2 bellard
    vga_draw_line24_8,
1282 4fa0f5d2 bellard
    vga_draw_line24_15,
1283 4fa0f5d2 bellard
    vga_draw_line24_16,
1284 4fa0f5d2 bellard
    vga_draw_line24_32,
1285 4fa0f5d2 bellard
1286 e89f66ec bellard
    vga_draw_line32_8,
1287 e89f66ec bellard
    vga_draw_line32_15,
1288 e89f66ec bellard
    vga_draw_line32_16,
1289 e89f66ec bellard
    vga_draw_line32_32,
1290 e89f66ec bellard
};
1291 e89f66ec bellard
1292 798b0c25 bellard
static int vga_get_bpp(VGAState *s)
1293 798b0c25 bellard
{
1294 798b0c25 bellard
    int ret;
1295 798b0c25 bellard
#ifdef CONFIG_BOCHS_VBE
1296 798b0c25 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1297 798b0c25 bellard
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1298 798b0c25 bellard
    } else 
1299 798b0c25 bellard
#endif
1300 798b0c25 bellard
    {
1301 798b0c25 bellard
        ret = 0;
1302 798b0c25 bellard
    }
1303 798b0c25 bellard
    return ret;
1304 798b0c25 bellard
}
1305 798b0c25 bellard
1306 a130a41e bellard
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1307 a130a41e bellard
{
1308 a130a41e bellard
    int width, height;
1309 a130a41e bellard
    
1310 a130a41e bellard
    width = (s->cr[0x01] + 1) * 8;
1311 a130a41e bellard
    height = s->cr[0x12] | 
1312 a130a41e bellard
        ((s->cr[0x07] & 0x02) << 7) | 
1313 a130a41e bellard
        ((s->cr[0x07] & 0x40) << 3);
1314 a130a41e bellard
    height = (height + 1);
1315 a130a41e bellard
    *pwidth = width;
1316 a130a41e bellard
    *pheight = height;
1317 a130a41e bellard
}
1318 a130a41e bellard
1319 a8aa669b bellard
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1320 a8aa669b bellard
{
1321 a8aa669b bellard
    int y;
1322 a8aa669b bellard
    if (y1 >= VGA_MAX_HEIGHT)
1323 a8aa669b bellard
        return;
1324 a8aa669b bellard
    if (y2 >= VGA_MAX_HEIGHT)
1325 a8aa669b bellard
        y2 = VGA_MAX_HEIGHT;
1326 a8aa669b bellard
    for(y = y1; y < y2; y++) {
1327 a8aa669b bellard
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1328 a8aa669b bellard
    }
1329 a8aa669b bellard
}
1330 a8aa669b bellard
1331 e89f66ec bellard
/* 
1332 e89f66ec bellard
 * graphic modes
1333 e89f66ec bellard
 */
1334 e89f66ec bellard
static void vga_draw_graphic(VGAState *s, int full_update)
1335 e89f66ec bellard
{
1336 17b0018b bellard
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1337 39cf7803 bellard
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1338 a07cf92a bellard
    int disp_width, multi_scan, multi_run;
1339 e89f66ec bellard
    uint8_t *d;
1340 39cf7803 bellard
    uint32_t v, addr1, addr;
1341 e89f66ec bellard
    vga_draw_line_func *vga_draw_line;
1342 17b0018b bellard
    
1343 e89f66ec bellard
    full_update |= update_basic_params(s);
1344 e89f66ec bellard
1345 a130a41e bellard
    s->get_resolution(s, &width, &height);
1346 17b0018b bellard
    disp_width = width;
1347 09a79b49 bellard
1348 e89f66ec bellard
    shift_control = (s->gr[0x05] >> 5) & 3;
1349 f6c958c8 bellard
    double_scan = (s->cr[0x09] >> 7);
1350 f6c958c8 bellard
    if (shift_control != 1) {
1351 f6c958c8 bellard
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1352 a07cf92a bellard
    } else {
1353 f6c958c8 bellard
        /* in CGA modes, multi_scan is ignored */
1354 f6c958c8 bellard
        /* XXX: is it correct ? */
1355 f6c958c8 bellard
        multi_scan = double_scan;
1356 a07cf92a bellard
    }
1357 a07cf92a bellard
    multi_run = multi_scan;
1358 17b0018b bellard
    if (shift_control != s->shift_control ||
1359 17b0018b bellard
        double_scan != s->double_scan) {
1360 e89f66ec bellard
        full_update = 1;
1361 e89f66ec bellard
        s->shift_control = shift_control;
1362 17b0018b bellard
        s->double_scan = double_scan;
1363 e89f66ec bellard
    }
1364 e89f66ec bellard
    
1365 17b0018b bellard
    if (shift_control == 0) {
1366 17b0018b bellard
        full_update |= update_palette16(s);
1367 17b0018b bellard
        if (s->sr[0x01] & 8) {
1368 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1369 17b0018b bellard
            disp_width <<= 1;
1370 17b0018b bellard
        } else {
1371 17b0018b bellard
            v = VGA_DRAW_LINE4;
1372 17b0018b bellard
        }
1373 17b0018b bellard
    } else if (shift_control == 1) {
1374 17b0018b bellard
        full_update |= update_palette16(s);
1375 17b0018b bellard
        if (s->sr[0x01] & 8) {
1376 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1377 17b0018b bellard
            disp_width <<= 1;
1378 17b0018b bellard
        } else {
1379 17b0018b bellard
            v = VGA_DRAW_LINE2;
1380 17b0018b bellard
        }
1381 17b0018b bellard
    } else {
1382 798b0c25 bellard
        switch(s->get_bpp(s)) {
1383 798b0c25 bellard
        default:
1384 798b0c25 bellard
        case 0:
1385 4fa0f5d2 bellard
            full_update |= update_palette256(s);
1386 4fa0f5d2 bellard
            v = VGA_DRAW_LINE8D2;
1387 798b0c25 bellard
            break;
1388 798b0c25 bellard
        case 8:
1389 798b0c25 bellard
            full_update |= update_palette256(s);
1390 798b0c25 bellard
            v = VGA_DRAW_LINE8;
1391 798b0c25 bellard
            break;
1392 798b0c25 bellard
        case 15:
1393 798b0c25 bellard
            v = VGA_DRAW_LINE15;
1394 798b0c25 bellard
            break;
1395 798b0c25 bellard
        case 16:
1396 798b0c25 bellard
            v = VGA_DRAW_LINE16;
1397 798b0c25 bellard
            break;
1398 798b0c25 bellard
        case 24:
1399 798b0c25 bellard
            v = VGA_DRAW_LINE24;
1400 798b0c25 bellard
            break;
1401 798b0c25 bellard
        case 32:
1402 798b0c25 bellard
            v = VGA_DRAW_LINE32;
1403 798b0c25 bellard
            break;
1404 4fa0f5d2 bellard
        }
1405 17b0018b bellard
    }
1406 e89f66ec bellard
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1407 17b0018b bellard
1408 17b0018b bellard
    if (disp_width != s->last_width ||
1409 17b0018b bellard
        height != s->last_height) {
1410 17b0018b bellard
        dpy_resize(s->ds, disp_width, height);
1411 2aebb3eb bellard
        s->last_scr_width = disp_width;
1412 2aebb3eb bellard
        s->last_scr_height = height;
1413 17b0018b bellard
        s->last_width = disp_width;
1414 17b0018b bellard
        s->last_height = height;
1415 17b0018b bellard
        full_update = 1;
1416 17b0018b bellard
    }
1417 a8aa669b bellard
    if (s->cursor_invalidate)
1418 a8aa669b bellard
        s->cursor_invalidate(s);
1419 a8aa669b bellard
    
1420 e89f66ec bellard
    line_offset = s->line_offset;
1421 17b0018b bellard
#if 0
1422 f6c958c8 bellard
    printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
1423 17b0018b bellard
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1424 17b0018b bellard
#endif
1425 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1426 39cf7803 bellard
    bwidth = width * 4;
1427 39cf7803 bellard
    y_start = -1;
1428 e89f66ec bellard
    page_min = 0x7fffffff;
1429 e89f66ec bellard
    page_max = -1;
1430 e89f66ec bellard
    d = s->ds->data;
1431 e89f66ec bellard
    linesize = s->ds->linesize;
1432 17b0018b bellard
    y1 = 0;
1433 e89f66ec bellard
    for(y = 0; y < height; y++) {
1434 e89f66ec bellard
        addr = addr1;
1435 39cf7803 bellard
        if (!(s->cr[0x17] & 1)) {
1436 17b0018b bellard
            int shift;
1437 e89f66ec bellard
            /* CGA compatibility handling */
1438 17b0018b bellard
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1439 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1440 e89f66ec bellard
        }
1441 39cf7803 bellard
        if (!(s->cr[0x17] & 2)) {
1442 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1443 e89f66ec bellard
        }
1444 4fa0f5d2 bellard
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1445 4fa0f5d2 bellard
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1446 4fa0f5d2 bellard
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1447 4fa0f5d2 bellard
            cpu_physical_memory_is_dirty(page1);
1448 4fa0f5d2 bellard
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1449 39cf7803 bellard
            /* if wide line, can use another page */
1450 4fa0f5d2 bellard
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1451 39cf7803 bellard
        }
1452 a8aa669b bellard
        /* explicit invalidation for the hardware cursor */
1453 a8aa669b bellard
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1454 e89f66ec bellard
        if (update) {
1455 39cf7803 bellard
            if (y_start < 0)
1456 39cf7803 bellard
                y_start = y;
1457 e89f66ec bellard
            if (page0 < page_min)
1458 e89f66ec bellard
                page_min = page0;
1459 e89f66ec bellard
            if (page1 > page_max)
1460 e89f66ec bellard
                page_max = page1;
1461 e89f66ec bellard
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1462 a8aa669b bellard
            if (s->cursor_draw_line)
1463 a8aa669b bellard
                s->cursor_draw_line(s, d, y);
1464 39cf7803 bellard
        } else {
1465 39cf7803 bellard
            if (y_start >= 0) {
1466 39cf7803 bellard
                /* flush to display */
1467 39cf7803 bellard
                dpy_update(s->ds, 0, y_start, 
1468 17b0018b bellard
                           disp_width, y - y_start);
1469 39cf7803 bellard
                y_start = -1;
1470 39cf7803 bellard
            }
1471 e89f66ec bellard
        }
1472 a07cf92a bellard
        if (!multi_run) {
1473 f6c958c8 bellard
            mask = (s->cr[0x17] & 3) ^ 3;
1474 f6c958c8 bellard
            if ((y1 & mask) == mask)
1475 f6c958c8 bellard
                addr1 += line_offset;
1476 f6c958c8 bellard
            y1++;
1477 a07cf92a bellard
            multi_run = multi_scan;
1478 a07cf92a bellard
        } else {
1479 a07cf92a bellard
            multi_run--;
1480 e89f66ec bellard
        }
1481 f6c958c8 bellard
        /* line compare acts on the displayed lines */
1482 f6c958c8 bellard
        if (y == s->line_compare)
1483 f6c958c8 bellard
            addr1 = 0;
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 46e50e9d bellard
int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1751 46e50e9d bellard
                   unsigned long vga_ram_offset, int vga_ram_size)
1752 798b0c25 bellard
{
1753 7b17d41e bellard
    VGAState *s;
1754 7b17d41e bellard
1755 7b17d41e bellard
    s = qemu_mallocz(sizeof(VGAState));
1756 7b17d41e bellard
    if (!s)
1757 7b17d41e bellard
        return -1;
1758 798b0c25 bellard
1759 798b0c25 bellard
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1760 e89f66ec bellard
1761 b0a21b53 bellard
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1762 b0a21b53 bellard
1763 0f35920c bellard
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1764 e89f66ec bellard
1765 0f35920c bellard
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1766 0f35920c bellard
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1767 0f35920c bellard
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1768 0f35920c bellard
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1769 e89f66ec bellard
1770 0f35920c bellard
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1771 e89f66ec bellard
1772 0f35920c bellard
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1773 0f35920c bellard
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1774 0f35920c bellard
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1775 0f35920c bellard
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1776 26aa7d72 bellard
    s->bank_offset = 0;
1777 e89f66ec bellard
1778 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1779 4fa0f5d2 bellard
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1780 cae61cef bellard
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1781 09a79b49 bellard
#if defined (TARGET_I386)
1782 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1783 09a79b49 bellard
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1784 4fa0f5d2 bellard
1785 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1786 09a79b49 bellard
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1787 646be93b bellard
1788 646be93b bellard
    /* old Bochs IO ports */
1789 09a79b49 bellard
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1790 09a79b49 bellard
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1791 646be93b bellard
1792 09a79b49 bellard
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1793 09a79b49 bellard
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1794 09a79b49 bellard
#else
1795 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1796 09a79b49 bellard
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1797 09a79b49 bellard
1798 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1799 09a79b49 bellard
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1800 4fa0f5d2 bellard
#endif
1801 09a79b49 bellard
#endif /* CONFIG_BOCHS_VBE */
1802 4fa0f5d2 bellard
1803 a4193c8a bellard
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1804 26aa7d72 bellard
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1805 26aa7d72 bellard
                                 vga_io_memory);
1806 1078f663 bellard
1807 46e50e9d bellard
    if (bus) {
1808 1078f663 bellard
        PCIDevice *d;
1809 1078f663 bellard
        uint8_t *pci_conf;
1810 1078f663 bellard
1811 46e50e9d bellard
        d = pci_register_device(bus, "VGA", 
1812 1078f663 bellard
                                sizeof(PCIDevice),
1813 46e50e9d bellard
                                -1, NULL, NULL);
1814 1078f663 bellard
        pci_conf = d->config;
1815 1078f663 bellard
        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1816 1078f663 bellard
        pci_conf[0x01] = 0x12;
1817 1078f663 bellard
        pci_conf[0x02] = 0x11;
1818 1078f663 bellard
        pci_conf[0x03] = 0x11;
1819 1078f663 bellard
        pci_conf[0x0a] = 0x00; // VGA controller 
1820 1078f663 bellard
        pci_conf[0x0b] = 0x03;
1821 1078f663 bellard
        pci_conf[0x0e] = 0x00; // header_type
1822 1078f663 bellard
1823 1078f663 bellard
        /* XXX: vga_ram_size must be a power of two */
1824 1078f663 bellard
        pci_register_io_region(d, 0, vga_ram_size, 
1825 1078f663 bellard
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1826 1078f663 bellard
    } else {
1827 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1828 1078f663 bellard
        /* XXX: use optimized standard vga accesses */
1829 1078f663 bellard
        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1830 1078f663 bellard
                                     vga_ram_size, vga_ram_offset);
1831 4fa0f5d2 bellard
#endif
1832 1078f663 bellard
    }
1833 e89f66ec bellard
    return 0;
1834 e89f66ec bellard
}
1835 59a983b9 bellard
1836 59a983b9 bellard
/********************************************************/
1837 59a983b9 bellard
/* vga screen dump */
1838 59a983b9 bellard
1839 59a983b9 bellard
static int vga_save_w, vga_save_h;
1840 59a983b9 bellard
1841 59a983b9 bellard
static void vga_save_dpy_update(DisplayState *s, 
1842 59a983b9 bellard
                                int x, int y, int w, int h)
1843 59a983b9 bellard
{
1844 59a983b9 bellard
}
1845 59a983b9 bellard
1846 59a983b9 bellard
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1847 59a983b9 bellard
{
1848 59a983b9 bellard
    s->linesize = w * 4;
1849 59a983b9 bellard
    s->data = qemu_malloc(h * s->linesize);
1850 59a983b9 bellard
    vga_save_w = w;
1851 59a983b9 bellard
    vga_save_h = h;
1852 59a983b9 bellard
}
1853 59a983b9 bellard
1854 59a983b9 bellard
static void vga_save_dpy_refresh(DisplayState *s)
1855 59a983b9 bellard
{
1856 59a983b9 bellard
}
1857 59a983b9 bellard
1858 59a983b9 bellard
static int ppm_save(const char *filename, uint8_t *data, 
1859 59a983b9 bellard
                    int w, int h, int linesize)
1860 59a983b9 bellard
{
1861 59a983b9 bellard
    FILE *f;
1862 59a983b9 bellard
    uint8_t *d, *d1;
1863 59a983b9 bellard
    unsigned int v;
1864 59a983b9 bellard
    int y, x;
1865 59a983b9 bellard
1866 59a983b9 bellard
    f = fopen(filename, "wb");
1867 59a983b9 bellard
    if (!f)
1868 59a983b9 bellard
        return -1;
1869 59a983b9 bellard
    fprintf(f, "P6\n%d %d\n%d\n",
1870 59a983b9 bellard
            w, h, 255);
1871 59a983b9 bellard
    d1 = data;
1872 59a983b9 bellard
    for(y = 0; y < h; y++) {
1873 59a983b9 bellard
        d = d1;
1874 59a983b9 bellard
        for(x = 0; x < w; x++) {
1875 59a983b9 bellard
            v = *(uint32_t *)d;
1876 59a983b9 bellard
            fputc((v >> 16) & 0xff, f);
1877 59a983b9 bellard
            fputc((v >> 8) & 0xff, f);
1878 59a983b9 bellard
            fputc((v) & 0xff, f);
1879 59a983b9 bellard
            d += 4;
1880 59a983b9 bellard
        }
1881 59a983b9 bellard
        d1 += linesize;
1882 59a983b9 bellard
    }
1883 59a983b9 bellard
    fclose(f);
1884 59a983b9 bellard
    return 0;
1885 59a983b9 bellard
}
1886 59a983b9 bellard
1887 59a983b9 bellard
/* save the vga display in a PPM image even if no display is
1888 59a983b9 bellard
   available */
1889 59a983b9 bellard
void vga_screen_dump(const char *filename)
1890 59a983b9 bellard
{
1891 7b17d41e bellard
    VGAState *s = vga_state;
1892 59a983b9 bellard
    DisplayState *saved_ds, ds1, *ds = &ds1;
1893 59a983b9 bellard
    
1894 59a983b9 bellard
    /* XXX: this is a little hackish */
1895 a130a41e bellard
    vga_invalidate_display();
1896 59a983b9 bellard
    saved_ds = s->ds;
1897 59a983b9 bellard
1898 59a983b9 bellard
    memset(ds, 0, sizeof(DisplayState));
1899 59a983b9 bellard
    ds->dpy_update = vga_save_dpy_update;
1900 59a983b9 bellard
    ds->dpy_resize = vga_save_dpy_resize;
1901 59a983b9 bellard
    ds->dpy_refresh = vga_save_dpy_refresh;
1902 59a983b9 bellard
    ds->depth = 32;
1903 59a983b9 bellard
1904 59a983b9 bellard
    s->ds = ds;
1905 59a983b9 bellard
    s->graphic_mode = -1;
1906 59a983b9 bellard
    vga_update_display();
1907 59a983b9 bellard
    
1908 59a983b9 bellard
    if (ds->data) {
1909 59a983b9 bellard
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1910 59a983b9 bellard
                 s->ds->linesize);
1911 59a983b9 bellard
        qemu_free(ds->data);
1912 59a983b9 bellard
    }
1913 59a983b9 bellard
    s->ds = saved_ds;
1914 59a983b9 bellard
}