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