Statistics
| Branch: | Revision:

root / hw / vga.c @ 4721c457

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