Statistics
| Branch: | Revision:

root / hw / tcx.c @ ff753bb9

History | View | Annotate | Download (17.7 kB)

1 420557e8 bellard
/*
2 6f7e9aec bellard
 * QEMU TCX Frame buffer
3 5fafdf24 ths
 *
4 6f7e9aec bellard
 * Copyright (c) 2003-2005 Fabrice Bellard
5 5fafdf24 ths
 *
6 420557e8 bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 420557e8 bellard
 * of this software and associated documentation files (the "Software"), to deal
8 420557e8 bellard
 * in the Software without restriction, including without limitation the rights
9 420557e8 bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 420557e8 bellard
 * copies of the Software, and to permit persons to whom the Software is
11 420557e8 bellard
 * furnished to do so, subject to the following conditions:
12 420557e8 bellard
 *
13 420557e8 bellard
 * The above copyright notice and this permission notice shall be included in
14 420557e8 bellard
 * all copies or substantial portions of the Software.
15 420557e8 bellard
 *
16 420557e8 bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 420557e8 bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 420557e8 bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 420557e8 bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 420557e8 bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 420557e8 bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 420557e8 bellard
 * THE SOFTWARE.
23 420557e8 bellard
 */
24 f40070c3 Blue Swirl
25 87ecb68b pbrook
#include "console.h"
26 94470844 blueswir1
#include "pixel_ops.h"
27 f40070c3 Blue Swirl
#include "sysbus.h"
28 ee6847d1 Gerd Hoffmann
#include "qdev-addr.h"
29 420557e8 bellard
30 420557e8 bellard
#define MAXX 1024
31 420557e8 bellard
#define MAXY 768
32 6f7e9aec bellard
#define TCX_DAC_NREGS 16
33 8508b89e blueswir1
#define TCX_THC_NREGS_8  0x081c
34 8508b89e blueswir1
#define TCX_THC_NREGS_24 0x1000
35 8508b89e blueswir1
#define TCX_TEC_NREGS    0x1000
36 420557e8 bellard
37 420557e8 bellard
typedef struct TCXState {
38 f40070c3 Blue Swirl
    SysBusDevice busdev;
39 c227f099 Anthony Liguori
    target_phys_addr_t addr;
40 420557e8 bellard
    DisplayState *ds;
41 8d5f07fa bellard
    uint8_t *vram;
42 eee0b836 blueswir1
    uint32_t *vram24, *cplane;
43 c227f099 Anthony Liguori
    ram_addr_t vram_offset, vram24_offset, cplane_offset;
44 ee6847d1 Gerd Hoffmann
    uint32_t vram_size;
45 eee0b836 blueswir1
    uint16_t width, height, depth;
46 e80cfcfc bellard
    uint8_t r[256], g[256], b[256];
47 21206a10 bellard
    uint32_t palette[256];
48 6f7e9aec bellard
    uint8_t dac_index, dac_state;
49 420557e8 bellard
} TCXState;
50 420557e8 bellard
51 95219897 pbrook
static void tcx_screen_dump(void *opaque, const char *filename);
52 eee0b836 blueswir1
static void tcx24_screen_dump(void *opaque, const char *filename);
53 d3ffcafe Blue Swirl
54 d3ffcafe Blue Swirl
static void tcx_set_dirty(TCXState *s)
55 d3ffcafe Blue Swirl
{
56 d3ffcafe Blue Swirl
    unsigned int i;
57 d3ffcafe Blue Swirl
58 d3ffcafe Blue Swirl
    for (i = 0; i < MAXX * MAXY; i += TARGET_PAGE_SIZE) {
59 d3ffcafe Blue Swirl
        cpu_physical_memory_set_dirty(s->vram_offset + i);
60 d3ffcafe Blue Swirl
    }
61 d3ffcafe Blue Swirl
}
62 d3ffcafe Blue Swirl
63 d3ffcafe Blue Swirl
static void tcx24_set_dirty(TCXState *s)
64 d3ffcafe Blue Swirl
{
65 d3ffcafe Blue Swirl
    unsigned int i;
66 d3ffcafe Blue Swirl
67 d3ffcafe Blue Swirl
    for (i = 0; i < MAXX * MAXY * 4; i += TARGET_PAGE_SIZE) {
68 d3ffcafe Blue Swirl
        cpu_physical_memory_set_dirty(s->vram24_offset + i);
69 d3ffcafe Blue Swirl
        cpu_physical_memory_set_dirty(s->cplane_offset + i);
70 d3ffcafe Blue Swirl
    }
71 d3ffcafe Blue Swirl
}
72 95219897 pbrook
73 21206a10 bellard
static void update_palette_entries(TCXState *s, int start, int end)
74 21206a10 bellard
{
75 21206a10 bellard
    int i;
76 21206a10 bellard
    for(i = start; i < end; i++) {
77 0e1f5a0c aliguori
        switch(ds_get_bits_per_pixel(s->ds)) {
78 21206a10 bellard
        default:
79 21206a10 bellard
        case 8:
80 21206a10 bellard
            s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
81 21206a10 bellard
            break;
82 21206a10 bellard
        case 15:
83 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
84 21206a10 bellard
            break;
85 21206a10 bellard
        case 16:
86 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
87 21206a10 bellard
            break;
88 21206a10 bellard
        case 32:
89 7b5d76da aliguori
            if (is_surface_bgr(s->ds->surface))
90 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
91 7b5d76da aliguori
            else
92 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
93 21206a10 bellard
            break;
94 21206a10 bellard
        }
95 21206a10 bellard
    }
96 d3ffcafe Blue Swirl
    if (s->depth == 24) {
97 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
98 d3ffcafe Blue Swirl
    } else {
99 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
100 d3ffcafe Blue Swirl
    }
101 21206a10 bellard
}
102 21206a10 bellard
103 5fafdf24 ths
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
104 f930d07e blueswir1
                            const uint8_t *s, int width)
105 420557e8 bellard
{
106 e80cfcfc bellard
    int x;
107 e80cfcfc bellard
    uint8_t val;
108 8bdc2159 ths
    uint32_t *p = (uint32_t *)d;
109 e80cfcfc bellard
110 e80cfcfc bellard
    for(x = 0; x < width; x++) {
111 f930d07e blueswir1
        val = *s++;
112 8bdc2159 ths
        *p++ = s1->palette[val];
113 e80cfcfc bellard
    }
114 420557e8 bellard
}
115 420557e8 bellard
116 5fafdf24 ths
static void tcx_draw_line16(TCXState *s1, uint8_t *d,
117 f930d07e blueswir1
                            const uint8_t *s, int width)
118 e80cfcfc bellard
{
119 e80cfcfc bellard
    int x;
120 e80cfcfc bellard
    uint8_t val;
121 8bdc2159 ths
    uint16_t *p = (uint16_t *)d;
122 8d5f07fa bellard
123 e80cfcfc bellard
    for(x = 0; x < width; x++) {
124 f930d07e blueswir1
        val = *s++;
125 8bdc2159 ths
        *p++ = s1->palette[val];
126 e80cfcfc bellard
    }
127 e80cfcfc bellard
}
128 e80cfcfc bellard
129 5fafdf24 ths
static void tcx_draw_line8(TCXState *s1, uint8_t *d,
130 f930d07e blueswir1
                           const uint8_t *s, int width)
131 420557e8 bellard
{
132 e80cfcfc bellard
    int x;
133 e80cfcfc bellard
    uint8_t val;
134 e80cfcfc bellard
135 e80cfcfc bellard
    for(x = 0; x < width; x++) {
136 f930d07e blueswir1
        val = *s++;
137 21206a10 bellard
        *d++ = s1->palette[val];
138 420557e8 bellard
    }
139 420557e8 bellard
}
140 420557e8 bellard
141 688ea2eb blueswir1
/*
142 688ea2eb blueswir1
  XXX Could be much more optimal:
143 688ea2eb blueswir1
  * detect if line/page/whole screen is in 24 bit mode
144 688ea2eb blueswir1
  * if destination is also BGR, use memcpy
145 688ea2eb blueswir1
  */
146 eee0b836 blueswir1
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
147 eee0b836 blueswir1
                                     const uint8_t *s, int width,
148 eee0b836 blueswir1
                                     const uint32_t *cplane,
149 eee0b836 blueswir1
                                     const uint32_t *s24)
150 eee0b836 blueswir1
{
151 7b5d76da aliguori
    int x, bgr, r, g, b;
152 688ea2eb blueswir1
    uint8_t val, *p8;
153 eee0b836 blueswir1
    uint32_t *p = (uint32_t *)d;
154 eee0b836 blueswir1
    uint32_t dval;
155 eee0b836 blueswir1
156 7b5d76da aliguori
    bgr = is_surface_bgr(s1->ds->surface);
157 eee0b836 blueswir1
    for(x = 0; x < width; x++, s++, s24++) {
158 688ea2eb blueswir1
        if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
159 688ea2eb blueswir1
            // 24-bit direct, BGR order
160 688ea2eb blueswir1
            p8 = (uint8_t *)s24;
161 688ea2eb blueswir1
            p8++;
162 688ea2eb blueswir1
            b = *p8++;
163 688ea2eb blueswir1
            g = *p8++;
164 f7e683b8 Blue Swirl
            r = *p8;
165 7b5d76da aliguori
            if (bgr)
166 7b5d76da aliguori
                dval = rgb_to_pixel32bgr(r, g, b);
167 7b5d76da aliguori
            else
168 7b5d76da aliguori
                dval = rgb_to_pixel32(r, g, b);
169 eee0b836 blueswir1
        } else {
170 eee0b836 blueswir1
            val = *s;
171 eee0b836 blueswir1
            dval = s1->palette[val];
172 eee0b836 blueswir1
        }
173 eee0b836 blueswir1
        *p++ = dval;
174 eee0b836 blueswir1
    }
175 eee0b836 blueswir1
}
176 eee0b836 blueswir1
177 c227f099 Anthony Liguori
static inline int check_dirty(ram_addr_t page, ram_addr_t page24,
178 c227f099 Anthony Liguori
                              ram_addr_t cpage)
179 eee0b836 blueswir1
{
180 eee0b836 blueswir1
    int ret;
181 eee0b836 blueswir1
    unsigned int off;
182 eee0b836 blueswir1
183 eee0b836 blueswir1
    ret = cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG);
184 eee0b836 blueswir1
    for (off = 0; off < TARGET_PAGE_SIZE * 4; off += TARGET_PAGE_SIZE) {
185 eee0b836 blueswir1
        ret |= cpu_physical_memory_get_dirty(page24 + off, VGA_DIRTY_FLAG);
186 eee0b836 blueswir1
        ret |= cpu_physical_memory_get_dirty(cpage + off, VGA_DIRTY_FLAG);
187 eee0b836 blueswir1
    }
188 eee0b836 blueswir1
    return ret;
189 eee0b836 blueswir1
}
190 eee0b836 blueswir1
191 c227f099 Anthony Liguori
static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
192 c227f099 Anthony Liguori
                               ram_addr_t page_max, ram_addr_t page24,
193 c227f099 Anthony Liguori
                              ram_addr_t cpage)
194 eee0b836 blueswir1
{
195 eee0b836 blueswir1
    cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
196 eee0b836 blueswir1
                                    VGA_DIRTY_FLAG);
197 eee0b836 blueswir1
    page_min -= ts->vram_offset;
198 eee0b836 blueswir1
    page_max -= ts->vram_offset;
199 eee0b836 blueswir1
    cpu_physical_memory_reset_dirty(page24 + page_min * 4,
200 eee0b836 blueswir1
                                    page24 + page_max * 4 + TARGET_PAGE_SIZE,
201 eee0b836 blueswir1
                                    VGA_DIRTY_FLAG);
202 eee0b836 blueswir1
    cpu_physical_memory_reset_dirty(cpage + page_min * 4,
203 eee0b836 blueswir1
                                    cpage + page_max * 4 + TARGET_PAGE_SIZE,
204 eee0b836 blueswir1
                                    VGA_DIRTY_FLAG);
205 eee0b836 blueswir1
}
206 eee0b836 blueswir1
207 e80cfcfc bellard
/* Fixed line length 1024 allows us to do nice tricks not possible on
208 e80cfcfc bellard
   VGA... */
209 95219897 pbrook
static void tcx_update_display(void *opaque)
210 420557e8 bellard
{
211 e80cfcfc bellard
    TCXState *ts = opaque;
212 c227f099 Anthony Liguori
    ram_addr_t page, page_min, page_max;
213 550be127 bellard
    int y, y_start, dd, ds;
214 e80cfcfc bellard
    uint8_t *d, *s;
215 b3ceef24 blueswir1
    void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
216 e80cfcfc bellard
217 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(ts->ds) == 0)
218 f930d07e blueswir1
        return;
219 6f7e9aec bellard
    page = ts->vram_offset;
220 e80cfcfc bellard
    y_start = -1;
221 c0c440f3 Blue Swirl
    page_min = -1;
222 550be127 bellard
    page_max = 0;
223 0e1f5a0c aliguori
    d = ds_get_data(ts->ds);
224 6f7e9aec bellard
    s = ts->vram;
225 0e1f5a0c aliguori
    dd = ds_get_linesize(ts->ds);
226 e80cfcfc bellard
    ds = 1024;
227 e80cfcfc bellard
228 0e1f5a0c aliguori
    switch (ds_get_bits_per_pixel(ts->ds)) {
229 e80cfcfc bellard
    case 32:
230 f930d07e blueswir1
        f = tcx_draw_line32;
231 f930d07e blueswir1
        break;
232 21206a10 bellard
    case 15:
233 21206a10 bellard
    case 16:
234 f930d07e blueswir1
        f = tcx_draw_line16;
235 f930d07e blueswir1
        break;
236 e80cfcfc bellard
    default:
237 e80cfcfc bellard
    case 8:
238 f930d07e blueswir1
        f = tcx_draw_line8;
239 f930d07e blueswir1
        break;
240 e80cfcfc bellard
    case 0:
241 f930d07e blueswir1
        return;
242 e80cfcfc bellard
    }
243 3b46e624 ths
244 6f7e9aec bellard
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
245 f930d07e blueswir1
        if (cpu_physical_memory_get_dirty(page, VGA_DIRTY_FLAG)) {
246 f930d07e blueswir1
            if (y_start < 0)
247 e80cfcfc bellard
                y_start = y;
248 e80cfcfc bellard
            if (page < page_min)
249 e80cfcfc bellard
                page_min = page;
250 e80cfcfc bellard
            if (page > page_max)
251 e80cfcfc bellard
                page_max = page;
252 f930d07e blueswir1
            f(ts, d, s, ts->width);
253 f930d07e blueswir1
            d += dd;
254 f930d07e blueswir1
            s += ds;
255 f930d07e blueswir1
            f(ts, d, s, ts->width);
256 f930d07e blueswir1
            d += dd;
257 f930d07e blueswir1
            s += ds;
258 f930d07e blueswir1
            f(ts, d, s, ts->width);
259 f930d07e blueswir1
            d += dd;
260 f930d07e blueswir1
            s += ds;
261 f930d07e blueswir1
            f(ts, d, s, ts->width);
262 f930d07e blueswir1
            d += dd;
263 f930d07e blueswir1
            s += ds;
264 f930d07e blueswir1
        } else {
265 e80cfcfc bellard
            if (y_start >= 0) {
266 e80cfcfc bellard
                /* flush to display */
267 5fafdf24 ths
                dpy_update(ts->ds, 0, y_start,
268 6f7e9aec bellard
                           ts->width, y - y_start);
269 e80cfcfc bellard
                y_start = -1;
270 e80cfcfc bellard
            }
271 f930d07e blueswir1
            d += dd * 4;
272 f930d07e blueswir1
            s += ds * 4;
273 f930d07e blueswir1
        }
274 e80cfcfc bellard
    }
275 e80cfcfc bellard
    if (y_start >= 0) {
276 f930d07e blueswir1
        /* flush to display */
277 f930d07e blueswir1
        dpy_update(ts->ds, 0, y_start,
278 f930d07e blueswir1
                   ts->width, y - y_start);
279 e80cfcfc bellard
    }
280 e80cfcfc bellard
    /* reset modified pages */
281 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
282 0a962c02 bellard
        cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE,
283 0a962c02 bellard
                                        VGA_DIRTY_FLAG);
284 e80cfcfc bellard
    }
285 420557e8 bellard
}
286 420557e8 bellard
287 eee0b836 blueswir1
static void tcx24_update_display(void *opaque)
288 eee0b836 blueswir1
{
289 eee0b836 blueswir1
    TCXState *ts = opaque;
290 c227f099 Anthony Liguori
    ram_addr_t page, page_min, page_max, cpage, page24;
291 eee0b836 blueswir1
    int y, y_start, dd, ds;
292 eee0b836 blueswir1
    uint8_t *d, *s;
293 eee0b836 blueswir1
    uint32_t *cptr, *s24;
294 eee0b836 blueswir1
295 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(ts->ds) != 32)
296 eee0b836 blueswir1
            return;
297 eee0b836 blueswir1
    page = ts->vram_offset;
298 eee0b836 blueswir1
    page24 = ts->vram24_offset;
299 eee0b836 blueswir1
    cpage = ts->cplane_offset;
300 eee0b836 blueswir1
    y_start = -1;
301 c0c440f3 Blue Swirl
    page_min = -1;
302 eee0b836 blueswir1
    page_max = 0;
303 0e1f5a0c aliguori
    d = ds_get_data(ts->ds);
304 eee0b836 blueswir1
    s = ts->vram;
305 eee0b836 blueswir1
    s24 = ts->vram24;
306 eee0b836 blueswir1
    cptr = ts->cplane;
307 0e1f5a0c aliguori
    dd = ds_get_linesize(ts->ds);
308 eee0b836 blueswir1
    ds = 1024;
309 eee0b836 blueswir1
310 eee0b836 blueswir1
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
311 eee0b836 blueswir1
            page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
312 22548760 blueswir1
        if (check_dirty(page, page24, cpage)) {
313 eee0b836 blueswir1
            if (y_start < 0)
314 eee0b836 blueswir1
                y_start = y;
315 eee0b836 blueswir1
            if (page < page_min)
316 eee0b836 blueswir1
                page_min = page;
317 eee0b836 blueswir1
            if (page > page_max)
318 eee0b836 blueswir1
                page_max = page;
319 eee0b836 blueswir1
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
320 eee0b836 blueswir1
            d += dd;
321 eee0b836 blueswir1
            s += ds;
322 eee0b836 blueswir1
            cptr += ds;
323 eee0b836 blueswir1
            s24 += ds;
324 eee0b836 blueswir1
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
325 eee0b836 blueswir1
            d += dd;
326 eee0b836 blueswir1
            s += ds;
327 eee0b836 blueswir1
            cptr += ds;
328 eee0b836 blueswir1
            s24 += ds;
329 eee0b836 blueswir1
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
330 eee0b836 blueswir1
            d += dd;
331 eee0b836 blueswir1
            s += ds;
332 eee0b836 blueswir1
            cptr += ds;
333 eee0b836 blueswir1
            s24 += ds;
334 eee0b836 blueswir1
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
335 eee0b836 blueswir1
            d += dd;
336 eee0b836 blueswir1
            s += ds;
337 eee0b836 blueswir1
            cptr += ds;
338 eee0b836 blueswir1
            s24 += ds;
339 eee0b836 blueswir1
        } else {
340 eee0b836 blueswir1
            if (y_start >= 0) {
341 eee0b836 blueswir1
                /* flush to display */
342 eee0b836 blueswir1
                dpy_update(ts->ds, 0, y_start,
343 eee0b836 blueswir1
                           ts->width, y - y_start);
344 eee0b836 blueswir1
                y_start = -1;
345 eee0b836 blueswir1
            }
346 eee0b836 blueswir1
            d += dd * 4;
347 eee0b836 blueswir1
            s += ds * 4;
348 eee0b836 blueswir1
            cptr += ds * 4;
349 eee0b836 blueswir1
            s24 += ds * 4;
350 eee0b836 blueswir1
        }
351 eee0b836 blueswir1
    }
352 eee0b836 blueswir1
    if (y_start >= 0) {
353 eee0b836 blueswir1
        /* flush to display */
354 eee0b836 blueswir1
        dpy_update(ts->ds, 0, y_start,
355 eee0b836 blueswir1
                   ts->width, y - y_start);
356 eee0b836 blueswir1
    }
357 eee0b836 blueswir1
    /* reset modified pages */
358 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
359 eee0b836 blueswir1
        reset_dirty(ts, page_min, page_max, page24, cpage);
360 eee0b836 blueswir1
    }
361 eee0b836 blueswir1
}
362 eee0b836 blueswir1
363 95219897 pbrook
static void tcx_invalidate_display(void *opaque)
364 420557e8 bellard
{
365 e80cfcfc bellard
    TCXState *s = opaque;
366 e80cfcfc bellard
367 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
368 d3ffcafe Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
369 420557e8 bellard
}
370 420557e8 bellard
371 eee0b836 blueswir1
static void tcx24_invalidate_display(void *opaque)
372 eee0b836 blueswir1
{
373 eee0b836 blueswir1
    TCXState *s = opaque;
374 eee0b836 blueswir1
375 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
376 d3ffcafe Blue Swirl
    tcx24_set_dirty(s);
377 d3ffcafe Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
378 eee0b836 blueswir1
}
379 eee0b836 blueswir1
380 e59fb374 Juan Quintela
static int vmstate_tcx_post_load(void *opaque, int version_id)
381 420557e8 bellard
{
382 420557e8 bellard
    TCXState *s = opaque;
383 3b46e624 ths
384 21206a10 bellard
    update_palette_entries(s, 0, 256);
385 d3ffcafe Blue Swirl
    if (s->depth == 24) {
386 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
387 d3ffcafe Blue Swirl
    } else {
388 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
389 d3ffcafe Blue Swirl
    }
390 5425a216 blueswir1
391 e80cfcfc bellard
    return 0;
392 420557e8 bellard
}
393 420557e8 bellard
394 c0c41a4b Blue Swirl
static const VMStateDescription vmstate_tcx = {
395 c0c41a4b Blue Swirl
    .name ="tcx",
396 c0c41a4b Blue Swirl
    .version_id = 4,
397 c0c41a4b Blue Swirl
    .minimum_version_id = 4,
398 c0c41a4b Blue Swirl
    .minimum_version_id_old = 4,
399 752ff2fa Juan Quintela
    .post_load = vmstate_tcx_post_load,
400 c0c41a4b Blue Swirl
    .fields      = (VMStateField []) {
401 c0c41a4b Blue Swirl
        VMSTATE_UINT16(height, TCXState),
402 c0c41a4b Blue Swirl
        VMSTATE_UINT16(width, TCXState),
403 c0c41a4b Blue Swirl
        VMSTATE_UINT16(depth, TCXState),
404 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(r, TCXState),
405 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(g, TCXState),
406 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(b, TCXState),
407 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_index, TCXState),
408 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_state, TCXState),
409 c0c41a4b Blue Swirl
        VMSTATE_END_OF_LIST()
410 c0c41a4b Blue Swirl
    }
411 c0c41a4b Blue Swirl
};
412 c0c41a4b Blue Swirl
413 7f23f812 Michael S. Tsirkin
static void tcx_reset(DeviceState *d)
414 420557e8 bellard
{
415 7f23f812 Michael S. Tsirkin
    TCXState *s = container_of(d, TCXState, busdev.qdev);
416 e80cfcfc bellard
417 e80cfcfc bellard
    /* Initialize palette */
418 e80cfcfc bellard
    memset(s->r, 0, 256);
419 e80cfcfc bellard
    memset(s->g, 0, 256);
420 e80cfcfc bellard
    memset(s->b, 0, 256);
421 e80cfcfc bellard
    s->r[255] = s->g[255] = s->b[255] = 255;
422 21206a10 bellard
    update_palette_entries(s, 0, 256);
423 e80cfcfc bellard
    memset(s->vram, 0, MAXX*MAXY);
424 eee0b836 blueswir1
    cpu_physical_memory_reset_dirty(s->vram_offset, s->vram_offset +
425 eee0b836 blueswir1
                                    MAXX * MAXY * (1 + 4 + 4), VGA_DIRTY_FLAG);
426 6f7e9aec bellard
    s->dac_index = 0;
427 6f7e9aec bellard
    s->dac_state = 0;
428 6f7e9aec bellard
}
429 6f7e9aec bellard
430 c227f099 Anthony Liguori
static uint32_t tcx_dac_readl(void *opaque, target_phys_addr_t addr)
431 6f7e9aec bellard
{
432 6f7e9aec bellard
    return 0;
433 6f7e9aec bellard
}
434 6f7e9aec bellard
435 c227f099 Anthony Liguori
static void tcx_dac_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
436 6f7e9aec bellard
{
437 6f7e9aec bellard
    TCXState *s = opaque;
438 6f7e9aec bellard
439 e64d7d59 blueswir1
    switch (addr) {
440 6f7e9aec bellard
    case 0:
441 f930d07e blueswir1
        s->dac_index = val >> 24;
442 f930d07e blueswir1
        s->dac_state = 0;
443 f930d07e blueswir1
        break;
444 e64d7d59 blueswir1
    case 4:
445 f930d07e blueswir1
        switch (s->dac_state) {
446 f930d07e blueswir1
        case 0:
447 f930d07e blueswir1
            s->r[s->dac_index] = val >> 24;
448 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
449 f930d07e blueswir1
            s->dac_state++;
450 f930d07e blueswir1
            break;
451 f930d07e blueswir1
        case 1:
452 f930d07e blueswir1
            s->g[s->dac_index] = val >> 24;
453 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
454 f930d07e blueswir1
            s->dac_state++;
455 f930d07e blueswir1
            break;
456 f930d07e blueswir1
        case 2:
457 f930d07e blueswir1
            s->b[s->dac_index] = val >> 24;
458 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
459 5c8cdbf8 blueswir1
            s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
460 f930d07e blueswir1
        default:
461 f930d07e blueswir1
            s->dac_state = 0;
462 f930d07e blueswir1
            break;
463 f930d07e blueswir1
        }
464 f930d07e blueswir1
        break;
465 6f7e9aec bellard
    default:
466 f930d07e blueswir1
        break;
467 6f7e9aec bellard
    }
468 6f7e9aec bellard
    return;
469 420557e8 bellard
}
470 420557e8 bellard
471 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const tcx_dac_read[3] = {
472 7c560456 blueswir1
    NULL,
473 7c560456 blueswir1
    NULL,
474 6f7e9aec bellard
    tcx_dac_readl,
475 6f7e9aec bellard
};
476 6f7e9aec bellard
477 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const tcx_dac_write[3] = {
478 7c560456 blueswir1
    NULL,
479 7c560456 blueswir1
    NULL,
480 6f7e9aec bellard
    tcx_dac_writel,
481 6f7e9aec bellard
};
482 6f7e9aec bellard
483 c227f099 Anthony Liguori
static uint32_t tcx_dummy_readl(void *opaque, target_phys_addr_t addr)
484 8508b89e blueswir1
{
485 8508b89e blueswir1
    return 0;
486 8508b89e blueswir1
}
487 8508b89e blueswir1
488 c227f099 Anthony Liguori
static void tcx_dummy_writel(void *opaque, target_phys_addr_t addr,
489 8508b89e blueswir1
                             uint32_t val)
490 8508b89e blueswir1
{
491 8508b89e blueswir1
}
492 8508b89e blueswir1
493 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const tcx_dummy_read[3] = {
494 7c560456 blueswir1
    NULL,
495 7c560456 blueswir1
    NULL,
496 8508b89e blueswir1
    tcx_dummy_readl,
497 8508b89e blueswir1
};
498 8508b89e blueswir1
499 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const tcx_dummy_write[3] = {
500 7c560456 blueswir1
    NULL,
501 7c560456 blueswir1
    NULL,
502 8508b89e blueswir1
    tcx_dummy_writel,
503 8508b89e blueswir1
};
504 8508b89e blueswir1
505 81a322d4 Gerd Hoffmann
static int tcx_init1(SysBusDevice *dev)
506 f40070c3 Blue Swirl
{
507 f40070c3 Blue Swirl
    TCXState *s = FROM_SYSBUS(TCXState, dev);
508 8508b89e blueswir1
    int io_memory, dummy_memory;
509 c227f099 Anthony Liguori
    ram_addr_t vram_offset;
510 ee6847d1 Gerd Hoffmann
    int size;
511 dc828ca1 pbrook
    uint8_t *vram_base;
512 dc828ca1 pbrook
513 1724f049 Alex Williamson
    vram_offset = qemu_ram_alloc(NULL, "tcx.vram", s->vram_size * (1 + 4 + 4));
514 dc828ca1 pbrook
    vram_base = qemu_get_ram_ptr(vram_offset);
515 e80cfcfc bellard
    s->vram_offset = vram_offset;
516 eee0b836 blueswir1
517 f40070c3 Blue Swirl
    /* 8-bit plane */
518 eee0b836 blueswir1
    s->vram = vram_base;
519 ee6847d1 Gerd Hoffmann
    size = s->vram_size;
520 f40070c3 Blue Swirl
    sysbus_init_mmio(dev, size, s->vram_offset);
521 eee0b836 blueswir1
    vram_offset += size;
522 eee0b836 blueswir1
    vram_base += size;
523 e80cfcfc bellard
524 f40070c3 Blue Swirl
    /* DAC */
525 1eed09cb Avi Kivity
    io_memory = cpu_register_io_memory(tcx_dac_read, tcx_dac_write, s);
526 f40070c3 Blue Swirl
    sysbus_init_mmio(dev, TCX_DAC_NREGS, io_memory);
527 eee0b836 blueswir1
528 f40070c3 Blue Swirl
    /* TEC (dummy) */
529 1eed09cb Avi Kivity
    dummy_memory = cpu_register_io_memory(tcx_dummy_read, tcx_dummy_write,
530 8508b89e blueswir1
                                          s);
531 f40070c3 Blue Swirl
    sysbus_init_mmio(dev, TCX_TEC_NREGS, dummy_memory);
532 f40070c3 Blue Swirl
    /* THC: NetBSD writes here even with 8-bit display: dummy */
533 f40070c3 Blue Swirl
    sysbus_init_mmio(dev, TCX_THC_NREGS_24, dummy_memory);
534 f40070c3 Blue Swirl
535 f40070c3 Blue Swirl
    if (s->depth == 24) {
536 f40070c3 Blue Swirl
        /* 24-bit plane */
537 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
538 eee0b836 blueswir1
        s->vram24 = (uint32_t *)vram_base;
539 eee0b836 blueswir1
        s->vram24_offset = vram_offset;
540 f40070c3 Blue Swirl
        sysbus_init_mmio(dev, size, vram_offset);
541 eee0b836 blueswir1
        vram_offset += size;
542 eee0b836 blueswir1
        vram_base += size;
543 eee0b836 blueswir1
544 f40070c3 Blue Swirl
        /* Control plane */
545 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
546 eee0b836 blueswir1
        s->cplane = (uint32_t *)vram_base;
547 eee0b836 blueswir1
        s->cplane_offset = vram_offset;
548 f40070c3 Blue Swirl
        sysbus_init_mmio(dev, size, vram_offset);
549 f40070c3 Blue Swirl
550 3023f332 aliguori
        s->ds = graphic_console_init(tcx24_update_display,
551 3023f332 aliguori
                                     tcx24_invalidate_display,
552 3023f332 aliguori
                                     tcx24_screen_dump, NULL, s);
553 eee0b836 blueswir1
    } else {
554 f40070c3 Blue Swirl
        /* THC 8 bit (dummy) */
555 f40070c3 Blue Swirl
        sysbus_init_mmio(dev, TCX_THC_NREGS_8, dummy_memory);
556 f40070c3 Blue Swirl
557 3023f332 aliguori
        s->ds = graphic_console_init(tcx_update_display,
558 3023f332 aliguori
                                     tcx_invalidate_display,
559 3023f332 aliguori
                                     tcx_screen_dump, NULL, s);
560 eee0b836 blueswir1
    }
561 e80cfcfc bellard
562 f40070c3 Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
563 81a322d4 Gerd Hoffmann
    return 0;
564 420557e8 bellard
}
565 420557e8 bellard
566 95219897 pbrook
static void tcx_screen_dump(void *opaque, const char *filename)
567 8d5f07fa bellard
{
568 e80cfcfc bellard
    TCXState *s = opaque;
569 8d5f07fa bellard
    FILE *f;
570 e80cfcfc bellard
    uint8_t *d, *d1, v;
571 8d5f07fa bellard
    int y, x;
572 8d5f07fa bellard
573 8d5f07fa bellard
    f = fopen(filename, "wb");
574 8d5f07fa bellard
    if (!f)
575 e80cfcfc bellard
        return;
576 6f7e9aec bellard
    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
577 6f7e9aec bellard
    d1 = s->vram;
578 6f7e9aec bellard
    for(y = 0; y < s->height; y++) {
579 8d5f07fa bellard
        d = d1;
580 6f7e9aec bellard
        for(x = 0; x < s->width; x++) {
581 8d5f07fa bellard
            v = *d;
582 e80cfcfc bellard
            fputc(s->r[v], f);
583 e80cfcfc bellard
            fputc(s->g[v], f);
584 e80cfcfc bellard
            fputc(s->b[v], f);
585 8d5f07fa bellard
            d++;
586 8d5f07fa bellard
        }
587 e80cfcfc bellard
        d1 += MAXX;
588 8d5f07fa bellard
    }
589 8d5f07fa bellard
    fclose(f);
590 8d5f07fa bellard
    return;
591 8d5f07fa bellard
}
592 8d5f07fa bellard
593 eee0b836 blueswir1
static void tcx24_screen_dump(void *opaque, const char *filename)
594 eee0b836 blueswir1
{
595 eee0b836 blueswir1
    TCXState *s = opaque;
596 eee0b836 blueswir1
    FILE *f;
597 eee0b836 blueswir1
    uint8_t *d, *d1, v;
598 eee0b836 blueswir1
    uint32_t *s24, *cptr, dval;
599 eee0b836 blueswir1
    int y, x;
600 8d5f07fa bellard
601 eee0b836 blueswir1
    f = fopen(filename, "wb");
602 eee0b836 blueswir1
    if (!f)
603 eee0b836 blueswir1
        return;
604 eee0b836 blueswir1
    fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
605 eee0b836 blueswir1
    d1 = s->vram;
606 eee0b836 blueswir1
    s24 = s->vram24;
607 eee0b836 blueswir1
    cptr = s->cplane;
608 eee0b836 blueswir1
    for(y = 0; y < s->height; y++) {
609 eee0b836 blueswir1
        d = d1;
610 eee0b836 blueswir1
        for(x = 0; x < s->width; x++, d++, s24++) {
611 eee0b836 blueswir1
            if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
612 eee0b836 blueswir1
                dval = *s24 & 0x00ffffff;
613 eee0b836 blueswir1
                fputc((dval >> 16) & 0xff, f);
614 eee0b836 blueswir1
                fputc((dval >> 8) & 0xff, f);
615 eee0b836 blueswir1
                fputc(dval & 0xff, f);
616 eee0b836 blueswir1
            } else {
617 eee0b836 blueswir1
                v = *d;
618 eee0b836 blueswir1
                fputc(s->r[v], f);
619 eee0b836 blueswir1
                fputc(s->g[v], f);
620 eee0b836 blueswir1
                fputc(s->b[v], f);
621 eee0b836 blueswir1
            }
622 eee0b836 blueswir1
        }
623 eee0b836 blueswir1
        d1 += MAXX;
624 eee0b836 blueswir1
    }
625 eee0b836 blueswir1
    fclose(f);
626 eee0b836 blueswir1
    return;
627 eee0b836 blueswir1
}
628 f40070c3 Blue Swirl
629 ee6847d1 Gerd Hoffmann
static SysBusDeviceInfo tcx_info = {
630 ee6847d1 Gerd Hoffmann
    .init = tcx_init1,
631 ee6847d1 Gerd Hoffmann
    .qdev.name  = "SUNW,tcx",
632 ee6847d1 Gerd Hoffmann
    .qdev.size  = sizeof(TCXState),
633 20bb8277 Gerd Hoffmann
    .qdev.reset = tcx_reset,
634 20bb8277 Gerd Hoffmann
    .qdev.vmsd  = &vmstate_tcx,
635 ee6847d1 Gerd Hoffmann
    .qdev.props = (Property[]) {
636 53dad499 Gerd Hoffmann
        DEFINE_PROP_TADDR("addr",      TCXState, addr,      -1),
637 53dad499 Gerd Hoffmann
        DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
638 53dad499 Gerd Hoffmann
        DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
639 53dad499 Gerd Hoffmann
        DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
640 53dad499 Gerd Hoffmann
        DEFINE_PROP_UINT16("depth",    TCXState, depth,     -1),
641 53dad499 Gerd Hoffmann
        DEFINE_PROP_END_OF_LIST(),
642 ee6847d1 Gerd Hoffmann
    }
643 ee6847d1 Gerd Hoffmann
};
644 ee6847d1 Gerd Hoffmann
645 f40070c3 Blue Swirl
static void tcx_register_devices(void)
646 f40070c3 Blue Swirl
{
647 ee6847d1 Gerd Hoffmann
    sysbus_register_withprop(&tcx_info);
648 f40070c3 Blue Swirl
}
649 f40070c3 Blue Swirl
650 f40070c3 Blue Swirl
device_init(tcx_register_devices)