Statistics
| Branch: | Revision:

root / hw / tcx.c @ 6efa6d50

History | View | Annotate | Download (20.4 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 a8170e5e Avi Kivity
    hwaddr addr;
40 420557e8 bellard
    DisplayState *ds;
41 8d5f07fa bellard
    uint8_t *vram;
42 eee0b836 blueswir1
    uint32_t *vram24, *cplane;
43 d08151bf Avi Kivity
    MemoryRegion vram_mem;
44 d08151bf Avi Kivity
    MemoryRegion vram_8bit;
45 d08151bf Avi Kivity
    MemoryRegion vram_24bit;
46 d08151bf Avi Kivity
    MemoryRegion vram_cplane;
47 d08151bf Avi Kivity
    MemoryRegion dac;
48 d08151bf Avi Kivity
    MemoryRegion tec;
49 d08151bf Avi Kivity
    MemoryRegion thc24;
50 d08151bf Avi Kivity
    MemoryRegion thc8;
51 d08151bf Avi Kivity
    ram_addr_t vram24_offset, cplane_offset;
52 ee6847d1 Gerd Hoffmann
    uint32_t vram_size;
53 21206a10 bellard
    uint32_t palette[256];
54 427a66c3 Blue Swirl
    uint8_t r[256], g[256], b[256];
55 427a66c3 Blue Swirl
    uint16_t width, height, depth;
56 6f7e9aec bellard
    uint8_t dac_index, dac_state;
57 420557e8 bellard
} TCXState;
58 420557e8 bellard
59 d7098135 Luiz Capitulino
static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
60 d7098135 Luiz Capitulino
                            Error **errp);
61 d7098135 Luiz Capitulino
static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
62 d7098135 Luiz Capitulino
                            Error **errp);
63 d3ffcafe Blue Swirl
64 d3ffcafe Blue Swirl
static void tcx_set_dirty(TCXState *s)
65 d3ffcafe Blue Swirl
{
66 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
67 d3ffcafe Blue Swirl
}
68 d3ffcafe Blue Swirl
69 d3ffcafe Blue Swirl
static void tcx24_set_dirty(TCXState *s)
70 d3ffcafe Blue Swirl
{
71 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, s->vram24_offset, MAXX * MAXY * 4);
72 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, s->cplane_offset, MAXX * MAXY * 4);
73 d3ffcafe Blue Swirl
}
74 95219897 pbrook
75 21206a10 bellard
static void update_palette_entries(TCXState *s, int start, int end)
76 21206a10 bellard
{
77 21206a10 bellard
    int i;
78 21206a10 bellard
    for(i = start; i < end; i++) {
79 0e1f5a0c aliguori
        switch(ds_get_bits_per_pixel(s->ds)) {
80 21206a10 bellard
        default:
81 21206a10 bellard
        case 8:
82 21206a10 bellard
            s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
83 21206a10 bellard
            break;
84 21206a10 bellard
        case 15:
85 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
86 21206a10 bellard
            break;
87 21206a10 bellard
        case 16:
88 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
89 21206a10 bellard
            break;
90 21206a10 bellard
        case 32:
91 7b5d76da aliguori
            if (is_surface_bgr(s->ds->surface))
92 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
93 7b5d76da aliguori
            else
94 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
95 21206a10 bellard
            break;
96 21206a10 bellard
        }
97 21206a10 bellard
    }
98 d3ffcafe Blue Swirl
    if (s->depth == 24) {
99 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
100 d3ffcafe Blue Swirl
    } else {
101 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
102 d3ffcafe Blue Swirl
    }
103 21206a10 bellard
}
104 21206a10 bellard
105 5fafdf24 ths
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
106 f930d07e blueswir1
                            const uint8_t *s, int width)
107 420557e8 bellard
{
108 e80cfcfc bellard
    int x;
109 e80cfcfc bellard
    uint8_t val;
110 8bdc2159 ths
    uint32_t *p = (uint32_t *)d;
111 e80cfcfc bellard
112 e80cfcfc bellard
    for(x = 0; x < width; x++) {
113 f930d07e blueswir1
        val = *s++;
114 8bdc2159 ths
        *p++ = s1->palette[val];
115 e80cfcfc bellard
    }
116 420557e8 bellard
}
117 420557e8 bellard
118 5fafdf24 ths
static void tcx_draw_line16(TCXState *s1, uint8_t *d,
119 f930d07e blueswir1
                            const uint8_t *s, int width)
120 e80cfcfc bellard
{
121 e80cfcfc bellard
    int x;
122 e80cfcfc bellard
    uint8_t val;
123 8bdc2159 ths
    uint16_t *p = (uint16_t *)d;
124 8d5f07fa bellard
125 e80cfcfc bellard
    for(x = 0; x < width; x++) {
126 f930d07e blueswir1
        val = *s++;
127 8bdc2159 ths
        *p++ = s1->palette[val];
128 e80cfcfc bellard
    }
129 e80cfcfc bellard
}
130 e80cfcfc bellard
131 5fafdf24 ths
static void tcx_draw_line8(TCXState *s1, uint8_t *d,
132 f930d07e blueswir1
                           const uint8_t *s, int width)
133 420557e8 bellard
{
134 e80cfcfc bellard
    int x;
135 e80cfcfc bellard
    uint8_t val;
136 e80cfcfc bellard
137 e80cfcfc bellard
    for(x = 0; x < width; x++) {
138 f930d07e blueswir1
        val = *s++;
139 21206a10 bellard
        *d++ = s1->palette[val];
140 420557e8 bellard
    }
141 420557e8 bellard
}
142 420557e8 bellard
143 688ea2eb blueswir1
/*
144 688ea2eb blueswir1
  XXX Could be much more optimal:
145 688ea2eb blueswir1
  * detect if line/page/whole screen is in 24 bit mode
146 688ea2eb blueswir1
  * if destination is also BGR, use memcpy
147 688ea2eb blueswir1
  */
148 eee0b836 blueswir1
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
149 eee0b836 blueswir1
                                     const uint8_t *s, int width,
150 eee0b836 blueswir1
                                     const uint32_t *cplane,
151 eee0b836 blueswir1
                                     const uint32_t *s24)
152 eee0b836 blueswir1
{
153 7b5d76da aliguori
    int x, bgr, r, g, b;
154 688ea2eb blueswir1
    uint8_t val, *p8;
155 eee0b836 blueswir1
    uint32_t *p = (uint32_t *)d;
156 eee0b836 blueswir1
    uint32_t dval;
157 eee0b836 blueswir1
158 7b5d76da aliguori
    bgr = is_surface_bgr(s1->ds->surface);
159 eee0b836 blueswir1
    for(x = 0; x < width; x++, s++, s24++) {
160 688ea2eb blueswir1
        if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
161 688ea2eb blueswir1
            // 24-bit direct, BGR order
162 688ea2eb blueswir1
            p8 = (uint8_t *)s24;
163 688ea2eb blueswir1
            p8++;
164 688ea2eb blueswir1
            b = *p8++;
165 688ea2eb blueswir1
            g = *p8++;
166 f7e683b8 Blue Swirl
            r = *p8;
167 7b5d76da aliguori
            if (bgr)
168 7b5d76da aliguori
                dval = rgb_to_pixel32bgr(r, g, b);
169 7b5d76da aliguori
            else
170 7b5d76da aliguori
                dval = rgb_to_pixel32(r, g, b);
171 eee0b836 blueswir1
        } else {
172 eee0b836 blueswir1
            val = *s;
173 eee0b836 blueswir1
            dval = s1->palette[val];
174 eee0b836 blueswir1
        }
175 eee0b836 blueswir1
        *p++ = dval;
176 eee0b836 blueswir1
    }
177 eee0b836 blueswir1
}
178 eee0b836 blueswir1
179 d08151bf Avi Kivity
static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
180 c227f099 Anthony Liguori
                              ram_addr_t cpage)
181 eee0b836 blueswir1
{
182 eee0b836 blueswir1
    int ret;
183 eee0b836 blueswir1
184 cd7a45c9 Blue Swirl
    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
185 cd7a45c9 Blue Swirl
                                  DIRTY_MEMORY_VGA);
186 cd7a45c9 Blue Swirl
    ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
187 cd7a45c9 Blue Swirl
                                   DIRTY_MEMORY_VGA);
188 cd7a45c9 Blue Swirl
    ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
189 cd7a45c9 Blue Swirl
                                   DIRTY_MEMORY_VGA);
190 eee0b836 blueswir1
    return ret;
191 eee0b836 blueswir1
}
192 eee0b836 blueswir1
193 c227f099 Anthony Liguori
static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
194 c227f099 Anthony Liguori
                               ram_addr_t page_max, ram_addr_t page24,
195 c227f099 Anthony Liguori
                              ram_addr_t cpage)
196 eee0b836 blueswir1
{
197 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
198 d08151bf Avi Kivity
                              page_min, page_max + TARGET_PAGE_SIZE,
199 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
200 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
201 d08151bf Avi Kivity
                              page24 + page_min * 4,
202 d08151bf Avi Kivity
                              page24 + page_max * 4 + TARGET_PAGE_SIZE,
203 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
204 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
205 d08151bf Avi Kivity
                              cpage + page_min * 4,
206 d08151bf Avi Kivity
                              cpage + page_max * 4 + TARGET_PAGE_SIZE,
207 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
208 eee0b836 blueswir1
}
209 eee0b836 blueswir1
210 e80cfcfc bellard
/* Fixed line length 1024 allows us to do nice tricks not possible on
211 e80cfcfc bellard
   VGA... */
212 95219897 pbrook
static void tcx_update_display(void *opaque)
213 420557e8 bellard
{
214 e80cfcfc bellard
    TCXState *ts = opaque;
215 c227f099 Anthony Liguori
    ram_addr_t page, page_min, page_max;
216 550be127 bellard
    int y, y_start, dd, ds;
217 e80cfcfc bellard
    uint8_t *d, *s;
218 b3ceef24 blueswir1
    void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
219 e80cfcfc bellard
220 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(ts->ds) == 0)
221 f930d07e blueswir1
        return;
222 d08151bf Avi Kivity
    page = 0;
223 e80cfcfc bellard
    y_start = -1;
224 c0c440f3 Blue Swirl
    page_min = -1;
225 550be127 bellard
    page_max = 0;
226 0e1f5a0c aliguori
    d = ds_get_data(ts->ds);
227 6f7e9aec bellard
    s = ts->vram;
228 0e1f5a0c aliguori
    dd = ds_get_linesize(ts->ds);
229 e80cfcfc bellard
    ds = 1024;
230 e80cfcfc bellard
231 0e1f5a0c aliguori
    switch (ds_get_bits_per_pixel(ts->ds)) {
232 e80cfcfc bellard
    case 32:
233 f930d07e blueswir1
        f = tcx_draw_line32;
234 f930d07e blueswir1
        break;
235 21206a10 bellard
    case 15:
236 21206a10 bellard
    case 16:
237 f930d07e blueswir1
        f = tcx_draw_line16;
238 f930d07e blueswir1
        break;
239 e80cfcfc bellard
    default:
240 e80cfcfc bellard
    case 8:
241 f930d07e blueswir1
        f = tcx_draw_line8;
242 f930d07e blueswir1
        break;
243 e80cfcfc bellard
    case 0:
244 f930d07e blueswir1
        return;
245 e80cfcfc bellard
    }
246 3b46e624 ths
247 6f7e9aec bellard
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
248 cd7a45c9 Blue Swirl
        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
249 cd7a45c9 Blue Swirl
                                    DIRTY_MEMORY_VGA)) {
250 f930d07e blueswir1
            if (y_start < 0)
251 e80cfcfc bellard
                y_start = y;
252 e80cfcfc bellard
            if (page < page_min)
253 e80cfcfc bellard
                page_min = page;
254 e80cfcfc bellard
            if (page > page_max)
255 e80cfcfc bellard
                page_max = page;
256 f930d07e blueswir1
            f(ts, d, s, ts->width);
257 f930d07e blueswir1
            d += dd;
258 f930d07e blueswir1
            s += ds;
259 f930d07e blueswir1
            f(ts, d, s, ts->width);
260 f930d07e blueswir1
            d += dd;
261 f930d07e blueswir1
            s += ds;
262 f930d07e blueswir1
            f(ts, d, s, ts->width);
263 f930d07e blueswir1
            d += dd;
264 f930d07e blueswir1
            s += ds;
265 f930d07e blueswir1
            f(ts, d, s, ts->width);
266 f930d07e blueswir1
            d += dd;
267 f930d07e blueswir1
            s += ds;
268 f930d07e blueswir1
        } else {
269 e80cfcfc bellard
            if (y_start >= 0) {
270 e80cfcfc bellard
                /* flush to display */
271 5fafdf24 ths
                dpy_update(ts->ds, 0, y_start,
272 6f7e9aec bellard
                           ts->width, y - y_start);
273 e80cfcfc bellard
                y_start = -1;
274 e80cfcfc bellard
            }
275 f930d07e blueswir1
            d += dd * 4;
276 f930d07e blueswir1
            s += ds * 4;
277 f930d07e blueswir1
        }
278 e80cfcfc bellard
    }
279 e80cfcfc bellard
    if (y_start >= 0) {
280 f930d07e blueswir1
        /* flush to display */
281 f930d07e blueswir1
        dpy_update(ts->ds, 0, y_start,
282 f930d07e blueswir1
                   ts->width, y - y_start);
283 e80cfcfc bellard
    }
284 e80cfcfc bellard
    /* reset modified pages */
285 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
286 d08151bf Avi Kivity
        memory_region_reset_dirty(&ts->vram_mem,
287 d08151bf Avi Kivity
                                  page_min, page_max + TARGET_PAGE_SIZE,
288 d08151bf Avi Kivity
                                  DIRTY_MEMORY_VGA);
289 e80cfcfc bellard
    }
290 420557e8 bellard
}
291 420557e8 bellard
292 eee0b836 blueswir1
static void tcx24_update_display(void *opaque)
293 eee0b836 blueswir1
{
294 eee0b836 blueswir1
    TCXState *ts = opaque;
295 c227f099 Anthony Liguori
    ram_addr_t page, page_min, page_max, cpage, page24;
296 eee0b836 blueswir1
    int y, y_start, dd, ds;
297 eee0b836 blueswir1
    uint8_t *d, *s;
298 eee0b836 blueswir1
    uint32_t *cptr, *s24;
299 eee0b836 blueswir1
300 0e1f5a0c aliguori
    if (ds_get_bits_per_pixel(ts->ds) != 32)
301 eee0b836 blueswir1
            return;
302 d08151bf Avi Kivity
    page = 0;
303 eee0b836 blueswir1
    page24 = ts->vram24_offset;
304 eee0b836 blueswir1
    cpage = ts->cplane_offset;
305 eee0b836 blueswir1
    y_start = -1;
306 c0c440f3 Blue Swirl
    page_min = -1;
307 eee0b836 blueswir1
    page_max = 0;
308 0e1f5a0c aliguori
    d = ds_get_data(ts->ds);
309 eee0b836 blueswir1
    s = ts->vram;
310 eee0b836 blueswir1
    s24 = ts->vram24;
311 eee0b836 blueswir1
    cptr = ts->cplane;
312 0e1f5a0c aliguori
    dd = ds_get_linesize(ts->ds);
313 eee0b836 blueswir1
    ds = 1024;
314 eee0b836 blueswir1
315 eee0b836 blueswir1
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
316 eee0b836 blueswir1
            page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
317 d08151bf Avi Kivity
        if (check_dirty(ts, page, page24, cpage)) {
318 eee0b836 blueswir1
            if (y_start < 0)
319 eee0b836 blueswir1
                y_start = y;
320 eee0b836 blueswir1
            if (page < page_min)
321 eee0b836 blueswir1
                page_min = page;
322 eee0b836 blueswir1
            if (page > page_max)
323 eee0b836 blueswir1
                page_max = page;
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
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
340 eee0b836 blueswir1
            d += dd;
341 eee0b836 blueswir1
            s += ds;
342 eee0b836 blueswir1
            cptr += ds;
343 eee0b836 blueswir1
            s24 += ds;
344 eee0b836 blueswir1
        } else {
345 eee0b836 blueswir1
            if (y_start >= 0) {
346 eee0b836 blueswir1
                /* flush to display */
347 eee0b836 blueswir1
                dpy_update(ts->ds, 0, y_start,
348 eee0b836 blueswir1
                           ts->width, y - y_start);
349 eee0b836 blueswir1
                y_start = -1;
350 eee0b836 blueswir1
            }
351 eee0b836 blueswir1
            d += dd * 4;
352 eee0b836 blueswir1
            s += ds * 4;
353 eee0b836 blueswir1
            cptr += ds * 4;
354 eee0b836 blueswir1
            s24 += ds * 4;
355 eee0b836 blueswir1
        }
356 eee0b836 blueswir1
    }
357 eee0b836 blueswir1
    if (y_start >= 0) {
358 eee0b836 blueswir1
        /* flush to display */
359 eee0b836 blueswir1
        dpy_update(ts->ds, 0, y_start,
360 eee0b836 blueswir1
                   ts->width, y - y_start);
361 eee0b836 blueswir1
    }
362 eee0b836 blueswir1
    /* reset modified pages */
363 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
364 eee0b836 blueswir1
        reset_dirty(ts, page_min, page_max, page24, cpage);
365 eee0b836 blueswir1
    }
366 eee0b836 blueswir1
}
367 eee0b836 blueswir1
368 95219897 pbrook
static void tcx_invalidate_display(void *opaque)
369 420557e8 bellard
{
370 e80cfcfc bellard
    TCXState *s = opaque;
371 e80cfcfc bellard
372 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
373 d3ffcafe Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
374 420557e8 bellard
}
375 420557e8 bellard
376 eee0b836 blueswir1
static void tcx24_invalidate_display(void *opaque)
377 eee0b836 blueswir1
{
378 eee0b836 blueswir1
    TCXState *s = opaque;
379 eee0b836 blueswir1
380 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
381 d3ffcafe Blue Swirl
    tcx24_set_dirty(s);
382 d3ffcafe Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
383 eee0b836 blueswir1
}
384 eee0b836 blueswir1
385 e59fb374 Juan Quintela
static int vmstate_tcx_post_load(void *opaque, int version_id)
386 420557e8 bellard
{
387 420557e8 bellard
    TCXState *s = opaque;
388 3b46e624 ths
389 21206a10 bellard
    update_palette_entries(s, 0, 256);
390 d3ffcafe Blue Swirl
    if (s->depth == 24) {
391 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
392 d3ffcafe Blue Swirl
    } else {
393 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
394 d3ffcafe Blue Swirl
    }
395 5425a216 blueswir1
396 e80cfcfc bellard
    return 0;
397 420557e8 bellard
}
398 420557e8 bellard
399 c0c41a4b Blue Swirl
static const VMStateDescription vmstate_tcx = {
400 c0c41a4b Blue Swirl
    .name ="tcx",
401 c0c41a4b Blue Swirl
    .version_id = 4,
402 c0c41a4b Blue Swirl
    .minimum_version_id = 4,
403 c0c41a4b Blue Swirl
    .minimum_version_id_old = 4,
404 752ff2fa Juan Quintela
    .post_load = vmstate_tcx_post_load,
405 c0c41a4b Blue Swirl
    .fields      = (VMStateField []) {
406 c0c41a4b Blue Swirl
        VMSTATE_UINT16(height, TCXState),
407 c0c41a4b Blue Swirl
        VMSTATE_UINT16(width, TCXState),
408 c0c41a4b Blue Swirl
        VMSTATE_UINT16(depth, TCXState),
409 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(r, TCXState),
410 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(g, TCXState),
411 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(b, TCXState),
412 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_index, TCXState),
413 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_state, TCXState),
414 c0c41a4b Blue Swirl
        VMSTATE_END_OF_LIST()
415 c0c41a4b Blue Swirl
    }
416 c0c41a4b Blue Swirl
};
417 c0c41a4b Blue Swirl
418 7f23f812 Michael S. Tsirkin
static void tcx_reset(DeviceState *d)
419 420557e8 bellard
{
420 7f23f812 Michael S. Tsirkin
    TCXState *s = container_of(d, TCXState, busdev.qdev);
421 e80cfcfc bellard
422 e80cfcfc bellard
    /* Initialize palette */
423 e80cfcfc bellard
    memset(s->r, 0, 256);
424 e80cfcfc bellard
    memset(s->g, 0, 256);
425 e80cfcfc bellard
    memset(s->b, 0, 256);
426 e80cfcfc bellard
    s->r[255] = s->g[255] = s->b[255] = 255;
427 21206a10 bellard
    update_palette_entries(s, 0, 256);
428 e80cfcfc bellard
    memset(s->vram, 0, MAXX*MAXY);
429 d08151bf Avi Kivity
    memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4),
430 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
431 6f7e9aec bellard
    s->dac_index = 0;
432 6f7e9aec bellard
    s->dac_state = 0;
433 6f7e9aec bellard
}
434 6f7e9aec bellard
435 a8170e5e Avi Kivity
static uint64_t tcx_dac_readl(void *opaque, hwaddr addr,
436 d08151bf Avi Kivity
                              unsigned size)
437 6f7e9aec bellard
{
438 6f7e9aec bellard
    return 0;
439 6f7e9aec bellard
}
440 6f7e9aec bellard
441 a8170e5e Avi Kivity
static void tcx_dac_writel(void *opaque, hwaddr addr, uint64_t val,
442 d08151bf Avi Kivity
                           unsigned size)
443 6f7e9aec bellard
{
444 6f7e9aec bellard
    TCXState *s = opaque;
445 6f7e9aec bellard
446 e64d7d59 blueswir1
    switch (addr) {
447 6f7e9aec bellard
    case 0:
448 f930d07e blueswir1
        s->dac_index = val >> 24;
449 f930d07e blueswir1
        s->dac_state = 0;
450 f930d07e blueswir1
        break;
451 e64d7d59 blueswir1
    case 4:
452 f930d07e blueswir1
        switch (s->dac_state) {
453 f930d07e blueswir1
        case 0:
454 f930d07e blueswir1
            s->r[s->dac_index] = val >> 24;
455 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
456 f930d07e blueswir1
            s->dac_state++;
457 f930d07e blueswir1
            break;
458 f930d07e blueswir1
        case 1:
459 f930d07e blueswir1
            s->g[s->dac_index] = val >> 24;
460 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
461 f930d07e blueswir1
            s->dac_state++;
462 f930d07e blueswir1
            break;
463 f930d07e blueswir1
        case 2:
464 f930d07e blueswir1
            s->b[s->dac_index] = val >> 24;
465 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
466 5c8cdbf8 blueswir1
            s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
467 f930d07e blueswir1
        default:
468 f930d07e blueswir1
            s->dac_state = 0;
469 f930d07e blueswir1
            break;
470 f930d07e blueswir1
        }
471 f930d07e blueswir1
        break;
472 6f7e9aec bellard
    default:
473 f930d07e blueswir1
        break;
474 6f7e9aec bellard
    }
475 420557e8 bellard
}
476 420557e8 bellard
477 d08151bf Avi Kivity
static const MemoryRegionOps tcx_dac_ops = {
478 d08151bf Avi Kivity
    .read = tcx_dac_readl,
479 d08151bf Avi Kivity
    .write = tcx_dac_writel,
480 d08151bf Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
481 d08151bf Avi Kivity
    .valid = {
482 d08151bf Avi Kivity
        .min_access_size = 4,
483 d08151bf Avi Kivity
        .max_access_size = 4,
484 d08151bf Avi Kivity
    },
485 6f7e9aec bellard
};
486 6f7e9aec bellard
487 a8170e5e Avi Kivity
static uint64_t dummy_readl(void *opaque, hwaddr addr,
488 d08151bf Avi Kivity
                            unsigned size)
489 8508b89e blueswir1
{
490 8508b89e blueswir1
    return 0;
491 8508b89e blueswir1
}
492 8508b89e blueswir1
493 a8170e5e Avi Kivity
static void dummy_writel(void *opaque, hwaddr addr,
494 d08151bf Avi Kivity
                         uint64_t val, unsigned size)
495 8508b89e blueswir1
{
496 8508b89e blueswir1
}
497 8508b89e blueswir1
498 d08151bf Avi Kivity
static const MemoryRegionOps dummy_ops = {
499 d08151bf Avi Kivity
    .read = dummy_readl,
500 d08151bf Avi Kivity
    .write = dummy_writel,
501 d08151bf Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
502 d08151bf Avi Kivity
    .valid = {
503 d08151bf Avi Kivity
        .min_access_size = 4,
504 d08151bf Avi Kivity
        .max_access_size = 4,
505 d08151bf Avi Kivity
    },
506 8508b89e blueswir1
};
507 8508b89e blueswir1
508 81a322d4 Gerd Hoffmann
static int tcx_init1(SysBusDevice *dev)
509 f40070c3 Blue Swirl
{
510 f40070c3 Blue Swirl
    TCXState *s = FROM_SYSBUS(TCXState, dev);
511 d08151bf Avi Kivity
    ram_addr_t vram_offset = 0;
512 ee6847d1 Gerd Hoffmann
    int size;
513 dc828ca1 pbrook
    uint8_t *vram_base;
514 dc828ca1 pbrook
515 c5705a77 Avi Kivity
    memory_region_init_ram(&s->vram_mem, "tcx.vram",
516 d08151bf Avi Kivity
                           s->vram_size * (1 + 4 + 4));
517 c5705a77 Avi Kivity
    vmstate_register_ram_global(&s->vram_mem);
518 d08151bf Avi Kivity
    vram_base = memory_region_get_ram_ptr(&s->vram_mem);
519 eee0b836 blueswir1
520 f40070c3 Blue Swirl
    /* 8-bit plane */
521 eee0b836 blueswir1
    s->vram = vram_base;
522 ee6847d1 Gerd Hoffmann
    size = s->vram_size;
523 d08151bf Avi Kivity
    memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
524 d08151bf Avi Kivity
                             &s->vram_mem, vram_offset, size);
525 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->vram_8bit);
526 eee0b836 blueswir1
    vram_offset += size;
527 eee0b836 blueswir1
    vram_base += size;
528 e80cfcfc bellard
529 f40070c3 Blue Swirl
    /* DAC */
530 d08151bf Avi Kivity
    memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
531 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->dac);
532 eee0b836 blueswir1
533 f40070c3 Blue Swirl
    /* TEC (dummy) */
534 d08151bf Avi Kivity
    memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
535 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->tec);
536 f40070c3 Blue Swirl
    /* THC: NetBSD writes here even with 8-bit display: dummy */
537 d08151bf Avi Kivity
    memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
538 d08151bf Avi Kivity
                          TCX_THC_NREGS_24);
539 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->thc24);
540 f40070c3 Blue Swirl
541 f40070c3 Blue Swirl
    if (s->depth == 24) {
542 f40070c3 Blue Swirl
        /* 24-bit plane */
543 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
544 eee0b836 blueswir1
        s->vram24 = (uint32_t *)vram_base;
545 eee0b836 blueswir1
        s->vram24_offset = vram_offset;
546 d08151bf Avi Kivity
        memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
547 d08151bf Avi Kivity
                                 &s->vram_mem, vram_offset, size);
548 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->vram_24bit);
549 eee0b836 blueswir1
        vram_offset += size;
550 eee0b836 blueswir1
        vram_base += size;
551 eee0b836 blueswir1
552 f40070c3 Blue Swirl
        /* Control plane */
553 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
554 eee0b836 blueswir1
        s->cplane = (uint32_t *)vram_base;
555 eee0b836 blueswir1
        s->cplane_offset = vram_offset;
556 d08151bf Avi Kivity
        memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
557 d08151bf Avi Kivity
                                 &s->vram_mem, vram_offset, size);
558 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->vram_cplane);
559 f40070c3 Blue Swirl
560 3023f332 aliguori
        s->ds = graphic_console_init(tcx24_update_display,
561 3023f332 aliguori
                                     tcx24_invalidate_display,
562 3023f332 aliguori
                                     tcx24_screen_dump, NULL, s);
563 eee0b836 blueswir1
    } else {
564 f40070c3 Blue Swirl
        /* THC 8 bit (dummy) */
565 d08151bf Avi Kivity
        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
566 d08151bf Avi Kivity
                              TCX_THC_NREGS_8);
567 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->thc8);
568 f40070c3 Blue Swirl
569 3023f332 aliguori
        s->ds = graphic_console_init(tcx_update_display,
570 3023f332 aliguori
                                     tcx_invalidate_display,
571 3023f332 aliguori
                                     tcx_screen_dump, NULL, s);
572 eee0b836 blueswir1
    }
573 e80cfcfc bellard
574 f40070c3 Blue Swirl
    qemu_console_resize(s->ds, s->width, s->height);
575 81a322d4 Gerd Hoffmann
    return 0;
576 420557e8 bellard
}
577 420557e8 bellard
578 d7098135 Luiz Capitulino
static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
579 d7098135 Luiz Capitulino
                            Error **errp)
580 8d5f07fa bellard
{
581 e80cfcfc bellard
    TCXState *s = opaque;
582 8d5f07fa bellard
    FILE *f;
583 e80cfcfc bellard
    uint8_t *d, *d1, v;
584 0ab6b636 Luiz Capitulino
    int ret, y, x;
585 8d5f07fa bellard
586 8d5f07fa bellard
    f = fopen(filename, "wb");
587 0ab6b636 Luiz Capitulino
    if (!f) {
588 0ab6b636 Luiz Capitulino
        error_setg(errp, "failed to open file '%s': %s", filename,
589 0ab6b636 Luiz Capitulino
                   strerror(errno));
590 e80cfcfc bellard
        return;
591 0ab6b636 Luiz Capitulino
    }
592 0ab6b636 Luiz Capitulino
    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
593 0ab6b636 Luiz Capitulino
    if (ret < 0) {
594 0ab6b636 Luiz Capitulino
        goto write_err;
595 0ab6b636 Luiz Capitulino
    }
596 6f7e9aec bellard
    d1 = s->vram;
597 6f7e9aec bellard
    for(y = 0; y < s->height; y++) {
598 8d5f07fa bellard
        d = d1;
599 6f7e9aec bellard
        for(x = 0; x < s->width; x++) {
600 8d5f07fa bellard
            v = *d;
601 0ab6b636 Luiz Capitulino
            ret = fputc(s->r[v], f);
602 0ab6b636 Luiz Capitulino
            if (ret == EOF) {
603 0ab6b636 Luiz Capitulino
                goto write_err;
604 0ab6b636 Luiz Capitulino
            }
605 0ab6b636 Luiz Capitulino
            ret = fputc(s->g[v], f);
606 0ab6b636 Luiz Capitulino
            if (ret == EOF) {
607 0ab6b636 Luiz Capitulino
                goto write_err;
608 0ab6b636 Luiz Capitulino
            }
609 0ab6b636 Luiz Capitulino
            ret = fputc(s->b[v], f);
610 0ab6b636 Luiz Capitulino
            if (ret == EOF) {
611 0ab6b636 Luiz Capitulino
                goto write_err;
612 0ab6b636 Luiz Capitulino
            }
613 8d5f07fa bellard
            d++;
614 8d5f07fa bellard
        }
615 e80cfcfc bellard
        d1 += MAXX;
616 8d5f07fa bellard
    }
617 0ab6b636 Luiz Capitulino
618 0ab6b636 Luiz Capitulino
out:
619 8d5f07fa bellard
    fclose(f);
620 8d5f07fa bellard
    return;
621 0ab6b636 Luiz Capitulino
622 0ab6b636 Luiz Capitulino
write_err:
623 0ab6b636 Luiz Capitulino
    error_setg(errp, "failed to write to file '%s': %s", filename,
624 0ab6b636 Luiz Capitulino
               strerror(errno));
625 0ab6b636 Luiz Capitulino
    unlink(filename);
626 0ab6b636 Luiz Capitulino
    goto out;
627 8d5f07fa bellard
}
628 8d5f07fa bellard
629 d7098135 Luiz Capitulino
static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
630 d7098135 Luiz Capitulino
                              Error **errp)
631 eee0b836 blueswir1
{
632 eee0b836 blueswir1
    TCXState *s = opaque;
633 eee0b836 blueswir1
    FILE *f;
634 eee0b836 blueswir1
    uint8_t *d, *d1, v;
635 eee0b836 blueswir1
    uint32_t *s24, *cptr, dval;
636 537f2d2b Luiz Capitulino
    int ret, y, x;
637 8d5f07fa bellard
638 eee0b836 blueswir1
    f = fopen(filename, "wb");
639 537f2d2b Luiz Capitulino
    if (!f) {
640 537f2d2b Luiz Capitulino
        error_setg(errp, "failed to open file '%s': %s", filename,
641 537f2d2b Luiz Capitulino
                   strerror(errno));
642 eee0b836 blueswir1
        return;
643 537f2d2b Luiz Capitulino
    }
644 537f2d2b Luiz Capitulino
    ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
645 537f2d2b Luiz Capitulino
    if (ret < 0) {
646 537f2d2b Luiz Capitulino
        goto write_err;
647 537f2d2b Luiz Capitulino
    }
648 eee0b836 blueswir1
    d1 = s->vram;
649 eee0b836 blueswir1
    s24 = s->vram24;
650 eee0b836 blueswir1
    cptr = s->cplane;
651 eee0b836 blueswir1
    for(y = 0; y < s->height; y++) {
652 eee0b836 blueswir1
        d = d1;
653 eee0b836 blueswir1
        for(x = 0; x < s->width; x++, d++, s24++) {
654 eee0b836 blueswir1
            if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
655 eee0b836 blueswir1
                dval = *s24 & 0x00ffffff;
656 537f2d2b Luiz Capitulino
                ret = fputc((dval >> 16) & 0xff, f);
657 537f2d2b Luiz Capitulino
                if (ret == EOF) {
658 537f2d2b Luiz Capitulino
                    goto write_err;
659 537f2d2b Luiz Capitulino
                }
660 537f2d2b Luiz Capitulino
                ret = fputc((dval >> 8) & 0xff, f);
661 537f2d2b Luiz Capitulino
                if (ret == EOF) {
662 537f2d2b Luiz Capitulino
                    goto write_err;
663 537f2d2b Luiz Capitulino
                }
664 537f2d2b Luiz Capitulino
                ret = fputc(dval & 0xff, f);
665 537f2d2b Luiz Capitulino
                if (ret == EOF) {
666 537f2d2b Luiz Capitulino
                    goto write_err;
667 537f2d2b Luiz Capitulino
                }
668 eee0b836 blueswir1
            } else {
669 eee0b836 blueswir1
                v = *d;
670 537f2d2b Luiz Capitulino
                ret = fputc(s->r[v], f);
671 537f2d2b Luiz Capitulino
                if (ret == EOF) {
672 537f2d2b Luiz Capitulino
                    goto write_err;
673 537f2d2b Luiz Capitulino
                }
674 537f2d2b Luiz Capitulino
                ret = fputc(s->g[v], f);
675 537f2d2b Luiz Capitulino
                if (ret == EOF) {
676 537f2d2b Luiz Capitulino
                    goto write_err;
677 537f2d2b Luiz Capitulino
                }
678 537f2d2b Luiz Capitulino
                ret = fputc(s->b[v], f);
679 537f2d2b Luiz Capitulino
                if (ret == EOF) {
680 537f2d2b Luiz Capitulino
                    goto write_err;
681 537f2d2b Luiz Capitulino
                }
682 eee0b836 blueswir1
            }
683 eee0b836 blueswir1
        }
684 eee0b836 blueswir1
        d1 += MAXX;
685 eee0b836 blueswir1
    }
686 537f2d2b Luiz Capitulino
687 537f2d2b Luiz Capitulino
out:
688 eee0b836 blueswir1
    fclose(f);
689 eee0b836 blueswir1
    return;
690 537f2d2b Luiz Capitulino
691 537f2d2b Luiz Capitulino
write_err:
692 537f2d2b Luiz Capitulino
    error_setg(errp, "failed to write to file '%s': %s", filename,
693 537f2d2b Luiz Capitulino
               strerror(errno));
694 537f2d2b Luiz Capitulino
    unlink(filename);
695 537f2d2b Luiz Capitulino
    goto out;
696 eee0b836 blueswir1
}
697 f40070c3 Blue Swirl
698 999e12bb Anthony Liguori
static Property tcx_properties[] = {
699 999e12bb Anthony Liguori
    DEFINE_PROP_TADDR("addr",      TCXState, addr,      -1),
700 999e12bb Anthony Liguori
    DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
701 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
702 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
703 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("depth",    TCXState, depth,     -1),
704 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
705 999e12bb Anthony Liguori
};
706 999e12bb Anthony Liguori
707 999e12bb Anthony Liguori
static void tcx_class_init(ObjectClass *klass, void *data)
708 999e12bb Anthony Liguori
{
709 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
710 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
711 999e12bb Anthony Liguori
712 999e12bb Anthony Liguori
    k->init = tcx_init1;
713 39bffca2 Anthony Liguori
    dc->reset = tcx_reset;
714 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_tcx;
715 39bffca2 Anthony Liguori
    dc->props = tcx_properties;
716 999e12bb Anthony Liguori
}
717 999e12bb Anthony Liguori
718 39bffca2 Anthony Liguori
static TypeInfo tcx_info = {
719 39bffca2 Anthony Liguori
    .name          = "SUNW,tcx",
720 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
721 39bffca2 Anthony Liguori
    .instance_size = sizeof(TCXState),
722 39bffca2 Anthony Liguori
    .class_init    = tcx_class_init,
723 ee6847d1 Gerd Hoffmann
};
724 ee6847d1 Gerd Hoffmann
725 83f7d43a Andreas Färber
static void tcx_register_types(void)
726 f40070c3 Blue Swirl
{
727 39bffca2 Anthony Liguori
    type_register_static(&tcx_info);
728 f40070c3 Blue Swirl
}
729 f40070c3 Blue Swirl
730 83f7d43a Andreas Färber
type_init(tcx_register_types)