Statistics
| Branch: | Revision:

root / hw / vga.c @ 78895427

History | View | Annotate | Download (68.4 kB)

1 e89f66ec bellard
/*
2 4fa0f5d2 bellard
 * QEMU VGA Emulator.
3 5fafdf24 ths
 *
4 e89f66ec bellard
 * Copyright (c) 2003 Fabrice Bellard
5 5fafdf24 ths
 *
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 87ecb68b pbrook
#include "hw.h"
25 87ecb68b pbrook
#include "console.h"
26 87ecb68b pbrook
#include "pc.h"
27 87ecb68b pbrook
#include "pci.h"
28 798b0c25 bellard
#include "vga_int.h"
29 94470844 blueswir1
#include "pixel_ops.h"
30 cb5a7aa8 malc
#include "qemu-timer.h"
31 50af3246 Juan Quintela
#include "kvm.h"
32 e89f66ec bellard
33 e89f66ec bellard
//#define DEBUG_VGA
34 17b0018b bellard
//#define DEBUG_VGA_MEM
35 a41bc9af bellard
//#define DEBUG_VGA_REG
36 a41bc9af bellard
37 4fa0f5d2 bellard
//#define DEBUG_BOCHS_VBE
38 4fa0f5d2 bellard
39 e89f66ec bellard
/* force some bits to zero */
40 798b0c25 bellard
const uint8_t sr_mask[8] = {
41 9e622b15 blueswir1
    0x03,
42 9e622b15 blueswir1
    0x3d,
43 9e622b15 blueswir1
    0x0f,
44 9e622b15 blueswir1
    0x3f,
45 9e622b15 blueswir1
    0x0e,
46 9e622b15 blueswir1
    0x00,
47 9e622b15 blueswir1
    0x00,
48 9e622b15 blueswir1
    0xff,
49 e89f66ec bellard
};
50 e89f66ec bellard
51 798b0c25 bellard
const uint8_t gr_mask[16] = {
52 9e622b15 blueswir1
    0x0f, /* 0x00 */
53 9e622b15 blueswir1
    0x0f, /* 0x01 */
54 9e622b15 blueswir1
    0x0f, /* 0x02 */
55 9e622b15 blueswir1
    0x1f, /* 0x03 */
56 9e622b15 blueswir1
    0x03, /* 0x04 */
57 9e622b15 blueswir1
    0x7b, /* 0x05 */
58 9e622b15 blueswir1
    0x0f, /* 0x06 */
59 9e622b15 blueswir1
    0x0f, /* 0x07 */
60 9e622b15 blueswir1
    0xff, /* 0x08 */
61 9e622b15 blueswir1
    0x00, /* 0x09 */
62 9e622b15 blueswir1
    0x00, /* 0x0a */
63 9e622b15 blueswir1
    0x00, /* 0x0b */
64 9e622b15 blueswir1
    0x00, /* 0x0c */
65 9e622b15 blueswir1
    0x00, /* 0x0d */
66 9e622b15 blueswir1
    0x00, /* 0x0e */
67 9e622b15 blueswir1
    0x00, /* 0x0f */
68 e89f66ec bellard
};
69 e89f66ec bellard
70 e89f66ec bellard
#define cbswap_32(__x) \
71 e89f66ec bellard
((uint32_t)( \
72 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
73 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
74 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
75 e89f66ec bellard
                (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
76 e89f66ec bellard
77 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
78 e89f66ec bellard
#define PAT(x) cbswap_32(x)
79 e89f66ec bellard
#else
80 e89f66ec bellard
#define PAT(x) (x)
81 e89f66ec bellard
#endif
82 e89f66ec bellard
83 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
84 b8ed223b bellard
#define BIG 1
85 b8ed223b bellard
#else
86 b8ed223b bellard
#define BIG 0
87 b8ed223b bellard
#endif
88 b8ed223b bellard
89 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
90 b8ed223b bellard
#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
91 b8ed223b bellard
#else
92 b8ed223b bellard
#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
93 b8ed223b bellard
#endif
94 b8ed223b bellard
95 e89f66ec bellard
static const uint32_t mask16[16] = {
96 e89f66ec bellard
    PAT(0x00000000),
97 e89f66ec bellard
    PAT(0x000000ff),
98 e89f66ec bellard
    PAT(0x0000ff00),
99 e89f66ec bellard
    PAT(0x0000ffff),
100 e89f66ec bellard
    PAT(0x00ff0000),
101 e89f66ec bellard
    PAT(0x00ff00ff),
102 e89f66ec bellard
    PAT(0x00ffff00),
103 e89f66ec bellard
    PAT(0x00ffffff),
104 e89f66ec bellard
    PAT(0xff000000),
105 e89f66ec bellard
    PAT(0xff0000ff),
106 e89f66ec bellard
    PAT(0xff00ff00),
107 e89f66ec bellard
    PAT(0xff00ffff),
108 e89f66ec bellard
    PAT(0xffff0000),
109 e89f66ec bellard
    PAT(0xffff00ff),
110 e89f66ec bellard
    PAT(0xffffff00),
111 e89f66ec bellard
    PAT(0xffffffff),
112 e89f66ec bellard
};
113 e89f66ec bellard
114 e89f66ec bellard
#undef PAT
115 e89f66ec bellard
116 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
117 e89f66ec bellard
#define PAT(x) (x)
118 e89f66ec bellard
#else
119 e89f66ec bellard
#define PAT(x) cbswap_32(x)
120 e89f66ec bellard
#endif
121 e89f66ec bellard
122 e89f66ec bellard
static const uint32_t dmask16[16] = {
123 e89f66ec bellard
    PAT(0x00000000),
124 e89f66ec bellard
    PAT(0x000000ff),
125 e89f66ec bellard
    PAT(0x0000ff00),
126 e89f66ec bellard
    PAT(0x0000ffff),
127 e89f66ec bellard
    PAT(0x00ff0000),
128 e89f66ec bellard
    PAT(0x00ff00ff),
129 e89f66ec bellard
    PAT(0x00ffff00),
130 e89f66ec bellard
    PAT(0x00ffffff),
131 e89f66ec bellard
    PAT(0xff000000),
132 e89f66ec bellard
    PAT(0xff0000ff),
133 e89f66ec bellard
    PAT(0xff00ff00),
134 e89f66ec bellard
    PAT(0xff00ffff),
135 e89f66ec bellard
    PAT(0xffff0000),
136 e89f66ec bellard
    PAT(0xffff00ff),
137 e89f66ec bellard
    PAT(0xffffff00),
138 e89f66ec bellard
    PAT(0xffffffff),
139 e89f66ec bellard
};
140 e89f66ec bellard
141 e89f66ec bellard
static const uint32_t dmask4[4] = {
142 e89f66ec bellard
    PAT(0x00000000),
143 e89f66ec bellard
    PAT(0x0000ffff),
144 e89f66ec bellard
    PAT(0xffff0000),
145 e89f66ec bellard
    PAT(0xffffffff),
146 e89f66ec bellard
};
147 e89f66ec bellard
148 e89f66ec bellard
static uint32_t expand4[256];
149 e89f66ec bellard
static uint16_t expand2[256];
150 17b0018b bellard
static uint8_t expand4to8[16];
151 e89f66ec bellard
152 95219897 pbrook
static void vga_screen_dump(void *opaque, const char *filename);
153 04a52b41 Stefano Stabellini
static char *screen_dump_filename;
154 04a52b41 Stefano Stabellini
static DisplayChangeListener *screen_dump_dcl;
155 95219897 pbrook
156 cedd91d2 Juan Quintela
static void vga_dumb_update_retrace_info(VGACommonState *s)
157 cb5a7aa8 malc
{
158 cb5a7aa8 malc
    (void) s;
159 cb5a7aa8 malc
}
160 cb5a7aa8 malc
161 cedd91d2 Juan Quintela
static void vga_precise_update_retrace_info(VGACommonState *s)
162 cb5a7aa8 malc
{
163 cb5a7aa8 malc
    int htotal_chars;
164 cb5a7aa8 malc
    int hretr_start_char;
165 cb5a7aa8 malc
    int hretr_skew_chars;
166 cb5a7aa8 malc
    int hretr_end_char;
167 cb5a7aa8 malc
168 cb5a7aa8 malc
    int vtotal_lines;
169 cb5a7aa8 malc
    int vretr_start_line;
170 cb5a7aa8 malc
    int vretr_end_line;
171 cb5a7aa8 malc
172 7f5b7d3e Blue Swirl
    int dots;
173 7f5b7d3e Blue Swirl
#if 0
174 7f5b7d3e Blue Swirl
    int div2, sldiv2;
175 7f5b7d3e Blue Swirl
#endif
176 cb5a7aa8 malc
    int clocking_mode;
177 cb5a7aa8 malc
    int clock_sel;
178 b0f74c87 balrog
    const int clk_hz[] = {25175000, 28322000, 25175000, 25175000};
179 cb5a7aa8 malc
    int64_t chars_per_sec;
180 cb5a7aa8 malc
    struct vga_precise_retrace *r = &s->retrace_info.precise;
181 cb5a7aa8 malc
182 cb5a7aa8 malc
    htotal_chars = s->cr[0x00] + 5;
183 cb5a7aa8 malc
    hretr_start_char = s->cr[0x04];
184 cb5a7aa8 malc
    hretr_skew_chars = (s->cr[0x05] >> 5) & 3;
185 cb5a7aa8 malc
    hretr_end_char = s->cr[0x05] & 0x1f;
186 cb5a7aa8 malc
187 cb5a7aa8 malc
    vtotal_lines = (s->cr[0x06]
188 cb5a7aa8 malc
                    | (((s->cr[0x07] & 1) | ((s->cr[0x07] >> 4) & 2)) << 8)) + 2
189 cb5a7aa8 malc
        ;
190 cb5a7aa8 malc
    vretr_start_line = s->cr[0x10]
191 cb5a7aa8 malc
        | ((((s->cr[0x07] >> 2) & 1) | ((s->cr[0x07] >> 6) & 2)) << 8)
192 cb5a7aa8 malc
        ;
193 cb5a7aa8 malc
    vretr_end_line = s->cr[0x11] & 0xf;
194 cb5a7aa8 malc
195 cb5a7aa8 malc
196 cb5a7aa8 malc
197 cb5a7aa8 malc
    clocking_mode = (s->sr[0x01] >> 3) & 1;
198 cb5a7aa8 malc
    clock_sel = (s->msr >> 2) & 3;
199 f87fc09b malc
    dots = (s->msr & 1) ? 8 : 9;
200 cb5a7aa8 malc
201 b0f74c87 balrog
    chars_per_sec = clk_hz[clock_sel] / dots;
202 cb5a7aa8 malc
203 cb5a7aa8 malc
    htotal_chars <<= clocking_mode;
204 cb5a7aa8 malc
205 cb5a7aa8 malc
    r->total_chars = vtotal_lines * htotal_chars;
206 cb5a7aa8 malc
    if (r->freq) {
207 6ee093c9 Juan Quintela
        r->ticks_per_char = get_ticks_per_sec() / (r->total_chars * r->freq);
208 cb5a7aa8 malc
    } else {
209 6ee093c9 Juan Quintela
        r->ticks_per_char = get_ticks_per_sec() / chars_per_sec;
210 cb5a7aa8 malc
    }
211 cb5a7aa8 malc
212 cb5a7aa8 malc
    r->vstart = vretr_start_line;
213 cb5a7aa8 malc
    r->vend = r->vstart + vretr_end_line + 1;
214 cb5a7aa8 malc
215 cb5a7aa8 malc
    r->hstart = hretr_start_char + hretr_skew_chars;
216 cb5a7aa8 malc
    r->hend = r->hstart + hretr_end_char + 1;
217 cb5a7aa8 malc
    r->htotal = htotal_chars;
218 cb5a7aa8 malc
219 f87fc09b malc
#if 0
220 7f5b7d3e Blue Swirl
    div2 = (s->cr[0x17] >> 2) & 1;
221 7f5b7d3e Blue Swirl
    sldiv2 = (s->cr[0x17] >> 3) & 1;
222 cb5a7aa8 malc
    printf (
223 f87fc09b malc
        "hz=%f\n"
224 cb5a7aa8 malc
        "htotal = %d\n"
225 cb5a7aa8 malc
        "hretr_start = %d\n"
226 cb5a7aa8 malc
        "hretr_skew = %d\n"
227 cb5a7aa8 malc
        "hretr_end = %d\n"
228 cb5a7aa8 malc
        "vtotal = %d\n"
229 cb5a7aa8 malc
        "vretr_start = %d\n"
230 cb5a7aa8 malc
        "vretr_end = %d\n"
231 cb5a7aa8 malc
        "div2 = %d sldiv2 = %d\n"
232 cb5a7aa8 malc
        "clocking_mode = %d\n"
233 cb5a7aa8 malc
        "clock_sel = %d %d\n"
234 cb5a7aa8 malc
        "dots = %d\n"
235 0bfcd599 Blue Swirl
        "ticks/char = %" PRId64 "\n"
236 cb5a7aa8 malc
        "\n",
237 6ee093c9 Juan Quintela
        (double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
238 cb5a7aa8 malc
        htotal_chars,
239 cb5a7aa8 malc
        hretr_start_char,
240 cb5a7aa8 malc
        hretr_skew_chars,
241 cb5a7aa8 malc
        hretr_end_char,
242 cb5a7aa8 malc
        vtotal_lines,
243 cb5a7aa8 malc
        vretr_start_line,
244 cb5a7aa8 malc
        vretr_end_line,
245 cb5a7aa8 malc
        div2, sldiv2,
246 cb5a7aa8 malc
        clocking_mode,
247 cb5a7aa8 malc
        clock_sel,
248 b0f74c87 balrog
        clk_hz[clock_sel],
249 cb5a7aa8 malc
        dots,
250 cb5a7aa8 malc
        r->ticks_per_char
251 cb5a7aa8 malc
        );
252 cb5a7aa8 malc
#endif
253 cb5a7aa8 malc
}
254 cb5a7aa8 malc
255 cedd91d2 Juan Quintela
static uint8_t vga_precise_retrace(VGACommonState *s)
256 cb5a7aa8 malc
{
257 cb5a7aa8 malc
    struct vga_precise_retrace *r = &s->retrace_info.precise;
258 cb5a7aa8 malc
    uint8_t val = s->st01 & ~(ST01_V_RETRACE | ST01_DISP_ENABLE);
259 cb5a7aa8 malc
260 cb5a7aa8 malc
    if (r->total_chars) {
261 cb5a7aa8 malc
        int cur_line, cur_line_char, cur_char;
262 cb5a7aa8 malc
        int64_t cur_tick;
263 cb5a7aa8 malc
264 cb5a7aa8 malc
        cur_tick = qemu_get_clock(vm_clock);
265 cb5a7aa8 malc
266 cb5a7aa8 malc
        cur_char = (cur_tick / r->ticks_per_char) % r->total_chars;
267 cb5a7aa8 malc
        cur_line = cur_char / r->htotal;
268 cb5a7aa8 malc
269 cb5a7aa8 malc
        if (cur_line >= r->vstart && cur_line <= r->vend) {
270 cb5a7aa8 malc
            val |= ST01_V_RETRACE | ST01_DISP_ENABLE;
271 f87fc09b malc
        } else {
272 f87fc09b malc
            cur_line_char = cur_char % r->htotal;
273 f87fc09b malc
            if (cur_line_char >= r->hstart && cur_line_char <= r->hend) {
274 f87fc09b malc
                val |= ST01_DISP_ENABLE;
275 f87fc09b malc
            }
276 cb5a7aa8 malc
        }
277 cb5a7aa8 malc
278 cb5a7aa8 malc
        return val;
279 cb5a7aa8 malc
    } else {
280 cb5a7aa8 malc
        return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
281 cb5a7aa8 malc
    }
282 cb5a7aa8 malc
}
283 cb5a7aa8 malc
284 cedd91d2 Juan Quintela
static uint8_t vga_dumb_retrace(VGACommonState *s)
285 cb5a7aa8 malc
{
286 cb5a7aa8 malc
    return s->st01 ^ (ST01_V_RETRACE | ST01_DISP_ENABLE);
287 cb5a7aa8 malc
}
288 cb5a7aa8 malc
289 25a18cbd Juan Quintela
int vga_ioport_invalid(VGACommonState *s, uint32_t addr)
290 25a18cbd Juan Quintela
{
291 25a18cbd Juan Quintela
    if (s->msr & MSR_COLOR_EMULATION) {
292 25a18cbd Juan Quintela
        /* Color */
293 25a18cbd Juan Quintela
        return (addr >= 0x3b0 && addr <= 0x3bf);
294 25a18cbd Juan Quintela
    } else {
295 25a18cbd Juan Quintela
        /* Monochrome */
296 25a18cbd Juan Quintela
        return (addr >= 0x3d0 && addr <= 0x3df);
297 25a18cbd Juan Quintela
    }
298 25a18cbd Juan Quintela
}
299 25a18cbd Juan Quintela
300 43bf782b Juan Quintela
uint32_t vga_ioport_read(void *opaque, uint32_t addr)
301 e89f66ec bellard
{
302 43bf782b Juan Quintela
    VGACommonState *s = opaque;
303 e89f66ec bellard
    int val, index;
304 e89f66ec bellard
305 25a18cbd Juan Quintela
    if (vga_ioport_invalid(s, addr)) {
306 e89f66ec bellard
        val = 0xff;
307 e89f66ec bellard
    } else {
308 e89f66ec bellard
        switch(addr) {
309 e89f66ec bellard
        case 0x3c0:
310 e89f66ec bellard
            if (s->ar_flip_flop == 0) {
311 e89f66ec bellard
                val = s->ar_index;
312 e89f66ec bellard
            } else {
313 e89f66ec bellard
                val = 0;
314 e89f66ec bellard
            }
315 e89f66ec bellard
            break;
316 e89f66ec bellard
        case 0x3c1:
317 e89f66ec bellard
            index = s->ar_index & 0x1f;
318 5fafdf24 ths
            if (index < 21)
319 e89f66ec bellard
                val = s->ar[index];
320 e89f66ec bellard
            else
321 e89f66ec bellard
                val = 0;
322 e89f66ec bellard
            break;
323 e89f66ec bellard
        case 0x3c2:
324 e89f66ec bellard
            val = s->st00;
325 e89f66ec bellard
            break;
326 e89f66ec bellard
        case 0x3c4:
327 e89f66ec bellard
            val = s->sr_index;
328 e89f66ec bellard
            break;
329 e89f66ec bellard
        case 0x3c5:
330 e89f66ec bellard
            val = s->sr[s->sr_index];
331 a41bc9af bellard
#ifdef DEBUG_VGA_REG
332 a41bc9af bellard
            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
333 a41bc9af bellard
#endif
334 e89f66ec bellard
            break;
335 e89f66ec bellard
        case 0x3c7:
336 e89f66ec bellard
            val = s->dac_state;
337 e89f66ec bellard
            break;
338 e9b43ea3 Juan Quintela
        case 0x3c8:
339 e9b43ea3 Juan Quintela
            val = s->dac_write_index;
340 e9b43ea3 Juan Quintela
            break;
341 e89f66ec bellard
        case 0x3c9:
342 e89f66ec bellard
            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
343 e89f66ec bellard
            if (++s->dac_sub_index == 3) {
344 e89f66ec bellard
                s->dac_sub_index = 0;
345 e89f66ec bellard
                s->dac_read_index++;
346 e89f66ec bellard
            }
347 e89f66ec bellard
            break;
348 e89f66ec bellard
        case 0x3ca:
349 e89f66ec bellard
            val = s->fcr;
350 e89f66ec bellard
            break;
351 e89f66ec bellard
        case 0x3cc:
352 e89f66ec bellard
            val = s->msr;
353 e89f66ec bellard
            break;
354 e89f66ec bellard
        case 0x3ce:
355 e89f66ec bellard
            val = s->gr_index;
356 e89f66ec bellard
            break;
357 e89f66ec bellard
        case 0x3cf:
358 e89f66ec bellard
            val = s->gr[s->gr_index];
359 a41bc9af bellard
#ifdef DEBUG_VGA_REG
360 a41bc9af bellard
            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
361 a41bc9af bellard
#endif
362 e89f66ec bellard
            break;
363 e89f66ec bellard
        case 0x3b4:
364 e89f66ec bellard
        case 0x3d4:
365 e89f66ec bellard
            val = s->cr_index;
366 e89f66ec bellard
            break;
367 e89f66ec bellard
        case 0x3b5:
368 e89f66ec bellard
        case 0x3d5:
369 e89f66ec bellard
            val = s->cr[s->cr_index];
370 a41bc9af bellard
#ifdef DEBUG_VGA_REG
371 a41bc9af bellard
            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
372 a41bc9af bellard
#endif
373 e89f66ec bellard
            break;
374 e89f66ec bellard
        case 0x3ba:
375 e89f66ec bellard
        case 0x3da:
376 e89f66ec bellard
            /* just toggle to fool polling */
377 cb5a7aa8 malc
            val = s->st01 = s->retrace(s);
378 e89f66ec bellard
            s->ar_flip_flop = 0;
379 e89f66ec bellard
            break;
380 e89f66ec bellard
        default:
381 e89f66ec bellard
            val = 0x00;
382 e89f66ec bellard
            break;
383 e89f66ec bellard
        }
384 e89f66ec bellard
    }
385 4fa0f5d2 bellard
#if defined(DEBUG_VGA)
386 e89f66ec bellard
    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
387 e89f66ec bellard
#endif
388 e89f66ec bellard
    return val;
389 e89f66ec bellard
}
390 e89f66ec bellard
391 43bf782b Juan Quintela
void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
392 e89f66ec bellard
{
393 43bf782b Juan Quintela
    VGACommonState *s = opaque;
394 5467a722 bellard
    int index;
395 e89f66ec bellard
396 e89f66ec bellard
    /* check port range access depending on color/monochrome mode */
397 25a18cbd Juan Quintela
    if (vga_ioport_invalid(s, addr)) {
398 e89f66ec bellard
        return;
399 25a18cbd Juan Quintela
    }
400 e89f66ec bellard
#ifdef DEBUG_VGA
401 e89f66ec bellard
    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
402 e89f66ec bellard
#endif
403 e89f66ec bellard
404 e89f66ec bellard
    switch(addr) {
405 e89f66ec bellard
    case 0x3c0:
406 e89f66ec bellard
        if (s->ar_flip_flop == 0) {
407 e89f66ec bellard
            val &= 0x3f;
408 e89f66ec bellard
            s->ar_index = val;
409 e89f66ec bellard
        } else {
410 e89f66ec bellard
            index = s->ar_index & 0x1f;
411 e89f66ec bellard
            switch(index) {
412 e89f66ec bellard
            case 0x00 ... 0x0f:
413 e89f66ec bellard
                s->ar[index] = val & 0x3f;
414 e89f66ec bellard
                break;
415 e89f66ec bellard
            case 0x10:
416 e89f66ec bellard
                s->ar[index] = val & ~0x10;
417 e89f66ec bellard
                break;
418 e89f66ec bellard
            case 0x11:
419 e89f66ec bellard
                s->ar[index] = val;
420 e89f66ec bellard
                break;
421 e89f66ec bellard
            case 0x12:
422 e89f66ec bellard
                s->ar[index] = val & ~0xc0;
423 e89f66ec bellard
                break;
424 e89f66ec bellard
            case 0x13:
425 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
426 e89f66ec bellard
                break;
427 e89f66ec bellard
            case 0x14:
428 e89f66ec bellard
                s->ar[index] = val & ~0xf0;
429 e89f66ec bellard
                break;
430 e89f66ec bellard
            default:
431 e89f66ec bellard
                break;
432 e89f66ec bellard
            }
433 e89f66ec bellard
        }
434 e89f66ec bellard
        s->ar_flip_flop ^= 1;
435 e89f66ec bellard
        break;
436 e89f66ec bellard
    case 0x3c2:
437 e89f66ec bellard
        s->msr = val & ~0x10;
438 cb5a7aa8 malc
        s->update_retrace_info(s);
439 e89f66ec bellard
        break;
440 e89f66ec bellard
    case 0x3c4:
441 e89f66ec bellard
        s->sr_index = val & 7;
442 e89f66ec bellard
        break;
443 e89f66ec bellard
    case 0x3c5:
444 a41bc9af bellard
#ifdef DEBUG_VGA_REG
445 a41bc9af bellard
        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
446 a41bc9af bellard
#endif
447 e89f66ec bellard
        s->sr[s->sr_index] = val & sr_mask[s->sr_index];
448 cb5a7aa8 malc
        if (s->sr_index == 1) s->update_retrace_info(s);
449 e89f66ec bellard
        break;
450 e89f66ec bellard
    case 0x3c7:
451 e89f66ec bellard
        s->dac_read_index = val;
452 e89f66ec bellard
        s->dac_sub_index = 0;
453 e89f66ec bellard
        s->dac_state = 3;
454 e89f66ec bellard
        break;
455 e89f66ec bellard
    case 0x3c8:
456 e89f66ec bellard
        s->dac_write_index = val;
457 e89f66ec bellard
        s->dac_sub_index = 0;
458 e89f66ec bellard
        s->dac_state = 0;
459 e89f66ec bellard
        break;
460 e89f66ec bellard
    case 0x3c9:
461 e89f66ec bellard
        s->dac_cache[s->dac_sub_index] = val;
462 e89f66ec bellard
        if (++s->dac_sub_index == 3) {
463 e89f66ec bellard
            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
464 e89f66ec bellard
            s->dac_sub_index = 0;
465 e89f66ec bellard
            s->dac_write_index++;
466 e89f66ec bellard
        }
467 e89f66ec bellard
        break;
468 e89f66ec bellard
    case 0x3ce:
469 e89f66ec bellard
        s->gr_index = val & 0x0f;
470 e89f66ec bellard
        break;
471 e89f66ec bellard
    case 0x3cf:
472 a41bc9af bellard
#ifdef DEBUG_VGA_REG
473 a41bc9af bellard
        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
474 a41bc9af bellard
#endif
475 e89f66ec bellard
        s->gr[s->gr_index] = val & gr_mask[s->gr_index];
476 e89f66ec bellard
        break;
477 e89f66ec bellard
    case 0x3b4:
478 e89f66ec bellard
    case 0x3d4:
479 e89f66ec bellard
        s->cr_index = val;
480 e89f66ec bellard
        break;
481 e89f66ec bellard
    case 0x3b5:
482 e89f66ec bellard
    case 0x3d5:
483 a41bc9af bellard
#ifdef DEBUG_VGA_REG
484 a41bc9af bellard
        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
485 a41bc9af bellard
#endif
486 e89f66ec bellard
        /* handle CR0-7 protection */
487 f6c958c8 bellard
        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
488 e89f66ec bellard
            /* can always write bit 4 of CR7 */
489 e89f66ec bellard
            if (s->cr_index == 7)
490 e89f66ec bellard
                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
491 e89f66ec bellard
            return;
492 e89f66ec bellard
        }
493 a46007a0 Juan Quintela
        s->cr[s->cr_index] = val;
494 cb5a7aa8 malc
495 cb5a7aa8 malc
        switch(s->cr_index) {
496 cb5a7aa8 malc
        case 0x00:
497 cb5a7aa8 malc
        case 0x04:
498 cb5a7aa8 malc
        case 0x05:
499 cb5a7aa8 malc
        case 0x06:
500 cb5a7aa8 malc
        case 0x07:
501 cb5a7aa8 malc
        case 0x11:
502 cb5a7aa8 malc
        case 0x17:
503 cb5a7aa8 malc
            s->update_retrace_info(s);
504 cb5a7aa8 malc
            break;
505 cb5a7aa8 malc
        }
506 e89f66ec bellard
        break;
507 e89f66ec bellard
    case 0x3ba:
508 e89f66ec bellard
    case 0x3da:
509 e89f66ec bellard
        s->fcr = val & 0x10;
510 e89f66ec bellard
        break;
511 e89f66ec bellard
    }
512 e89f66ec bellard
}
513 e89f66ec bellard
514 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
515 09a79b49 bellard
static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
516 4fa0f5d2 bellard
{
517 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
518 4fa0f5d2 bellard
    uint32_t val;
519 09a79b49 bellard
    val = s->vbe_index;
520 09a79b49 bellard
    return val;
521 09a79b49 bellard
}
522 4fa0f5d2 bellard
523 09a79b49 bellard
static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
524 09a79b49 bellard
{
525 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
526 09a79b49 bellard
    uint32_t val;
527 09a79b49 bellard
528 af92284b Gerd Hoffmann
    if (s->vbe_index < VBE_DISPI_INDEX_NB) {
529 8454df8b bellard
        if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_GETCAPS) {
530 8454df8b bellard
            switch(s->vbe_index) {
531 8454df8b bellard
                /* XXX: do not hardcode ? */
532 8454df8b bellard
            case VBE_DISPI_INDEX_XRES:
533 8454df8b bellard
                val = VBE_DISPI_MAX_XRES;
534 8454df8b bellard
                break;
535 8454df8b bellard
            case VBE_DISPI_INDEX_YRES:
536 8454df8b bellard
                val = VBE_DISPI_MAX_YRES;
537 8454df8b bellard
                break;
538 8454df8b bellard
            case VBE_DISPI_INDEX_BPP:
539 8454df8b bellard
                val = VBE_DISPI_MAX_BPP;
540 8454df8b bellard
                break;
541 8454df8b bellard
            default:
542 5fafdf24 ths
                val = s->vbe_regs[s->vbe_index];
543 8454df8b bellard
                break;
544 8454df8b bellard
            }
545 8454df8b bellard
        } else {
546 5fafdf24 ths
            val = s->vbe_regs[s->vbe_index];
547 8454df8b bellard
        }
548 af92284b Gerd Hoffmann
    } else if (s->vbe_index == VBE_DISPI_INDEX_VIDEO_MEMORY_64K) {
549 af92284b Gerd Hoffmann
        val = s->vram_size / (64 * 1024);
550 8454df8b bellard
    } else {
551 09a79b49 bellard
        val = 0;
552 8454df8b bellard
    }
553 4fa0f5d2 bellard
#ifdef DEBUG_BOCHS_VBE
554 09a79b49 bellard
    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
555 4fa0f5d2 bellard
#endif
556 4fa0f5d2 bellard
    return val;
557 4fa0f5d2 bellard
}
558 4fa0f5d2 bellard
559 09a79b49 bellard
static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
560 09a79b49 bellard
{
561 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
562 09a79b49 bellard
    s->vbe_index = val;
563 09a79b49 bellard
}
564 09a79b49 bellard
565 09a79b49 bellard
static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
566 4fa0f5d2 bellard
{
567 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
568 4fa0f5d2 bellard
569 09a79b49 bellard
    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
570 4fa0f5d2 bellard
#ifdef DEBUG_BOCHS_VBE
571 4fa0f5d2 bellard
        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
572 4fa0f5d2 bellard
#endif
573 4fa0f5d2 bellard
        switch(s->vbe_index) {
574 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_ID:
575 cae61cef bellard
            if (val == VBE_DISPI_ID0 ||
576 cae61cef bellard
                val == VBE_DISPI_ID1 ||
577 37dd208d bellard
                val == VBE_DISPI_ID2 ||
578 37dd208d bellard
                val == VBE_DISPI_ID3 ||
579 37dd208d bellard
                val == VBE_DISPI_ID4) {
580 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
581 cae61cef bellard
            }
582 4fa0f5d2 bellard
            break;
583 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_XRES:
584 cae61cef bellard
            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
585 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
586 cae61cef bellard
            }
587 4fa0f5d2 bellard
            break;
588 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_YRES:
589 cae61cef bellard
            if (val <= VBE_DISPI_MAX_YRES) {
590 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
591 cae61cef bellard
            }
592 4fa0f5d2 bellard
            break;
593 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_BPP:
594 4fa0f5d2 bellard
            if (val == 0)
595 4fa0f5d2 bellard
                val = 8;
596 5fafdf24 ths
            if (val == 4 || val == 8 || val == 15 ||
597 cae61cef bellard
                val == 16 || val == 24 || val == 32) {
598 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
599 cae61cef bellard
            }
600 4fa0f5d2 bellard
            break;
601 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_BANK:
602 42fc925e bellard
            if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
603 42fc925e bellard
              val &= (s->vbe_bank_mask >> 2);
604 42fc925e bellard
            } else {
605 42fc925e bellard
              val &= s->vbe_bank_mask;
606 42fc925e bellard
            }
607 cae61cef bellard
            s->vbe_regs[s->vbe_index] = val;
608 26aa7d72 bellard
            s->bank_offset = (val << 16);
609 4fa0f5d2 bellard
            break;
610 4fa0f5d2 bellard
        case VBE_DISPI_INDEX_ENABLE:
611 8454df8b bellard
            if ((val & VBE_DISPI_ENABLED) &&
612 8454df8b bellard
                !(s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED)) {
613 4fa0f5d2 bellard
                int h, shift_control;
614 4fa0f5d2 bellard
615 5fafdf24 ths
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
616 4fa0f5d2 bellard
                    s->vbe_regs[VBE_DISPI_INDEX_XRES];
617 5fafdf24 ths
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
618 4fa0f5d2 bellard
                    s->vbe_regs[VBE_DISPI_INDEX_YRES];
619 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
620 4fa0f5d2 bellard
                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
621 3b46e624 ths
622 4fa0f5d2 bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
623 4fa0f5d2 bellard
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
624 4fa0f5d2 bellard
                else
625 5fafdf24 ths
                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
626 4fa0f5d2 bellard
                        ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
627 4fa0f5d2 bellard
                s->vbe_start_addr = 0;
628 8454df8b bellard
629 4fa0f5d2 bellard
                /* clear the screen (should be done in BIOS) */
630 4fa0f5d2 bellard
                if (!(val & VBE_DISPI_NOCLEARMEM)) {
631 5fafdf24 ths
                    memset(s->vram_ptr, 0,
632 4fa0f5d2 bellard
                           s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
633 4fa0f5d2 bellard
                }
634 3b46e624 ths
635 cae61cef bellard
                /* we initialize the VGA graphic mode (should be done
636 cae61cef bellard
                   in BIOS) */
637 cae61cef bellard
                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
638 4fa0f5d2 bellard
                s->cr[0x17] |= 3; /* no CGA modes */
639 4fa0f5d2 bellard
                s->cr[0x13] = s->vbe_line_offset >> 3;
640 4fa0f5d2 bellard
                /* width */
641 4fa0f5d2 bellard
                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
642 8454df8b bellard
                /* height (only meaningful if < 1024) */
643 4fa0f5d2 bellard
                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
644 4fa0f5d2 bellard
                s->cr[0x12] = h;
645 5fafdf24 ths
                s->cr[0x07] = (s->cr[0x07] & ~0x42) |
646 4fa0f5d2 bellard
                    ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
647 4fa0f5d2 bellard
                /* line compare to 1023 */
648 4fa0f5d2 bellard
                s->cr[0x18] = 0xff;
649 4fa0f5d2 bellard
                s->cr[0x07] |= 0x10;
650 4fa0f5d2 bellard
                s->cr[0x09] |= 0x40;
651 3b46e624 ths
652 4fa0f5d2 bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
653 4fa0f5d2 bellard
                    shift_control = 0;
654 4fa0f5d2 bellard
                    s->sr[0x01] &= ~8; /* no double line */
655 4fa0f5d2 bellard
                } else {
656 4fa0f5d2 bellard
                    shift_control = 2;
657 646be93b bellard
                    s->sr[4] |= 0x08; /* set chain 4 mode */
658 141253b2 bellard
                    s->sr[2] |= 0x0f; /* activate all planes */
659 4fa0f5d2 bellard
                }
660 4fa0f5d2 bellard
                s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
661 4fa0f5d2 bellard
                s->cr[0x09] &= ~0x9f; /* no double scan */
662 cae61cef bellard
            } else {
663 cae61cef bellard
                /* XXX: the bios should do that */
664 26aa7d72 bellard
                s->bank_offset = 0;
665 cae61cef bellard
            }
666 37dd208d bellard
            s->dac_8bit = (val & VBE_DISPI_8BIT_DAC) > 0;
667 141253b2 bellard
            s->vbe_regs[s->vbe_index] = val;
668 cae61cef bellard
            break;
669 cae61cef bellard
        case VBE_DISPI_INDEX_VIRT_WIDTH:
670 cae61cef bellard
            {
671 cae61cef bellard
                int w, h, line_offset;
672 cae61cef bellard
673 cae61cef bellard
                if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
674 cae61cef bellard
                    return;
675 cae61cef bellard
                w = val;
676 cae61cef bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
677 cae61cef bellard
                    line_offset = w >> 1;
678 cae61cef bellard
                else
679 cae61cef bellard
                    line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
680 cae61cef bellard
                h = s->vram_size / line_offset;
681 cae61cef bellard
                /* XXX: support weird bochs semantics ? */
682 cae61cef bellard
                if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
683 cae61cef bellard
                    return;
684 cae61cef bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
685 cae61cef bellard
                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
686 cae61cef bellard
                s->vbe_line_offset = line_offset;
687 cae61cef bellard
            }
688 cae61cef bellard
            break;
689 cae61cef bellard
        case VBE_DISPI_INDEX_X_OFFSET:
690 cae61cef bellard
        case VBE_DISPI_INDEX_Y_OFFSET:
691 cae61cef bellard
            {
692 cae61cef bellard
                int x;
693 cae61cef bellard
                s->vbe_regs[s->vbe_index] = val;
694 cae61cef bellard
                s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
695 cae61cef bellard
                x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
696 cae61cef bellard
                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
697 cae61cef bellard
                    s->vbe_start_addr += x >> 1;
698 cae61cef bellard
                else
699 cae61cef bellard
                    s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
700 cae61cef bellard
                s->vbe_start_addr >>= 2;
701 4fa0f5d2 bellard
            }
702 4fa0f5d2 bellard
            break;
703 4fa0f5d2 bellard
        default:
704 4fa0f5d2 bellard
            break;
705 4fa0f5d2 bellard
        }
706 4fa0f5d2 bellard
    }
707 4fa0f5d2 bellard
}
708 4fa0f5d2 bellard
#endif
709 4fa0f5d2 bellard
710 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
711 c227f099 Anthony Liguori
uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
712 e89f66ec bellard
{
713 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
714 e89f66ec bellard
    int memory_map_mode, plane;
715 e89f66ec bellard
    uint32_t ret;
716 3b46e624 ths
717 e89f66ec bellard
    /* convert to VGA memory offset */
718 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
719 26aa7d72 bellard
    addr &= 0x1ffff;
720 e89f66ec bellard
    switch(memory_map_mode) {
721 e89f66ec bellard
    case 0:
722 e89f66ec bellard
        break;
723 e89f66ec bellard
    case 1:
724 26aa7d72 bellard
        if (addr >= 0x10000)
725 e89f66ec bellard
            return 0xff;
726 cae61cef bellard
        addr += s->bank_offset;
727 e89f66ec bellard
        break;
728 e89f66ec bellard
    case 2:
729 26aa7d72 bellard
        addr -= 0x10000;
730 e89f66ec bellard
        if (addr >= 0x8000)
731 e89f66ec bellard
            return 0xff;
732 e89f66ec bellard
        break;
733 e89f66ec bellard
    default:
734 e89f66ec bellard
    case 3:
735 26aa7d72 bellard
        addr -= 0x18000;
736 c92b2e84 bellard
        if (addr >= 0x8000)
737 c92b2e84 bellard
            return 0xff;
738 e89f66ec bellard
        break;
739 e89f66ec bellard
    }
740 3b46e624 ths
741 e89f66ec bellard
    if (s->sr[4] & 0x08) {
742 e89f66ec bellard
        /* chain 4 mode : simplest access */
743 e89f66ec bellard
        ret = s->vram_ptr[addr];
744 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
745 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
746 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
747 e89f66ec bellard
        ret = s->vram_ptr[((addr & ~1) << 1) | plane];
748 e89f66ec bellard
    } else {
749 e89f66ec bellard
        /* standard VGA latched access */
750 e89f66ec bellard
        s->latch = ((uint32_t *)s->vram_ptr)[addr];
751 e89f66ec bellard
752 e89f66ec bellard
        if (!(s->gr[5] & 0x08)) {
753 e89f66ec bellard
            /* read mode 0 */
754 e89f66ec bellard
            plane = s->gr[4];
755 b8ed223b bellard
            ret = GET_PLANE(s->latch, plane);
756 e89f66ec bellard
        } else {
757 e89f66ec bellard
            /* read mode 1 */
758 e89f66ec bellard
            ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
759 e89f66ec bellard
            ret |= ret >> 16;
760 e89f66ec bellard
            ret |= ret >> 8;
761 e89f66ec bellard
            ret = (~ret) & 0xff;
762 e89f66ec bellard
        }
763 e89f66ec bellard
    }
764 e89f66ec bellard
    return ret;
765 e89f66ec bellard
}
766 e89f66ec bellard
767 c227f099 Anthony Liguori
static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
768 e89f66ec bellard
{
769 e89f66ec bellard
    uint32_t v;
770 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
771 a4193c8a bellard
    v = vga_mem_readb(opaque, addr) << 8;
772 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1);
773 09a79b49 bellard
#else
774 a4193c8a bellard
    v = vga_mem_readb(opaque, addr);
775 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 8;
776 09a79b49 bellard
#endif
777 e89f66ec bellard
    return v;
778 e89f66ec bellard
}
779 e89f66ec bellard
780 c227f099 Anthony Liguori
static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
781 e89f66ec bellard
{
782 e89f66ec bellard
    uint32_t v;
783 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
784 a4193c8a bellard
    v = vga_mem_readb(opaque, addr) << 24;
785 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 16;
786 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 2) << 8;
787 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 3);
788 09a79b49 bellard
#else
789 a4193c8a bellard
    v = vga_mem_readb(opaque, addr);
790 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 1) << 8;
791 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 2) << 16;
792 a4193c8a bellard
    v |= vga_mem_readb(opaque, addr + 3) << 24;
793 09a79b49 bellard
#endif
794 e89f66ec bellard
    return v;
795 e89f66ec bellard
}
796 e89f66ec bellard
797 e89f66ec bellard
/* called for accesses between 0xa0000 and 0xc0000 */
798 c227f099 Anthony Liguori
void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
799 e89f66ec bellard
{
800 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
801 546fa6ab bellard
    int memory_map_mode, plane, write_mode, b, func_select, mask;
802 e89f66ec bellard
    uint32_t write_mask, bit_mask, set_mask;
803 e89f66ec bellard
804 17b0018b bellard
#ifdef DEBUG_VGA_MEM
805 0bf9e31a Blue Swirl
    printf("vga: [0x" TARGET_FMT_plx "] = 0x%02x\n", addr, val);
806 e89f66ec bellard
#endif
807 e89f66ec bellard
    /* convert to VGA memory offset */
808 e89f66ec bellard
    memory_map_mode = (s->gr[6] >> 2) & 3;
809 26aa7d72 bellard
    addr &= 0x1ffff;
810 e89f66ec bellard
    switch(memory_map_mode) {
811 e89f66ec bellard
    case 0:
812 e89f66ec bellard
        break;
813 e89f66ec bellard
    case 1:
814 26aa7d72 bellard
        if (addr >= 0x10000)
815 e89f66ec bellard
            return;
816 cae61cef bellard
        addr += s->bank_offset;
817 e89f66ec bellard
        break;
818 e89f66ec bellard
    case 2:
819 26aa7d72 bellard
        addr -= 0x10000;
820 e89f66ec bellard
        if (addr >= 0x8000)
821 e89f66ec bellard
            return;
822 e89f66ec bellard
        break;
823 e89f66ec bellard
    default:
824 e89f66ec bellard
    case 3:
825 26aa7d72 bellard
        addr -= 0x18000;
826 c92b2e84 bellard
        if (addr >= 0x8000)
827 c92b2e84 bellard
            return;
828 e89f66ec bellard
        break;
829 e89f66ec bellard
    }
830 3b46e624 ths
831 e89f66ec bellard
    if (s->sr[4] & 0x08) {
832 e89f66ec bellard
        /* chain 4 mode : simplest access */
833 e89f66ec bellard
        plane = addr & 3;
834 546fa6ab bellard
        mask = (1 << plane);
835 546fa6ab bellard
        if (s->sr[2] & mask) {
836 e89f66ec bellard
            s->vram_ptr[addr] = val;
837 17b0018b bellard
#ifdef DEBUG_VGA_MEM
838 0bf9e31a Blue Swirl
            printf("vga: chain4: [0x" TARGET_FMT_plx "]\n", addr);
839 e89f66ec bellard
#endif
840 546fa6ab bellard
            s->plane_updated |= mask; /* only used to detect font change */
841 4fa0f5d2 bellard
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
842 e89f66ec bellard
        }
843 e89f66ec bellard
    } else if (s->gr[5] & 0x10) {
844 e89f66ec bellard
        /* odd/even mode (aka text mode mapping) */
845 e89f66ec bellard
        plane = (s->gr[4] & 2) | (addr & 1);
846 546fa6ab bellard
        mask = (1 << plane);
847 546fa6ab bellard
        if (s->sr[2] & mask) {
848 e89f66ec bellard
            addr = ((addr & ~1) << 1) | plane;
849 e89f66ec bellard
            s->vram_ptr[addr] = val;
850 17b0018b bellard
#ifdef DEBUG_VGA_MEM
851 0bf9e31a Blue Swirl
            printf("vga: odd/even: [0x" TARGET_FMT_plx "]\n", addr);
852 e89f66ec bellard
#endif
853 546fa6ab bellard
            s->plane_updated |= mask; /* only used to detect font change */
854 4fa0f5d2 bellard
            cpu_physical_memory_set_dirty(s->vram_offset + addr);
855 e89f66ec bellard
        }
856 e89f66ec bellard
    } else {
857 e89f66ec bellard
        /* standard VGA latched access */
858 e89f66ec bellard
        write_mode = s->gr[5] & 3;
859 e89f66ec bellard
        switch(write_mode) {
860 e89f66ec bellard
        default:
861 e89f66ec bellard
        case 0:
862 e89f66ec bellard
            /* rotate */
863 e89f66ec bellard
            b = s->gr[3] & 7;
864 e89f66ec bellard
            val = ((val >> b) | (val << (8 - b))) & 0xff;
865 e89f66ec bellard
            val |= val << 8;
866 e89f66ec bellard
            val |= val << 16;
867 e89f66ec bellard
868 e89f66ec bellard
            /* apply set/reset mask */
869 e89f66ec bellard
            set_mask = mask16[s->gr[1]];
870 e89f66ec bellard
            val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
871 e89f66ec bellard
            bit_mask = s->gr[8];
872 e89f66ec bellard
            break;
873 e89f66ec bellard
        case 1:
874 e89f66ec bellard
            val = s->latch;
875 e89f66ec bellard
            goto do_write;
876 e89f66ec bellard
        case 2:
877 e89f66ec bellard
            val = mask16[val & 0x0f];
878 e89f66ec bellard
            bit_mask = s->gr[8];
879 e89f66ec bellard
            break;
880 e89f66ec bellard
        case 3:
881 e89f66ec bellard
            /* rotate */
882 e89f66ec bellard
            b = s->gr[3] & 7;
883 a41bc9af bellard
            val = (val >> b) | (val << (8 - b));
884 e89f66ec bellard
885 e89f66ec bellard
            bit_mask = s->gr[8] & val;
886 e89f66ec bellard
            val = mask16[s->gr[0]];
887 e89f66ec bellard
            break;
888 e89f66ec bellard
        }
889 e89f66ec bellard
890 e89f66ec bellard
        /* apply logical operation */
891 e89f66ec bellard
        func_select = s->gr[3] >> 3;
892 e89f66ec bellard
        switch(func_select) {
893 e89f66ec bellard
        case 0:
894 e89f66ec bellard
        default:
895 e89f66ec bellard
            /* nothing to do */
896 e89f66ec bellard
            break;
897 e89f66ec bellard
        case 1:
898 e89f66ec bellard
            /* and */
899 e89f66ec bellard
            val &= s->latch;
900 e89f66ec bellard
            break;
901 e89f66ec bellard
        case 2:
902 e89f66ec bellard
            /* or */
903 e89f66ec bellard
            val |= s->latch;
904 e89f66ec bellard
            break;
905 e89f66ec bellard
        case 3:
906 e89f66ec bellard
            /* xor */
907 e89f66ec bellard
            val ^= s->latch;
908 e89f66ec bellard
            break;
909 e89f66ec bellard
        }
910 e89f66ec bellard
911 e89f66ec bellard
        /* apply bit mask */
912 e89f66ec bellard
        bit_mask |= bit_mask << 8;
913 e89f66ec bellard
        bit_mask |= bit_mask << 16;
914 e89f66ec bellard
        val = (val & bit_mask) | (s->latch & ~bit_mask);
915 e89f66ec bellard
916 e89f66ec bellard
    do_write:
917 e89f66ec bellard
        /* mask data according to sr[2] */
918 546fa6ab bellard
        mask = s->sr[2];
919 546fa6ab bellard
        s->plane_updated |= mask; /* only used to detect font change */
920 546fa6ab bellard
        write_mask = mask16[mask];
921 5fafdf24 ths
        ((uint32_t *)s->vram_ptr)[addr] =
922 5fafdf24 ths
            (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
923 e89f66ec bellard
            (val & write_mask);
924 17b0018b bellard
#ifdef DEBUG_VGA_MEM
925 0bf9e31a Blue Swirl
        printf("vga: latch: [0x" TARGET_FMT_plx "] mask=0x%08x val=0x%08x\n",
926 0bf9e31a Blue Swirl
               addr * 4, write_mask, val);
927 e89f66ec bellard
#endif
928 0bf9e31a Blue Swirl
        cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
929 e89f66ec bellard
    }
930 e89f66ec bellard
}
931 e89f66ec bellard
932 c227f099 Anthony Liguori
static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
933 e89f66ec bellard
{
934 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
935 a4193c8a bellard
    vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
936 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, val & 0xff);
937 09a79b49 bellard
#else
938 a4193c8a bellard
    vga_mem_writeb(opaque, addr, val & 0xff);
939 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
940 09a79b49 bellard
#endif
941 e89f66ec bellard
}
942 e89f66ec bellard
943 c227f099 Anthony Liguori
static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
944 e89f66ec bellard
{
945 09a79b49 bellard
#ifdef TARGET_WORDS_BIGENDIAN
946 a4193c8a bellard
    vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
947 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
948 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
949 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 3, val & 0xff);
950 09a79b49 bellard
#else
951 a4193c8a bellard
    vga_mem_writeb(opaque, addr, val & 0xff);
952 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
953 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
954 a4193c8a bellard
    vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
955 09a79b49 bellard
#endif
956 e89f66ec bellard
}
957 e89f66ec bellard
958 e89f66ec bellard
typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
959 e89f66ec bellard
                             const uint8_t *font_ptr, int h,
960 e89f66ec bellard
                             uint32_t fgcol, uint32_t bgcol);
961 e89f66ec bellard
typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
962 5fafdf24 ths
                                  const uint8_t *font_ptr, int h,
963 e89f66ec bellard
                                  uint32_t fgcol, uint32_t bgcol, int dup9);
964 cedd91d2 Juan Quintela
typedef void vga_draw_line_func(VGACommonState *s1, uint8_t *d,
965 e89f66ec bellard
                                const uint8_t *s, int width);
966 e89f66ec bellard
967 e89f66ec bellard
#define DEPTH 8
968 e89f66ec bellard
#include "vga_template.h"
969 e89f66ec bellard
970 e89f66ec bellard
#define DEPTH 15
971 e89f66ec bellard
#include "vga_template.h"
972 e89f66ec bellard
973 a2502b58 blueswir1
#define BGR_FORMAT
974 a2502b58 blueswir1
#define DEPTH 15
975 a2502b58 blueswir1
#include "vga_template.h"
976 a2502b58 blueswir1
977 a2502b58 blueswir1
#define DEPTH 16
978 a2502b58 blueswir1
#include "vga_template.h"
979 a2502b58 blueswir1
980 a2502b58 blueswir1
#define BGR_FORMAT
981 e89f66ec bellard
#define DEPTH 16
982 e89f66ec bellard
#include "vga_template.h"
983 e89f66ec bellard
984 e89f66ec bellard
#define DEPTH 32
985 e89f66ec bellard
#include "vga_template.h"
986 e89f66ec bellard
987 d3079cd2 bellard
#define BGR_FORMAT
988 d3079cd2 bellard
#define DEPTH 32
989 d3079cd2 bellard
#include "vga_template.h"
990 d3079cd2 bellard
991 17b0018b bellard
static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
992 17b0018b bellard
{
993 17b0018b bellard
    unsigned int col;
994 17b0018b bellard
    col = rgb_to_pixel8(r, g, b);
995 17b0018b bellard
    col |= col << 8;
996 17b0018b bellard
    col |= col << 16;
997 17b0018b bellard
    return col;
998 17b0018b bellard
}
999 17b0018b bellard
1000 17b0018b bellard
static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
1001 17b0018b bellard
{
1002 17b0018b bellard
    unsigned int col;
1003 17b0018b bellard
    col = rgb_to_pixel15(r, g, b);
1004 17b0018b bellard
    col |= col << 16;
1005 17b0018b bellard
    return col;
1006 17b0018b bellard
}
1007 17b0018b bellard
1008 b29169d2 blueswir1
static unsigned int rgb_to_pixel15bgr_dup(unsigned int r, unsigned int g,
1009 b29169d2 blueswir1
                                          unsigned int b)
1010 b29169d2 blueswir1
{
1011 b29169d2 blueswir1
    unsigned int col;
1012 b29169d2 blueswir1
    col = rgb_to_pixel15bgr(r, g, b);
1013 b29169d2 blueswir1
    col |= col << 16;
1014 b29169d2 blueswir1
    return col;
1015 b29169d2 blueswir1
}
1016 b29169d2 blueswir1
1017 17b0018b bellard
static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
1018 17b0018b bellard
{
1019 17b0018b bellard
    unsigned int col;
1020 17b0018b bellard
    col = rgb_to_pixel16(r, g, b);
1021 17b0018b bellard
    col |= col << 16;
1022 17b0018b bellard
    return col;
1023 17b0018b bellard
}
1024 17b0018b bellard
1025 b29169d2 blueswir1
static unsigned int rgb_to_pixel16bgr_dup(unsigned int r, unsigned int g,
1026 b29169d2 blueswir1
                                          unsigned int b)
1027 b29169d2 blueswir1
{
1028 b29169d2 blueswir1
    unsigned int col;
1029 b29169d2 blueswir1
    col = rgb_to_pixel16bgr(r, g, b);
1030 b29169d2 blueswir1
    col |= col << 16;
1031 b29169d2 blueswir1
    return col;
1032 b29169d2 blueswir1
}
1033 b29169d2 blueswir1
1034 17b0018b bellard
static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
1035 17b0018b bellard
{
1036 17b0018b bellard
    unsigned int col;
1037 17b0018b bellard
    col = rgb_to_pixel32(r, g, b);
1038 17b0018b bellard
    return col;
1039 17b0018b bellard
}
1040 17b0018b bellard
1041 d3079cd2 bellard
static unsigned int rgb_to_pixel32bgr_dup(unsigned int r, unsigned int g, unsigned b)
1042 d3079cd2 bellard
{
1043 d3079cd2 bellard
    unsigned int col;
1044 d3079cd2 bellard
    col = rgb_to_pixel32bgr(r, g, b);
1045 d3079cd2 bellard
    return col;
1046 d3079cd2 bellard
}
1047 d3079cd2 bellard
1048 e89f66ec bellard
/* return true if the palette was modified */
1049 cedd91d2 Juan Quintela
static int update_palette16(VGACommonState *s)
1050 e89f66ec bellard
{
1051 17b0018b bellard
    int full_update, i;
1052 e89f66ec bellard
    uint32_t v, col, *palette;
1053 e89f66ec bellard
1054 e89f66ec bellard
    full_update = 0;
1055 e89f66ec bellard
    palette = s->last_palette;
1056 e89f66ec bellard
    for(i = 0; i < 16; i++) {
1057 e89f66ec bellard
        v = s->ar[i];
1058 e89f66ec bellard
        if (s->ar[0x10] & 0x80)
1059 e89f66ec bellard
            v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
1060 e89f66ec bellard
        else
1061 e89f66ec bellard
            v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
1062 e89f66ec bellard
        v = v * 3;
1063 5fafdf24 ths
        col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1064 5fafdf24 ths
                              c6_to_8(s->palette[v + 1]),
1065 17b0018b bellard
                              c6_to_8(s->palette[v + 2]));
1066 17b0018b bellard
        if (col != palette[i]) {
1067 17b0018b bellard
            full_update = 1;
1068 17b0018b bellard
            palette[i] = col;
1069 e89f66ec bellard
        }
1070 17b0018b bellard
    }
1071 17b0018b bellard
    return full_update;
1072 17b0018b bellard
}
1073 17b0018b bellard
1074 17b0018b bellard
/* return true if the palette was modified */
1075 cedd91d2 Juan Quintela
static int update_palette256(VGACommonState *s)
1076 17b0018b bellard
{
1077 17b0018b bellard
    int full_update, i;
1078 17b0018b bellard
    uint32_t v, col, *palette;
1079 17b0018b bellard
1080 17b0018b bellard
    full_update = 0;
1081 17b0018b bellard
    palette = s->last_palette;
1082 17b0018b bellard
    v = 0;
1083 17b0018b bellard
    for(i = 0; i < 256; i++) {
1084 37dd208d bellard
        if (s->dac_8bit) {
1085 5fafdf24 ths
          col = s->rgb_to_pixel(s->palette[v],
1086 5fafdf24 ths
                                s->palette[v + 1],
1087 37dd208d bellard
                                s->palette[v + 2]);
1088 37dd208d bellard
        } else {
1089 5fafdf24 ths
          col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
1090 5fafdf24 ths
                                c6_to_8(s->palette[v + 1]),
1091 37dd208d bellard
                                c6_to_8(s->palette[v + 2]));
1092 37dd208d bellard
        }
1093 e89f66ec bellard
        if (col != palette[i]) {
1094 e89f66ec bellard
            full_update = 1;
1095 e89f66ec bellard
            palette[i] = col;
1096 e89f66ec bellard
        }
1097 17b0018b bellard
        v += 3;
1098 e89f66ec bellard
    }
1099 e89f66ec bellard
    return full_update;
1100 e89f66ec bellard
}
1101 e89f66ec bellard
1102 cedd91d2 Juan Quintela
static void vga_get_offsets(VGACommonState *s,
1103 5fafdf24 ths
                            uint32_t *pline_offset,
1104 83acc96b bellard
                            uint32_t *pstart_addr,
1105 83acc96b bellard
                            uint32_t *pline_compare)
1106 e89f66ec bellard
{
1107 83acc96b bellard
    uint32_t start_addr, line_offset, line_compare;
1108 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
1109 4fa0f5d2 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1110 4fa0f5d2 bellard
        line_offset = s->vbe_line_offset;
1111 4fa0f5d2 bellard
        start_addr = s->vbe_start_addr;
1112 83acc96b bellard
        line_compare = 65535;
1113 4fa0f5d2 bellard
    } else
1114 4fa0f5d2 bellard
#endif
1115 3b46e624 ths
    {
1116 4fa0f5d2 bellard
        /* compute line_offset in bytes */
1117 4fa0f5d2 bellard
        line_offset = s->cr[0x13];
1118 4fa0f5d2 bellard
        line_offset <<= 3;
1119 08e48902 bellard
1120 4fa0f5d2 bellard
        /* starting address */
1121 4fa0f5d2 bellard
        start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
1122 83acc96b bellard
1123 83acc96b bellard
        /* line compare */
1124 5fafdf24 ths
        line_compare = s->cr[0x18] |
1125 83acc96b bellard
            ((s->cr[0x07] & 0x10) << 4) |
1126 83acc96b bellard
            ((s->cr[0x09] & 0x40) << 3);
1127 4fa0f5d2 bellard
    }
1128 798b0c25 bellard
    *pline_offset = line_offset;
1129 798b0c25 bellard
    *pstart_addr = start_addr;
1130 83acc96b bellard
    *pline_compare = line_compare;
1131 798b0c25 bellard
}
1132 798b0c25 bellard
1133 798b0c25 bellard
/* update start_addr and line_offset. Return TRUE if modified */
1134 cedd91d2 Juan Quintela
static int update_basic_params(VGACommonState *s)
1135 798b0c25 bellard
{
1136 798b0c25 bellard
    int full_update;
1137 798b0c25 bellard
    uint32_t start_addr, line_offset, line_compare;
1138 3b46e624 ths
1139 798b0c25 bellard
    full_update = 0;
1140 798b0c25 bellard
1141 83acc96b bellard
    s->get_offsets(s, &line_offset, &start_addr, &line_compare);
1142 e89f66ec bellard
1143 e89f66ec bellard
    if (line_offset != s->line_offset ||
1144 e89f66ec bellard
        start_addr != s->start_addr ||
1145 e89f66ec bellard
        line_compare != s->line_compare) {
1146 e89f66ec bellard
        s->line_offset = line_offset;
1147 e89f66ec bellard
        s->start_addr = start_addr;
1148 e89f66ec bellard
        s->line_compare = line_compare;
1149 e89f66ec bellard
        full_update = 1;
1150 e89f66ec bellard
    }
1151 e89f66ec bellard
    return full_update;
1152 e89f66ec bellard
}
1153 e89f66ec bellard
1154 b29169d2 blueswir1
#define NB_DEPTHS 7
1155 d3079cd2 bellard
1156 d3079cd2 bellard
static inline int get_depth_index(DisplayState *s)
1157 e89f66ec bellard
{
1158 0e1f5a0c aliguori
    switch(ds_get_bits_per_pixel(s)) {
1159 e89f66ec bellard
    default:
1160 e89f66ec bellard
    case 8:
1161 e89f66ec bellard
        return 0;
1162 e89f66ec bellard
    case 15:
1163 8927bcfd aliguori
        return 1;
1164 e89f66ec bellard
    case 16:
1165 8927bcfd aliguori
        return 2;
1166 e89f66ec bellard
    case 32:
1167 7b5d76da aliguori
        if (is_surface_bgr(s->surface))
1168 7b5d76da aliguori
            return 4;
1169 7b5d76da aliguori
        else
1170 7b5d76da aliguori
            return 3;
1171 e89f66ec bellard
    }
1172 e89f66ec bellard
}
1173 e89f66ec bellard
1174 68f04a3c Blue Swirl
static vga_draw_glyph8_func * const vga_draw_glyph8_table[NB_DEPTHS] = {
1175 e89f66ec bellard
    vga_draw_glyph8_8,
1176 e89f66ec bellard
    vga_draw_glyph8_16,
1177 e89f66ec bellard
    vga_draw_glyph8_16,
1178 e89f66ec bellard
    vga_draw_glyph8_32,
1179 d3079cd2 bellard
    vga_draw_glyph8_32,
1180 b29169d2 blueswir1
    vga_draw_glyph8_16,
1181 b29169d2 blueswir1
    vga_draw_glyph8_16,
1182 e89f66ec bellard
};
1183 e89f66ec bellard
1184 68f04a3c Blue Swirl
static vga_draw_glyph8_func * const vga_draw_glyph16_table[NB_DEPTHS] = {
1185 17b0018b bellard
    vga_draw_glyph16_8,
1186 17b0018b bellard
    vga_draw_glyph16_16,
1187 17b0018b bellard
    vga_draw_glyph16_16,
1188 17b0018b bellard
    vga_draw_glyph16_32,
1189 d3079cd2 bellard
    vga_draw_glyph16_32,
1190 b29169d2 blueswir1
    vga_draw_glyph16_16,
1191 b29169d2 blueswir1
    vga_draw_glyph16_16,
1192 17b0018b bellard
};
1193 17b0018b bellard
1194 68f04a3c Blue Swirl
static vga_draw_glyph9_func * const vga_draw_glyph9_table[NB_DEPTHS] = {
1195 e89f66ec bellard
    vga_draw_glyph9_8,
1196 e89f66ec bellard
    vga_draw_glyph9_16,
1197 e89f66ec bellard
    vga_draw_glyph9_16,
1198 e89f66ec bellard
    vga_draw_glyph9_32,
1199 d3079cd2 bellard
    vga_draw_glyph9_32,
1200 b29169d2 blueswir1
    vga_draw_glyph9_16,
1201 b29169d2 blueswir1
    vga_draw_glyph9_16,
1202 e89f66ec bellard
};
1203 3b46e624 ths
1204 e89f66ec bellard
static const uint8_t cursor_glyph[32 * 4] = {
1205 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1206 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1207 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1208 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1209 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1210 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1211 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1212 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1213 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1214 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1215 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1216 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1217 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1218 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1219 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1220 e89f66ec bellard
    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1221 3b46e624 ths
};
1222 e89f66ec bellard
1223 cedd91d2 Juan Quintela
static void vga_get_text_resolution(VGACommonState *s, int *pwidth, int *pheight,
1224 4c5e8c5c blueswir1
                                    int *pcwidth, int *pcheight)
1225 4c5e8c5c blueswir1
{
1226 4c5e8c5c blueswir1
    int width, cwidth, height, cheight;
1227 4c5e8c5c blueswir1
1228 4c5e8c5c blueswir1
    /* total width & height */
1229 4c5e8c5c blueswir1
    cheight = (s->cr[9] & 0x1f) + 1;
1230 4c5e8c5c blueswir1
    cwidth = 8;
1231 4c5e8c5c blueswir1
    if (!(s->sr[1] & 0x01))
1232 4c5e8c5c blueswir1
        cwidth = 9;
1233 4c5e8c5c blueswir1
    if (s->sr[1] & 0x08)
1234 4c5e8c5c blueswir1
        cwidth = 16; /* NOTE: no 18 pixel wide */
1235 4c5e8c5c blueswir1
    width = (s->cr[0x01] + 1);
1236 4c5e8c5c blueswir1
    if (s->cr[0x06] == 100) {
1237 4c5e8c5c blueswir1
        /* ugly hack for CGA 160x100x16 - explain me the logic */
1238 4c5e8c5c blueswir1
        height = 100;
1239 4c5e8c5c blueswir1
    } else {
1240 4c5e8c5c blueswir1
        height = s->cr[0x12] |
1241 4c5e8c5c blueswir1
            ((s->cr[0x07] & 0x02) << 7) |
1242 4c5e8c5c blueswir1
            ((s->cr[0x07] & 0x40) << 3);
1243 4c5e8c5c blueswir1
        height = (height + 1) / cheight;
1244 4c5e8c5c blueswir1
    }
1245 4c5e8c5c blueswir1
1246 4c5e8c5c blueswir1
    *pwidth = width;
1247 4c5e8c5c blueswir1
    *pheight = height;
1248 4c5e8c5c blueswir1
    *pcwidth = cwidth;
1249 4c5e8c5c blueswir1
    *pcheight = cheight;
1250 4c5e8c5c blueswir1
}
1251 4c5e8c5c blueswir1
1252 7d957bd8 aliguori
typedef unsigned int rgb_to_pixel_dup_func(unsigned int r, unsigned int g, unsigned b);
1253 7d957bd8 aliguori
1254 68f04a3c Blue Swirl
static rgb_to_pixel_dup_func * const rgb_to_pixel_dup_table[NB_DEPTHS] = {
1255 bdb19571 aliguori
    rgb_to_pixel8_dup,
1256 bdb19571 aliguori
    rgb_to_pixel15_dup,
1257 bdb19571 aliguori
    rgb_to_pixel16_dup,
1258 bdb19571 aliguori
    rgb_to_pixel32_dup,
1259 bdb19571 aliguori
    rgb_to_pixel32bgr_dup,
1260 bdb19571 aliguori
    rgb_to_pixel15bgr_dup,
1261 bdb19571 aliguori
    rgb_to_pixel16bgr_dup,
1262 bdb19571 aliguori
};
1263 7d957bd8 aliguori
1264 5fafdf24 ths
/*
1265 5fafdf24 ths
 * Text mode update
1266 e89f66ec bellard
 * Missing:
1267 e89f66ec bellard
 * - double scan
1268 5fafdf24 ths
 * - double width
1269 e89f66ec bellard
 * - underline
1270 e89f66ec bellard
 * - flashing
1271 e89f66ec bellard
 */
1272 cedd91d2 Juan Quintela
static void vga_draw_text(VGACommonState *s, int full_update)
1273 e89f66ec bellard
{
1274 e89f66ec bellard
    int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
1275 cae334cd malc
    int cx_min, cx_max, linesize, x_incr, line, line1;
1276 e89f66ec bellard
    uint32_t offset, fgcol, bgcol, v, cursor_offset;
1277 d1984194 malc
    uint8_t *d1, *d, *src, *dest, *cursor_ptr;
1278 e89f66ec bellard
    const uint8_t *font_ptr, *font_base[2];
1279 e89f66ec bellard
    int dup9, line_offset, depth_index;
1280 e89f66ec bellard
    uint32_t *palette;
1281 e89f66ec bellard
    uint32_t *ch_attr_ptr;
1282 e89f66ec bellard
    vga_draw_glyph8_func *vga_draw_glyph8;
1283 e89f66ec bellard
    vga_draw_glyph9_func *vga_draw_glyph9;
1284 e89f66ec bellard
1285 e89f66ec bellard
    /* compute font data address (in plane 2) */
1286 e89f66ec bellard
    v = s->sr[3];
1287 1078f663 bellard
    offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
1288 e89f66ec bellard
    if (offset != s->font_offsets[0]) {
1289 e89f66ec bellard
        s->font_offsets[0] = offset;
1290 e89f66ec bellard
        full_update = 1;
1291 e89f66ec bellard
    }
1292 e89f66ec bellard
    font_base[0] = s->vram_ptr + offset;
1293 e89f66ec bellard
1294 1078f663 bellard
    offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
1295 e89f66ec bellard
    font_base[1] = s->vram_ptr + offset;
1296 e89f66ec bellard
    if (offset != s->font_offsets[1]) {
1297 e89f66ec bellard
        s->font_offsets[1] = offset;
1298 e89f66ec bellard
        full_update = 1;
1299 e89f66ec bellard
    }
1300 546fa6ab bellard
    if (s->plane_updated & (1 << 2)) {
1301 546fa6ab bellard
        /* if the plane 2 was modified since the last display, it
1302 546fa6ab bellard
           indicates the font may have been modified */
1303 546fa6ab bellard
        s->plane_updated = 0;
1304 546fa6ab bellard
        full_update = 1;
1305 546fa6ab bellard
    }
1306 799e709b aliguori
    full_update |= update_basic_params(s);
1307 e89f66ec bellard
1308 e89f66ec bellard
    line_offset = s->line_offset;
1309 e89f66ec bellard
1310 4c5e8c5c blueswir1
    vga_get_text_resolution(s, &width, &height, &cw, &cheight);
1311 3294b949 bellard
    if ((height * width) > CH_ATTR_SIZE) {
1312 3294b949 bellard
        /* better than nothing: exit if transient size is too big */
1313 3294b949 bellard
        return;
1314 3294b949 bellard
    }
1315 3294b949 bellard
1316 799e709b aliguori
    if (width != s->last_width || height != s->last_height ||
1317 799e709b aliguori
        cw != s->last_cw || cheight != s->last_ch || s->last_depth) {
1318 799e709b aliguori
        s->last_scr_width = width * cw;
1319 799e709b aliguori
        s->last_scr_height = height * cheight;
1320 799e709b aliguori
        qemu_console_resize(s->ds, s->last_scr_width, s->last_scr_height);
1321 799e709b aliguori
        s->last_depth = 0;
1322 799e709b aliguori
        s->last_width = width;
1323 799e709b aliguori
        s->last_height = height;
1324 799e709b aliguori
        s->last_ch = cheight;
1325 799e709b aliguori
        s->last_cw = cw;
1326 799e709b aliguori
        full_update = 1;
1327 799e709b aliguori
    }
1328 7d957bd8 aliguori
    s->rgb_to_pixel =
1329 7d957bd8 aliguori
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1330 7d957bd8 aliguori
    full_update |= update_palette16(s);
1331 7d957bd8 aliguori
    palette = s->last_palette;
1332 7d957bd8 aliguori
    x_incr = cw * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1333 7d957bd8 aliguori
1334 e89f66ec bellard
    cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
1335 e89f66ec bellard
    if (cursor_offset != s->cursor_offset ||
1336 e89f66ec bellard
        s->cr[0xa] != s->cursor_start ||
1337 e89f66ec bellard
        s->cr[0xb] != s->cursor_end) {
1338 e89f66ec bellard
      /* if the cursor position changed, we update the old and new
1339 e89f66ec bellard
         chars */
1340 e89f66ec bellard
        if (s->cursor_offset < CH_ATTR_SIZE)
1341 e89f66ec bellard
            s->last_ch_attr[s->cursor_offset] = -1;
1342 e89f66ec bellard
        if (cursor_offset < CH_ATTR_SIZE)
1343 e89f66ec bellard
            s->last_ch_attr[cursor_offset] = -1;
1344 e89f66ec bellard
        s->cursor_offset = cursor_offset;
1345 e89f66ec bellard
        s->cursor_start = s->cr[0xa];
1346 e89f66ec bellard
        s->cursor_end = s->cr[0xb];
1347 e89f66ec bellard
    }
1348 39cf7803 bellard
    cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
1349 3b46e624 ths
1350 d3079cd2 bellard
    depth_index = get_depth_index(s->ds);
1351 17b0018b bellard
    if (cw == 16)
1352 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
1353 17b0018b bellard
    else
1354 17b0018b bellard
        vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
1355 e89f66ec bellard
    vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
1356 3b46e624 ths
1357 0e1f5a0c aliguori
    dest = ds_get_data(s->ds);
1358 0e1f5a0c aliguori
    linesize = ds_get_linesize(s->ds);
1359 e89f66ec bellard
    ch_attr_ptr = s->last_ch_attr;
1360 d1984194 malc
    line = 0;
1361 d1984194 malc
    offset = s->start_addr * 4;
1362 e89f66ec bellard
    for(cy = 0; cy < height; cy++) {
1363 e89f66ec bellard
        d1 = dest;
1364 d1984194 malc
        src = s->vram_ptr + offset;
1365 e89f66ec bellard
        cx_min = width;
1366 e89f66ec bellard
        cx_max = -1;
1367 e89f66ec bellard
        for(cx = 0; cx < width; cx++) {
1368 e89f66ec bellard
            ch_attr = *(uint16_t *)src;
1369 e89f66ec bellard
            if (full_update || ch_attr != *ch_attr_ptr) {
1370 e89f66ec bellard
                if (cx < cx_min)
1371 e89f66ec bellard
                    cx_min = cx;
1372 e89f66ec bellard
                if (cx > cx_max)
1373 e89f66ec bellard
                    cx_max = cx;
1374 e89f66ec bellard
                *ch_attr_ptr = ch_attr;
1375 e2542fe2 Juan Quintela
#ifdef HOST_WORDS_BIGENDIAN
1376 e89f66ec bellard
                ch = ch_attr >> 8;
1377 e89f66ec bellard
                cattr = ch_attr & 0xff;
1378 e89f66ec bellard
#else
1379 e89f66ec bellard
                ch = ch_attr & 0xff;
1380 e89f66ec bellard
                cattr = ch_attr >> 8;
1381 e89f66ec bellard
#endif
1382 e89f66ec bellard
                font_ptr = font_base[(cattr >> 3) & 1];
1383 e89f66ec bellard
                font_ptr += 32 * 4 * ch;
1384 e89f66ec bellard
                bgcol = palette[cattr >> 4];
1385 e89f66ec bellard
                fgcol = palette[cattr & 0x0f];
1386 17b0018b bellard
                if (cw != 9) {
1387 5fafdf24 ths
                    vga_draw_glyph8(d1, linesize,
1388 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol);
1389 e89f66ec bellard
                } else {
1390 e89f66ec bellard
                    dup9 = 0;
1391 e89f66ec bellard
                    if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
1392 e89f66ec bellard
                        dup9 = 1;
1393 5fafdf24 ths
                    vga_draw_glyph9(d1, linesize,
1394 e89f66ec bellard
                                    font_ptr, cheight, fgcol, bgcol, dup9);
1395 e89f66ec bellard
                }
1396 e89f66ec bellard
                if (src == cursor_ptr &&
1397 e89f66ec bellard
                    !(s->cr[0x0a] & 0x20)) {
1398 e89f66ec bellard
                    int line_start, line_last, h;
1399 e89f66ec bellard
                    /* draw the cursor */
1400 e89f66ec bellard
                    line_start = s->cr[0x0a] & 0x1f;
1401 e89f66ec bellard
                    line_last = s->cr[0x0b] & 0x1f;
1402 e89f66ec bellard
                    /* XXX: check that */
1403 e89f66ec bellard
                    if (line_last > cheight - 1)
1404 e89f66ec bellard
                        line_last = cheight - 1;
1405 e89f66ec bellard
                    if (line_last >= line_start && line_start < cheight) {
1406 e89f66ec bellard
                        h = line_last - line_start + 1;
1407 e89f66ec bellard
                        d = d1 + linesize * line_start;
1408 17b0018b bellard
                        if (cw != 9) {
1409 5fafdf24 ths
                            vga_draw_glyph8(d, linesize,
1410 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol);
1411 e89f66ec bellard
                        } else {
1412 5fafdf24 ths
                            vga_draw_glyph9(d, linesize,
1413 e89f66ec bellard
                                            cursor_glyph, h, fgcol, bgcol, 1);
1414 e89f66ec bellard
                        }
1415 e89f66ec bellard
                    }
1416 e89f66ec bellard
                }
1417 e89f66ec bellard
            }
1418 e89f66ec bellard
            d1 += x_incr;
1419 e89f66ec bellard
            src += 4;
1420 e89f66ec bellard
            ch_attr_ptr++;
1421 e89f66ec bellard
        }
1422 e89f66ec bellard
        if (cx_max != -1) {
1423 5fafdf24 ths
            dpy_update(s->ds, cx_min * cw, cy * cheight,
1424 e89f66ec bellard
                       (cx_max - cx_min + 1) * cw, cheight);
1425 e89f66ec bellard
        }
1426 e89f66ec bellard
        dest += linesize * cheight;
1427 cae334cd malc
        line1 = line + cheight;
1428 cae334cd malc
        offset += line_offset;
1429 cae334cd malc
        if (line < s->line_compare && line1 >= s->line_compare) {
1430 d1984194 malc
            offset = 0;
1431 d1984194 malc
        }
1432 cae334cd malc
        line = line1;
1433 e89f66ec bellard
    }
1434 e89f66ec bellard
}
1435 e89f66ec bellard
1436 17b0018b bellard
enum {
1437 17b0018b bellard
    VGA_DRAW_LINE2,
1438 17b0018b bellard
    VGA_DRAW_LINE2D2,
1439 17b0018b bellard
    VGA_DRAW_LINE4,
1440 17b0018b bellard
    VGA_DRAW_LINE4D2,
1441 17b0018b bellard
    VGA_DRAW_LINE8D2,
1442 17b0018b bellard
    VGA_DRAW_LINE8,
1443 17b0018b bellard
    VGA_DRAW_LINE15,
1444 17b0018b bellard
    VGA_DRAW_LINE16,
1445 4fa0f5d2 bellard
    VGA_DRAW_LINE24,
1446 17b0018b bellard
    VGA_DRAW_LINE32,
1447 17b0018b bellard
    VGA_DRAW_LINE_NB,
1448 17b0018b bellard
};
1449 17b0018b bellard
1450 68f04a3c Blue Swirl
static vga_draw_line_func * const vga_draw_line_table[NB_DEPTHS * VGA_DRAW_LINE_NB] = {
1451 e89f66ec bellard
    vga_draw_line2_8,
1452 e89f66ec bellard
    vga_draw_line2_16,
1453 e89f66ec bellard
    vga_draw_line2_16,
1454 e89f66ec bellard
    vga_draw_line2_32,
1455 d3079cd2 bellard
    vga_draw_line2_32,
1456 b29169d2 blueswir1
    vga_draw_line2_16,
1457 b29169d2 blueswir1
    vga_draw_line2_16,
1458 e89f66ec bellard
1459 17b0018b bellard
    vga_draw_line2d2_8,
1460 17b0018b bellard
    vga_draw_line2d2_16,
1461 17b0018b bellard
    vga_draw_line2d2_16,
1462 17b0018b bellard
    vga_draw_line2d2_32,
1463 d3079cd2 bellard
    vga_draw_line2d2_32,
1464 b29169d2 blueswir1
    vga_draw_line2d2_16,
1465 b29169d2 blueswir1
    vga_draw_line2d2_16,
1466 17b0018b bellard
1467 e89f66ec bellard
    vga_draw_line4_8,
1468 e89f66ec bellard
    vga_draw_line4_16,
1469 e89f66ec bellard
    vga_draw_line4_16,
1470 e89f66ec bellard
    vga_draw_line4_32,
1471 d3079cd2 bellard
    vga_draw_line4_32,
1472 b29169d2 blueswir1
    vga_draw_line4_16,
1473 b29169d2 blueswir1
    vga_draw_line4_16,
1474 e89f66ec bellard
1475 17b0018b bellard
    vga_draw_line4d2_8,
1476 17b0018b bellard
    vga_draw_line4d2_16,
1477 17b0018b bellard
    vga_draw_line4d2_16,
1478 17b0018b bellard
    vga_draw_line4d2_32,
1479 d3079cd2 bellard
    vga_draw_line4d2_32,
1480 b29169d2 blueswir1
    vga_draw_line4d2_16,
1481 b29169d2 blueswir1
    vga_draw_line4d2_16,
1482 17b0018b bellard
1483 17b0018b bellard
    vga_draw_line8d2_8,
1484 17b0018b bellard
    vga_draw_line8d2_16,
1485 17b0018b bellard
    vga_draw_line8d2_16,
1486 17b0018b bellard
    vga_draw_line8d2_32,
1487 d3079cd2 bellard
    vga_draw_line8d2_32,
1488 b29169d2 blueswir1
    vga_draw_line8d2_16,
1489 b29169d2 blueswir1
    vga_draw_line8d2_16,
1490 17b0018b bellard
1491 e89f66ec bellard
    vga_draw_line8_8,
1492 e89f66ec bellard
    vga_draw_line8_16,
1493 e89f66ec bellard
    vga_draw_line8_16,
1494 e89f66ec bellard
    vga_draw_line8_32,
1495 d3079cd2 bellard
    vga_draw_line8_32,
1496 b29169d2 blueswir1
    vga_draw_line8_16,
1497 b29169d2 blueswir1
    vga_draw_line8_16,
1498 e89f66ec bellard
1499 e89f66ec bellard
    vga_draw_line15_8,
1500 e89f66ec bellard
    vga_draw_line15_15,
1501 e89f66ec bellard
    vga_draw_line15_16,
1502 e89f66ec bellard
    vga_draw_line15_32,
1503 d3079cd2 bellard
    vga_draw_line15_32bgr,
1504 b29169d2 blueswir1
    vga_draw_line15_15bgr,
1505 b29169d2 blueswir1
    vga_draw_line15_16bgr,
1506 e89f66ec bellard
1507 e89f66ec bellard
    vga_draw_line16_8,
1508 e89f66ec bellard
    vga_draw_line16_15,
1509 e89f66ec bellard
    vga_draw_line16_16,
1510 e89f66ec bellard
    vga_draw_line16_32,
1511 d3079cd2 bellard
    vga_draw_line16_32bgr,
1512 b29169d2 blueswir1
    vga_draw_line16_15bgr,
1513 b29169d2 blueswir1
    vga_draw_line16_16bgr,
1514 e89f66ec bellard
1515 4fa0f5d2 bellard
    vga_draw_line24_8,
1516 4fa0f5d2 bellard
    vga_draw_line24_15,
1517 4fa0f5d2 bellard
    vga_draw_line24_16,
1518 4fa0f5d2 bellard
    vga_draw_line24_32,
1519 d3079cd2 bellard
    vga_draw_line24_32bgr,
1520 b29169d2 blueswir1
    vga_draw_line24_15bgr,
1521 b29169d2 blueswir1
    vga_draw_line24_16bgr,
1522 4fa0f5d2 bellard
1523 e89f66ec bellard
    vga_draw_line32_8,
1524 e89f66ec bellard
    vga_draw_line32_15,
1525 e89f66ec bellard
    vga_draw_line32_16,
1526 e89f66ec bellard
    vga_draw_line32_32,
1527 d3079cd2 bellard
    vga_draw_line32_32bgr,
1528 b29169d2 blueswir1
    vga_draw_line32_15bgr,
1529 b29169d2 blueswir1
    vga_draw_line32_16bgr,
1530 d3079cd2 bellard
};
1531 d3079cd2 bellard
1532 cedd91d2 Juan Quintela
static int vga_get_bpp(VGACommonState *s)
1533 798b0c25 bellard
{
1534 798b0c25 bellard
    int ret;
1535 798b0c25 bellard
#ifdef CONFIG_BOCHS_VBE
1536 798b0c25 bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1537 798b0c25 bellard
        ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
1538 5fafdf24 ths
    } else
1539 798b0c25 bellard
#endif
1540 798b0c25 bellard
    {
1541 798b0c25 bellard
        ret = 0;
1542 798b0c25 bellard
    }
1543 798b0c25 bellard
    return ret;
1544 798b0c25 bellard
}
1545 798b0c25 bellard
1546 cedd91d2 Juan Quintela
static void vga_get_resolution(VGACommonState *s, int *pwidth, int *pheight)
1547 a130a41e bellard
{
1548 a130a41e bellard
    int width, height;
1549 3b46e624 ths
1550 8454df8b bellard
#ifdef CONFIG_BOCHS_VBE
1551 8454df8b bellard
    if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
1552 8454df8b bellard
        width = s->vbe_regs[VBE_DISPI_INDEX_XRES];
1553 8454df8b bellard
        height = s->vbe_regs[VBE_DISPI_INDEX_YRES];
1554 5fafdf24 ths
    } else
1555 8454df8b bellard
#endif
1556 8454df8b bellard
    {
1557 8454df8b bellard
        width = (s->cr[0x01] + 1) * 8;
1558 5fafdf24 ths
        height = s->cr[0x12] |
1559 5fafdf24 ths
            ((s->cr[0x07] & 0x02) << 7) |
1560 8454df8b bellard
            ((s->cr[0x07] & 0x40) << 3);
1561 8454df8b bellard
        height = (height + 1);
1562 8454df8b bellard
    }
1563 a130a41e bellard
    *pwidth = width;
1564 a130a41e bellard
    *pheight = height;
1565 a130a41e bellard
}
1566 a130a41e bellard
1567 cedd91d2 Juan Quintela
void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2)
1568 a8aa669b bellard
{
1569 a8aa669b bellard
    int y;
1570 a8aa669b bellard
    if (y1 >= VGA_MAX_HEIGHT)
1571 a8aa669b bellard
        return;
1572 a8aa669b bellard
    if (y2 >= VGA_MAX_HEIGHT)
1573 a8aa669b bellard
        y2 = VGA_MAX_HEIGHT;
1574 a8aa669b bellard
    for(y = y1; y < y2; y++) {
1575 a8aa669b bellard
        s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
1576 a8aa669b bellard
    }
1577 a8aa669b bellard
}
1578 a8aa669b bellard
1579 cedd91d2 Juan Quintela
static void vga_sync_dirty_bitmap(VGACommonState *s)
1580 2bec46dc aliguori
{
1581 2bec46dc aliguori
    if (s->map_addr)
1582 2bec46dc aliguori
        cpu_physical_sync_dirty_bitmap(s->map_addr, s->map_end);
1583 2bec46dc aliguori
1584 2bec46dc aliguori
    if (s->lfb_vram_mapped) {
1585 2bec46dc aliguori
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa0000, 0xa8000);
1586 2bec46dc aliguori
        cpu_physical_sync_dirty_bitmap(isa_mem_base + 0xa8000, 0xb0000);
1587 2bec46dc aliguori
    }
1588 f0138a63 Anthony Liguori
1589 f0138a63 Anthony Liguori
#ifdef CONFIG_BOCHS_VBE
1590 f0138a63 Anthony Liguori
    if (s->vbe_mapped) {
1591 f0138a63 Anthony Liguori
        cpu_physical_sync_dirty_bitmap(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
1592 f0138a63 Anthony Liguori
                                       VBE_DISPI_LFB_PHYSICAL_ADDRESS + s->vram_size);
1593 f0138a63 Anthony Liguori
    }
1594 f0138a63 Anthony Liguori
#endif
1595 f0138a63 Anthony Liguori
1596 2bec46dc aliguori
}
1597 2bec46dc aliguori
1598 50af3246 Juan Quintela
void vga_dirty_log_start(VGACommonState *s)
1599 50af3246 Juan Quintela
{
1600 50af3246 Juan Quintela
    if (kvm_enabled() && s->map_addr)
1601 50af3246 Juan Quintela
        kvm_log_start(s->map_addr, s->map_end - s->map_addr);
1602 50af3246 Juan Quintela
1603 50af3246 Juan Quintela
    if (kvm_enabled() && s->lfb_vram_mapped) {
1604 50af3246 Juan Quintela
        kvm_log_start(isa_mem_base + 0xa0000, 0x8000);
1605 50af3246 Juan Quintela
        kvm_log_start(isa_mem_base + 0xa8000, 0x8000);
1606 50af3246 Juan Quintela
    }
1607 f0138a63 Anthony Liguori
1608 f0138a63 Anthony Liguori
#ifdef CONFIG_BOCHS_VBE
1609 f0138a63 Anthony Liguori
    if (kvm_enabled() && s->vbe_mapped) {
1610 f0138a63 Anthony Liguori
        kvm_log_start(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1611 f0138a63 Anthony Liguori
    }
1612 f0138a63 Anthony Liguori
#endif
1613 b5cc6e32 Anthony Liguori
}
1614 b5cc6e32 Anthony Liguori
1615 b5cc6e32 Anthony Liguori
void vga_dirty_log_stop(VGACommonState *s)
1616 b5cc6e32 Anthony Liguori
{
1617 b5cc6e32 Anthony Liguori
    if (kvm_enabled() && s->map_addr)
1618 b5cc6e32 Anthony Liguori
        kvm_log_stop(s->map_addr, s->map_end - s->map_addr);
1619 b5cc6e32 Anthony Liguori
1620 b5cc6e32 Anthony Liguori
    if (kvm_enabled() && s->lfb_vram_mapped) {
1621 cce83b7d Marcelo Tosatti
        kvm_log_stop(isa_mem_base + 0xa0000, 0x8000);
1622 cce83b7d Marcelo Tosatti
        kvm_log_stop(isa_mem_base + 0xa8000, 0x8000);
1623 b5cc6e32 Anthony Liguori
    }
1624 f0138a63 Anthony Liguori
1625 b5cc6e32 Anthony Liguori
#ifdef CONFIG_BOCHS_VBE
1626 b5cc6e32 Anthony Liguori
    if (kvm_enabled() && s->vbe_mapped) {
1627 b5cc6e32 Anthony Liguori
        kvm_log_stop(VBE_DISPI_LFB_PHYSICAL_ADDRESS, s->vram_size);
1628 b5cc6e32 Anthony Liguori
    }
1629 b5cc6e32 Anthony Liguori
#endif
1630 b5cc6e32 Anthony Liguori
}
1631 b5cc6e32 Anthony Liguori
1632 b5cc6e32 Anthony Liguori
void vga_dirty_log_restart(VGACommonState *s)
1633 b5cc6e32 Anthony Liguori
{
1634 b5cc6e32 Anthony Liguori
    vga_dirty_log_stop(s);
1635 b5cc6e32 Anthony Liguori
    vga_dirty_log_start(s);
1636 50af3246 Juan Quintela
}
1637 50af3246 Juan Quintela
1638 799e709b aliguori
/*
1639 799e709b aliguori
 * graphic modes
1640 799e709b aliguori
 */
1641 cedd91d2 Juan Quintela
static void vga_draw_graphic(VGACommonState *s, int full_update)
1642 e89f66ec bellard
{
1643 12c7e75a Avi Kivity
    int y1, y, update, linesize, y_start, double_scan, mask, depth;
1644 12c7e75a Avi Kivity
    int width, height, shift_control, line_offset, bwidth, bits;
1645 c227f099 Anthony Liguori
    ram_addr_t page0, page1, page_min, page_max;
1646 a07cf92a bellard
    int disp_width, multi_scan, multi_run;
1647 799e709b aliguori
    uint8_t *d;
1648 799e709b aliguori
    uint32_t v, addr1, addr;
1649 799e709b aliguori
    vga_draw_line_func *vga_draw_line;
1650 799e709b aliguori
1651 799e709b aliguori
    full_update |= update_basic_params(s);
1652 799e709b aliguori
1653 799e709b aliguori
    if (!full_update)
1654 799e709b aliguori
        vga_sync_dirty_bitmap(s);
1655 2bec46dc aliguori
1656 a130a41e bellard
    s->get_resolution(s, &width, &height);
1657 17b0018b bellard
    disp_width = width;
1658 09a79b49 bellard
1659 e89f66ec bellard
    shift_control = (s->gr[0x05] >> 5) & 3;
1660 f6c958c8 bellard
    double_scan = (s->cr[0x09] >> 7);
1661 799e709b aliguori
    if (shift_control != 1) {
1662 799e709b aliguori
        multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
1663 799e709b aliguori
    } else {
1664 799e709b aliguori
        /* in CGA modes, multi_scan is ignored */
1665 799e709b aliguori
        /* XXX: is it correct ? */
1666 799e709b aliguori
        multi_scan = double_scan;
1667 799e709b aliguori
    }
1668 799e709b aliguori
    multi_run = multi_scan;
1669 17b0018b bellard
    if (shift_control != s->shift_control ||
1670 17b0018b bellard
        double_scan != s->double_scan) {
1671 799e709b aliguori
        full_update = 1;
1672 e89f66ec bellard
        s->shift_control = shift_control;
1673 17b0018b bellard
        s->double_scan = double_scan;
1674 e89f66ec bellard
    }
1675 3b46e624 ths
1676 aba35a6c malc
    if (shift_control == 0) {
1677 aba35a6c malc
        if (s->sr[0x01] & 8) {
1678 aba35a6c malc
            disp_width <<= 1;
1679 aba35a6c malc
        }
1680 aba35a6c malc
    } else if (shift_control == 1) {
1681 aba35a6c malc
        if (s->sr[0x01] & 8) {
1682 aba35a6c malc
            disp_width <<= 1;
1683 aba35a6c malc
        }
1684 aba35a6c malc
    }
1685 aba35a6c malc
1686 799e709b aliguori
    depth = s->get_bpp(s);
1687 e3697092 aurel32
    if (s->line_offset != s->last_line_offset ||
1688 e3697092 aurel32
        disp_width != s->last_width ||
1689 e3697092 aurel32
        height != s->last_height ||
1690 799e709b aliguori
        s->last_depth != depth) {
1691 e2542fe2 Juan Quintela
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
1692 e3697092 aurel32
        if (depth == 16 || depth == 32) {
1693 0da2ea1b malc
#else
1694 0da2ea1b malc
        if (depth == 32) {
1695 0da2ea1b malc
#endif
1696 b8c18e4c aliguori
            qemu_free_displaysurface(s->ds);
1697 b8c18e4c aliguori
            s->ds->surface = qemu_create_displaysurface_from(disp_width, height, depth,
1698 b8c18e4c aliguori
                    s->line_offset,
1699 b8c18e4c aliguori
                    s->vram_ptr + (s->start_addr * 4));
1700 e2542fe2 Juan Quintela
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
1701 b8c18e4c aliguori
            s->ds->surface->pf = qemu_different_endianness_pixelformat(depth);
1702 0da2ea1b malc
#endif
1703 b8c18e4c aliguori
            dpy_resize(s->ds);
1704 e3697092 aurel32
        } else {
1705 e3697092 aurel32
            qemu_console_resize(s->ds, disp_width, height);
1706 e3697092 aurel32
        }
1707 e3697092 aurel32
        s->last_scr_width = disp_width;
1708 e3697092 aurel32
        s->last_scr_height = height;
1709 e3697092 aurel32
        s->last_width = disp_width;
1710 e3697092 aurel32
        s->last_height = height;
1711 e3697092 aurel32
        s->last_line_offset = s->line_offset;
1712 e3697092 aurel32
        s->last_depth = depth;
1713 799e709b aliguori
        full_update = 1;
1714 799e709b aliguori
    } else if (is_buffer_shared(s->ds->surface) &&
1715 e3697092 aurel32
               (full_update || s->ds->surface->data != s->vram_ptr + (s->start_addr * 4))) {
1716 e3697092 aurel32
        s->ds->surface->data = s->vram_ptr + (s->start_addr * 4);
1717 e3697092 aurel32
        dpy_setdata(s->ds);
1718 e3697092 aurel32
    }
1719 e3697092 aurel32
1720 e3697092 aurel32
    s->rgb_to_pixel =
1721 e3697092 aurel32
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1722 e3697092 aurel32
1723 799e709b aliguori
    if (shift_control == 0) {
1724 17b0018b bellard
        full_update |= update_palette16(s);
1725 17b0018b bellard
        if (s->sr[0x01] & 8) {
1726 17b0018b bellard
            v = VGA_DRAW_LINE4D2;
1727 17b0018b bellard
        } else {
1728 17b0018b bellard
            v = VGA_DRAW_LINE4;
1729 17b0018b bellard
        }
1730 15342721 aurel32
        bits = 4;
1731 799e709b aliguori
    } else if (shift_control == 1) {
1732 17b0018b bellard
        full_update |= update_palette16(s);
1733 17b0018b bellard
        if (s->sr[0x01] & 8) {
1734 17b0018b bellard
            v = VGA_DRAW_LINE2D2;
1735 17b0018b bellard
        } else {
1736 17b0018b bellard
            v = VGA_DRAW_LINE2;
1737 17b0018b bellard
        }
1738 15342721 aurel32
        bits = 4;
1739 17b0018b bellard
    } else {
1740 798b0c25 bellard
        switch(s->get_bpp(s)) {
1741 798b0c25 bellard
        default:
1742 798b0c25 bellard
        case 0:
1743 4fa0f5d2 bellard
            full_update |= update_palette256(s);
1744 4fa0f5d2 bellard
            v = VGA_DRAW_LINE8D2;
1745 15342721 aurel32
            bits = 4;
1746 798b0c25 bellard
            break;
1747 798b0c25 bellard
        case 8:
1748 798b0c25 bellard
            full_update |= update_palette256(s);
1749 798b0c25 bellard
            v = VGA_DRAW_LINE8;
1750 15342721 aurel32
            bits = 8;
1751 798b0c25 bellard
            break;
1752 798b0c25 bellard
        case 15:
1753 798b0c25 bellard
            v = VGA_DRAW_LINE15;
1754 15342721 aurel32
            bits = 16;
1755 798b0c25 bellard
            break;
1756 798b0c25 bellard
        case 16:
1757 798b0c25 bellard
            v = VGA_DRAW_LINE16;
1758 15342721 aurel32
            bits = 16;
1759 798b0c25 bellard
            break;
1760 798b0c25 bellard
        case 24:
1761 798b0c25 bellard
            v = VGA_DRAW_LINE24;
1762 15342721 aurel32
            bits = 24;
1763 798b0c25 bellard
            break;
1764 798b0c25 bellard
        case 32:
1765 798b0c25 bellard
            v = VGA_DRAW_LINE32;
1766 15342721 aurel32
            bits = 32;
1767 798b0c25 bellard
            break;
1768 4fa0f5d2 bellard
        }
1769 17b0018b bellard
    }
1770 d3079cd2 bellard
    vga_draw_line = vga_draw_line_table[v * NB_DEPTHS + get_depth_index(s->ds)];
1771 17b0018b bellard
1772 7d957bd8 aliguori
    if (!is_buffer_shared(s->ds->surface) && s->cursor_invalidate)
1773 a8aa669b bellard
        s->cursor_invalidate(s);
1774 3b46e624 ths
1775 e89f66ec bellard
    line_offset = s->line_offset;
1776 17b0018b bellard
#if 0
1777 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",
1778 17b0018b bellard
           width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
1779 17b0018b bellard
#endif
1780 e89f66ec bellard
    addr1 = (s->start_addr * 4);
1781 15342721 aurel32
    bwidth = (width * bits + 7) / 8;
1782 39cf7803 bellard
    y_start = -1;
1783 12c7e75a Avi Kivity
    page_min = -1;
1784 12c7e75a Avi Kivity
    page_max = 0;
1785 0e1f5a0c aliguori
    d = ds_get_data(s->ds);
1786 0e1f5a0c aliguori
    linesize = ds_get_linesize(s->ds);
1787 17b0018b bellard
    y1 = 0;
1788 e89f66ec bellard
    for(y = 0; y < height; y++) {
1789 e89f66ec bellard
        addr = addr1;
1790 39cf7803 bellard
        if (!(s->cr[0x17] & 1)) {
1791 17b0018b bellard
            int shift;
1792 e89f66ec bellard
            /* CGA compatibility handling */
1793 17b0018b bellard
            shift = 14 + ((s->cr[0x17] >> 6) & 1);
1794 17b0018b bellard
            addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
1795 e89f66ec bellard
        }
1796 39cf7803 bellard
        if (!(s->cr[0x17] & 2)) {
1797 17b0018b bellard
            addr = (addr & ~0x8000) | ((y1 & 2) << 14);
1798 e89f66ec bellard
        }
1799 4fa0f5d2 bellard
        page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
1800 4fa0f5d2 bellard
        page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
1801 5fafdf24 ths
        update = full_update |
1802 0a962c02 bellard
            cpu_physical_memory_get_dirty(page0, VGA_DIRTY_FLAG) |
1803 0a962c02 bellard
            cpu_physical_memory_get_dirty(page1, VGA_DIRTY_FLAG);
1804 4fa0f5d2 bellard
        if ((page1 - page0) > TARGET_PAGE_SIZE) {
1805 39cf7803 bellard
            /* if wide line, can use another page */
1806 5fafdf24 ths
            update |= cpu_physical_memory_get_dirty(page0 + TARGET_PAGE_SIZE,
1807 0a962c02 bellard
                                                    VGA_DIRTY_FLAG);
1808 39cf7803 bellard
        }
1809 a8aa669b bellard
        /* explicit invalidation for the hardware cursor */
1810 a8aa669b bellard
        update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
1811 e89f66ec bellard
        if (update) {
1812 39cf7803 bellard
            if (y_start < 0)
1813 39cf7803 bellard
                y_start = y;
1814 e89f66ec bellard
            if (page0 < page_min)
1815 e89f66ec bellard
                page_min = page0;
1816 e89f66ec bellard
            if (page1 > page_max)
1817 e89f66ec bellard
                page_max = page1;
1818 7d957bd8 aliguori
            if (!(is_buffer_shared(s->ds->surface))) {
1819 7d957bd8 aliguori
                vga_draw_line(s, d, s->vram_ptr + addr, width);
1820 7d957bd8 aliguori
                if (s->cursor_draw_line)
1821 7d957bd8 aliguori
                    s->cursor_draw_line(s, d, y);
1822 7d957bd8 aliguori
            }
1823 39cf7803 bellard
        } else {
1824 39cf7803 bellard
            if (y_start >= 0) {
1825 39cf7803 bellard
                /* flush to display */
1826 5fafdf24 ths
                dpy_update(s->ds, 0, y_start,
1827 799e709b aliguori
                           disp_width, y - y_start);
1828 39cf7803 bellard
                y_start = -1;
1829 39cf7803 bellard
            }
1830 e89f66ec bellard
        }
1831 a07cf92a bellard
        if (!multi_run) {
1832 f6c958c8 bellard
            mask = (s->cr[0x17] & 3) ^ 3;
1833 f6c958c8 bellard
            if ((y1 & mask) == mask)
1834 f6c958c8 bellard
                addr1 += line_offset;
1835 f6c958c8 bellard
            y1++;
1836 799e709b aliguori
            multi_run = multi_scan;
1837 a07cf92a bellard
        } else {
1838 a07cf92a bellard
            multi_run--;
1839 e89f66ec bellard
        }
1840 f6c958c8 bellard
        /* line compare acts on the displayed lines */
1841 f6c958c8 bellard
        if (y == s->line_compare)
1842 f6c958c8 bellard
            addr1 = 0;
1843 e89f66ec bellard
        d += linesize;
1844 e89f66ec bellard
    }
1845 39cf7803 bellard
    if (y_start >= 0) {
1846 39cf7803 bellard
        /* flush to display */
1847 5fafdf24 ths
        dpy_update(s->ds, 0, y_start,
1848 799e709b aliguori
                   disp_width, y - y_start);
1849 39cf7803 bellard
    }
1850 e89f66ec bellard
    /* reset modified pages */
1851 12c7e75a Avi Kivity
    if (page_max >= page_min) {
1852 0a962c02 bellard
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
1853 0a962c02 bellard
                                        VGA_DIRTY_FLAG);
1854 e89f66ec bellard
    }
1855 a8aa669b bellard
    memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
1856 e89f66ec bellard
}
1857 e89f66ec bellard
1858 cedd91d2 Juan Quintela
static void vga_draw_blank(VGACommonState *s, int full_update)
1859 2aebb3eb bellard
{
1860 2aebb3eb bellard
    int i, w, val;
1861 2aebb3eb bellard
    uint8_t *d;
1862 2aebb3eb bellard
1863 2aebb3eb bellard
    if (!full_update)
1864 2aebb3eb bellard
        return;
1865 2aebb3eb bellard
    if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
1866 2aebb3eb bellard
        return;
1867 2bec46dc aliguori
1868 7d957bd8 aliguori
    s->rgb_to_pixel =
1869 7d957bd8 aliguori
        rgb_to_pixel_dup_table[get_depth_index(s->ds)];
1870 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(s->ds) == 8)
1871 2aebb3eb bellard
        val = s->rgb_to_pixel(0, 0, 0);
1872 2aebb3eb bellard
    else
1873 2aebb3eb bellard
        val = 0;
1874 0e1f5a0c aliguori
    w = s->last_scr_width * ((ds_get_bits_per_pixel(s->ds) + 7) >> 3);
1875 0e1f5a0c aliguori
    d = ds_get_data(s->ds);
1876 2aebb3eb bellard
    for(i = 0; i < s->last_scr_height; i++) {
1877 2aebb3eb bellard
        memset(d, val, w);
1878 0e1f5a0c aliguori
        d += ds_get_linesize(s->ds);
1879 2aebb3eb bellard
    }
1880 5fafdf24 ths
    dpy_update(s->ds, 0, 0,
1881 2aebb3eb bellard
               s->last_scr_width, s->last_scr_height);
1882 2aebb3eb bellard
}
1883 2aebb3eb bellard
1884 799e709b aliguori
#define GMODE_TEXT     0
1885 799e709b aliguori
#define GMODE_GRAPH    1
1886 799e709b aliguori
#define GMODE_BLANK 2
1887 799e709b aliguori
1888 95219897 pbrook
static void vga_update_display(void *opaque)
1889 e89f66ec bellard
{
1890 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
1891 799e709b aliguori
    int full_update, graphic_mode;
1892 e89f66ec bellard
1893 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(s->ds) == 0) {
1894 0f35920c bellard
        /* nothing to do */
1895 59a983b9 bellard
    } else {
1896 3098b9fd Aurelien Jarno
        full_update = 0;
1897 799e709b aliguori
        if (!(s->ar_index & 0x20)) {
1898 799e709b aliguori
            graphic_mode = GMODE_BLANK;
1899 799e709b aliguori
        } else {
1900 799e709b aliguori
            graphic_mode = s->gr[6] & 1;
1901 799e709b aliguori
        }
1902 799e709b aliguori
        if (graphic_mode != s->graphic_mode) {
1903 799e709b aliguori
            s->graphic_mode = graphic_mode;
1904 799e709b aliguori
            full_update = 1;
1905 799e709b aliguori
        }
1906 799e709b aliguori
        switch(graphic_mode) {
1907 2aebb3eb bellard
        case GMODE_TEXT:
1908 e89f66ec bellard
            vga_draw_text(s, full_update);
1909 2aebb3eb bellard
            break;
1910 2aebb3eb bellard
        case GMODE_GRAPH:
1911 2aebb3eb bellard
            vga_draw_graphic(s, full_update);
1912 2aebb3eb bellard
            break;
1913 2aebb3eb bellard
        case GMODE_BLANK:
1914 2aebb3eb bellard
        default:
1915 2aebb3eb bellard
            vga_draw_blank(s, full_update);
1916 2aebb3eb bellard
            break;
1917 2aebb3eb bellard
        }
1918 e89f66ec bellard
    }
1919 e89f66ec bellard
}
1920 e89f66ec bellard
1921 a130a41e bellard
/* force a full display refresh */
1922 95219897 pbrook
static void vga_invalidate_display(void *opaque)
1923 a130a41e bellard
{
1924 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
1925 3b46e624 ths
1926 3098b9fd Aurelien Jarno
    s->last_width = -1;
1927 3098b9fd Aurelien Jarno
    s->last_height = -1;
1928 a130a41e bellard
}
1929 a130a41e bellard
1930 03a3e7ba Juan Quintela
void vga_common_reset(VGACommonState *s)
1931 e89f66ec bellard
{
1932 6e6b7363 blueswir1
    s->lfb_addr = 0;
1933 6e6b7363 blueswir1
    s->lfb_end = 0;
1934 6e6b7363 blueswir1
    s->map_addr = 0;
1935 6e6b7363 blueswir1
    s->map_end = 0;
1936 6e6b7363 blueswir1
    s->lfb_vram_mapped = 0;
1937 6e6b7363 blueswir1
    s->sr_index = 0;
1938 6e6b7363 blueswir1
    memset(s->sr, '\0', sizeof(s->sr));
1939 6e6b7363 blueswir1
    s->gr_index = 0;
1940 6e6b7363 blueswir1
    memset(s->gr, '\0', sizeof(s->gr));
1941 6e6b7363 blueswir1
    s->ar_index = 0;
1942 6e6b7363 blueswir1
    memset(s->ar, '\0', sizeof(s->ar));
1943 6e6b7363 blueswir1
    s->ar_flip_flop = 0;
1944 6e6b7363 blueswir1
    s->cr_index = 0;
1945 6e6b7363 blueswir1
    memset(s->cr, '\0', sizeof(s->cr));
1946 6e6b7363 blueswir1
    s->msr = 0;
1947 6e6b7363 blueswir1
    s->fcr = 0;
1948 6e6b7363 blueswir1
    s->st00 = 0;
1949 6e6b7363 blueswir1
    s->st01 = 0;
1950 6e6b7363 blueswir1
    s->dac_state = 0;
1951 6e6b7363 blueswir1
    s->dac_sub_index = 0;
1952 6e6b7363 blueswir1
    s->dac_read_index = 0;
1953 6e6b7363 blueswir1
    s->dac_write_index = 0;
1954 6e6b7363 blueswir1
    memset(s->dac_cache, '\0', sizeof(s->dac_cache));
1955 6e6b7363 blueswir1
    s->dac_8bit = 0;
1956 6e6b7363 blueswir1
    memset(s->palette, '\0', sizeof(s->palette));
1957 6e6b7363 blueswir1
    s->bank_offset = 0;
1958 6e6b7363 blueswir1
#ifdef CONFIG_BOCHS_VBE
1959 6e6b7363 blueswir1
    s->vbe_index = 0;
1960 6e6b7363 blueswir1
    memset(s->vbe_regs, '\0', sizeof(s->vbe_regs));
1961 af92284b Gerd Hoffmann
    s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
1962 6e6b7363 blueswir1
    s->vbe_start_addr = 0;
1963 6e6b7363 blueswir1
    s->vbe_line_offset = 0;
1964 6e6b7363 blueswir1
    s->vbe_bank_mask = (s->vram_size >> 16) - 1;
1965 6e6b7363 blueswir1
#endif
1966 6e6b7363 blueswir1
    memset(s->font_offsets, '\0', sizeof(s->font_offsets));
1967 799e709b aliguori
    s->graphic_mode = -1; /* force full update */
1968 6e6b7363 blueswir1
    s->shift_control = 0;
1969 6e6b7363 blueswir1
    s->double_scan = 0;
1970 6e6b7363 blueswir1
    s->line_offset = 0;
1971 6e6b7363 blueswir1
    s->line_compare = 0;
1972 6e6b7363 blueswir1
    s->start_addr = 0;
1973 6e6b7363 blueswir1
    s->plane_updated = 0;
1974 6e6b7363 blueswir1
    s->last_cw = 0;
1975 6e6b7363 blueswir1
    s->last_ch = 0;
1976 6e6b7363 blueswir1
    s->last_width = 0;
1977 6e6b7363 blueswir1
    s->last_height = 0;
1978 6e6b7363 blueswir1
    s->last_scr_width = 0;
1979 6e6b7363 blueswir1
    s->last_scr_height = 0;
1980 6e6b7363 blueswir1
    s->cursor_start = 0;
1981 6e6b7363 blueswir1
    s->cursor_end = 0;
1982 6e6b7363 blueswir1
    s->cursor_offset = 0;
1983 6e6b7363 blueswir1
    memset(s->invalidated_y_table, '\0', sizeof(s->invalidated_y_table));
1984 6e6b7363 blueswir1
    memset(s->last_palette, '\0', sizeof(s->last_palette));
1985 6e6b7363 blueswir1
    memset(s->last_ch_attr, '\0', sizeof(s->last_ch_attr));
1986 6e6b7363 blueswir1
    switch (vga_retrace_method) {
1987 6e6b7363 blueswir1
    case VGA_RETRACE_DUMB:
1988 6e6b7363 blueswir1
        break;
1989 6e6b7363 blueswir1
    case VGA_RETRACE_PRECISE:
1990 6e6b7363 blueswir1
        memset(&s->retrace_info, 0, sizeof (s->retrace_info));
1991 6e6b7363 blueswir1
        break;
1992 6e6b7363 blueswir1
    }
1993 e89f66ec bellard
}
1994 e89f66ec bellard
1995 03a3e7ba Juan Quintela
static void vga_reset(void *opaque)
1996 03a3e7ba Juan Quintela
{
1997 cedd91d2 Juan Quintela
    VGACommonState *s =  opaque;
1998 03a3e7ba Juan Quintela
    vga_common_reset(s);
1999 03a3e7ba Juan Quintela
}
2000 03a3e7ba Juan Quintela
2001 4d3b6f6e balrog
#define TEXTMODE_X(x)        ((x) % width)
2002 4d3b6f6e balrog
#define TEXTMODE_Y(x)        ((x) / width)
2003 4d3b6f6e balrog
#define VMEM2CHTYPE(v)        ((v & 0xff0007ff) | \
2004 4d3b6f6e balrog
        ((v & 0x00000800) << 10) | ((v & 0x00007000) >> 1))
2005 4d3b6f6e balrog
/* relay text rendering to the display driver
2006 4d3b6f6e balrog
 * instead of doing a full vga_update_display() */
2007 c227f099 Anthony Liguori
static void vga_update_text(void *opaque, console_ch_t *chardata)
2008 4d3b6f6e balrog
{
2009 cedd91d2 Juan Quintela
    VGACommonState *s =  opaque;
2010 799e709b aliguori
    int graphic_mode, i, cursor_offset, cursor_visible;
2011 4d3b6f6e balrog
    int cw, cheight, width, height, size, c_min, c_max;
2012 4d3b6f6e balrog
    uint32_t *src;
2013 c227f099 Anthony Liguori
    console_ch_t *dst, val;
2014 4d3b6f6e balrog
    char msg_buffer[80];
2015 799e709b aliguori
    int full_update = 0;
2016 799e709b aliguori
2017 799e709b aliguori
    if (!(s->ar_index & 0x20)) {
2018 799e709b aliguori
        graphic_mode = GMODE_BLANK;
2019 799e709b aliguori
    } else {
2020 799e709b aliguori
        graphic_mode = s->gr[6] & 1;
2021 799e709b aliguori
    }
2022 799e709b aliguori
    if (graphic_mode != s->graphic_mode) {
2023 799e709b aliguori
        s->graphic_mode = graphic_mode;
2024 799e709b aliguori
        full_update = 1;
2025 799e709b aliguori
    }
2026 799e709b aliguori
    if (s->last_width == -1) {
2027 799e709b aliguori
        s->last_width = 0;
2028 799e709b aliguori
        full_update = 1;
2029 799e709b aliguori
    }
2030 4d3b6f6e balrog
2031 799e709b aliguori
    switch (graphic_mode) {
2032 4d3b6f6e balrog
    case GMODE_TEXT:
2033 4d3b6f6e balrog
        /* TODO: update palette */
2034 799e709b aliguori
        full_update |= update_basic_params(s);
2035 4d3b6f6e balrog
2036 799e709b aliguori
        /* total width & height */
2037 799e709b aliguori
        cheight = (s->cr[9] & 0x1f) + 1;
2038 799e709b aliguori
        cw = 8;
2039 799e709b aliguori
        if (!(s->sr[1] & 0x01))
2040 799e709b aliguori
            cw = 9;
2041 799e709b aliguori
        if (s->sr[1] & 0x08)
2042 799e709b aliguori
            cw = 16; /* NOTE: no 18 pixel wide */
2043 799e709b aliguori
        width = (s->cr[0x01] + 1);
2044 799e709b aliguori
        if (s->cr[0x06] == 100) {
2045 799e709b aliguori
            /* ugly hack for CGA 160x100x16 - explain me the logic */
2046 799e709b aliguori
            height = 100;
2047 799e709b aliguori
        } else {
2048 799e709b aliguori
            height = s->cr[0x12] | 
2049 799e709b aliguori
                ((s->cr[0x07] & 0x02) << 7) | 
2050 799e709b aliguori
                ((s->cr[0x07] & 0x40) << 3);
2051 799e709b aliguori
            height = (height + 1) / cheight;
2052 4d3b6f6e balrog
        }
2053 4d3b6f6e balrog
2054 4d3b6f6e balrog
        size = (height * width);
2055 4d3b6f6e balrog
        if (size > CH_ATTR_SIZE) {
2056 4d3b6f6e balrog
            if (!full_update)
2057 4d3b6f6e balrog
                return;
2058 4d3b6f6e balrog
2059 363a37d5 blueswir1
            snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Text mode",
2060 363a37d5 blueswir1
                     width, height);
2061 4d3b6f6e balrog
            break;
2062 4d3b6f6e balrog
        }
2063 4d3b6f6e balrog
2064 799e709b aliguori
        if (width != s->last_width || height != s->last_height ||
2065 799e709b aliguori
            cw != s->last_cw || cheight != s->last_ch) {
2066 799e709b aliguori
            s->last_scr_width = width * cw;
2067 799e709b aliguori
            s->last_scr_height = height * cheight;
2068 799e709b aliguori
            s->ds->surface->width = width;
2069 799e709b aliguori
            s->ds->surface->height = height;
2070 799e709b aliguori
            dpy_resize(s->ds);
2071 799e709b aliguori
            s->last_width = width;
2072 799e709b aliguori
            s->last_height = height;
2073 799e709b aliguori
            s->last_ch = cheight;
2074 799e709b aliguori
            s->last_cw = cw;
2075 799e709b aliguori
            full_update = 1;
2076 799e709b aliguori
        }
2077 799e709b aliguori
2078 4d3b6f6e balrog
        /* Update "hardware" cursor */
2079 4d3b6f6e balrog
        cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
2080 4d3b6f6e balrog
        if (cursor_offset != s->cursor_offset ||
2081 4d3b6f6e balrog
            s->cr[0xa] != s->cursor_start ||
2082 4d3b6f6e balrog
            s->cr[0xb] != s->cursor_end || full_update) {
2083 4d3b6f6e balrog
            cursor_visible = !(s->cr[0xa] & 0x20);
2084 4d3b6f6e balrog
            if (cursor_visible && cursor_offset < size && cursor_offset >= 0)
2085 4d3b6f6e balrog
                dpy_cursor(s->ds,
2086 4d3b6f6e balrog
                           TEXTMODE_X(cursor_offset),
2087 4d3b6f6e balrog
                           TEXTMODE_Y(cursor_offset));
2088 4d3b6f6e balrog
            else
2089 4d3b6f6e balrog
                dpy_cursor(s->ds, -1, -1);
2090 4d3b6f6e balrog
            s->cursor_offset = cursor_offset;
2091 4d3b6f6e balrog
            s->cursor_start = s->cr[0xa];
2092 4d3b6f6e balrog
            s->cursor_end = s->cr[0xb];
2093 4d3b6f6e balrog
        }
2094 4d3b6f6e balrog
2095 4d3b6f6e balrog
        src = (uint32_t *) s->vram_ptr + s->start_addr;
2096 4d3b6f6e balrog
        dst = chardata;
2097 4d3b6f6e balrog
2098 4d3b6f6e balrog
        if (full_update) {
2099 4d3b6f6e balrog
            for (i = 0; i < size; src ++, dst ++, i ++)
2100 4d3b6f6e balrog
                console_write_ch(dst, VMEM2CHTYPE(*src));
2101 4d3b6f6e balrog
2102 4d3b6f6e balrog
            dpy_update(s->ds, 0, 0, width, height);
2103 4d3b6f6e balrog
        } else {
2104 4d3b6f6e balrog
            c_max = 0;
2105 4d3b6f6e balrog
2106 4d3b6f6e balrog
            for (i = 0; i < size; src ++, dst ++, i ++) {
2107 4d3b6f6e balrog
                console_write_ch(&val, VMEM2CHTYPE(*src));
2108 4d3b6f6e balrog
                if (*dst != val) {
2109 4d3b6f6e balrog
                    *dst = val;
2110 4d3b6f6e balrog
                    c_max = i;
2111 4d3b6f6e balrog
                    break;
2112 4d3b6f6e balrog
                }
2113 4d3b6f6e balrog
            }
2114 4d3b6f6e balrog
            c_min = i;
2115 4d3b6f6e balrog
            for (; i < size; src ++, dst ++, i ++) {
2116 4d3b6f6e balrog
                console_write_ch(&val, VMEM2CHTYPE(*src));
2117 4d3b6f6e balrog
                if (*dst != val) {
2118 4d3b6f6e balrog
                    *dst = val;
2119 4d3b6f6e balrog
                    c_max = i;
2120 4d3b6f6e balrog
                }
2121 4d3b6f6e balrog
            }
2122 4d3b6f6e balrog
2123 4d3b6f6e balrog
            if (c_min <= c_max) {
2124 4d3b6f6e balrog
                i = TEXTMODE_Y(c_min);
2125 4d3b6f6e balrog
                dpy_update(s->ds, 0, i, width, TEXTMODE_Y(c_max) - i + 1);
2126 4d3b6f6e balrog
            }
2127 4d3b6f6e balrog
        }
2128 4d3b6f6e balrog
2129 4d3b6f6e balrog
        return;
2130 4d3b6f6e balrog
    case GMODE_GRAPH:
2131 4d3b6f6e balrog
        if (!full_update)
2132 4d3b6f6e balrog
            return;
2133 4d3b6f6e balrog
2134 4d3b6f6e balrog
        s->get_resolution(s, &width, &height);
2135 363a37d5 blueswir1
        snprintf(msg_buffer, sizeof(msg_buffer), "%i x %i Graphic mode",
2136 363a37d5 blueswir1
                 width, height);
2137 4d3b6f6e balrog
        break;
2138 4d3b6f6e balrog
    case GMODE_BLANK:
2139 4d3b6f6e balrog
    default:
2140 4d3b6f6e balrog
        if (!full_update)
2141 4d3b6f6e balrog
            return;
2142 4d3b6f6e balrog
2143 363a37d5 blueswir1
        snprintf(msg_buffer, sizeof(msg_buffer), "VGA Blank mode");
2144 4d3b6f6e balrog
        break;
2145 4d3b6f6e balrog
    }
2146 4d3b6f6e balrog
2147 4d3b6f6e balrog
    /* Display a message */
2148 5228c2d3 balrog
    s->last_width = 60;
2149 5228c2d3 balrog
    s->last_height = height = 3;
2150 4d3b6f6e balrog
    dpy_cursor(s->ds, -1, -1);
2151 7d957bd8 aliguori
    s->ds->surface->width = s->last_width;
2152 7d957bd8 aliguori
    s->ds->surface->height = height;
2153 7d957bd8 aliguori
    dpy_resize(s->ds);
2154 4d3b6f6e balrog
2155 5228c2d3 balrog
    for (dst = chardata, i = 0; i < s->last_width * height; i ++)
2156 4d3b6f6e balrog
        console_write_ch(dst ++, ' ');
2157 4d3b6f6e balrog
2158 4d3b6f6e balrog
    size = strlen(msg_buffer);
2159 5228c2d3 balrog
    width = (s->last_width - size) / 2;
2160 5228c2d3 balrog
    dst = chardata + s->last_width + width;
2161 4d3b6f6e balrog
    for (i = 0; i < size; i ++)
2162 4d3b6f6e balrog
        console_write_ch(dst ++, 0x00200100 | msg_buffer[i]);
2163 4d3b6f6e balrog
2164 5228c2d3 balrog
    dpy_update(s->ds, 0, 0, s->last_width, height);
2165 4d3b6f6e balrog
}
2166 4d3b6f6e balrog
2167 f97e36b9 Juan Quintela
CPUReadMemoryFunc * const vga_mem_read[3] = {
2168 e89f66ec bellard
    vga_mem_readb,
2169 e89f66ec bellard
    vga_mem_readw,
2170 e89f66ec bellard
    vga_mem_readl,
2171 e89f66ec bellard
};
2172 e89f66ec bellard
2173 f97e36b9 Juan Quintela
CPUWriteMemoryFunc * const vga_mem_write[3] = {
2174 e89f66ec bellard
    vga_mem_writeb,
2175 e89f66ec bellard
    vga_mem_writew,
2176 e89f66ec bellard
    vga_mem_writel,
2177 e89f66ec bellard
};
2178 e89f66ec bellard
2179 11b6b345 Juan Quintela
static int vga_common_post_load(void *opaque, int version_id)
2180 b0a21b53 bellard
{
2181 0d65ddc3 Juan Quintela
    VGACommonState *s = opaque;
2182 11b6b345 Juan Quintela
2183 11b6b345 Juan Quintela
    /* force refresh */
2184 11b6b345 Juan Quintela
    s->graphic_mode = -1;
2185 11b6b345 Juan Quintela
    return 0;
2186 11b6b345 Juan Quintela
}
2187 11b6b345 Juan Quintela
2188 11b6b345 Juan Quintela
const VMStateDescription vmstate_vga_common = {
2189 11b6b345 Juan Quintela
    .name = "vga",
2190 11b6b345 Juan Quintela
    .version_id = 2,
2191 11b6b345 Juan Quintela
    .minimum_version_id = 2,
2192 11b6b345 Juan Quintela
    .minimum_version_id_old = 2,
2193 11b6b345 Juan Quintela
    .post_load = vga_common_post_load,
2194 11b6b345 Juan Quintela
    .fields      = (VMStateField []) {
2195 11b6b345 Juan Quintela
        VMSTATE_UINT32(latch, VGACommonState),
2196 11b6b345 Juan Quintela
        VMSTATE_UINT8(sr_index, VGACommonState),
2197 11b6b345 Juan Quintela
        VMSTATE_PARTIAL_BUFFER(sr, VGACommonState, 8),
2198 11b6b345 Juan Quintela
        VMSTATE_UINT8(gr_index, VGACommonState),
2199 11b6b345 Juan Quintela
        VMSTATE_PARTIAL_BUFFER(gr, VGACommonState, 16),
2200 11b6b345 Juan Quintela
        VMSTATE_UINT8(ar_index, VGACommonState),
2201 11b6b345 Juan Quintela
        VMSTATE_BUFFER(ar, VGACommonState),
2202 11b6b345 Juan Quintela
        VMSTATE_INT32(ar_flip_flop, VGACommonState),
2203 11b6b345 Juan Quintela
        VMSTATE_UINT8(cr_index, VGACommonState),
2204 11b6b345 Juan Quintela
        VMSTATE_BUFFER(cr, VGACommonState),
2205 11b6b345 Juan Quintela
        VMSTATE_UINT8(msr, VGACommonState),
2206 11b6b345 Juan Quintela
        VMSTATE_UINT8(fcr, VGACommonState),
2207 11b6b345 Juan Quintela
        VMSTATE_UINT8(st00, VGACommonState),
2208 11b6b345 Juan Quintela
        VMSTATE_UINT8(st01, VGACommonState),
2209 11b6b345 Juan Quintela
2210 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_state, VGACommonState),
2211 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_sub_index, VGACommonState),
2212 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_read_index, VGACommonState),
2213 11b6b345 Juan Quintela
        VMSTATE_UINT8(dac_write_index, VGACommonState),
2214 11b6b345 Juan Quintela
        VMSTATE_BUFFER(dac_cache, VGACommonState),
2215 11b6b345 Juan Quintela
        VMSTATE_BUFFER(palette, VGACommonState),
2216 11b6b345 Juan Quintela
2217 11b6b345 Juan Quintela
        VMSTATE_INT32(bank_offset, VGACommonState),
2218 11b6b345 Juan Quintela
        VMSTATE_UINT8_EQUAL(is_vbe_vmstate, VGACommonState),
2219 b0a21b53 bellard
#ifdef CONFIG_BOCHS_VBE
2220 11b6b345 Juan Quintela
        VMSTATE_UINT16(vbe_index, VGACommonState),
2221 11b6b345 Juan Quintela
        VMSTATE_UINT16_ARRAY(vbe_regs, VGACommonState, VBE_DISPI_INDEX_NB),
2222 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_start_addr, VGACommonState),
2223 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_line_offset, VGACommonState),
2224 11b6b345 Juan Quintela
        VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
2225 b0a21b53 bellard
#endif
2226 11b6b345 Juan Quintela
        VMSTATE_END_OF_LIST()
2227 11b6b345 Juan Quintela
    }
2228 11b6b345 Juan Quintela
};
2229 11b6b345 Juan Quintela
2230 a4a2f59c Juan Quintela
void vga_common_init(VGACommonState *s, int vga_ram_size)
2231 e89f66ec bellard
{
2232 17b0018b bellard
    int i, j, v, b;
2233 e89f66ec bellard
2234 e89f66ec bellard
    for(i = 0;i < 256; i++) {
2235 e89f66ec bellard
        v = 0;
2236 e89f66ec bellard
        for(j = 0; j < 8; j++) {
2237 e89f66ec bellard
            v |= ((i >> j) & 1) << (j * 4);
2238 e89f66ec bellard
        }
2239 e89f66ec bellard
        expand4[i] = v;
2240 e89f66ec bellard
2241 e89f66ec bellard
        v = 0;
2242 e89f66ec bellard
        for(j = 0; j < 4; j++) {
2243 e89f66ec bellard
            v |= ((i >> (2 * j)) & 3) << (j * 4);
2244 e89f66ec bellard
        }
2245 e89f66ec bellard
        expand2[i] = v;
2246 e89f66ec bellard
    }
2247 17b0018b bellard
    for(i = 0; i < 16; i++) {
2248 17b0018b bellard
        v = 0;
2249 17b0018b bellard
        for(j = 0; j < 4; j++) {
2250 17b0018b bellard
            b = ((i >> j) & 1);
2251 17b0018b bellard
            v |= b << (2 * j);
2252 17b0018b bellard
            v |= b << (2 * j + 1);
2253 17b0018b bellard
        }
2254 17b0018b bellard
        expand4to8[i] = v;
2255 17b0018b bellard
    }
2256 e89f66ec bellard
2257 2a3138ab Juan Quintela
#ifdef CONFIG_BOCHS_VBE
2258 2a3138ab Juan Quintela
    s->is_vbe_vmstate = 1;
2259 2a3138ab Juan Quintela
#else
2260 2a3138ab Juan Quintela
    s->is_vbe_vmstate = 0;
2261 2a3138ab Juan Quintela
#endif
2262 1724f049 Alex Williamson
    s->vram_offset = qemu_ram_alloc(NULL, "vga.vram", vga_ram_size);
2263 b584726d pbrook
    s->vram_ptr = qemu_get_ram_ptr(s->vram_offset);
2264 e89f66ec bellard
    s->vram_size = vga_ram_size;
2265 798b0c25 bellard
    s->get_bpp = vga_get_bpp;
2266 798b0c25 bellard
    s->get_offsets = vga_get_offsets;
2267 a130a41e bellard
    s->get_resolution = vga_get_resolution;
2268 d34cab9f ths
    s->update = vga_update_display;
2269 d34cab9f ths
    s->invalidate = vga_invalidate_display;
2270 d34cab9f ths
    s->screen_dump = vga_screen_dump;
2271 4d3b6f6e balrog
    s->text_update = vga_update_text;
2272 cb5a7aa8 malc
    switch (vga_retrace_method) {
2273 cb5a7aa8 malc
    case VGA_RETRACE_DUMB:
2274 cb5a7aa8 malc
        s->retrace = vga_dumb_retrace;
2275 cb5a7aa8 malc
        s->update_retrace_info = vga_dumb_update_retrace_info;
2276 cb5a7aa8 malc
        break;
2277 cb5a7aa8 malc
2278 cb5a7aa8 malc
    case VGA_RETRACE_PRECISE:
2279 cb5a7aa8 malc
        s->retrace = vga_precise_retrace;
2280 cb5a7aa8 malc
        s->update_retrace_info = vga_precise_update_retrace_info;
2281 cb5a7aa8 malc
        break;
2282 cb5a7aa8 malc
    }
2283 798b0c25 bellard
}
2284 798b0c25 bellard
2285 d2269f6f bellard
/* used by both ISA and PCI */
2286 cedd91d2 Juan Quintela
void vga_init(VGACommonState *s)
2287 798b0c25 bellard
{
2288 d2269f6f bellard
    int vga_io_memory;
2289 7b17d41e bellard
2290 a08d4367 Jan Kiszka
    qemu_register_reset(vga_reset, s);
2291 b0a21b53 bellard
2292 0f35920c bellard
    register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
2293 e89f66ec bellard
2294 0f35920c bellard
    register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
2295 0f35920c bellard
    register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
2296 0f35920c bellard
    register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
2297 0f35920c bellard
    register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
2298 e89f66ec bellard
2299 0f35920c bellard
    register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
2300 e89f66ec bellard
2301 0f35920c bellard
    register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
2302 0f35920c bellard
    register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
2303 0f35920c bellard
    register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
2304 0f35920c bellard
    register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
2305 26aa7d72 bellard
    s->bank_offset = 0;
2306 e89f66ec bellard
2307 4fa0f5d2 bellard
#ifdef CONFIG_BOCHS_VBE
2308 09a79b49 bellard
#if defined (TARGET_I386)
2309 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2310 09a79b49 bellard
    register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
2311 4fa0f5d2 bellard
2312 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2313 09a79b49 bellard
    register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
2314 09a79b49 bellard
#else
2315 09a79b49 bellard
    register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
2316 09a79b49 bellard
    register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
2317 09a79b49 bellard
2318 09a79b49 bellard
    register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
2319 09a79b49 bellard
    register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
2320 4fa0f5d2 bellard
#endif
2321 09a79b49 bellard
#endif /* CONFIG_BOCHS_VBE */
2322 4fa0f5d2 bellard
2323 1eed09cb Avi Kivity
    vga_io_memory = cpu_register_io_memory(vga_mem_read, vga_mem_write, s);
2324 5fafdf24 ths
    cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
2325 26aa7d72 bellard
                                 vga_io_memory);
2326 f65ed4c1 aliguori
    qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
2327 d2269f6f bellard
}
2328 d2269f6f bellard
2329 f0138a63 Anthony Liguori
void vga_init_vbe(VGACommonState *s)
2330 f0138a63 Anthony Liguori
{
2331 f0138a63 Anthony Liguori
#ifdef CONFIG_BOCHS_VBE
2332 f0138a63 Anthony Liguori
    /* XXX: use optimized standard vga accesses */
2333 f0138a63 Anthony Liguori
    cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
2334 f0138a63 Anthony Liguori
                                 VGA_RAM_SIZE, s->vram_offset);
2335 f0138a63 Anthony Liguori
    s->vbe_mapped = 1;
2336 f0138a63 Anthony Liguori
#endif 
2337 f0138a63 Anthony Liguori
}
2338 59a983b9 bellard
/********************************************************/
2339 59a983b9 bellard
/* vga screen dump */
2340 59a983b9 bellard
2341 04a52b41 Stefano Stabellini
static void vga_save_dpy_update(DisplayState *ds,
2342 59a983b9 bellard
                                int x, int y, int w, int h)
2343 59a983b9 bellard
{
2344 04a52b41 Stefano Stabellini
    if (screen_dump_filename) {
2345 04a52b41 Stefano Stabellini
        ppm_save(screen_dump_filename, ds->surface);
2346 04a52b41 Stefano Stabellini
        screen_dump_filename = NULL;
2347 04a52b41 Stefano Stabellini
    }
2348 59a983b9 bellard
}
2349 59a983b9 bellard
2350 7d957bd8 aliguori
static void vga_save_dpy_resize(DisplayState *s)
2351 59a983b9 bellard
{
2352 59a983b9 bellard
}
2353 59a983b9 bellard
2354 59a983b9 bellard
static void vga_save_dpy_refresh(DisplayState *s)
2355 59a983b9 bellard
{
2356 59a983b9 bellard
}
2357 59a983b9 bellard
2358 e07d630a aliguori
int ppm_save(const char *filename, struct DisplaySurface *ds)
2359 59a983b9 bellard
{
2360 59a983b9 bellard
    FILE *f;
2361 59a983b9 bellard
    uint8_t *d, *d1;
2362 e07d630a aliguori
    uint32_t v;
2363 59a983b9 bellard
    int y, x;
2364 e07d630a aliguori
    uint8_t r, g, b;
2365 59a983b9 bellard
2366 59a983b9 bellard
    f = fopen(filename, "wb");
2367 59a983b9 bellard
    if (!f)
2368 59a983b9 bellard
        return -1;
2369 59a983b9 bellard
    fprintf(f, "P6\n%d %d\n%d\n",
2370 e07d630a aliguori
            ds->width, ds->height, 255);
2371 e07d630a aliguori
    d1 = ds->data;
2372 e07d630a aliguori
    for(y = 0; y < ds->height; y++) {
2373 59a983b9 bellard
        d = d1;
2374 e07d630a aliguori
        for(x = 0; x < ds->width; x++) {
2375 e07d630a aliguori
            if (ds->pf.bits_per_pixel == 32)
2376 e07d630a aliguori
                v = *(uint32_t *)d;
2377 e07d630a aliguori
            else
2378 e07d630a aliguori
                v = (uint32_t) (*(uint16_t *)d);
2379 e07d630a aliguori
            r = ((v >> ds->pf.rshift) & ds->pf.rmax) * 256 /
2380 e07d630a aliguori
                (ds->pf.rmax + 1);
2381 e07d630a aliguori
            g = ((v >> ds->pf.gshift) & ds->pf.gmax) * 256 /
2382 e07d630a aliguori
                (ds->pf.gmax + 1);
2383 e07d630a aliguori
            b = ((v >> ds->pf.bshift) & ds->pf.bmax) * 256 /
2384 e07d630a aliguori
                (ds->pf.bmax + 1);
2385 e07d630a aliguori
            fputc(r, f);
2386 e07d630a aliguori
            fputc(g, f);
2387 e07d630a aliguori
            fputc(b, f);
2388 e07d630a aliguori
            d += ds->pf.bytes_per_pixel;
2389 59a983b9 bellard
        }
2390 e07d630a aliguori
        d1 += ds->linesize;
2391 59a983b9 bellard
    }
2392 59a983b9 bellard
    fclose(f);
2393 59a983b9 bellard
    return 0;
2394 59a983b9 bellard
}
2395 59a983b9 bellard
2396 04a52b41 Stefano Stabellini
static DisplayChangeListener* vga_screen_dump_init(DisplayState *ds)
2397 4c5e8c5c blueswir1
{
2398 04a52b41 Stefano Stabellini
    DisplayChangeListener *dcl;
2399 4c5e8c5c blueswir1
2400 04a52b41 Stefano Stabellini
    dcl = qemu_mallocz(sizeof(DisplayChangeListener));
2401 04a52b41 Stefano Stabellini
    dcl->dpy_update = vga_save_dpy_update;
2402 04a52b41 Stefano Stabellini
    dcl->dpy_resize = vga_save_dpy_resize;
2403 04a52b41 Stefano Stabellini
    dcl->dpy_refresh = vga_save_dpy_refresh;
2404 04a52b41 Stefano Stabellini
    register_displaychangelistener(ds, dcl);
2405 04a52b41 Stefano Stabellini
    return dcl;
2406 4c5e8c5c blueswir1
}
2407 4c5e8c5c blueswir1
2408 4c5e8c5c blueswir1
/* save the vga display in a PPM image even if no display is
2409 4c5e8c5c blueswir1
   available */
2410 4c5e8c5c blueswir1
static void vga_screen_dump(void *opaque, const char *filename)
2411 4c5e8c5c blueswir1
{
2412 cedd91d2 Juan Quintela
    VGACommonState *s = opaque;
2413 4c5e8c5c blueswir1
2414 04a52b41 Stefano Stabellini
    if (!screen_dump_dcl)
2415 04a52b41 Stefano Stabellini
        screen_dump_dcl = vga_screen_dump_init(s->ds);
2416 04a52b41 Stefano Stabellini
2417 04a52b41 Stefano Stabellini
    screen_dump_filename = (char *)filename;
2418 9d1b494a aliguori
    vga_invalidate_display(s);
2419 04a52b41 Stefano Stabellini
    vga_hw_update();
2420 4c5e8c5c blueswir1
}