qemu/hw/ipack/tpci200.c
<<
>>
Prefs
   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
  57typedef 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
  77static 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
  88static 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
  97static 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
 107static 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
 169static 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
 186static 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
 200static 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
 240static 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
 307static 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
 368static 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
 417static 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
 447static 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
 476static 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
 502static 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
 526static 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
 540static 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
 550static 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
 560static 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
 570static 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
 580static 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
 618static 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
 632static 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
 648static 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
 659static void tpci200_register_types(void)
 660{
 661    type_register_static(&tpci200_info);
 662}
 663
 664type_init(tpci200_register_types)
 665