Statistics
| Branch: | Revision:

root / hw / vga.c @ 95219897

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