xref: /qemu/hw/ipack/tpci200.c (revision abff1abf)
1 /*
2  * QEMU TEWS TPCI200 IndustryPack carrier emulation
3  *
4  * Copyright (C) 2012 Igalia, S.L.
5  * Author: Alberto Garcia <berto@igalia.com>
6  *
7  * This code is licensed under the GNU GPL v2 or (at your option) any
8  * later version.
9  */
10 
11 #include "qemu/osdep.h"
12 #include "qemu/units.h"
13 #include "hw/ipack/ipack.h"
14 #include "hw/irq.h"
15 #include "hw/pci/pci.h"
16 #include "migration/vmstate.h"
17 #include "qemu/bitops.h"
18 #include "qemu/module.h"
19 
20 /* #define DEBUG_TPCI */
21 
22 #ifdef DEBUG_TPCI
23 #define DPRINTF(fmt, ...) \
24     do { fprintf(stderr, "TPCI200: " fmt, ## __VA_ARGS__); } while (0)
25 #else
26 #define DPRINTF(fmt, ...) do { } while (0)
27 #endif
28 
29 #define N_MODULES 4
30 
31 #define IP_ID_SPACE  2
32 #define IP_INT_SPACE 3
33 #define IP_IO_SPACE_ADDR_MASK  0x7F
34 #define IP_ID_SPACE_ADDR_MASK  0x3F
35 #define IP_INT_SPACE_ADDR_MASK 0x3F
36 
37 #define STATUS_INT(IP, INTNO) BIT((IP) * 2 + (INTNO))
38 #define STATUS_TIME(IP)       BIT((IP) + 12)
39 #define STATUS_ERR_ANY        0xF00
40 
41 #define CTRL_CLKRATE          BIT(0)
42 #define CTRL_RECOVER          BIT(1)
43 #define CTRL_TIME_INT         BIT(2)
44 #define CTRL_ERR_INT          BIT(3)
45 #define CTRL_INT_EDGE(INTNO)  BIT(4 + (INTNO))
46 #define CTRL_INT(INTNO)       BIT(6 + (INTNO))
47 
48 #define REG_REV_ID    0x00
49 #define REG_IP_A_CTRL 0x02
50 #define REG_IP_B_CTRL 0x04
51 #define REG_IP_C_CTRL 0x06
52 #define REG_IP_D_CTRL 0x08
53 #define REG_RESET     0x0A
54 #define REG_STATUS    0x0C
55 #define IP_N_FROM_REG(REG) ((REG) / 2 - 1)
56 
57 typedef struct {
58     PCIDevice dev;
59     IPackBus bus;
60     MemoryRegion mmio;
61     MemoryRegion io;
62     MemoryRegion las0;
63     MemoryRegion las1;
64     MemoryRegion las2;
65     MemoryRegion las3;
66     bool big_endian[3];
67     uint8_t ctrl[N_MODULES];
68     uint16_t status;
69     uint8_t int_set;
70 } TPCI200State;
71 
72 #define TYPE_TPCI200 "tpci200"
73 
74 #define TPCI200(obj) \
75     OBJECT_CHECK(TPCI200State, (obj), TYPE_TPCI200)
76 
77 static const uint8_t local_config_regs[] = {
78     0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0x00,
79     0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
80     0x00, 0x08, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01,
81     0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x60, 0x41, 0xD4,
82     0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x01,
83     0x14, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x08, 0x01, 0x02,
84     0x00, 0x04, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0x02, 0x41,
85     0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x00, 0x52, 0x92, 0x24, 0x02
86 };
87 
88 static void adjust_addr(bool big_endian, hwaddr *addr, unsigned size)
89 {
90     /* During 8 bit access in big endian mode,
91        odd and even addresses are swapped */
92     if (big_endian && size == 1) {
93         *addr ^= 1;
94     }
95 }
96 
97 static uint64_t adjust_value(bool big_endian, uint64_t *val, unsigned size)
98 {
99     /* Local spaces only support 8/16 bit access,
100      * so there's no need to care for sizes > 2 */
101     if (big_endian && size == 2) {
102         *val = bswap16(*val);
103     }
104     return *val;
105 }
106 
107 static void tpci200_set_irq(void *opaque, int intno, int level)
108 {
109     IPackDevice *ip = opaque;
110     IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(DEVICE(ip)));
111     PCIDevice *pcidev = PCI_DEVICE(BUS(bus)->parent);
112     TPCI200State *dev = TPCI200(pcidev);
113     unsigned ip_n = ip->slot;
114     uint16_t prev_status = dev->status;
115 
116     assert(ip->slot >= 0 && ip->slot < N_MODULES);
117 
118     /* The requested interrupt must be enabled in the IP CONTROL
119      * register */
120     if (!(dev->ctrl[ip_n] & CTRL_INT(intno))) {
121         return;
122     }
123 
124     /* Update the interrupt status in the IP STATUS register */
125     if (level) {
126         dev->status |=  STATUS_INT(ip_n, intno);
127     } else {
128         dev->status &= ~STATUS_INT(ip_n, intno);
129     }
130 
131     /* Return if there are no changes */
132     if (dev->status == prev_status) {
133         return;
134     }
135 
136     DPRINTF("IP %u INT%u#: %u\n", ip_n, intno, level);
137 
138     /* Check if the interrupt is edge sensitive */
139     if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) {
140         if (level) {
141             pci_set_irq(&dev->dev, !dev->int_set);
142             pci_set_irq(&dev->dev,  dev->int_set);
143         }
144     } else {
145         unsigned i, j;
146         uint16_t level_status = dev->status;
147 
148         /* Check if there are any level sensitive interrupts set by
149            removing the ones that are edge sensitive from the status
150            register */
151         for (i = 0; i < N_MODULES; i++) {
152             for (j = 0; j < 2; j++) {
153                 if (dev->ctrl[i] & CTRL_INT_EDGE(j)) {
154                     level_status &= ~STATUS_INT(i, j);
155                 }
156             }
157         }
158 
159         if (level_status && !dev->int_set) {
160             pci_irq_assert(&dev->dev);
161             dev->int_set = 1;
162         } else if (!level_status && dev->int_set) {
163             pci_irq_deassert(&dev->dev);
164             dev->int_set = 0;
165         }
166     }
167 }
168 
169 static uint64_t tpci200_read_cfg(void *opaque, hwaddr addr, unsigned size)
170 {
171     TPCI200State *s = opaque;
172     uint8_t ret = 0;
173     if (addr < ARRAY_SIZE(local_config_regs)) {
174         ret = local_config_regs[addr];
175     }
176     /* Endianness is stored in the first bit of these registers */
177     if ((addr == 0x2b && s->big_endian[0]) ||
178         (addr == 0x2f && s->big_endian[1]) ||
179         (addr == 0x33 && s->big_endian[2])) {
180         ret |= 1;
181     }
182     DPRINTF("Read from LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) ret);
183     return ret;
184 }
185 
186 static void tpci200_write_cfg(void *opaque, hwaddr addr, uint64_t val,
187                               unsigned size)
188 {
189     TPCI200State *s = opaque;
190     /* Endianness is stored in the first bit of these registers */
191     if (addr == 0x2b || addr == 0x2f || addr == 0x33) {
192         unsigned las = (addr - 0x2b) / 4;
193         s->big_endian[las] = val & 1;
194         DPRINTF("LAS%u big endian mode: %u\n", las, (unsigned) val & 1);
195     } else {
196         DPRINTF("Write to LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) val);
197     }
198 }
199 
200 static uint64_t tpci200_read_las0(void *opaque, hwaddr addr, unsigned size)
201 {
202     TPCI200State *s = opaque;
203     uint64_t ret = 0;
204 
205     switch (addr) {
206 
207     case REG_REV_ID:
208         DPRINTF("Read REVISION ID\n"); /* Current value is 0x00 */
209         break;
210 
211     case REG_IP_A_CTRL:
212     case REG_IP_B_CTRL:
213     case REG_IP_C_CTRL:
214     case REG_IP_D_CTRL:
215         {
216             unsigned ip_n = IP_N_FROM_REG(addr);
217             ret = s->ctrl[ip_n];
218             DPRINTF("Read IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) ret);
219         }
220         break;
221 
222     case REG_RESET:
223         DPRINTF("Read RESET\n"); /* Not implemented */
224         break;
225 
226     case REG_STATUS:
227         ret = s->status;
228         DPRINTF("Read STATUS: 0x%x\n", (unsigned) ret);
229         break;
230 
231     /* Reserved */
232     default:
233         DPRINTF("Unsupported read from LAS0 0x%x\n", (unsigned) addr);
234         break;
235     }
236 
237     return adjust_value(s->big_endian[0], &ret, size);
238 }
239 
240 static void tpci200_write_las0(void *opaque, hwaddr addr, uint64_t val,
241                                unsigned size)
242 {
243     TPCI200State *s = opaque;
244 
245     adjust_value(s->big_endian[0], &val, size);
246 
247     switch (addr) {
248 
249     case REG_REV_ID:
250         DPRINTF("Write Revision ID: 0x%x\n", (unsigned) val); /* No effect */
251         break;
252 
253     case REG_IP_A_CTRL:
254     case REG_IP_B_CTRL:
255     case REG_IP_C_CTRL:
256     case REG_IP_D_CTRL:
257         {
258             unsigned ip_n = IP_N_FROM_REG(addr);
259             s->ctrl[ip_n] = val;
260             DPRINTF("Write IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) val);
261         }
262         break;
263 
264     case REG_RESET:
265         DPRINTF("Write RESET: 0x%x\n", (unsigned) val); /* Not implemented */
266         break;
267 
268     case REG_STATUS:
269         {
270             unsigned i;
271 
272             for (i = 0; i < N_MODULES; i++) {
273                 IPackDevice *ip = ipack_device_find(&s->bus, i);
274 
275                 if (ip != NULL) {
276                     if (val & STATUS_INT(i, 0)) {
277                         DPRINTF("Clear IP %c INT0# status\n", 'A' + i);
278                         qemu_irq_lower(ip->irq[0]);
279                     }
280                     if (val & STATUS_INT(i, 1)) {
281                         DPRINTF("Clear IP %c INT1# status\n", 'A' + i);
282                         qemu_irq_lower(ip->irq[1]);
283                     }
284                 }
285 
286                 if (val & STATUS_TIME(i)) {
287                     DPRINTF("Clear IP %c timeout\n", 'A' + i);
288                     s->status &= ~STATUS_TIME(i);
289                 }
290             }
291 
292             if (val & STATUS_ERR_ANY) {
293                 DPRINTF("Unexpected write to STATUS register: 0x%x\n",
294                         (unsigned) val);
295             }
296         }
297         break;
298 
299     /* Reserved */
300     default:
301         DPRINTF("Unsupported write to LAS0 0x%x: 0x%x\n",
302                 (unsigned) addr, (unsigned) val);
303         break;
304     }
305 }
306 
307 static uint64_t tpci200_read_las1(void *opaque, hwaddr addr, unsigned size)
308 {
309     TPCI200State *s = opaque;
310     IPackDevice *ip;
311     uint64_t ret = 0;
312     unsigned ip_n, space;
313     uint8_t offset;
314 
315     adjust_addr(s->big_endian[1], &addr, size);
316 
317     /*
318      * The address is divided into the IP module number (0-4), the IP
319      * address space (I/O, ID, INT) and the offset within that space.
320      */
321     ip_n = addr >> 8;
322     space = (addr >> 6) & 3;
323     ip = ipack_device_find(&s->bus, ip_n);
324 
325     if (ip == NULL) {
326         DPRINTF("Read LAS1: IP module %u not installed\n", ip_n);
327     } else {
328         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
329         switch (space) {
330 
331         case IP_ID_SPACE:
332             offset = addr & IP_ID_SPACE_ADDR_MASK;
333             if (k->id_read) {
334                 ret = k->id_read(ip, offset);
335             }
336             break;
337 
338         case IP_INT_SPACE:
339             offset = addr & IP_INT_SPACE_ADDR_MASK;
340 
341             /* Read address 0 to ACK IP INT0# and address 2 to ACK IP INT1# */
342             if (offset == 0 || offset == 2) {
343                 unsigned intno = offset / 2;
344                 bool int_set = s->status & STATUS_INT(ip_n, intno);
345                 bool int_edge_sensitive = s->ctrl[ip_n] & CTRL_INT_EDGE(intno);
346                 if (int_set && !int_edge_sensitive) {
347                     qemu_irq_lower(ip->irq[intno]);
348                 }
349             }
350 
351             if (k->int_read) {
352                 ret = k->int_read(ip, offset);
353             }
354             break;
355 
356         default:
357             offset = addr & IP_IO_SPACE_ADDR_MASK;
358             if (k->io_read) {
359                 ret = k->io_read(ip, offset);
360             }
361             break;
362         }
363     }
364 
365     return adjust_value(s->big_endian[1], &ret, size);
366 }
367 
368 static void tpci200_write_las1(void *opaque, hwaddr addr, uint64_t val,
369                                unsigned size)
370 {
371     TPCI200State *s = opaque;
372     IPackDevice *ip;
373     unsigned ip_n, space;
374     uint8_t offset;
375 
376     adjust_addr(s->big_endian[1], &addr, size);
377     adjust_value(s->big_endian[1], &val, size);
378 
379     /*
380      * The address is divided into the IP module number, the IP
381      * address space (I/O, ID, INT) and the offset within that space.
382      */
383     ip_n = addr >> 8;
384     space = (addr >> 6) & 3;
385     ip = ipack_device_find(&s->bus, ip_n);
386 
387     if (ip == NULL) {
388         DPRINTF("Write LAS1: IP module %u not installed\n", ip_n);
389     } else {
390         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
391         switch (space) {
392 
393         case IP_ID_SPACE:
394             offset = addr & IP_ID_SPACE_ADDR_MASK;
395             if (k->id_write) {
396                 k->id_write(ip, offset, val);
397             }
398             break;
399 
400         case IP_INT_SPACE:
401             offset = addr & IP_INT_SPACE_ADDR_MASK;
402             if (k->int_write) {
403                 k->int_write(ip, offset, val);
404             }
405             break;
406 
407         default:
408             offset = addr & IP_IO_SPACE_ADDR_MASK;
409             if (k->io_write) {
410                 k->io_write(ip, offset, val);
411             }
412             break;
413         }
414     }
415 }
416 
417 static uint64_t tpci200_read_las2(void *opaque, hwaddr addr, unsigned size)
418 {
419     TPCI200State *s = opaque;
420     IPackDevice *ip;
421     uint64_t ret = 0;
422     unsigned ip_n;
423     uint32_t offset;
424 
425     adjust_addr(s->big_endian[2], &addr, size);
426 
427     /*
428      * The address is divided into the IP module number and the offset
429      * within the IP module MEM space.
430      */
431     ip_n = addr >> 23;
432     offset = addr & 0x7fffff;
433     ip = ipack_device_find(&s->bus, ip_n);
434 
435     if (ip == NULL) {
436         DPRINTF("Read LAS2: IP module %u not installed\n", ip_n);
437     } else {
438         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
439         if (k->mem_read16) {
440             ret = k->mem_read16(ip, offset);
441         }
442     }
443 
444     return adjust_value(s->big_endian[2], &ret, size);
445 }
446 
447 static void tpci200_write_las2(void *opaque, hwaddr addr, uint64_t val,
448                                unsigned size)
449 {
450     TPCI200State *s = opaque;
451     IPackDevice *ip;
452     unsigned ip_n;
453     uint32_t offset;
454 
455     adjust_addr(s->big_endian[2], &addr, size);
456     adjust_value(s->big_endian[2], &val, size);
457 
458     /*
459      * The address is divided into the IP module number and the offset
460      * within the IP module MEM space.
461      */
462     ip_n = addr >> 23;
463     offset = addr & 0x7fffff;
464     ip = ipack_device_find(&s->bus, ip_n);
465 
466     if (ip == NULL) {
467         DPRINTF("Write LAS2: IP module %u not installed\n", ip_n);
468     } else {
469         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
470         if (k->mem_write16) {
471             k->mem_write16(ip, offset, val);
472         }
473     }
474 }
475 
476 static uint64_t tpci200_read_las3(void *opaque, hwaddr addr, unsigned size)
477 {
478     TPCI200State *s = opaque;
479     IPackDevice *ip;
480     uint64_t ret = 0;
481     /*
482      * The address is divided into the IP module number and the offset
483      * within the IP module MEM space.
484      */
485     unsigned ip_n = addr >> 22;
486     uint32_t offset = addr & 0x3fffff;
487 
488     ip = ipack_device_find(&s->bus, ip_n);
489 
490     if (ip == NULL) {
491         DPRINTF("Read LAS3: IP module %u not installed\n", ip_n);
492     } else {
493         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
494         if (k->mem_read8) {
495             ret = k->mem_read8(ip, offset);
496         }
497     }
498 
499     return ret;
500 }
501 
502 static void tpci200_write_las3(void *opaque, hwaddr addr, uint64_t val,
503                                unsigned size)
504 {
505     TPCI200State *s = opaque;
506     IPackDevice *ip;
507     /*
508      * The address is divided into the IP module number and the offset
509      * within the IP module MEM space.
510      */
511     unsigned ip_n = addr >> 22;
512     uint32_t offset = addr & 0x3fffff;
513 
514     ip = ipack_device_find(&s->bus, ip_n);
515 
516     if (ip == NULL) {
517         DPRINTF("Write LAS3: IP module %u not installed\n", ip_n);
518     } else {
519         IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
520         if (k->mem_write8) {
521             k->mem_write8(ip, offset, val);
522         }
523     }
524 }
525 
526 static const MemoryRegionOps tpci200_cfg_ops = {
527     .read = tpci200_read_cfg,
528     .write = tpci200_write_cfg,
529     .endianness = DEVICE_NATIVE_ENDIAN,
530     .valid =  {
531         .min_access_size = 1,
532         .max_access_size = 4
533     },
534     .impl = {
535         .min_access_size = 1,
536         .max_access_size = 1
537     }
538 };
539 
540 static const MemoryRegionOps tpci200_las0_ops = {
541     .read = tpci200_read_las0,
542     .write = tpci200_write_las0,
543     .endianness = DEVICE_NATIVE_ENDIAN,
544     .valid =  {
545         .min_access_size = 2,
546         .max_access_size = 2
547     }
548 };
549 
550 static const MemoryRegionOps tpci200_las1_ops = {
551     .read = tpci200_read_las1,
552     .write = tpci200_write_las1,
553     .endianness = DEVICE_NATIVE_ENDIAN,
554     .valid =  {
555         .min_access_size = 1,
556         .max_access_size = 2
557     }
558 };
559 
560 static const MemoryRegionOps tpci200_las2_ops = {
561     .read = tpci200_read_las2,
562     .write = tpci200_write_las2,
563     .endianness = DEVICE_NATIVE_ENDIAN,
564     .valid =  {
565         .min_access_size = 1,
566         .max_access_size = 2
567     }
568 };
569 
570 static const MemoryRegionOps tpci200_las3_ops = {
571     .read = tpci200_read_las3,
572     .write = tpci200_write_las3,
573     .endianness = DEVICE_NATIVE_ENDIAN,
574     .valid =  {
575         .min_access_size = 1,
576         .max_access_size = 1
577     }
578 };
579 
580 static void tpci200_realize(PCIDevice *pci_dev, Error **errp)
581 {
582     TPCI200State *s = TPCI200(pci_dev);
583     uint8_t *c = s->dev.config;
584 
585     pci_set_word(c + PCI_COMMAND, 0x0003);
586     pci_set_word(c + PCI_STATUS,  0x0280);
587 
588     pci_set_byte(c + PCI_INTERRUPT_PIN, 0x01); /* Interrupt pin A */
589 
590     pci_set_byte(c + PCI_CAPABILITY_LIST, 0x40);
591     pci_set_long(c + 0x40, 0x48014801);
592     pci_set_long(c + 0x48, 0x00024C06);
593     pci_set_long(c + 0x4C, 0x00000003);
594 
595     memory_region_init_io(&s->mmio, OBJECT(s), &tpci200_cfg_ops,
596                           s, "tpci200_mmio", 128);
597     memory_region_init_io(&s->io, OBJECT(s),   &tpci200_cfg_ops,
598                           s, "tpci200_io",   128);
599     memory_region_init_io(&s->las0, OBJECT(s), &tpci200_las0_ops,
600                           s, "tpci200_las0", 256);
601     memory_region_init_io(&s->las1, OBJECT(s), &tpci200_las1_ops,
602                           s, "tpci200_las1", 1024);
603     memory_region_init_io(&s->las2, OBJECT(s), &tpci200_las2_ops,
604                           s, "tpci200_las2", 32 * MiB);
605     memory_region_init_io(&s->las3, OBJECT(s), &tpci200_las3_ops,
606                           s, "tpci200_las3", 16 * MiB);
607     pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
608     pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO,     &s->io);
609     pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las0);
610     pci_register_bar(&s->dev, 3, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las1);
611     pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las2);
612     pci_register_bar(&s->dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las3);
613 
614     ipack_bus_new_inplace(&s->bus, sizeof(s->bus), DEVICE(pci_dev), NULL,
615                           N_MODULES, tpci200_set_irq);
616 }
617 
618 static const VMStateDescription vmstate_tpci200 = {
619     .name = "tpci200",
620     .version_id = 1,
621     .minimum_version_id = 1,
622     .fields = (VMStateField[]) {
623         VMSTATE_PCI_DEVICE(dev, TPCI200State),
624         VMSTATE_BOOL_ARRAY(big_endian, TPCI200State, 3),
625         VMSTATE_UINT8_ARRAY(ctrl, TPCI200State, N_MODULES),
626         VMSTATE_UINT16(status, TPCI200State),
627         VMSTATE_UINT8(int_set, TPCI200State),
628         VMSTATE_END_OF_LIST()
629     }
630 };
631 
632 static void tpci200_class_init(ObjectClass *klass, void *data)
633 {
634     DeviceClass *dc = DEVICE_CLASS(klass);
635     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
636 
637     k->realize = tpci200_realize;
638     k->vendor_id = PCI_VENDOR_ID_TEWS;
639     k->device_id = PCI_DEVICE_ID_TEWS_TPCI200;
640     k->class_id = PCI_CLASS_BRIDGE_OTHER;
641     k->subsystem_vendor_id = PCI_VENDOR_ID_TEWS;
642     k->subsystem_id = 0x300A;
643     set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
644     dc->desc = "TEWS TPCI200 IndustryPack carrier";
645     dc->vmsd = &vmstate_tpci200;
646 }
647 
648 static const TypeInfo tpci200_info = {
649     .name          = TYPE_TPCI200,
650     .parent        = TYPE_PCI_DEVICE,
651     .instance_size = sizeof(TPCI200State),
652     .class_init    = tpci200_class_init,
653     .interfaces = (InterfaceInfo[]) {
654         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
655         { },
656     },
657 };
658 
659 static void tpci200_register_types(void)
660 {
661     type_register_static(&tpci200_info);
662 }
663 
664 type_init(tpci200_register_types)
665