]> Git Repo - qemu.git/blob - hw/display/tcx.c
Merge branch 'tcg-s390' of git://github.com/rth7680/qemu
[qemu.git] / hw / display / tcx.c
1 /*
2  * QEMU TCX Frame buffer
3  *
4  * Copyright (c) 2003-2005 Fabrice Bellard
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24
25 #include "qemu-common.h"
26 #include "ui/console.h"
27 #include "ui/pixel_ops.h"
28 #include "hw/sysbus.h"
29 #include "hw/qdev-addr.h"
30
31 #define MAXX 1024
32 #define MAXY 768
33 #define TCX_DAC_NREGS 16
34 #define TCX_THC_NREGS_8  0x081c
35 #define TCX_THC_NREGS_24 0x1000
36 #define TCX_TEC_NREGS    0x1000
37
38 typedef struct TCXState {
39     SysBusDevice busdev;
40     QemuConsole *con;
41     uint8_t *vram;
42     uint32_t *vram24, *cplane;
43     MemoryRegion vram_mem;
44     MemoryRegion vram_8bit;
45     MemoryRegion vram_24bit;
46     MemoryRegion vram_cplane;
47     MemoryRegion dac;
48     MemoryRegion tec;
49     MemoryRegion thc24;
50     MemoryRegion thc8;
51     ram_addr_t vram24_offset, cplane_offset;
52     uint32_t vram_size;
53     uint32_t palette[256];
54     uint8_t r[256], g[256], b[256];
55     uint16_t width, height, depth;
56     uint8_t dac_index, dac_state;
57 } TCXState;
58
59 static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
60                             Error **errp);
61 static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
62                             Error **errp);
63
64 static void tcx_set_dirty(TCXState *s)
65 {
66     memory_region_set_dirty(&s->vram_mem, 0, MAXX * MAXY);
67 }
68
69 static void tcx24_set_dirty(TCXState *s)
70 {
71     memory_region_set_dirty(&s->vram_mem, s->vram24_offset, MAXX * MAXY * 4);
72     memory_region_set_dirty(&s->vram_mem, s->cplane_offset, MAXX * MAXY * 4);
73 }
74
75 static void update_palette_entries(TCXState *s, int start, int end)
76 {
77     DisplaySurface *surface = qemu_console_surface(s->con);
78     int i;
79
80     for (i = start; i < end; i++) {
81         switch (surface_bits_per_pixel(surface)) {
82         default:
83         case 8:
84             s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]);
85             break;
86         case 15:
87             s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]);
88             break;
89         case 16:
90             s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]);
91             break;
92         case 32:
93             if (is_surface_bgr(surface)) {
94                 s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
95             } else {
96                 s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
97             }
98             break;
99         }
100     }
101     if (s->depth == 24) {
102         tcx24_set_dirty(s);
103     } else {
104         tcx_set_dirty(s);
105     }
106 }
107
108 static void tcx_draw_line32(TCXState *s1, uint8_t *d,
109                             const uint8_t *s, int width)
110 {
111     int x;
112     uint8_t val;
113     uint32_t *p = (uint32_t *)d;
114
115     for(x = 0; x < width; x++) {
116         val = *s++;
117         *p++ = s1->palette[val];
118     }
119 }
120
121 static void tcx_draw_line16(TCXState *s1, uint8_t *d,
122                             const uint8_t *s, int width)
123 {
124     int x;
125     uint8_t val;
126     uint16_t *p = (uint16_t *)d;
127
128     for(x = 0; x < width; x++) {
129         val = *s++;
130         *p++ = s1->palette[val];
131     }
132 }
133
134 static void tcx_draw_line8(TCXState *s1, uint8_t *d,
135                            const uint8_t *s, int width)
136 {
137     int x;
138     uint8_t val;
139
140     for(x = 0; x < width; x++) {
141         val = *s++;
142         *d++ = s1->palette[val];
143     }
144 }
145
146 /*
147   XXX Could be much more optimal:
148   * detect if line/page/whole screen is in 24 bit mode
149   * if destination is also BGR, use memcpy
150   */
151 static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
152                                      const uint8_t *s, int width,
153                                      const uint32_t *cplane,
154                                      const uint32_t *s24)
155 {
156     DisplaySurface *surface = qemu_console_surface(s1->con);
157     int x, bgr, r, g, b;
158     uint8_t val, *p8;
159     uint32_t *p = (uint32_t *)d;
160     uint32_t dval;
161
162     bgr = is_surface_bgr(surface);
163     for(x = 0; x < width; x++, s++, s24++) {
164         if ((be32_to_cpu(*cplane++) & 0xff000000) == 0x03000000) {
165             // 24-bit direct, BGR order
166             p8 = (uint8_t *)s24;
167             p8++;
168             b = *p8++;
169             g = *p8++;
170             r = *p8;
171             if (bgr)
172                 dval = rgb_to_pixel32bgr(r, g, b);
173             else
174                 dval = rgb_to_pixel32(r, g, b);
175         } else {
176             val = *s;
177             dval = s1->palette[val];
178         }
179         *p++ = dval;
180     }
181 }
182
183 static inline int check_dirty(TCXState *s, ram_addr_t page, ram_addr_t page24,
184                               ram_addr_t cpage)
185 {
186     int ret;
187
188     ret = memory_region_get_dirty(&s->vram_mem, page, TARGET_PAGE_SIZE,
189                                   DIRTY_MEMORY_VGA);
190     ret |= memory_region_get_dirty(&s->vram_mem, page24, TARGET_PAGE_SIZE * 4,
191                                    DIRTY_MEMORY_VGA);
192     ret |= memory_region_get_dirty(&s->vram_mem, cpage, TARGET_PAGE_SIZE * 4,
193                                    DIRTY_MEMORY_VGA);
194     return ret;
195 }
196
197 static inline void reset_dirty(TCXState *ts, ram_addr_t page_min,
198                                ram_addr_t page_max, ram_addr_t page24,
199                               ram_addr_t cpage)
200 {
201     memory_region_reset_dirty(&ts->vram_mem,
202                               page_min, page_max + TARGET_PAGE_SIZE,
203                               DIRTY_MEMORY_VGA);
204     memory_region_reset_dirty(&ts->vram_mem,
205                               page24 + page_min * 4,
206                               page24 + page_max * 4 + TARGET_PAGE_SIZE,
207                               DIRTY_MEMORY_VGA);
208     memory_region_reset_dirty(&ts->vram_mem,
209                               cpage + page_min * 4,
210                               cpage + page_max * 4 + TARGET_PAGE_SIZE,
211                               DIRTY_MEMORY_VGA);
212 }
213
214 /* Fixed line length 1024 allows us to do nice tricks not possible on
215    VGA... */
216 static void tcx_update_display(void *opaque)
217 {
218     TCXState *ts = opaque;
219     DisplaySurface *surface = qemu_console_surface(ts->con);
220     ram_addr_t page, page_min, page_max;
221     int y, y_start, dd, ds;
222     uint8_t *d, *s;
223     void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width);
224
225     if (surface_bits_per_pixel(surface) == 0) {
226         return;
227     }
228
229     page = 0;
230     y_start = -1;
231     page_min = -1;
232     page_max = 0;
233     d = surface_data(surface);
234     s = ts->vram;
235     dd = surface_stride(surface);
236     ds = 1024;
237
238     switch (surface_bits_per_pixel(surface)) {
239     case 32:
240         f = tcx_draw_line32;
241         break;
242     case 15:
243     case 16:
244         f = tcx_draw_line16;
245         break;
246     default:
247     case 8:
248         f = tcx_draw_line8;
249         break;
250     case 0:
251         return;
252     }
253
254     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) {
255         if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
256                                     DIRTY_MEMORY_VGA)) {
257             if (y_start < 0)
258                 y_start = y;
259             if (page < page_min)
260                 page_min = page;
261             if (page > page_max)
262                 page_max = page;
263             f(ts, d, s, ts->width);
264             d += dd;
265             s += ds;
266             f(ts, d, s, ts->width);
267             d += dd;
268             s += ds;
269             f(ts, d, s, ts->width);
270             d += dd;
271             s += ds;
272             f(ts, d, s, ts->width);
273             d += dd;
274             s += ds;
275         } else {
276             if (y_start >= 0) {
277                 /* flush to display */
278                 dpy_gfx_update(ts->con, 0, y_start,
279                                ts->width, y - y_start);
280                 y_start = -1;
281             }
282             d += dd * 4;
283             s += ds * 4;
284         }
285     }
286     if (y_start >= 0) {
287         /* flush to display */
288         dpy_gfx_update(ts->con, 0, y_start,
289                        ts->width, y - y_start);
290     }
291     /* reset modified pages */
292     if (page_max >= page_min) {
293         memory_region_reset_dirty(&ts->vram_mem,
294                                   page_min, page_max + TARGET_PAGE_SIZE,
295                                   DIRTY_MEMORY_VGA);
296     }
297 }
298
299 static void tcx24_update_display(void *opaque)
300 {
301     TCXState *ts = opaque;
302     DisplaySurface *surface = qemu_console_surface(ts->con);
303     ram_addr_t page, page_min, page_max, cpage, page24;
304     int y, y_start, dd, ds;
305     uint8_t *d, *s;
306     uint32_t *cptr, *s24;
307
308     if (surface_bits_per_pixel(surface) != 32) {
309             return;
310     }
311
312     page = 0;
313     page24 = ts->vram24_offset;
314     cpage = ts->cplane_offset;
315     y_start = -1;
316     page_min = -1;
317     page_max = 0;
318     d = surface_data(surface);
319     s = ts->vram;
320     s24 = ts->vram24;
321     cptr = ts->cplane;
322     dd = surface_stride(surface);
323     ds = 1024;
324
325     for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE,
326             page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
327         if (check_dirty(ts, page, page24, cpage)) {
328             if (y_start < 0)
329                 y_start = y;
330             if (page < page_min)
331                 page_min = page;
332             if (page > page_max)
333                 page_max = page;
334             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
335             d += dd;
336             s += ds;
337             cptr += ds;
338             s24 += ds;
339             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
340             d += dd;
341             s += ds;
342             cptr += ds;
343             s24 += ds;
344             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
345             d += dd;
346             s += ds;
347             cptr += ds;
348             s24 += ds;
349             tcx24_draw_line32(ts, d, s, ts->width, cptr, s24);
350             d += dd;
351             s += ds;
352             cptr += ds;
353             s24 += ds;
354         } else {
355             if (y_start >= 0) {
356                 /* flush to display */
357                 dpy_gfx_update(ts->con, 0, y_start,
358                                ts->width, y - y_start);
359                 y_start = -1;
360             }
361             d += dd * 4;
362             s += ds * 4;
363             cptr += ds * 4;
364             s24 += ds * 4;
365         }
366     }
367     if (y_start >= 0) {
368         /* flush to display */
369         dpy_gfx_update(ts->con, 0, y_start,
370                        ts->width, y - y_start);
371     }
372     /* reset modified pages */
373     if (page_max >= page_min) {
374         reset_dirty(ts, page_min, page_max, page24, cpage);
375     }
376 }
377
378 static void tcx_invalidate_display(void *opaque)
379 {
380     TCXState *s = opaque;
381
382     tcx_set_dirty(s);
383     qemu_console_resize(s->con, s->width, s->height);
384 }
385
386 static void tcx24_invalidate_display(void *opaque)
387 {
388     TCXState *s = opaque;
389
390     tcx_set_dirty(s);
391     tcx24_set_dirty(s);
392     qemu_console_resize(s->con, s->width, s->height);
393 }
394
395 static int vmstate_tcx_post_load(void *opaque, int version_id)
396 {
397     TCXState *s = opaque;
398
399     update_palette_entries(s, 0, 256);
400     if (s->depth == 24) {
401         tcx24_set_dirty(s);
402     } else {
403         tcx_set_dirty(s);
404     }
405
406     return 0;
407 }
408
409 static const VMStateDescription vmstate_tcx = {
410     .name ="tcx",
411     .version_id = 4,
412     .minimum_version_id = 4,
413     .minimum_version_id_old = 4,
414     .post_load = vmstate_tcx_post_load,
415     .fields      = (VMStateField []) {
416         VMSTATE_UINT16(height, TCXState),
417         VMSTATE_UINT16(width, TCXState),
418         VMSTATE_UINT16(depth, TCXState),
419         VMSTATE_BUFFER(r, TCXState),
420         VMSTATE_BUFFER(g, TCXState),
421         VMSTATE_BUFFER(b, TCXState),
422         VMSTATE_UINT8(dac_index, TCXState),
423         VMSTATE_UINT8(dac_state, TCXState),
424         VMSTATE_END_OF_LIST()
425     }
426 };
427
428 static void tcx_reset(DeviceState *d)
429 {
430     TCXState *s = container_of(d, TCXState, busdev.qdev);
431
432     /* Initialize palette */
433     memset(s->r, 0, 256);
434     memset(s->g, 0, 256);
435     memset(s->b, 0, 256);
436     s->r[255] = s->g[255] = s->b[255] = 255;
437     update_palette_entries(s, 0, 256);
438     memset(s->vram, 0, MAXX*MAXY);
439     memory_region_reset_dirty(&s->vram_mem, 0, MAXX * MAXY * (1 + 4 + 4),
440                               DIRTY_MEMORY_VGA);
441     s->dac_index = 0;
442     s->dac_state = 0;
443 }
444
445 static uint64_t tcx_dac_readl(void *opaque, hwaddr addr,
446                               unsigned size)
447 {
448     return 0;
449 }
450
451 static void tcx_dac_writel(void *opaque, hwaddr addr, uint64_t val,
452                            unsigned size)
453 {
454     TCXState *s = opaque;
455
456     switch (addr) {
457     case 0:
458         s->dac_index = val >> 24;
459         s->dac_state = 0;
460         break;
461     case 4:
462         switch (s->dac_state) {
463         case 0:
464             s->r[s->dac_index] = val >> 24;
465             update_palette_entries(s, s->dac_index, s->dac_index + 1);
466             s->dac_state++;
467             break;
468         case 1:
469             s->g[s->dac_index] = val >> 24;
470             update_palette_entries(s, s->dac_index, s->dac_index + 1);
471             s->dac_state++;
472             break;
473         case 2:
474             s->b[s->dac_index] = val >> 24;
475             update_palette_entries(s, s->dac_index, s->dac_index + 1);
476             s->dac_index = (s->dac_index + 1) & 255; // Index autoincrement
477         default:
478             s->dac_state = 0;
479             break;
480         }
481         break;
482     default:
483         break;
484     }
485 }
486
487 static const MemoryRegionOps tcx_dac_ops = {
488     .read = tcx_dac_readl,
489     .write = tcx_dac_writel,
490     .endianness = DEVICE_NATIVE_ENDIAN,
491     .valid = {
492         .min_access_size = 4,
493         .max_access_size = 4,
494     },
495 };
496
497 static uint64_t dummy_readl(void *opaque, hwaddr addr,
498                             unsigned size)
499 {
500     return 0;
501 }
502
503 static void dummy_writel(void *opaque, hwaddr addr,
504                          uint64_t val, unsigned size)
505 {
506 }
507
508 static const MemoryRegionOps dummy_ops = {
509     .read = dummy_readl,
510     .write = dummy_writel,
511     .endianness = DEVICE_NATIVE_ENDIAN,
512     .valid = {
513         .min_access_size = 4,
514         .max_access_size = 4,
515     },
516 };
517
518 static int tcx_init1(SysBusDevice *dev)
519 {
520     TCXState *s = FROM_SYSBUS(TCXState, dev);
521     ram_addr_t vram_offset = 0;
522     int size;
523     uint8_t *vram_base;
524
525     memory_region_init_ram(&s->vram_mem, "tcx.vram",
526                            s->vram_size * (1 + 4 + 4));
527     vmstate_register_ram_global(&s->vram_mem);
528     vram_base = memory_region_get_ram_ptr(&s->vram_mem);
529
530     /* 8-bit plane */
531     s->vram = vram_base;
532     size = s->vram_size;
533     memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit",
534                              &s->vram_mem, vram_offset, size);
535     sysbus_init_mmio(dev, &s->vram_8bit);
536     vram_offset += size;
537     vram_base += size;
538
539     /* DAC */
540     memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS);
541     sysbus_init_mmio(dev, &s->dac);
542
543     /* TEC (dummy) */
544     memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS);
545     sysbus_init_mmio(dev, &s->tec);
546     /* THC: NetBSD writes here even with 8-bit display: dummy */
547     memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24",
548                           TCX_THC_NREGS_24);
549     sysbus_init_mmio(dev, &s->thc24);
550
551     if (s->depth == 24) {
552         /* 24-bit plane */
553         size = s->vram_size * 4;
554         s->vram24 = (uint32_t *)vram_base;
555         s->vram24_offset = vram_offset;
556         memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit",
557                                  &s->vram_mem, vram_offset, size);
558         sysbus_init_mmio(dev, &s->vram_24bit);
559         vram_offset += size;
560         vram_base += size;
561
562         /* Control plane */
563         size = s->vram_size * 4;
564         s->cplane = (uint32_t *)vram_base;
565         s->cplane_offset = vram_offset;
566         memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane",
567                                  &s->vram_mem, vram_offset, size);
568         sysbus_init_mmio(dev, &s->vram_cplane);
569
570         s->con = graphic_console_init(tcx24_update_display,
571                                       tcx24_invalidate_display,
572                                       tcx24_screen_dump, NULL, s);
573     } else {
574         /* THC 8 bit (dummy) */
575         memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8",
576                               TCX_THC_NREGS_8);
577         sysbus_init_mmio(dev, &s->thc8);
578
579         s->con = graphic_console_init(tcx_update_display,
580                                       tcx_invalidate_display,
581                                       tcx_screen_dump, NULL, s);
582     }
583
584     qemu_console_resize(s->con, s->width, s->height);
585     return 0;
586 }
587
588 static void tcx_screen_dump(void *opaque, const char *filename, bool cswitch,
589                             Error **errp)
590 {
591     TCXState *s = opaque;
592     FILE *f;
593     uint8_t *d, *d1, v;
594     int ret, y, x;
595
596     f = fopen(filename, "wb");
597     if (!f) {
598         error_setg(errp, "failed to open file '%s': %s", filename,
599                    strerror(errno));
600         return;
601     }
602     ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
603     if (ret < 0) {
604         goto write_err;
605     }
606     d1 = s->vram;
607     for(y = 0; y < s->height; y++) {
608         d = d1;
609         for(x = 0; x < s->width; x++) {
610             v = *d;
611             ret = fputc(s->r[v], f);
612             if (ret == EOF) {
613                 goto write_err;
614             }
615             ret = fputc(s->g[v], f);
616             if (ret == EOF) {
617                 goto write_err;
618             }
619             ret = fputc(s->b[v], f);
620             if (ret == EOF) {
621                 goto write_err;
622             }
623             d++;
624         }
625         d1 += MAXX;
626     }
627
628 out:
629     fclose(f);
630     return;
631
632 write_err:
633     error_setg(errp, "failed to write to file '%s': %s", filename,
634                strerror(errno));
635     unlink(filename);
636     goto out;
637 }
638
639 static void tcx24_screen_dump(void *opaque, const char *filename, bool cswitch,
640                               Error **errp)
641 {
642     TCXState *s = opaque;
643     FILE *f;
644     uint8_t *d, *d1, v;
645     uint32_t *s24, *cptr, dval;
646     int ret, y, x;
647
648     f = fopen(filename, "wb");
649     if (!f) {
650         error_setg(errp, "failed to open file '%s': %s", filename,
651                    strerror(errno));
652         return;
653     }
654     ret = fprintf(f, "P6\n%d %d\n%d\n", s->width, s->height, 255);
655     if (ret < 0) {
656         goto write_err;
657     }
658     d1 = s->vram;
659     s24 = s->vram24;
660     cptr = s->cplane;
661     for(y = 0; y < s->height; y++) {
662         d = d1;
663         for(x = 0; x < s->width; x++, d++, s24++) {
664             if ((*cptr++ & 0xff000000) == 0x03000000) { // 24-bit direct
665                 dval = *s24 & 0x00ffffff;
666                 ret = fputc((dval >> 16) & 0xff, f);
667                 if (ret == EOF) {
668                     goto write_err;
669                 }
670                 ret = fputc((dval >> 8) & 0xff, f);
671                 if (ret == EOF) {
672                     goto write_err;
673                 }
674                 ret = fputc(dval & 0xff, f);
675                 if (ret == EOF) {
676                     goto write_err;
677                 }
678             } else {
679                 v = *d;
680                 ret = fputc(s->r[v], f);
681                 if (ret == EOF) {
682                     goto write_err;
683                 }
684                 ret = fputc(s->g[v], f);
685                 if (ret == EOF) {
686                     goto write_err;
687                 }
688                 ret = fputc(s->b[v], f);
689                 if (ret == EOF) {
690                     goto write_err;
691                 }
692             }
693         }
694         d1 += MAXX;
695     }
696
697 out:
698     fclose(f);
699     return;
700
701 write_err:
702     error_setg(errp, "failed to write to file '%s': %s", filename,
703                strerror(errno));
704     unlink(filename);
705     goto out;
706 }
707
708 static Property tcx_properties[] = {
709     DEFINE_PROP_HEX32("vram_size", TCXState, vram_size, -1),
710     DEFINE_PROP_UINT16("width",    TCXState, width,     -1),
711     DEFINE_PROP_UINT16("height",   TCXState, height,    -1),
712     DEFINE_PROP_UINT16("depth",    TCXState, depth,     -1),
713     DEFINE_PROP_END_OF_LIST(),
714 };
715
716 static void tcx_class_init(ObjectClass *klass, void *data)
717 {
718     DeviceClass *dc = DEVICE_CLASS(klass);
719     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
720
721     k->init = tcx_init1;
722     dc->reset = tcx_reset;
723     dc->vmsd = &vmstate_tcx;
724     dc->props = tcx_properties;
725 }
726
727 static const TypeInfo tcx_info = {
728     .name          = "SUNW,tcx",
729     .parent        = TYPE_SYS_BUS_DEVICE,
730     .instance_size = sizeof(TCXState),
731     .class_init    = tcx_class_init,
732 };
733
734 static void tcx_register_types(void)
735 {
736     type_register_static(&tcx_info);
737 }
738
739 type_init(tcx_register_types)
This page took 0.063754 seconds and 4 git commands to generate.