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