Statistics
| Branch: | Revision:

root / hw / display / tcx.c @ f487b677

History | View | Annotate | Download (17.5 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 077805fa Paolo Bonzini
#include "qemu-common.h"
26 28ecbaee Paolo Bonzini
#include "ui/console.h"
27 28ecbaee Paolo Bonzini
#include "ui/pixel_ops.h"
28 83c9f4ca Paolo Bonzini
#include "hw/sysbus.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 c78f7137 Gerd Hoffmann
    QemuConsole *con;
40 8d5f07fa bellard
    uint8_t *vram;
41 eee0b836 blueswir1
    uint32_t *vram24, *cplane;
42 d08151bf Avi Kivity
    MemoryRegion vram_mem;
43 d08151bf Avi Kivity
    MemoryRegion vram_8bit;
44 d08151bf Avi Kivity
    MemoryRegion vram_24bit;
45 d08151bf Avi Kivity
    MemoryRegion vram_cplane;
46 d08151bf Avi Kivity
    MemoryRegion dac;
47 d08151bf Avi Kivity
    MemoryRegion tec;
48 d08151bf Avi Kivity
    MemoryRegion thc24;
49 d08151bf Avi Kivity
    MemoryRegion thc8;
50 d08151bf Avi Kivity
    ram_addr_t vram24_offset, cplane_offset;
51 ee6847d1 Gerd Hoffmann
    uint32_t vram_size;
52 21206a10 bellard
    uint32_t palette[256];
53 427a66c3 Blue Swirl
    uint8_t r[256], g[256], b[256];
54 427a66c3 Blue Swirl
    uint16_t width, height, depth;
55 6f7e9aec bellard
    uint8_t dac_index, dac_state;
56 420557e8 bellard
} TCXState;
57 420557e8 bellard
58 d3ffcafe Blue Swirl
static void tcx_set_dirty(TCXState *s)
59 d3ffcafe Blue Swirl
{
60 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
61 d3ffcafe Blue Swirl
}
62 d3ffcafe Blue Swirl
63 d3ffcafe Blue Swirl
static void tcx24_set_dirty(TCXState *s)
64 d3ffcafe Blue Swirl
{
65 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, s->vram24_offset, MAXX * MAXY * 4);
66 fd4aa979 Blue Swirl
    memory_region_set_dirty(&s->vram_mem, s->cplane_offset, MAXX * MAXY * 4);
67 d3ffcafe Blue Swirl
}
68 95219897 pbrook
69 21206a10 bellard
static void update_palette_entries(TCXState *s, int start, int end)
70 21206a10 bellard
{
71 c78f7137 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(s->con);
72 21206a10 bellard
    int i;
73 c78f7137 Gerd Hoffmann
74 c78f7137 Gerd Hoffmann
    for (i = start; i < end; i++) {
75 c78f7137 Gerd Hoffmann
        switch (surface_bits_per_pixel(surface)) {
76 21206a10 bellard
        default:
77 21206a10 bellard
        case 8:
78 21206a10 bellard
            s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
79 21206a10 bellard
            break;
80 21206a10 bellard
        case 15:
81 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
82 21206a10 bellard
            break;
83 21206a10 bellard
        case 16:
84 8927bcfd aliguori
            s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
85 21206a10 bellard
            break;
86 21206a10 bellard
        case 32:
87 c78f7137 Gerd Hoffmann
            if (is_surface_bgr(surface)) {
88 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
89 c78f7137 Gerd Hoffmann
            } else {
90 7b5d76da aliguori
                s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
91 c78f7137 Gerd Hoffmann
            }
92 21206a10 bellard
            break;
93 21206a10 bellard
        }
94 21206a10 bellard
    }
95 d3ffcafe Blue Swirl
    if (s->depth == 24) {
96 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
97 d3ffcafe Blue Swirl
    } else {
98 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
99 d3ffcafe Blue Swirl
    }
100 21206a10 bellard
}
101 21206a10 bellard
102 5fafdf24 ths
static void tcx_draw_line32(TCXState *s1, uint8_t *d,
103 f930d07e blueswir1
                            const uint8_t *s, int width)
104 420557e8 bellard
{
105 e80cfcfc bellard
    int x;
106 e80cfcfc bellard
    uint8_t val;
107 8bdc2159 ths
    uint32_t *p = (uint32_t *)d;
108 e80cfcfc bellard
109 e80cfcfc bellard
    for(x = 0; x < width; x++) {
110 f930d07e blueswir1
        val = *s++;
111 8bdc2159 ths
        *p++ = s1->palette[val];
112 e80cfcfc bellard
    }
113 420557e8 bellard
}
114 420557e8 bellard
115 5fafdf24 ths
static void tcx_draw_line16(TCXState *s1, uint8_t *d,
116 f930d07e blueswir1
                            const uint8_t *s, int width)
117 e80cfcfc bellard
{
118 e80cfcfc bellard
    int x;
119 e80cfcfc bellard
    uint8_t val;
120 8bdc2159 ths
    uint16_t *p = (uint16_t *)d;
121 8d5f07fa bellard
122 e80cfcfc bellard
    for(x = 0; x < width; x++) {
123 f930d07e blueswir1
        val = *s++;
124 8bdc2159 ths
        *p++ = s1->palette[val];
125 e80cfcfc bellard
    }
126 e80cfcfc bellard
}
127 e80cfcfc bellard
128 5fafdf24 ths
static void tcx_draw_line8(TCXState *s1, uint8_t *d,
129 f930d07e blueswir1
                           const uint8_t *s, int width)
130 420557e8 bellard
{
131 e80cfcfc bellard
    int x;
132 e80cfcfc bellard
    uint8_t val;
133 e80cfcfc bellard
134 e80cfcfc bellard
    for(x = 0; x < width; x++) {
135 f930d07e blueswir1
        val = *s++;
136 21206a10 bellard
        *d++ = s1->palette[val];
137 420557e8 bellard
    }
138 420557e8 bellard
}
139 420557e8 bellard
140 688ea2eb blueswir1
/*
141 688ea2eb blueswir1
  XXX Could be much more optimal:
142 688ea2eb blueswir1
  * detect if line/page/whole screen is in 24 bit mode
143 688ea2eb blueswir1
  * if destination is also BGR, use memcpy
144 688ea2eb blueswir1
  */
145 eee0b836 blueswir1
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
146 eee0b836 blueswir1
                                     const uint8_t *s, int width,
147 eee0b836 blueswir1
                                     const uint32_t *cplane,
148 eee0b836 blueswir1
                                     const uint32_t *s24)
149 eee0b836 blueswir1
{
150 c78f7137 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(s1->con);
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 c78f7137 Gerd Hoffmann
    bgr = is_surface_bgr(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 d08151bf Avi Kivity
static inline int check_dirty(TCXState *s, 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
182 cd7a45c9 Blue Swirl
    ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
183 cd7a45c9 Blue Swirl
                                  DIRTY_MEMORY_VGA);
184 cd7a45c9 Blue Swirl
    ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
185 cd7a45c9 Blue Swirl
                                   DIRTY_MEMORY_VGA);
186 cd7a45c9 Blue Swirl
    ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
187 cd7a45c9 Blue Swirl
                                   DIRTY_MEMORY_VGA);
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 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
196 f10acc8b Mark Cave-Ayland
                              page_min,
197 f10acc8b Mark Cave-Ayland
                              (page_max - page_min) + TARGET_PAGE_SIZE,
198 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
199 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
200 d08151bf Avi Kivity
                              page24 + page_min * 4,
201 f10acc8b Mark Cave-Ayland
                              (page_max - page_min) * 4 + TARGET_PAGE_SIZE,
202 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
203 d08151bf Avi Kivity
    memory_region_reset_dirty(&ts->vram_mem,
204 d08151bf Avi Kivity
                              cpage + page_min * 4,
205 f10acc8b Mark Cave-Ayland
                              (page_max - page_min) * 4 + TARGET_PAGE_SIZE,
206 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
207 eee0b836 blueswir1
}
208 eee0b836 blueswir1
209 e80cfcfc bellard
/* Fixed line length 1024 allows us to do nice tricks not possible on
210 e80cfcfc bellard
   VGA... */
211 95219897 pbrook
static void tcx_update_display(void *opaque)
212 420557e8 bellard
{
213 e80cfcfc bellard
    TCXState *ts = opaque;
214 c78f7137 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(ts->con);
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 c78f7137 Gerd Hoffmann
    if (surface_bits_per_pixel(surface) == 0) {
221 f930d07e blueswir1
        return;
222 c78f7137 Gerd Hoffmann
    }
223 c78f7137 Gerd Hoffmann
224 d08151bf Avi Kivity
    page = 0;
225 e80cfcfc bellard
    y_start = -1;
226 c0c440f3 Blue Swirl
    page_min = -1;
227 550be127 bellard
    page_max = 0;
228 c78f7137 Gerd Hoffmann
    d = surface_data(surface);
229 6f7e9aec bellard
    s = ts->vram;
230 c78f7137 Gerd Hoffmann
    dd = surface_stride(surface);
231 e80cfcfc bellard
    ds = 1024;
232 e80cfcfc bellard
233 c78f7137 Gerd Hoffmann
    switch (surface_bits_per_pixel(surface)) {
234 e80cfcfc bellard
    case 32:
235 f930d07e blueswir1
        f = tcx_draw_line32;
236 f930d07e blueswir1
        break;
237 21206a10 bellard
    case 15:
238 21206a10 bellard
    case 16:
239 f930d07e blueswir1
        f = tcx_draw_line16;
240 f930d07e blueswir1
        break;
241 e80cfcfc bellard
    default:
242 e80cfcfc bellard
    case 8:
243 f930d07e blueswir1
        f = tcx_draw_line8;
244 f930d07e blueswir1
        break;
245 e80cfcfc bellard
    case 0:
246 f930d07e blueswir1
        return;
247 e80cfcfc bellard
    }
248 3b46e624 ths
249 6f7e9aec bellard
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
250 cd7a45c9 Blue Swirl
        if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
251 cd7a45c9 Blue Swirl
                                    DIRTY_MEMORY_VGA)) {
252 f930d07e blueswir1
            if (y_start < 0)
253 e80cfcfc bellard
                y_start = y;
254 e80cfcfc bellard
            if (page < page_min)
255 e80cfcfc bellard
                page_min = page;
256 e80cfcfc bellard
            if (page > page_max)
257 e80cfcfc bellard
                page_max = page;
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
            f(ts, d, s, ts->width);
265 f930d07e blueswir1
            d += dd;
266 f930d07e blueswir1
            s += ds;
267 f930d07e blueswir1
            f(ts, d, s, ts->width);
268 f930d07e blueswir1
            d += dd;
269 f930d07e blueswir1
            s += ds;
270 f930d07e blueswir1
        } else {
271 e80cfcfc bellard
            if (y_start >= 0) {
272 e80cfcfc bellard
                /* flush to display */
273 c78f7137 Gerd Hoffmann
                dpy_gfx_update(ts->con, 0, y_start,
274 a93a4a22 Gerd Hoffmann
                               ts->width, y - y_start);
275 e80cfcfc bellard
                y_start = -1;
276 e80cfcfc bellard
            }
277 f930d07e blueswir1
            d += dd * 4;
278 f930d07e blueswir1
            s += ds * 4;
279 f930d07e blueswir1
        }
280 e80cfcfc bellard
    }
281 e80cfcfc bellard
    if (y_start >= 0) {
282 f930d07e blueswir1
        /* flush to display */
283 c78f7137 Gerd Hoffmann
        dpy_gfx_update(ts->con, 0, y_start,
284 a93a4a22 Gerd Hoffmann
                       ts->width, y - y_start);
285 e80cfcfc bellard
    }
286 e80cfcfc bellard
    /* reset modified pages */
287 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
288 d08151bf Avi Kivity
        memory_region_reset_dirty(&ts->vram_mem,
289 f10acc8b Mark Cave-Ayland
                                  page_min,
290 f10acc8b Mark Cave-Ayland
                                  (page_max - page_min) + TARGET_PAGE_SIZE,
291 d08151bf Avi Kivity
                                  DIRTY_MEMORY_VGA);
292 e80cfcfc bellard
    }
293 420557e8 bellard
}
294 420557e8 bellard
295 eee0b836 blueswir1
static void tcx24_update_display(void *opaque)
296 eee0b836 blueswir1
{
297 eee0b836 blueswir1
    TCXState *ts = opaque;
298 c78f7137 Gerd Hoffmann
    DisplaySurface *surface = qemu_console_surface(ts->con);
299 c227f099 Anthony Liguori
    ram_addr_t page, page_min, page_max, cpage, page24;
300 eee0b836 blueswir1
    int y, y_start, dd, ds;
301 eee0b836 blueswir1
    uint8_t *d, *s;
302 eee0b836 blueswir1
    uint32_t *cptr, *s24;
303 eee0b836 blueswir1
304 c78f7137 Gerd Hoffmann
    if (surface_bits_per_pixel(surface) != 32) {
305 eee0b836 blueswir1
            return;
306 c78f7137 Gerd Hoffmann
    }
307 c78f7137 Gerd Hoffmann
308 d08151bf Avi Kivity
    page = 0;
309 eee0b836 blueswir1
    page24 = ts->vram24_offset;
310 eee0b836 blueswir1
    cpage = ts->cplane_offset;
311 eee0b836 blueswir1
    y_start = -1;
312 c0c440f3 Blue Swirl
    page_min = -1;
313 eee0b836 blueswir1
    page_max = 0;
314 c78f7137 Gerd Hoffmann
    d = surface_data(surface);
315 eee0b836 blueswir1
    s = ts->vram;
316 eee0b836 blueswir1
    s24 = ts->vram24;
317 eee0b836 blueswir1
    cptr = ts->cplane;
318 c78f7137 Gerd Hoffmann
    dd = surface_stride(surface);
319 eee0b836 blueswir1
    ds = 1024;
320 eee0b836 blueswir1
321 eee0b836 blueswir1
    for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
322 eee0b836 blueswir1
            page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
323 d08151bf Avi Kivity
        if (check_dirty(ts, page, page24, cpage)) {
324 eee0b836 blueswir1
            if (y_start < 0)
325 eee0b836 blueswir1
                y_start = y;
326 eee0b836 blueswir1
            if (page < page_min)
327 eee0b836 blueswir1
                page_min = page;
328 eee0b836 blueswir1
            if (page > page_max)
329 eee0b836 blueswir1
                page_max = page;
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
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
341 eee0b836 blueswir1
            d += dd;
342 eee0b836 blueswir1
            s += ds;
343 eee0b836 blueswir1
            cptr += ds;
344 eee0b836 blueswir1
            s24 += ds;
345 eee0b836 blueswir1
            tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
346 eee0b836 blueswir1
            d += dd;
347 eee0b836 blueswir1
            s += ds;
348 eee0b836 blueswir1
            cptr += ds;
349 eee0b836 blueswir1
            s24 += ds;
350 eee0b836 blueswir1
        } else {
351 eee0b836 blueswir1
            if (y_start >= 0) {
352 eee0b836 blueswir1
                /* flush to display */
353 c78f7137 Gerd Hoffmann
                dpy_gfx_update(ts->con, 0, y_start,
354 a93a4a22 Gerd Hoffmann
                               ts->width, y - y_start);
355 eee0b836 blueswir1
                y_start = -1;
356 eee0b836 blueswir1
            }
357 eee0b836 blueswir1
            d += dd * 4;
358 eee0b836 blueswir1
            s += ds * 4;
359 eee0b836 blueswir1
            cptr += ds * 4;
360 eee0b836 blueswir1
            s24 += ds * 4;
361 eee0b836 blueswir1
        }
362 eee0b836 blueswir1
    }
363 eee0b836 blueswir1
    if (y_start >= 0) {
364 eee0b836 blueswir1
        /* flush to display */
365 c78f7137 Gerd Hoffmann
        dpy_gfx_update(ts->con, 0, y_start,
366 a93a4a22 Gerd Hoffmann
                       ts->width, y - y_start);
367 eee0b836 blueswir1
    }
368 eee0b836 blueswir1
    /* reset modified pages */
369 c0c440f3 Blue Swirl
    if (page_max >= page_min) {
370 eee0b836 blueswir1
        reset_dirty(ts, page_min, page_max, page24, cpage);
371 eee0b836 blueswir1
    }
372 eee0b836 blueswir1
}
373 eee0b836 blueswir1
374 95219897 pbrook
static void tcx_invalidate_display(void *opaque)
375 420557e8 bellard
{
376 e80cfcfc bellard
    TCXState *s = opaque;
377 e80cfcfc bellard
378 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
379 c78f7137 Gerd Hoffmann
    qemu_console_resize(s->con, s->width, s->height);
380 420557e8 bellard
}
381 420557e8 bellard
382 eee0b836 blueswir1
static void tcx24_invalidate_display(void *opaque)
383 eee0b836 blueswir1
{
384 eee0b836 blueswir1
    TCXState *s = opaque;
385 eee0b836 blueswir1
386 d3ffcafe Blue Swirl
    tcx_set_dirty(s);
387 d3ffcafe Blue Swirl
    tcx24_set_dirty(s);
388 c78f7137 Gerd Hoffmann
    qemu_console_resize(s->con, s->width, s->height);
389 eee0b836 blueswir1
}
390 eee0b836 blueswir1
391 e59fb374 Juan Quintela
static int vmstate_tcx_post_load(void *opaque, int version_id)
392 420557e8 bellard
{
393 420557e8 bellard
    TCXState *s = opaque;
394 3b46e624 ths
395 21206a10 bellard
    update_palette_entries(s, 0, 256);
396 d3ffcafe Blue Swirl
    if (s->depth == 24) {
397 d3ffcafe Blue Swirl
        tcx24_set_dirty(s);
398 d3ffcafe Blue Swirl
    } else {
399 d3ffcafe Blue Swirl
        tcx_set_dirty(s);
400 d3ffcafe Blue Swirl
    }
401 5425a216 blueswir1
402 e80cfcfc bellard
    return 0;
403 420557e8 bellard
}
404 420557e8 bellard
405 c0c41a4b Blue Swirl
static const VMStateDescription vmstate_tcx = {
406 c0c41a4b Blue Swirl
    .name ="tcx",
407 c0c41a4b Blue Swirl
    .version_id = 4,
408 c0c41a4b Blue Swirl
    .minimum_version_id = 4,
409 c0c41a4b Blue Swirl
    .minimum_version_id_old = 4,
410 752ff2fa Juan Quintela
    .post_load = vmstate_tcx_post_load,
411 c0c41a4b Blue Swirl
    .fields      = (VMStateField []) {
412 c0c41a4b Blue Swirl
        VMSTATE_UINT16(height, TCXState),
413 c0c41a4b Blue Swirl
        VMSTATE_UINT16(width, TCXState),
414 c0c41a4b Blue Swirl
        VMSTATE_UINT16(depth, TCXState),
415 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(r, TCXState),
416 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(g, TCXState),
417 c0c41a4b Blue Swirl
        VMSTATE_BUFFER(b, TCXState),
418 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_index, TCXState),
419 c0c41a4b Blue Swirl
        VMSTATE_UINT8(dac_state, TCXState),
420 c0c41a4b Blue Swirl
        VMSTATE_END_OF_LIST()
421 c0c41a4b Blue Swirl
    }
422 c0c41a4b Blue Swirl
};
423 c0c41a4b Blue Swirl
424 7f23f812 Michael S. Tsirkin
static void tcx_reset(DeviceState *d)
425 420557e8 bellard
{
426 7f23f812 Michael S. Tsirkin
    TCXState *s = container_of(d, TCXState, busdev.qdev);
427 e80cfcfc bellard
428 e80cfcfc bellard
    /* Initialize palette */
429 e80cfcfc bellard
    memset(s->r, 0, 256);
430 e80cfcfc bellard
    memset(s->g, 0, 256);
431 e80cfcfc bellard
    memset(s->b, 0, 256);
432 e80cfcfc bellard
    s->r[255] = s->g[255] = s->b[255] = 255;
433 21206a10 bellard
    update_palette_entries(s, 0, 256);
434 e80cfcfc bellard
    memset(s->vram, 0, MAXX*MAXY);
435 d08151bf Avi Kivity
    memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4),
436 d08151bf Avi Kivity
                              DIRTY_MEMORY_VGA);
437 6f7e9aec bellard
    s->dac_index = 0;
438 6f7e9aec bellard
    s->dac_state = 0;
439 6f7e9aec bellard
}
440 6f7e9aec bellard
441 a8170e5e Avi Kivity
static uint64_t tcx_dac_readl(void *opaque, hwaddr addr,
442 d08151bf Avi Kivity
                              unsigned size)
443 6f7e9aec bellard
{
444 6f7e9aec bellard
    return 0;
445 6f7e9aec bellard
}
446 6f7e9aec bellard
447 a8170e5e Avi Kivity
static void tcx_dac_writel(void *opaque, hwaddr addr, uint64_t val,
448 d08151bf Avi Kivity
                           unsigned size)
449 6f7e9aec bellard
{
450 6f7e9aec bellard
    TCXState *s = opaque;
451 6f7e9aec bellard
452 e64d7d59 blueswir1
    switch (addr) {
453 6f7e9aec bellard
    case 0:
454 f930d07e blueswir1
        s->dac_index = val >> 24;
455 f930d07e blueswir1
        s->dac_state = 0;
456 f930d07e blueswir1
        break;
457 e64d7d59 blueswir1
    case 4:
458 f930d07e blueswir1
        switch (s->dac_state) {
459 f930d07e blueswir1
        case 0:
460 f930d07e blueswir1
            s->r[s->dac_index] = val >> 24;
461 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
462 f930d07e blueswir1
            s->dac_state++;
463 f930d07e blueswir1
            break;
464 f930d07e blueswir1
        case 1:
465 f930d07e blueswir1
            s->g[s->dac_index] = val >> 24;
466 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
467 f930d07e blueswir1
            s->dac_state++;
468 f930d07e blueswir1
            break;
469 f930d07e blueswir1
        case 2:
470 f930d07e blueswir1
            s->b[s->dac_index] = val >> 24;
471 21206a10 bellard
            update_palette_entries(s, s->dac_index, s->dac_index + 1);
472 5c8cdbf8 blueswir1
            s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
473 f930d07e blueswir1
        default:
474 f930d07e blueswir1
            s->dac_state = 0;
475 f930d07e blueswir1
            break;
476 f930d07e blueswir1
        }
477 f930d07e blueswir1
        break;
478 6f7e9aec bellard
    default:
479 f930d07e blueswir1
        break;
480 6f7e9aec bellard
    }
481 420557e8 bellard
}
482 420557e8 bellard
483 d08151bf Avi Kivity
static const MemoryRegionOps tcx_dac_ops = {
484 d08151bf Avi Kivity
    .read = tcx_dac_readl,
485 d08151bf Avi Kivity
    .write = tcx_dac_writel,
486 d08151bf Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
487 d08151bf Avi Kivity
    .valid = {
488 d08151bf Avi Kivity
        .min_access_size = 4,
489 d08151bf Avi Kivity
        .max_access_size = 4,
490 d08151bf Avi Kivity
    },
491 6f7e9aec bellard
};
492 6f7e9aec bellard
493 a8170e5e Avi Kivity
static uint64_t dummy_readl(void *opaque, hwaddr addr,
494 d08151bf Avi Kivity
                            unsigned size)
495 8508b89e blueswir1
{
496 8508b89e blueswir1
    return 0;
497 8508b89e blueswir1
}
498 8508b89e blueswir1
499 a8170e5e Avi Kivity
static void dummy_writel(void *opaque, hwaddr addr,
500 d08151bf Avi Kivity
                         uint64_t val, unsigned size)
501 8508b89e blueswir1
{
502 8508b89e blueswir1
}
503 8508b89e blueswir1
504 d08151bf Avi Kivity
static const MemoryRegionOps dummy_ops = {
505 d08151bf Avi Kivity
    .read = dummy_readl,
506 d08151bf Avi Kivity
    .write = dummy_writel,
507 d08151bf Avi Kivity
    .endianness = DEVICE_NATIVE_ENDIAN,
508 d08151bf Avi Kivity
    .valid = {
509 d08151bf Avi Kivity
        .min_access_size = 4,
510 d08151bf Avi Kivity
        .max_access_size = 4,
511 d08151bf Avi Kivity
    },
512 8508b89e blueswir1
};
513 8508b89e blueswir1
514 380cd056 Gerd Hoffmann
static const GraphicHwOps tcx_ops = {
515 380cd056 Gerd Hoffmann
    .invalidate = tcx_invalidate_display,
516 380cd056 Gerd Hoffmann
    .gfx_update = tcx_update_display,
517 380cd056 Gerd Hoffmann
};
518 380cd056 Gerd Hoffmann
519 380cd056 Gerd Hoffmann
static const GraphicHwOps tcx24_ops = {
520 380cd056 Gerd Hoffmann
    .invalidate = tcx24_invalidate_display,
521 380cd056 Gerd Hoffmann
    .gfx_update = tcx24_update_display,
522 380cd056 Gerd Hoffmann
};
523 380cd056 Gerd Hoffmann
524 81a322d4 Gerd Hoffmann
static int tcx_init1(SysBusDevice *dev)
525 f40070c3 Blue Swirl
{
526 f40070c3 Blue Swirl
    TCXState *s = FROM_SYSBUS(TCXState, dev);
527 d08151bf Avi Kivity
    ram_addr_t vram_offset = 0;
528 ee6847d1 Gerd Hoffmann
    int size;
529 dc828ca1 pbrook
    uint8_t *vram_base;
530 dc828ca1 pbrook
531 c5705a77 Avi Kivity
    memory_region_init_ram(&s->vram_mem, "tcx.vram",
532 d08151bf Avi Kivity
                           s->vram_size * (1 + 4 + 4));
533 c5705a77 Avi Kivity
    vmstate_register_ram_global(&s->vram_mem);
534 d08151bf Avi Kivity
    vram_base = memory_region_get_ram_ptr(&s->vram_mem);
535 eee0b836 blueswir1
536 f40070c3 Blue Swirl
    /* 8-bit plane */
537 eee0b836 blueswir1
    s->vram = vram_base;
538 ee6847d1 Gerd Hoffmann
    size = s->vram_size;
539 d08151bf Avi Kivity
    memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
540 d08151bf Avi Kivity
                             &s->vram_mem, vram_offset, size);
541 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->vram_8bit);
542 eee0b836 blueswir1
    vram_offset += size;
543 eee0b836 blueswir1
    vram_base += size;
544 e80cfcfc bellard
545 f40070c3 Blue Swirl
    /* DAC */
546 d08151bf Avi Kivity
    memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
547 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->dac);
548 eee0b836 blueswir1
549 f40070c3 Blue Swirl
    /* TEC (dummy) */
550 d08151bf Avi Kivity
    memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
551 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->tec);
552 f40070c3 Blue Swirl
    /* THC: NetBSD writes here even with 8-bit display: dummy */
553 d08151bf Avi Kivity
    memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
554 d08151bf Avi Kivity
                          TCX_THC_NREGS_24);
555 750ecd44 Avi Kivity
    sysbus_init_mmio(dev, &s->thc24);
556 f40070c3 Blue Swirl
557 f40070c3 Blue Swirl
    if (s->depth == 24) {
558 f40070c3 Blue Swirl
        /* 24-bit plane */
559 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
560 eee0b836 blueswir1
        s->vram24 = (uint32_t *)vram_base;
561 eee0b836 blueswir1
        s->vram24_offset = vram_offset;
562 d08151bf Avi Kivity
        memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
563 d08151bf Avi Kivity
                                 &s->vram_mem, vram_offset, size);
564 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->vram_24bit);
565 eee0b836 blueswir1
        vram_offset += size;
566 eee0b836 blueswir1
        vram_base += size;
567 eee0b836 blueswir1
568 f40070c3 Blue Swirl
        /* Control plane */
569 ee6847d1 Gerd Hoffmann
        size = s->vram_size * 4;
570 eee0b836 blueswir1
        s->cplane = (uint32_t *)vram_base;
571 eee0b836 blueswir1
        s->cplane_offset = vram_offset;
572 d08151bf Avi Kivity
        memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
573 d08151bf Avi Kivity
                                 &s->vram_mem, vram_offset, size);
574 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->vram_cplane);
575 f40070c3 Blue Swirl
576 aa2beaa1 Gerd Hoffmann
        s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, s);
577 eee0b836 blueswir1
    } else {
578 f40070c3 Blue Swirl
        /* THC 8 bit (dummy) */
579 d08151bf Avi Kivity
        memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
580 d08151bf Avi Kivity
                              TCX_THC_NREGS_8);
581 750ecd44 Avi Kivity
        sysbus_init_mmio(dev, &s->thc8);
582 f40070c3 Blue Swirl
583 aa2beaa1 Gerd Hoffmann
        s->con = graphic_console_init(DEVICE(dev), &tcx_ops, s);
584 eee0b836 blueswir1
    }
585 e80cfcfc bellard
586 c78f7137 Gerd Hoffmann
    qemu_console_resize(s->con, s->width, s->height);
587 81a322d4 Gerd Hoffmann
    return 0;
588 420557e8 bellard
}
589 420557e8 bellard
590 999e12bb Anthony Liguori
static Property tcx_properties[] = {
591 999e12bb Anthony Liguori
    DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
592 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
593 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
594 999e12bb Anthony Liguori
    DEFINE_PROP_UINT16("depth",    TCXState, depth,     -1),
595 999e12bb Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
596 999e12bb Anthony Liguori
};
597 999e12bb Anthony Liguori
598 999e12bb Anthony Liguori
static void tcx_class_init(ObjectClass *klass, void *data)
599 999e12bb Anthony Liguori
{
600 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
601 999e12bb Anthony Liguori
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
602 999e12bb Anthony Liguori
603 999e12bb Anthony Liguori
    k->init = tcx_init1;
604 39bffca2 Anthony Liguori
    dc->reset = tcx_reset;
605 39bffca2 Anthony Liguori
    dc->vmsd = &vmstate_tcx;
606 39bffca2 Anthony Liguori
    dc->props = tcx_properties;
607 999e12bb Anthony Liguori
}
608 999e12bb Anthony Liguori
609 8c43a6f0 Andreas Färber
static const TypeInfo tcx_info = {
610 39bffca2 Anthony Liguori
    .name          = "SUNW,tcx",
611 39bffca2 Anthony Liguori
    .parent        = TYPE_SYS_BUS_DEVICE,
612 39bffca2 Anthony Liguori
    .instance_size = sizeof(TCXState),
613 39bffca2 Anthony Liguori
    .class_init    = tcx_class_init,
614 ee6847d1 Gerd Hoffmann
};
615 ee6847d1 Gerd Hoffmann
616 83f7d43a Andreas Färber
static void tcx_register_types(void)
617 f40070c3 Blue Swirl
{
618 39bffca2 Anthony Liguori
    type_register_static(&tcx_info);
619 f40070c3 Blue Swirl
}
620 f40070c3 Blue Swirl
621 83f7d43a Andreas Färber
type_init(tcx_register_types)