Statistics
| Branch: | Revision:

root / hw / vga.c @ e6eccb38

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 e89f66ec bellard
        if ((s->cr[11] & 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 e89f66ec bellard
    /* XXX: TODO */
828 e89f66ec bellard
    return 0;
829 e89f66ec bellard
}
830 e89f66ec bellard
831 e89f66ec bellard
static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
832 e89f66ec bellard
{
833 e89f66ec bellard
    return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
834 e89f66ec bellard
}
835 e89f66ec bellard
836 e89f66ec bellard
static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
837 e89f66ec bellard
{
838 e89f66ec bellard
    return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
839 e89f66ec bellard
}
840 e89f66ec bellard
841 e89f66ec bellard
static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
842 e89f66ec bellard
{
843 e89f66ec bellard
    return (r << 16) | (g << 8) | b;
844 e89f66ec bellard
}
845 e89f66ec bellard
846 e89f66ec bellard
#define DEPTH 8
847 e89f66ec bellard
#include "vga_template.h"
848 e89f66ec bellard
849 e89f66ec bellard
#define DEPTH 15
850 e89f66ec bellard
#include "vga_template.h"
851 e89f66ec bellard
852 e89f66ec bellard
#define DEPTH 16
853 e89f66ec bellard
#include "vga_template.h"
854 e89f66ec bellard
855 e89f66ec bellard
#define DEPTH 32
856 e89f66ec bellard
#include "vga_template.h"
857 e89f66ec bellard
858 17b0018b bellard
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
859 17b0018b bellard
{
860 17b0018b bellard
    unsigned int col;
861 17b0018b bellard
    col = rgb_to_pixel8(r, g, b);
862 17b0018b bellard
    col |= col << 8;
863 17b0018b bellard
    col |= col << 16;
864 17b0018b bellard
    return col;
865 17b0018b bellard
}
866 17b0018b bellard
867 17b0018b bellard
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
868 17b0018b bellard
{
869 17b0018b bellard
    unsigned int col;
870 17b0018b bellard
    col = rgb_to_pixel15(r, g, b);
871 17b0018b bellard
    col |= col << 16;
872 17b0018b bellard
    return col;
873 17b0018b bellard
}
874 17b0018b bellard
875 17b0018b bellard
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
876 17b0018b bellard
{
877 17b0018b bellard
    unsigned int col;
878 17b0018b bellard
    col = rgb_to_pixel16(r, g, b);
879 17b0018b bellard
    col |= col << 16;
880 17b0018b bellard
    return col;
881 17b0018b bellard
}
882 17b0018b bellard
883 17b0018b bellard
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
884 17b0018b bellard
{
885 17b0018b bellard
    unsigned int col;
886 17b0018b bellard
    col = rgb_to_pixel32(r, g, b);
887 17b0018b bellard
    return col;
888 17b0018b bellard
}
889 17b0018b bellard
890 e89f66ec bellard
/* return true if the palette was modified */
891 e89f66ec bellard
static int update_palette16(VGAState *s)
892 e89f66ec bellard
{
893 17b0018b bellard
    int full_update, i;
894 e89f66ec bellard
    uint32_t v, col, *palette;
895 e89f66ec bellard
896 e89f66ec bellard
    full_update = 0;
897 e89f66ec bellard
    palette = s->last_palette;
898 e89f66ec bellard
    for(i = 0; i < 16; i++) {
899 e89f66ec bellard
        v = s->ar[i];
900 e89f66ec bellard
        if (s->ar[0x10] & 0x80)
901 e89f66ec bellard
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
902 e89f66ec bellard
        else
903 e89f66ec bellard
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
904 e89f66ec bellard
        v = v * 3;
905 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
906 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
907 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
908 17b0018b bellard
        if (col != palette[i]) {
909 17b0018b bellard
            full_update = 1;
910 17b0018b bellard
            palette[i] = col;
911 e89f66ec bellard
        }
912 17b0018b bellard
    }
913 17b0018b bellard
    return full_update;
914 17b0018b bellard
}
915 17b0018b bellard
916 17b0018b bellard
/* return true if the palette was modified */
917 17b0018b bellard
static int update_palette256(VGAState *s)
918 17b0018b bellard
{
919 17b0018b bellard
    int full_update, i;
920 17b0018b bellard
    uint32_t v, col, *palette;
921 17b0018b bellard
922 17b0018b bellard
    full_update = 0;
923 17b0018b bellard
    palette = s->last_palette;
924 17b0018b bellard
    v = 0;
925 17b0018b bellard
    for(i = 0; i < 256; i++) {
926 17b0018b bellard
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]), 
927 17b0018b bellard
                              c6_to_8(s->palette[v + 1]), 
928 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
929 e89f66ec bellard
        if (col != palette[i]) {
930 e89f66ec bellard
            full_update = 1;
931 e89f66ec bellard
            palette[i] = col;
932 e89f66ec bellard
        }
933 17b0018b bellard
        v += 3;
934 e89f66ec bellard
    }
935 e89f66ec bellard
    return full_update;
936 e89f66ec bellard
}
937 e89f66ec bellard
938 798b0c25 bellard
static void vga_get_offsets(VGAState *s, 
939 798b0c25 bellard
                            uint32_t *pline_offset, 
940 798b0c25 bellard
                            uint32_t *pstart_addr)
941 e89f66ec bellard
{
942 798b0c25 bellard
    uint32_t start_addr, line_offset;
943 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
944 4fa0f5d2 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
945 4fa0f5d2 bellard
        line_offset = s->vbe_line_offset;
946 4fa0f5d2 bellard
        start_addr = s->vbe_start_addr;
947 4fa0f5d2 bellard
    } else
948 4fa0f5d2 bellard
#endif
949 4fa0f5d2 bellard
    {  
950 4fa0f5d2 bellard
        /* compute line_offset in bytes */
951 4fa0f5d2 bellard
        line_offset = s->cr[0x13];
952 a41bc9af bellard
#ifdef CONFIG_S3VGA
953 5467a722 bellard
        {
954 5467a722 bellard
            uinr32_t v;
955 5467a722 bellard
            v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
956 5467a722 bellard
            if (v == 0)
957 5467a722 bellard
                v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
958 5467a722 bellard
            line_offset |= (v << 8);
959 5467a722 bellard
        }
960 a41bc9af bellard
#endif
961 4fa0f5d2 bellard
        line_offset <<= 3;
962 4fa0f5d2 bellard
        
963 4fa0f5d2 bellard
        /* starting address */
964 4fa0f5d2 bellard
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
965 a41bc9af bellard
#ifdef CONFIG_S3VGA
966 4fa0f5d2 bellard
        start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
967 a41bc9af bellard
#endif
968 4fa0f5d2 bellard
    }
969 798b0c25 bellard
    *pline_offset = line_offset;
970 798b0c25 bellard
    *pstart_addr = start_addr;
971 798b0c25 bellard
}
972 798b0c25 bellard
973 798b0c25 bellard
/* update start_addr and line_offset. Return TRUE if modified */
974 798b0c25 bellard
static int update_basic_params(VGAState *s)
975 798b0c25 bellard
{
976 798b0c25 bellard
    int full_update;
977 798b0c25 bellard
    uint32_t start_addr, line_offset, line_compare;
978 4fa0f5d2 bellard
    
979 798b0c25 bellard
    full_update = 0;
980 798b0c25 bellard
981 798b0c25 bellard
    s->get_offsets(s, &line_offset, &start_addr);
982 e89f66ec bellard
    /* line compare */
983 e89f66ec bellard
    line_compare = s->cr[0x18] | 
984 e89f66ec bellard
        ((s->cr[0x07] & 0x10) << 4) |
985 e89f66ec bellard
        ((s->cr[0x09] & 0x40) << 3);
986 e89f66ec bellard
987 e89f66ec bellard
    if (line_offset != s->line_offset ||
988 e89f66ec bellard
        start_addr != s->start_addr ||
989 e89f66ec bellard
        line_compare != s->line_compare) {
990 e89f66ec bellard
        s->line_offset = line_offset;
991 e89f66ec bellard
        s->start_addr = start_addr;
992 e89f66ec bellard
        s->line_compare = line_compare;
993 e89f66ec bellard
        full_update = 1;
994 e89f66ec bellard
    }
995 e89f66ec bellard
    return full_update;
996 e89f66ec bellard
}
997 e89f66ec bellard
998 e89f66ec bellard
static inline int get_depth_index(int depth)
999 e89f66ec bellard
{
1000 e89f66ec bellard
    switch(depth) {
1001 e89f66ec bellard
    default:
1002 e89f66ec bellard
    case 8:
1003 e89f66ec bellard
        return 0;
1004 e89f66ec bellard
    case 15:
1005 e89f66ec bellard
        return 1;
1006 e89f66ec bellard
    case 16:
1007 e89f66ec bellard
        return 2;
1008 e89f66ec bellard
    case 32:
1009 e89f66ec bellard
        return 3;
1010 e89f66ec bellard
    }
1011 e89f66ec bellard
}
1012 e89f66ec bellard
1013 e89f66ec bellard
static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
1014 e89f66ec bellard
    vga_draw_glyph8_8,
1015 e89f66ec bellard
    vga_draw_glyph8_16,
1016 e89f66ec bellard
    vga_draw_glyph8_16,
1017 e89f66ec bellard
    vga_draw_glyph8_32,
1018 e89f66ec bellard
};
1019 e89f66ec bellard
1020 17b0018b bellard
static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
1021 17b0018b bellard
    vga_draw_glyph16_8,
1022 17b0018b bellard
    vga_draw_glyph16_16,
1023 17b0018b bellard
    vga_draw_glyph16_16,
1024 17b0018b bellard
    vga_draw_glyph16_32,
1025 17b0018b bellard
};
1026 17b0018b bellard
1027 e89f66ec bellard
static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
1028 e89f66ec bellard
    vga_draw_glyph9_8,
1029 e89f66ec bellard
    vga_draw_glyph9_16,
1030 e89f66ec bellard
    vga_draw_glyph9_16,
1031 e89f66ec bellard
    vga_draw_glyph9_32,
1032 e89f66ec bellard
};
1033 e89f66ec bellard
    
1034 e89f66ec bellard
static const uint8_t cursor_glyph[32 * 4] = {
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
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1051 e89f66ec bellard
};    
1052 e89f66ec bellard
1053 e89f66ec bellard
/* 
1054 e89f66ec bellard
 * Text mode update 
1055 e89f66ec bellard
 * Missing:
1056 e89f66ec bellard
 * - double scan
1057 e89f66ec bellard
 * - double width 
1058 e89f66ec bellard
 * - underline
1059 e89f66ec bellard
 * - flashing
1060 e89f66ec bellard
 */
1061 e89f66ec bellard
static void vga_draw_text(VGAState *s, int full_update)
1062 e89f66ec bellard
{
1063 e89f66ec bellard
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1064 e89f66ec bellard
    int cx_min, cx_max, linesize, x_incr;
1065 e89f66ec bellard
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1066 e89f66ec bellard
    uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
1067 e89f66ec bellard
    const uint8_t *font_ptr, *font_base[2];
1068 e89f66ec bellard
    int dup9, line_offset, depth_index;
1069 e89f66ec bellard
    uint32_t *palette;
1070 e89f66ec bellard
    uint32_t *ch_attr_ptr;
1071 e89f66ec bellard
    vga_draw_glyph8_func *vga_draw_glyph8;
1072 e89f66ec bellard
    vga_draw_glyph9_func *vga_draw_glyph9;
1073 e89f66ec bellard
1074 e89f66ec bellard
    full_update |= update_palette16(s);
1075 e89f66ec bellard
    palette = s->last_palette;
1076 e89f66ec bellard
    
1077 e89f66ec bellard
    /* compute font data address (in plane 2) */
1078 e89f66ec bellard
    v = s->sr[3];
1079 1078f663 bellard
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1080 e89f66ec bellard
    if (offset != s->font_offsets[0]) {
1081 e89f66ec bellard
        s->font_offsets[0] = offset;
1082 e89f66ec bellard
        full_update = 1;
1083 e89f66ec bellard
    }
1084 e89f66ec bellard
    font_base[0] = s->vram_ptr + offset;
1085 e89f66ec bellard
1086 1078f663 bellard
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1087 e89f66ec bellard
    font_base[1] = s->vram_ptr + offset;
1088 e89f66ec bellard
    if (offset != s->font_offsets[1]) {
1089 e89f66ec bellard
        s->font_offsets[1] = offset;
1090 e89f66ec bellard
        full_update = 1;
1091 e89f66ec bellard
    }
1092 e89f66ec bellard
1093 e89f66ec bellard
    full_update |= update_basic_params(s);
1094 e89f66ec bellard
1095 e89f66ec bellard
    line_offset = s->line_offset;
1096 e89f66ec bellard
    s1 = s->vram_ptr + (s->start_addr * 4);
1097 e89f66ec bellard
1098 e89f66ec bellard
    /* total width & height */
1099 e89f66ec bellard
    cheight = (s->cr[9] & 0x1f) + 1;
1100 e89f66ec bellard
    cw = 8;
1101 eccabc6e bellard
    if (!(s->sr[1] & 0x01))
1102 e89f66ec bellard
        cw = 9;
1103 17b0018b bellard
    if (s->sr[1] & 0x08)
1104 17b0018b bellard
        cw = 16; /* NOTE: no 18 pixel wide */
1105 e89f66ec bellard
    x_incr = cw * ((s->ds->depth + 7) >> 3);
1106 e89f66ec bellard
    width = (s->cr[0x01] + 1);
1107 17b0018b bellard
    if (s->cr[0x06] == 100) {
1108 17b0018b bellard
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1109 17b0018b bellard
        height = 100;
1110 17b0018b bellard
    } else {
1111 17b0018b bellard
        height = s->cr[0x12] | 
1112 17b0018b bellard
            ((s->cr[0x07] & 0x02) << 7) | 
1113 17b0018b bellard
            ((s->cr[0x07] & 0x40) << 3);
1114 17b0018b bellard
        height = (height + 1) / cheight;
1115 17b0018b bellard
    }
1116 3294b949 bellard
    if ((height * width) > CH_ATTR_SIZE) {
1117 3294b949 bellard
        /* better than nothing: exit if transient size is too big */
1118 3294b949 bellard
        return;
1119 3294b949 bellard
    }
1120 3294b949 bellard
1121 e89f66ec bellard
    if (width != s->last_width || height != s->last_height ||
1122 eccabc6e bellard
        cw != s->last_cw || cheight != s->last_ch) {
1123 2aebb3eb bellard
        s->last_scr_width = width * cw;
1124 2aebb3eb bellard
        s->last_scr_height = height * cheight;
1125 2aebb3eb bellard
        dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
1126 e89f66ec bellard
        s->last_width = width;
1127 e89f66ec bellard
        s->last_height = height;
1128 e89f66ec bellard
        s->last_ch = cheight;
1129 e89f66ec bellard
        s->last_cw = cw;
1130 e89f66ec bellard
        full_update = 1;
1131 e89f66ec bellard
    }
1132 e89f66ec bellard
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1133 e89f66ec bellard
    if (cursor_offset != s->cursor_offset ||
1134 e89f66ec bellard
        s->cr[0xa] != s->cursor_start ||
1135 e89f66ec bellard
        s->cr[0xb] != s->cursor_end) {
1136 e89f66ec bellard
      /* if the cursor position changed, we update the old and new
1137 e89f66ec bellard
         chars */
1138 e89f66ec bellard
        if (s->cursor_offset < CH_ATTR_SIZE)
1139 e89f66ec bellard
            s->last_ch_attr[s->cursor_offset] = -1;
1140 e89f66ec bellard
        if (cursor_offset < CH_ATTR_SIZE)
1141 e89f66ec bellard
            s->last_ch_attr[cursor_offset] = -1;
1142 e89f66ec bellard
        s->cursor_offset = cursor_offset;
1143 e89f66ec bellard
        s->cursor_start = s->cr[0xa];
1144 e89f66ec bellard
        s->cursor_end = s->cr[0xb];
1145 e89f66ec bellard
    }
1146 39cf7803 bellard
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1147 e89f66ec bellard
    
1148 e89f66ec bellard
    depth_index = get_depth_index(s->ds->depth);
1149 17b0018b bellard
    if (cw == 16)
1150 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1151 17b0018b bellard
    else
1152 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1153 e89f66ec bellard
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1154 e89f66ec bellard
    
1155 e89f66ec bellard
    dest = s->ds->data;
1156 e89f66ec bellard
    linesize = s->ds->linesize;
1157 e89f66ec bellard
    ch_attr_ptr = s->last_ch_attr;
1158 e89f66ec bellard
    for(cy = 0; cy < height; cy++) {
1159 e89f66ec bellard
        d1 = dest;
1160 e89f66ec bellard
        src = s1;
1161 e89f66ec bellard
        cx_min = width;
1162 e89f66ec bellard
        cx_max = -1;
1163 e89f66ec bellard
        for(cx = 0; cx < width; cx++) {
1164 e89f66ec bellard
            ch_attr = *(uint16_t *)src;
1165 e89f66ec bellard
            if (full_update || ch_attr != *ch_attr_ptr) {
1166 e89f66ec bellard
                if (cx < cx_min)
1167 e89f66ec bellard
                    cx_min = cx;
1168 e89f66ec bellard
                if (cx > cx_max)
1169 e89f66ec bellard
                    cx_max = cx;
1170 e89f66ec bellard
                *ch_attr_ptr = ch_attr;
1171 e89f66ec bellard
#ifdef WORDS_BIGENDIAN
1172 e89f66ec bellard
                ch = ch_attr >> 8;
1173 e89f66ec bellard
                cattr = ch_attr & 0xff;
1174 e89f66ec bellard
#else
1175 e89f66ec bellard
                ch = ch_attr & 0xff;
1176 e89f66ec bellard
                cattr = ch_attr >> 8;
1177 e89f66ec bellard
#endif
1178 e89f66ec bellard
                font_ptr = font_base[(cattr >> 3) & 1];
1179 e89f66ec bellard
                font_ptr += 32 * 4 * ch;
1180 e89f66ec bellard
                bgcol = palette[cattr >> 4];
1181 e89f66ec bellard
                fgcol = palette[cattr & 0x0f];
1182 17b0018b bellard
                if (cw != 9) {
1183 e89f66ec bellard
                    vga_draw_glyph8(d1, linesize, 
1184 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol);
1185 e89f66ec bellard
                } else {
1186 e89f66ec bellard
                    dup9 = 0;
1187 e89f66ec bellard
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1188 e89f66ec bellard
                        dup9 = 1;
1189 e89f66ec bellard
                    vga_draw_glyph9(d1, linesize, 
1190 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1191 e89f66ec bellard
                }
1192 e89f66ec bellard
                if (src == cursor_ptr &&
1193 e89f66ec bellard
                    !(s->cr[0x0a] & 0x20)) {
1194 e89f66ec bellard
                    int line_start, line_last, h;
1195 e89f66ec bellard
                    /* draw the cursor */
1196 e89f66ec bellard
                    line_start = s->cr[0x0a] & 0x1f;
1197 e89f66ec bellard
                    line_last = s->cr[0x0b] & 0x1f;
1198 e89f66ec bellard
                    /* XXX: check that */
1199 e89f66ec bellard
                    if (line_last > cheight - 1)
1200 e89f66ec bellard
                        line_last = cheight - 1;
1201 e89f66ec bellard
                    if (line_last >= line_start && line_start < cheight) {
1202 e89f66ec bellard
                        h = line_last - line_start + 1;
1203 e89f66ec bellard
                        d = d1 + linesize * line_start;
1204 17b0018b bellard
                        if (cw != 9) {
1205 e89f66ec bellard
                            vga_draw_glyph8(d, linesize, 
1206 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol);
1207 e89f66ec bellard
                        } else {
1208 e89f66ec bellard
                            vga_draw_glyph9(d, linesize, 
1209 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol, 1);
1210 e89f66ec bellard
                        }
1211 e89f66ec bellard
                    }
1212 e89f66ec bellard
                }
1213 e89f66ec bellard
            }
1214 e89f66ec bellard
            d1 += x_incr;
1215 e89f66ec bellard
            src += 4;
1216 e89f66ec bellard
            ch_attr_ptr++;
1217 e89f66ec bellard
        }
1218 e89f66ec bellard
        if (cx_max != -1) {
1219 e89f66ec bellard
            dpy_update(s->ds, cx_min * cw, cy * cheight, 
1220 e89f66ec bellard
                       (cx_max - cx_min + 1) * cw, cheight);
1221 e89f66ec bellard
        }
1222 e89f66ec bellard
        dest += linesize * cheight;
1223 e89f66ec bellard
        s1 += line_offset;
1224 e89f66ec bellard
    }
1225 e89f66ec bellard
}
1226 e89f66ec bellard
1227 17b0018b bellard
enum {
1228 17b0018b bellard
    VGA_DRAW_LINE2,
1229 17b0018b bellard
    VGA_DRAW_LINE2D2,
1230 17b0018b bellard
    VGA_DRAW_LINE4,
1231 17b0018b bellard
    VGA_DRAW_LINE4D2,
1232 17b0018b bellard
    VGA_DRAW_LINE8D2,
1233 17b0018b bellard
    VGA_DRAW_LINE8,
1234 17b0018b bellard
    VGA_DRAW_LINE15,
1235 17b0018b bellard
    VGA_DRAW_LINE16,
1236 4fa0f5d2 bellard
    VGA_DRAW_LINE24,
1237 17b0018b bellard
    VGA_DRAW_LINE32,
1238 17b0018b bellard
    VGA_DRAW_LINE_NB,
1239 17b0018b bellard
};
1240 17b0018b bellard
1241 17b0018b bellard
static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
1242 e89f66ec bellard
    vga_draw_line2_8,
1243 e89f66ec bellard
    vga_draw_line2_16,
1244 e89f66ec bellard
    vga_draw_line2_16,
1245 e89f66ec bellard
    vga_draw_line2_32,
1246 e89f66ec bellard
1247 17b0018b bellard
    vga_draw_line2d2_8,
1248 17b0018b bellard
    vga_draw_line2d2_16,
1249 17b0018b bellard
    vga_draw_line2d2_16,
1250 17b0018b bellard
    vga_draw_line2d2_32,
1251 17b0018b bellard
1252 e89f66ec bellard
    vga_draw_line4_8,
1253 e89f66ec bellard
    vga_draw_line4_16,
1254 e89f66ec bellard
    vga_draw_line4_16,
1255 e89f66ec bellard
    vga_draw_line4_32,
1256 e89f66ec bellard
1257 17b0018b bellard
    vga_draw_line4d2_8,
1258 17b0018b bellard
    vga_draw_line4d2_16,
1259 17b0018b bellard
    vga_draw_line4d2_16,
1260 17b0018b bellard
    vga_draw_line4d2_32,
1261 17b0018b bellard
1262 17b0018b bellard
    vga_draw_line8d2_8,
1263 17b0018b bellard
    vga_draw_line8d2_16,
1264 17b0018b bellard
    vga_draw_line8d2_16,
1265 17b0018b bellard
    vga_draw_line8d2_32,
1266 17b0018b bellard
1267 e89f66ec bellard
    vga_draw_line8_8,
1268 e89f66ec bellard
    vga_draw_line8_16,
1269 e89f66ec bellard
    vga_draw_line8_16,
1270 e89f66ec bellard
    vga_draw_line8_32,
1271 e89f66ec bellard
1272 e89f66ec bellard
    vga_draw_line15_8,
1273 e89f66ec bellard
    vga_draw_line15_15,
1274 e89f66ec bellard
    vga_draw_line15_16,
1275 e89f66ec bellard
    vga_draw_line15_32,
1276 e89f66ec bellard
1277 e89f66ec bellard
    vga_draw_line16_8,
1278 e89f66ec bellard
    vga_draw_line16_15,
1279 e89f66ec bellard
    vga_draw_line16_16,
1280 e89f66ec bellard
    vga_draw_line16_32,
1281 e89f66ec bellard
1282 4fa0f5d2 bellard
    vga_draw_line24_8,
1283 4fa0f5d2 bellard
    vga_draw_line24_15,
1284 4fa0f5d2 bellard
    vga_draw_line24_16,
1285 4fa0f5d2 bellard
    vga_draw_line24_32,
1286 4fa0f5d2 bellard
1287 e89f66ec bellard
    vga_draw_line32_8,
1288 e89f66ec bellard
    vga_draw_line32_15,
1289 e89f66ec bellard
    vga_draw_line32_16,
1290 e89f66ec bellard
    vga_draw_line32_32,
1291 e89f66ec bellard
};
1292 e89f66ec bellard
1293 798b0c25 bellard
static int vga_get_bpp(VGAState *s)
1294 798b0c25 bellard
{
1295 798b0c25 bellard
    int ret;
1296 798b0c25 bellard
#ifdef CONFIG_BOCHS_VBE
1297 798b0c25 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1298 798b0c25 bellard
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1299 798b0c25 bellard
    } else 
1300 798b0c25 bellard
#endif
1301 798b0c25 bellard
    {
1302 798b0c25 bellard
        ret = 0;
1303 798b0c25 bellard
    }
1304 798b0c25 bellard
    return ret;
1305 798b0c25 bellard
}
1306 798b0c25 bellard
1307 a130a41e bellard
static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
1308 a130a41e bellard
{
1309 a130a41e bellard
    int width, height;
1310 a130a41e bellard
    
1311 a130a41e bellard
    width = (s->cr[0x01] + 1) * 8;
1312 a130a41e bellard
    height = s->cr[0x12] | 
1313 a130a41e bellard
        ((s->cr[0x07] & 0x02) << 7) | 
1314 a130a41e bellard
        ((s->cr[0x07] & 0x40) << 3);
1315 a130a41e bellard
    height = (height + 1);
1316 a130a41e bellard
    *pwidth = width;
1317 a130a41e bellard
    *pheight = height;
1318 a130a41e bellard
}
1319 a130a41e bellard
1320 a8aa669b bellard
void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
1321 a8aa669b bellard
{
1322 a8aa669b bellard
    int y;
1323 a8aa669b bellard
    if (y1 >= VGA_MAX_HEIGHT)
1324 a8aa669b bellard
        return;
1325 a8aa669b bellard
    if (y2 >= VGA_MAX_HEIGHT)
1326 a8aa669b bellard
        y2 = VGA_MAX_HEIGHT;
1327 a8aa669b bellard
    for(y = y1; y < y2; y++) {
1328 a8aa669b bellard
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1329 a8aa669b bellard
    }
1330 a8aa669b bellard
}
1331 a8aa669b bellard
1332 e89f66ec bellard
/* 
1333 e89f66ec bellard
 * graphic modes
1334 e89f66ec bellard
 */
1335 e89f66ec bellard
static void vga_draw_graphic(VGAState *s, int full_update)
1336 e89f66ec bellard
{
1337 17b0018b bellard
    int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
1338 39cf7803 bellard
    int width, height, shift_control, line_offset, page0, page1, bwidth;
1339 a07cf92a bellard
    int disp_width, multi_scan, multi_run;
1340 e89f66ec bellard
    uint8_t *d;
1341 39cf7803 bellard
    uint32_t v, addr1, addr;
1342 e89f66ec bellard
    vga_draw_line_func *vga_draw_line;
1343 17b0018b bellard
    
1344 e89f66ec bellard
    full_update |= update_basic_params(s);
1345 e89f66ec bellard
1346 a130a41e bellard
    s->get_resolution(s, &width, &height);
1347 17b0018b bellard
    disp_width = width;
1348 09a79b49 bellard
1349 e89f66ec bellard
    shift_control = (s->gr[0x05] >> 5) & 3;
1350 a07cf92a bellard
    double_scan = (s->cr[0x09] & 0x80);
1351 a07cf92a bellard
    if (shift_control > 1) {
1352 a07cf92a bellard
        multi_scan = (s->cr[0x09] & 0x1f);
1353 a07cf92a bellard
    } else {
1354 a07cf92a bellard
        multi_scan = 0;
1355 a07cf92a bellard
    }
1356 a07cf92a bellard
    multi_run = multi_scan;
1357 17b0018b bellard
    if (shift_control != s->shift_control ||
1358 17b0018b bellard
        double_scan != s->double_scan) {
1359 e89f66ec bellard
        full_update = 1;
1360 e89f66ec bellard
        s->shift_control = shift_control;
1361 17b0018b bellard
        s->double_scan = double_scan;
1362 e89f66ec bellard
    }
1363 e89f66ec bellard
    
1364 17b0018b bellard
    if (shift_control == 0) {
1365 17b0018b bellard
        full_update |= update_palette16(s);
1366 17b0018b bellard
        if (s->sr[0x01] & 8) {
1367 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1368 17b0018b bellard
            disp_width <<= 1;
1369 17b0018b bellard
        } else {
1370 17b0018b bellard
            v = VGA_DRAW_LINE4;
1371 17b0018b bellard
        }
1372 17b0018b bellard
    } else if (shift_control == 1) {
1373 17b0018b bellard
        full_update |= update_palette16(s);
1374 17b0018b bellard
        if (s->sr[0x01] & 8) {
1375 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1376 17b0018b bellard
            disp_width <<= 1;
1377 17b0018b bellard
        } else {
1378 17b0018b bellard
            v = VGA_DRAW_LINE2;
1379 17b0018b bellard
        }
1380 17b0018b bellard
    } else {
1381 798b0c25 bellard
        switch(s->get_bpp(s)) {
1382 798b0c25 bellard
        default:
1383 798b0c25 bellard
        case 0:
1384 4fa0f5d2 bellard
            full_update |= update_palette256(s);
1385 4fa0f5d2 bellard
            v = VGA_DRAW_LINE8D2;
1386 798b0c25 bellard
            break;
1387 798b0c25 bellard
        case 8:
1388 798b0c25 bellard
            full_update |= update_palette256(s);
1389 798b0c25 bellard
            v = VGA_DRAW_LINE8;
1390 798b0c25 bellard
            break;
1391 798b0c25 bellard
        case 15:
1392 798b0c25 bellard
            v = VGA_DRAW_LINE15;
1393 798b0c25 bellard
            break;
1394 798b0c25 bellard
        case 16:
1395 798b0c25 bellard
            v = VGA_DRAW_LINE16;
1396 798b0c25 bellard
            break;
1397 798b0c25 bellard
        case 24:
1398 798b0c25 bellard
            v = VGA_DRAW_LINE24;
1399 798b0c25 bellard
            break;
1400 798b0c25 bellard
        case 32:
1401 798b0c25 bellard
            v = VGA_DRAW_LINE32;
1402 798b0c25 bellard
            break;
1403 4fa0f5d2 bellard
        }
1404 17b0018b bellard
    }
1405 e89f66ec bellard
    vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
1406 17b0018b bellard
1407 17b0018b bellard
    if (disp_width != s->last_width ||
1408 17b0018b bellard
        height != s->last_height) {
1409 17b0018b bellard
        dpy_resize(s->ds, disp_width, height);
1410 2aebb3eb bellard
        s->last_scr_width = disp_width;
1411 2aebb3eb bellard
        s->last_scr_height = height;
1412 17b0018b bellard
        s->last_width = disp_width;
1413 17b0018b bellard
        s->last_height = height;
1414 17b0018b bellard
        full_update = 1;
1415 17b0018b bellard
    }
1416 a8aa669b bellard
    if (s->cursor_invalidate)
1417 a8aa669b bellard
        s->cursor_invalidate(s);
1418 a8aa669b bellard
    
1419 e89f66ec bellard
    line_offset = s->line_offset;
1420 17b0018b bellard
#if 0
1421 17b0018b bellard
    printf("w=%d h=%d v=%d line_offset=%d double_scan=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=%02x\n",
1422 17b0018b bellard
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1423 17b0018b bellard
#endif
1424 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1425 39cf7803 bellard
    bwidth = width * 4;
1426 39cf7803 bellard
    y_start = -1;
1427 e89f66ec bellard
    page_min = 0x7fffffff;
1428 e89f66ec bellard
    page_max = -1;
1429 e89f66ec bellard
    d = s->ds->data;
1430 e89f66ec bellard
    linesize = s->ds->linesize;
1431 17b0018b bellard
    y1 = 0;
1432 e89f66ec bellard
    for(y = 0; y < height; y++) {
1433 e89f66ec bellard
        addr = addr1;
1434 39cf7803 bellard
        if (!(s->cr[0x17] & 1)) {
1435 17b0018b bellard
            int shift;
1436 e89f66ec bellard
            /* CGA compatibility handling */
1437 17b0018b bellard
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1438 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1439 e89f66ec bellard
        }
1440 39cf7803 bellard
        if (!(s->cr[0x17] & 2)) {
1441 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1442 e89f66ec bellard
        }
1443 4fa0f5d2 bellard
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1444 4fa0f5d2 bellard
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1445 4fa0f5d2 bellard
        update = full_update | cpu_physical_memory_is_dirty(page0) |
1446 4fa0f5d2 bellard
            cpu_physical_memory_is_dirty(page1);
1447 4fa0f5d2 bellard
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1448 39cf7803 bellard
            /* if wide line, can use another page */
1449 4fa0f5d2 bellard
            update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
1450 39cf7803 bellard
        }
1451 a8aa669b bellard
        /* explicit invalidation for the hardware cursor */
1452 a8aa669b bellard
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1453 e89f66ec bellard
        if (update) {
1454 39cf7803 bellard
            if (y_start < 0)
1455 39cf7803 bellard
                y_start = y;
1456 e89f66ec bellard
            if (page0 < page_min)
1457 e89f66ec bellard
                page_min = page0;
1458 e89f66ec bellard
            if (page1 > page_max)
1459 e89f66ec bellard
                page_max = page1;
1460 e89f66ec bellard
            vga_draw_line(s, d, s->vram_ptr + addr, width);
1461 a8aa669b bellard
            if (s->cursor_draw_line)
1462 a8aa669b bellard
                s->cursor_draw_line(s, d, y);
1463 39cf7803 bellard
        } else {
1464 39cf7803 bellard
            if (y_start >= 0) {
1465 39cf7803 bellard
                /* flush to display */
1466 39cf7803 bellard
                dpy_update(s->ds, 0, y_start, 
1467 17b0018b bellard
                           disp_width, y - y_start);
1468 39cf7803 bellard
                y_start = -1;
1469 39cf7803 bellard
            }
1470 e89f66ec bellard
        }
1471 a07cf92a bellard
        if (!multi_run) {
1472 a07cf92a bellard
            if (!double_scan || (y & 1) != 0) {
1473 a07cf92a bellard
                if (y1 == s->line_compare) {
1474 a07cf92a bellard
                    addr1 = 0;
1475 a07cf92a bellard
                } else {
1476 a07cf92a bellard
                    mask = (s->cr[0x17] & 3) ^ 3;
1477 a07cf92a bellard
                    if ((y1 & mask) == mask)
1478 a07cf92a bellard
                        addr1 += line_offset;
1479 a07cf92a bellard
                }
1480 a07cf92a bellard
                y1++;
1481 17b0018b bellard
            }
1482 a07cf92a bellard
            multi_run = multi_scan;
1483 a07cf92a bellard
        } else {
1484 a07cf92a bellard
            multi_run--;
1485 17b0018b bellard
            y1++;
1486 e89f66ec bellard
        }
1487 e89f66ec bellard
        d += linesize;
1488 e89f66ec bellard
    }
1489 39cf7803 bellard
    if (y_start >= 0) {
1490 39cf7803 bellard
        /* flush to display */
1491 39cf7803 bellard
        dpy_update(s->ds, 0, y_start, 
1492 17b0018b bellard
                   disp_width, y - y_start);
1493 39cf7803 bellard
    }
1494 e89f66ec bellard
    /* reset modified pages */
1495 e89f66ec bellard
    if (page_max != -1) {
1496 4fa0f5d2 bellard
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
1497 e89f66ec bellard
    }
1498 a8aa669b bellard
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1499 e89f66ec bellard
}
1500 e89f66ec bellard
1501 2aebb3eb bellard
static void vga_draw_blank(VGAState *s, int full_update)
1502 2aebb3eb bellard
{
1503 2aebb3eb bellard
    int i, w, val;
1504 2aebb3eb bellard
    uint8_t *d;
1505 2aebb3eb bellard
1506 2aebb3eb bellard
    if (!full_update)
1507 2aebb3eb bellard
        return;
1508 2aebb3eb bellard
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1509 2aebb3eb bellard
        return;
1510 2aebb3eb bellard
    if (s->ds->depth == 8) 
1511 2aebb3eb bellard
        val = s->rgb_to_pixel(0, 0, 0);
1512 2aebb3eb bellard
    else
1513 2aebb3eb bellard
        val = 0;
1514 2aebb3eb bellard
    w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
1515 2aebb3eb bellard
    d = s->ds->data;
1516 2aebb3eb bellard
    for(i = 0; i < s->last_scr_height; i++) {
1517 2aebb3eb bellard
        memset(d, val, w);
1518 2aebb3eb bellard
        d += s->ds->linesize;
1519 2aebb3eb bellard
    }
1520 2aebb3eb bellard
    dpy_update(s->ds, 0, 0, 
1521 2aebb3eb bellard
               s->last_scr_width, s->last_scr_height);
1522 2aebb3eb bellard
}
1523 2aebb3eb bellard
1524 2aebb3eb bellard
#define GMODE_TEXT     0
1525 2aebb3eb bellard
#define GMODE_GRAPH    1
1526 2aebb3eb bellard
#define GMODE_BLANK 2 
1527 2aebb3eb bellard
1528 e89f66ec bellard
void vga_update_display(void)
1529 e89f66ec bellard
{
1530 7b17d41e bellard
    VGAState *s = vga_state;
1531 e89f66ec bellard
    int full_update, graphic_mode;
1532 e89f66ec bellard
1533 e89f66ec bellard
    if (s->ds->depth == 0) {
1534 0f35920c bellard
        /* nothing to do */
1535 59a983b9 bellard
    } else {
1536 59a983b9 bellard
        switch(s->ds->depth) {
1537 59a983b9 bellard
        case 8:
1538 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel8_dup;
1539 59a983b9 bellard
            break;
1540 59a983b9 bellard
        case 15:
1541 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel15_dup;
1542 59a983b9 bellard
            break;
1543 59a983b9 bellard
        default:
1544 59a983b9 bellard
        case 16:
1545 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel16_dup;
1546 59a983b9 bellard
            break;
1547 59a983b9 bellard
        case 32:
1548 59a983b9 bellard
            s->rgb_to_pixel = rgb_to_pixel32_dup;
1549 59a983b9 bellard
            break;
1550 59a983b9 bellard
        }
1551 59a983b9 bellard
        
1552 e89f66ec bellard
        full_update = 0;
1553 2aebb3eb bellard
        if (!(s->ar_index & 0x20)) {
1554 2aebb3eb bellard
            graphic_mode = GMODE_BLANK;
1555 2aebb3eb bellard
        } else {
1556 2aebb3eb bellard
            graphic_mode = s->gr[6] & 1;
1557 2aebb3eb bellard
        }
1558 e89f66ec bellard
        if (graphic_mode != s->graphic_mode) {
1559 e89f66ec bellard
            s->graphic_mode = graphic_mode;
1560 e89f66ec bellard
            full_update = 1;
1561 e89f66ec bellard
        }
1562 2aebb3eb bellard
        switch(graphic_mode) {
1563 2aebb3eb bellard
        case GMODE_TEXT:
1564 e89f66ec bellard
            vga_draw_text(s, full_update);
1565 2aebb3eb bellard
            break;
1566 2aebb3eb bellard
        case GMODE_GRAPH:
1567 2aebb3eb bellard
            vga_draw_graphic(s, full_update);
1568 2aebb3eb bellard
            break;
1569 2aebb3eb bellard
        case GMODE_BLANK:
1570 2aebb3eb bellard
        default:
1571 2aebb3eb bellard
            vga_draw_blank(s, full_update);
1572 2aebb3eb bellard
            break;
1573 2aebb3eb bellard
        }
1574 e89f66ec bellard
    }
1575 e89f66ec bellard
}
1576 e89f66ec bellard
1577 a130a41e bellard
/* force a full display refresh */
1578 a130a41e bellard
void vga_invalidate_display(void)
1579 a130a41e bellard
{
1580 a130a41e bellard
    VGAState *s = vga_state;
1581 a130a41e bellard
    
1582 a130a41e bellard
    s->last_width = -1;
1583 a130a41e bellard
    s->last_height = -1;
1584 a130a41e bellard
}
1585 a130a41e bellard
1586 59a983b9 bellard
static void vga_reset(VGAState *s)
1587 e89f66ec bellard
{
1588 e89f66ec bellard
    memset(s, 0, sizeof(VGAState));
1589 a41bc9af bellard
#ifdef CONFIG_S3VGA
1590 e89f66ec bellard
    /* chip ID for 8c968 */
1591 e89f66ec bellard
    s->cr[0x2d] = 0x88;
1592 e89f66ec bellard
    s->cr[0x2e] = 0xb0;
1593 e89f66ec bellard
    s->cr[0x2f] = 0x01; /* XXX: check revision code */
1594 e89f66ec bellard
    s->cr[0x30] = 0xe1;
1595 a41bc9af bellard
#endif
1596 e89f66ec bellard
    s->graphic_mode = -1; /* force full update */
1597 e89f66ec bellard
}
1598 e89f66ec bellard
1599 59a983b9 bellard
static CPUReadMemoryFunc *vga_mem_read[3] = {
1600 e89f66ec bellard
    vga_mem_readb,
1601 e89f66ec bellard
    vga_mem_readw,
1602 e89f66ec bellard
    vga_mem_readl,
1603 e89f66ec bellard
};
1604 e89f66ec bellard
1605 59a983b9 bellard
static CPUWriteMemoryFunc *vga_mem_write[3] = {
1606 e89f66ec bellard
    vga_mem_writeb,
1607 e89f66ec bellard
    vga_mem_writew,
1608 e89f66ec bellard
    vga_mem_writel,
1609 e89f66ec bellard
};
1610 e89f66ec bellard
1611 b0a21b53 bellard
static void vga_save(QEMUFile *f, void *opaque)
1612 b0a21b53 bellard
{
1613 b0a21b53 bellard
    VGAState *s = opaque;
1614 b0a21b53 bellard
    int i;
1615 b0a21b53 bellard
1616 b0a21b53 bellard
    qemu_put_be32s(f, &s->latch);
1617 b0a21b53 bellard
    qemu_put_8s(f, &s->sr_index);
1618 b0a21b53 bellard
    qemu_put_buffer(f, s->sr, 8);
1619 b0a21b53 bellard
    qemu_put_8s(f, &s->gr_index);
1620 b0a21b53 bellard
    qemu_put_buffer(f, s->gr, 16);
1621 b0a21b53 bellard
    qemu_put_8s(f, &s->ar_index);
1622 b0a21b53 bellard
    qemu_put_buffer(f, s->ar, 21);
1623 b0a21b53 bellard
    qemu_put_be32s(f, &s->ar_flip_flop);
1624 b0a21b53 bellard
    qemu_put_8s(f, &s->cr_index);
1625 b0a21b53 bellard
    qemu_put_buffer(f, s->cr, 256);
1626 b0a21b53 bellard
    qemu_put_8s(f, &s->msr);
1627 b0a21b53 bellard
    qemu_put_8s(f, &s->fcr);
1628 b0a21b53 bellard
    qemu_put_8s(f, &s->st00);
1629 b0a21b53 bellard
    qemu_put_8s(f, &s->st01);
1630 b0a21b53 bellard
1631 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_state);
1632 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_sub_index);
1633 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_read_index);
1634 b0a21b53 bellard
    qemu_put_8s(f, &s->dac_write_index);
1635 b0a21b53 bellard
    qemu_put_buffer(f, s->dac_cache, 3);
1636 b0a21b53 bellard
    qemu_put_buffer(f, s->palette, 768);
1637 b0a21b53 bellard
1638 b0a21b53 bellard
    qemu_put_be32s(f, &s->bank_offset);
1639 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
1640 b0a21b53 bellard
    qemu_put_byte(f, 1);
1641 b0a21b53 bellard
    qemu_put_be16s(f, &s->vbe_index);
1642 b0a21b53 bellard
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1643 b0a21b53 bellard
        qemu_put_be16s(f, &s->vbe_regs[i]);
1644 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_start_addr);
1645 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_line_offset);
1646 b0a21b53 bellard
    qemu_put_be32s(f, &s->vbe_bank_mask);
1647 b0a21b53 bellard
#else
1648 b0a21b53 bellard
    qemu_put_byte(f, 0);
1649 b0a21b53 bellard
#endif
1650 b0a21b53 bellard
}
1651 b0a21b53 bellard
1652 b0a21b53 bellard
static int vga_load(QEMUFile *f, void *opaque, int version_id)
1653 b0a21b53 bellard
{
1654 b0a21b53 bellard
    VGAState *s = opaque;
1655 b0a21b53 bellard
    int is_vbe, i;
1656 b0a21b53 bellard
1657 b0a21b53 bellard
    if (version_id != 1)
1658 b0a21b53 bellard
        return -EINVAL;
1659 b0a21b53 bellard
1660 b0a21b53 bellard
    qemu_get_be32s(f, &s->latch);
1661 b0a21b53 bellard
    qemu_get_8s(f, &s->sr_index);
1662 b0a21b53 bellard
    qemu_get_buffer(f, s->sr, 8);
1663 b0a21b53 bellard
    qemu_get_8s(f, &s->gr_index);
1664 b0a21b53 bellard
    qemu_get_buffer(f, s->gr, 16);
1665 b0a21b53 bellard
    qemu_get_8s(f, &s->ar_index);
1666 b0a21b53 bellard
    qemu_get_buffer(f, s->ar, 21);
1667 b0a21b53 bellard
    qemu_get_be32s(f, &s->ar_flip_flop);
1668 b0a21b53 bellard
    qemu_get_8s(f, &s->cr_index);
1669 b0a21b53 bellard
    qemu_get_buffer(f, s->cr, 256);
1670 b0a21b53 bellard
    qemu_get_8s(f, &s->msr);
1671 b0a21b53 bellard
    qemu_get_8s(f, &s->fcr);
1672 b0a21b53 bellard
    qemu_get_8s(f, &s->st00);
1673 b0a21b53 bellard
    qemu_get_8s(f, &s->st01);
1674 b0a21b53 bellard
1675 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_state);
1676 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_sub_index);
1677 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_read_index);
1678 b0a21b53 bellard
    qemu_get_8s(f, &s->dac_write_index);
1679 b0a21b53 bellard
    qemu_get_buffer(f, s->dac_cache, 3);
1680 b0a21b53 bellard
    qemu_get_buffer(f, s->palette, 768);
1681 b0a21b53 bellard
1682 b0a21b53 bellard
    qemu_get_be32s(f, &s->bank_offset);
1683 b0a21b53 bellard
    is_vbe = qemu_get_byte(f);
1684 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
1685 b0a21b53 bellard
    if (!is_vbe)
1686 b0a21b53 bellard
        return -EINVAL;
1687 b0a21b53 bellard
    qemu_get_be16s(f, &s->vbe_index);
1688 b0a21b53 bellard
    for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
1689 b0a21b53 bellard
        qemu_get_be16s(f, &s->vbe_regs[i]);
1690 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_start_addr);
1691 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_line_offset);
1692 b0a21b53 bellard
    qemu_get_be32s(f, &s->vbe_bank_mask);
1693 b0a21b53 bellard
#else
1694 b0a21b53 bellard
    if (is_vbe)
1695 b0a21b53 bellard
        return -EINVAL;
1696 b0a21b53 bellard
#endif
1697 b0a21b53 bellard
1698 b0a21b53 bellard
    /* force refresh */
1699 b0a21b53 bellard
    s->graphic_mode = -1;
1700 b0a21b53 bellard
    return 0;
1701 b0a21b53 bellard
}
1702 b0a21b53 bellard
1703 1078f663 bellard
static void vga_map(PCIDevice *pci_dev, int region_num, 
1704 1078f663 bellard
                    uint32_t addr, uint32_t size, int type)
1705 1078f663 bellard
{
1706 7b17d41e bellard
    VGAState *s = vga_state;
1707 1078f663 bellard
1708 1078f663 bellard
    cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
1709 1078f663 bellard
}
1710 1078f663 bellard
1711 798b0c25 bellard
void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, 
1712 798b0c25 bellard
                     unsigned long vga_ram_offset, int vga_ram_size)
1713 e89f66ec bellard
{
1714 17b0018b bellard
    int i, j, v, b;
1715 e89f66ec bellard
1716 e89f66ec bellard
    for(i = 0;i < 256; i++) {
1717 e89f66ec bellard
        v = 0;
1718 e89f66ec bellard
        for(j = 0; j < 8; j++) {
1719 e89f66ec bellard
            v |= ((i >> j) & 1) << (j * 4);
1720 e89f66ec bellard
        }
1721 e89f66ec bellard
        expand4[i] = v;
1722 e89f66ec bellard
1723 e89f66ec bellard
        v = 0;
1724 e89f66ec bellard
        for(j = 0; j < 4; j++) {
1725 e89f66ec bellard
            v |= ((i >> (2 * j)) & 3) << (j * 4);
1726 e89f66ec bellard
        }
1727 e89f66ec bellard
        expand2[i] = v;
1728 e89f66ec bellard
    }
1729 17b0018b bellard
    for(i = 0; i < 16; i++) {
1730 17b0018b bellard
        v = 0;
1731 17b0018b bellard
        for(j = 0; j < 4; j++) {
1732 17b0018b bellard
            b = ((i >> j) & 1);
1733 17b0018b bellard
            v |= b << (2 * j);
1734 17b0018b bellard
            v |= b << (2 * j + 1);
1735 17b0018b bellard
        }
1736 17b0018b bellard
        expand4to8[i] = v;
1737 17b0018b bellard
    }
1738 e89f66ec bellard
1739 e89f66ec bellard
    vga_reset(s);
1740 e89f66ec bellard
1741 e89f66ec bellard
    s->vram_ptr = vga_ram_base;
1742 e89f66ec bellard
    s->vram_offset = vga_ram_offset;
1743 e89f66ec bellard
    s->vram_size = vga_ram_size;
1744 e89f66ec bellard
    s->ds = ds;
1745 798b0c25 bellard
    s->get_bpp = vga_get_bpp;
1746 798b0c25 bellard
    s->get_offsets = vga_get_offsets;
1747 a130a41e bellard
    s->get_resolution = vga_get_resolution;
1748 7b17d41e bellard
    /* XXX: currently needed for display */
1749 7b17d41e bellard
    vga_state = s;
1750 798b0c25 bellard
}
1751 798b0c25 bellard
1752 798b0c25 bellard
1753 46e50e9d bellard
int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, 
1754 46e50e9d bellard
                   unsigned long vga_ram_offset, int vga_ram_size)
1755 798b0c25 bellard
{
1756 7b17d41e bellard
    VGAState *s;
1757 7b17d41e bellard
1758 7b17d41e bellard
    s = qemu_mallocz(sizeof(VGAState));
1759 7b17d41e bellard
    if (!s)
1760 7b17d41e bellard
        return -1;
1761 798b0c25 bellard
1762 798b0c25 bellard
    vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
1763 e89f66ec bellard
1764 b0a21b53 bellard
    register_savevm("vga", 0, 1, vga_save, vga_load, s);
1765 b0a21b53 bellard
1766 0f35920c bellard
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
1767 e89f66ec bellard
1768 0f35920c bellard
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
1769 0f35920c bellard
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
1770 0f35920c bellard
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
1771 0f35920c bellard
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
1772 e89f66ec bellard
1773 0f35920c bellard
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
1774 e89f66ec bellard
1775 0f35920c bellard
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
1776 0f35920c bellard
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
1777 0f35920c bellard
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
1778 0f35920c bellard
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
1779 26aa7d72 bellard
    s->bank_offset = 0;
1780 e89f66ec bellard
1781 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1782 4fa0f5d2 bellard
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
1783 cae61cef bellard
    s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
1784 09a79b49 bellard
#if defined (TARGET_I386)
1785 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1786 09a79b49 bellard
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
1787 4fa0f5d2 bellard
1788 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1789 09a79b49 bellard
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
1790 646be93b bellard
1791 646be93b bellard
    /* old Bochs IO ports */
1792 09a79b49 bellard
    register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
1793 09a79b49 bellard
    register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
1794 646be93b bellard
1795 09a79b49 bellard
    register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
1796 09a79b49 bellard
    register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); 
1797 09a79b49 bellard
#else
1798 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
1799 09a79b49 bellard
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
1800 09a79b49 bellard
1801 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
1802 09a79b49 bellard
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
1803 4fa0f5d2 bellard
#endif
1804 09a79b49 bellard
#endif /* CONFIG_BOCHS_VBE */
1805 4fa0f5d2 bellard
1806 a4193c8a bellard
    vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
1807 26aa7d72 bellard
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, 
1808 26aa7d72 bellard
                                 vga_io_memory);
1809 1078f663 bellard
1810 46e50e9d bellard
    if (bus) {
1811 1078f663 bellard
        PCIDevice *d;
1812 1078f663 bellard
        uint8_t *pci_conf;
1813 1078f663 bellard
1814 46e50e9d bellard
        d = pci_register_device(bus, "VGA", 
1815 1078f663 bellard
                                sizeof(PCIDevice),
1816 46e50e9d bellard
                                -1, NULL, NULL);
1817 1078f663 bellard
        pci_conf = d->config;
1818 1078f663 bellard
        pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
1819 1078f663 bellard
        pci_conf[0x01] = 0x12;
1820 1078f663 bellard
        pci_conf[0x02] = 0x11;
1821 1078f663 bellard
        pci_conf[0x03] = 0x11;
1822 1078f663 bellard
        pci_conf[0x0a] = 0x00; // VGA controller 
1823 1078f663 bellard
        pci_conf[0x0b] = 0x03;
1824 1078f663 bellard
        pci_conf[0x0e] = 0x00; // header_type
1825 1078f663 bellard
1826 1078f663 bellard
        /* XXX: vga_ram_size must be a power of two */
1827 1078f663 bellard
        pci_register_io_region(d, 0, vga_ram_size, 
1828 1078f663 bellard
                               PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
1829 1078f663 bellard
    } else {
1830 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1831 1078f663 bellard
        /* XXX: use optimized standard vga accesses */
1832 1078f663 bellard
        cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, 
1833 1078f663 bellard
                                     vga_ram_size, vga_ram_offset);
1834 4fa0f5d2 bellard
#endif
1835 1078f663 bellard
    }
1836 e89f66ec bellard
    return 0;
1837 e89f66ec bellard
}
1838 59a983b9 bellard
1839 59a983b9 bellard
/********************************************************/
1840 59a983b9 bellard
/* vga screen dump */
1841 59a983b9 bellard
1842 59a983b9 bellard
static int vga_save_w, vga_save_h;
1843 59a983b9 bellard
1844 59a983b9 bellard
static void vga_save_dpy_update(DisplayState *s, 
1845 59a983b9 bellard
                                int x, int y, int w, int h)
1846 59a983b9 bellard
{
1847 59a983b9 bellard
}
1848 59a983b9 bellard
1849 59a983b9 bellard
static void vga_save_dpy_resize(DisplayState *s, int w, int h)
1850 59a983b9 bellard
{
1851 59a983b9 bellard
    s->linesize = w * 4;
1852 59a983b9 bellard
    s->data = qemu_malloc(h * s->linesize);
1853 59a983b9 bellard
    vga_save_w = w;
1854 59a983b9 bellard
    vga_save_h = h;
1855 59a983b9 bellard
}
1856 59a983b9 bellard
1857 59a983b9 bellard
static void vga_save_dpy_refresh(DisplayState *s)
1858 59a983b9 bellard
{
1859 59a983b9 bellard
}
1860 59a983b9 bellard
1861 59a983b9 bellard
static int ppm_save(const char *filename, uint8_t *data, 
1862 59a983b9 bellard
                    int w, int h, int linesize)
1863 59a983b9 bellard
{
1864 59a983b9 bellard
    FILE *f;
1865 59a983b9 bellard
    uint8_t *d, *d1;
1866 59a983b9 bellard
    unsigned int v;
1867 59a983b9 bellard
    int y, x;
1868 59a983b9 bellard
1869 59a983b9 bellard
    f = fopen(filename, "wb");
1870 59a983b9 bellard
    if (!f)
1871 59a983b9 bellard
        return -1;
1872 59a983b9 bellard
    fprintf(f, "P6\n%d %d\n%d\n",
1873 59a983b9 bellard
            w, h, 255);
1874 59a983b9 bellard
    d1 = data;
1875 59a983b9 bellard
    for(y = 0; y < h; y++) {
1876 59a983b9 bellard
        d = d1;
1877 59a983b9 bellard
        for(x = 0; x < w; x++) {
1878 59a983b9 bellard
            v = *(uint32_t *)d;
1879 59a983b9 bellard
            fputc((v >> 16) & 0xff, f);
1880 59a983b9 bellard
            fputc((v >> 8) & 0xff, f);
1881 59a983b9 bellard
            fputc((v) & 0xff, f);
1882 59a983b9 bellard
            d += 4;
1883 59a983b9 bellard
        }
1884 59a983b9 bellard
        d1 += linesize;
1885 59a983b9 bellard
    }
1886 59a983b9 bellard
    fclose(f);
1887 59a983b9 bellard
    return 0;
1888 59a983b9 bellard
}
1889 59a983b9 bellard
1890 59a983b9 bellard
/* save the vga display in a PPM image even if no display is
1891 59a983b9 bellard
   available */
1892 59a983b9 bellard
void vga_screen_dump(const char *filename)
1893 59a983b9 bellard
{
1894 7b17d41e bellard
    VGAState *s = vga_state;
1895 59a983b9 bellard
    DisplayState *saved_ds, ds1, *ds = &ds1;
1896 59a983b9 bellard
    
1897 59a983b9 bellard
    /* XXX: this is a little hackish */
1898 a130a41e bellard
    vga_invalidate_display();
1899 59a983b9 bellard
    saved_ds = s->ds;
1900 59a983b9 bellard
1901 59a983b9 bellard
    memset(ds, 0, sizeof(DisplayState));
1902 59a983b9 bellard
    ds->dpy_update = vga_save_dpy_update;
1903 59a983b9 bellard
    ds->dpy_resize = vga_save_dpy_resize;
1904 59a983b9 bellard
    ds->dpy_refresh = vga_save_dpy_refresh;
1905 59a983b9 bellard
    ds->depth = 32;
1906 59a983b9 bellard
1907 59a983b9 bellard
    s->ds = ds;
1908 59a983b9 bellard
    s->graphic_mode = -1;
1909 59a983b9 bellard
    vga_update_display();
1910 59a983b9 bellard
    
1911 59a983b9 bellard
    if (ds->data) {
1912 59a983b9 bellard
        ppm_save(filename, ds->data, vga_save_w, vga_save_h, 
1913 59a983b9 bellard
                 s->ds->linesize);
1914 59a983b9 bellard
        qemu_free(ds->data);
1915 59a983b9 bellard
    }
1916 59a983b9 bellard
    s->ds = saved_ds;
1917 59a983b9 bellard
}