Statistics
| Branch: | Revision:

root / hw / tcx.c @ 7fc2f2c0

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