Statistics
| Branch: | Revision:

root / hw / tpci200.c @ 3e3648b2

History | View | Annotate | Download (18.7 kB)

1
/*
2
 * QEMU TEWS TPCI200 IndustryPack carrier emulation
3
 *
4
 * Copyright (C) 2012 Igalia, S.L.
5
 * Author: Alberto Garcia <agarcia@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 "ipack.h"
12
#include "pci/pci.h"
13
#include "qemu/bitops.h"
14
#include <stdio.h>
15

    
16
/* #define DEBUG_TPCI */
17

    
18
#ifdef DEBUG_TPCI
19
#define DPRINTF(fmt, ...) \
20
    do { fprintf(stderr, "TPCI200: " fmt, ## __VA_ARGS__); } while (0)
21
#else
22
#define DPRINTF(fmt, ...) do { } while (0)
23
#endif
24

    
25
#define N_MODULES 4
26

    
27
#define IP_ID_SPACE  2
28
#define IP_INT_SPACE 3
29
#define IP_IO_SPACE_ADDR_MASK  0x7F
30
#define IP_ID_SPACE_ADDR_MASK  0x3F
31
#define IP_INT_SPACE_ADDR_MASK 0x3F
32

    
33
#define STATUS_INT(IP, INTNO) BIT((IP) * 2 + (INTNO))
34
#define STATUS_TIME(IP)       BIT((IP) + 12)
35
#define STATUS_ERR_ANY        0xF00
36

    
37
#define CTRL_CLKRATE          BIT(0)
38
#define CTRL_RECOVER          BIT(1)
39
#define CTRL_TIME_INT         BIT(2)
40
#define CTRL_ERR_INT          BIT(3)
41
#define CTRL_INT_EDGE(INTNO)  BIT(4 + (INTNO))
42
#define CTRL_INT(INTNO)       BIT(6 + (INTNO))
43

    
44
#define REG_REV_ID    0x00
45
#define REG_IP_A_CTRL 0x02
46
#define REG_IP_B_CTRL 0x04
47
#define REG_IP_C_CTRL 0x06
48
#define REG_IP_D_CTRL 0x08
49
#define REG_RESET     0x0A
50
#define REG_STATUS    0x0C
51
#define IP_N_FROM_REG(REG) ((REG) / 2 - 1)
52

    
53
typedef struct {
54
    PCIDevice dev;
55
    IPackBus bus;
56
    MemoryRegion mmio;
57
    MemoryRegion io;
58
    MemoryRegion las0;
59
    MemoryRegion las1;
60
    MemoryRegion las2;
61
    MemoryRegion las3;
62
    bool big_endian[3];
63
    uint8_t ctrl[N_MODULES];
64
    uint16_t status;
65
    uint8_t int_set;
66
} TPCI200State;
67

    
68
#define TYPE_TPCI200 "tpci200"
69

    
70
#define TPCI200(obj) \
71
    OBJECT_CHECK(TPCI200State, (obj), TYPE_TPCI200)
72

    
73
static const uint8_t local_config_regs[] = {
74
    0x00, 0xFF, 0xFF, 0x0F, 0x00, 0xFC, 0xFF, 0x0F, 0x00, 0x00, 0x00,
75
    0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
76
    0x00, 0x08, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01,
77
    0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x60, 0x41, 0xD4,
78
    0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x41, 0x14, 0xA2, 0x20, 0x01,
79
    0x14, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x08, 0x01, 0x02,
80
    0x00, 0x04, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0x02, 0x41,
81
    0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x00, 0x52, 0x92, 0x24, 0x02
82
};
83

    
84
static void adjust_addr(bool big_endian, hwaddr *addr, unsigned size)
85
{
86
    /* During 8 bit access in big endian mode,
87
       odd and even addresses are swapped */
88
    if (big_endian && size == 1) {
89
        *addr ^= 1;
90
    }
91
}
92

    
93
static uint64_t adjust_value(bool big_endian, uint64_t *val, unsigned size)
94
{
95
    /* Local spaces only support 8/16 bit access,
96
     * so there's no need to care for sizes > 2 */
97
    if (big_endian && size == 2) {
98
        *val = bswap16(*val);
99
    }
100
    return *val;
101
}
102

    
103
static void tpci200_set_irq(void *opaque, int intno, int level)
104
{
105
    IPackDevice *ip = opaque;
106
    IPackBus *bus = IPACK_BUS(qdev_get_parent_bus(DEVICE(ip)));
107
    PCIDevice *pcidev = PCI_DEVICE(BUS(bus)->parent);
108
    TPCI200State *dev = TPCI200(pcidev);
109
    unsigned ip_n = ip->slot;
110
    uint16_t prev_status = dev->status;
111

    
112
    assert(ip->slot >= 0 && ip->slot < N_MODULES);
113

    
114
    /* The requested interrupt must be enabled in the IP CONTROL
115
     * register */
116
    if (!(dev->ctrl[ip_n] & CTRL_INT(intno))) {
117
        return;
118
    }
119

    
120
    /* Update the interrupt status in the IP STATUS register */
121
    if (level) {
122
        dev->status |=  STATUS_INT(ip_n, intno);
123
    } else {
124
        dev->status &= ~STATUS_INT(ip_n, intno);
125
    }
126

    
127
    /* Return if there are no changes */
128
    if (dev->status == prev_status) {
129
        return;
130
    }
131

    
132
    DPRINTF("IP %u INT%u#: %u\n", ip_n, intno, level);
133

    
134
    /* Check if the interrupt is edge sensitive */
135
    if (dev->ctrl[ip_n] & CTRL_INT_EDGE(intno)) {
136
        if (level) {
137
            qemu_set_irq(dev->dev.irq[0], !dev->int_set);
138
            qemu_set_irq(dev->dev.irq[0],  dev->int_set);
139
        }
140
    } else {
141
        unsigned i, j;
142
        uint16_t level_status = dev->status;
143

    
144
        /* Check if there are any level sensitive interrupts set by
145
           removing the ones that are edge sensitive from the status
146
           register */
147
        for (i = 0; i < N_MODULES; i++) {
148
            for (j = 0; j < 2; j++) {
149
                if (dev->ctrl[i] & CTRL_INT_EDGE(j)) {
150
                    level_status &= ~STATUS_INT(i, j);
151
                }
152
            }
153
        }
154

    
155
        if (level_status && !dev->int_set) {
156
            qemu_irq_raise(dev->dev.irq[0]);
157
            dev->int_set = 1;
158
        } else if (!level_status && dev->int_set) {
159
            qemu_irq_lower(dev->dev.irq[0]);
160
            dev->int_set = 0;
161
        }
162
    }
163
}
164

    
165
static uint64_t tpci200_read_cfg(void *opaque, hwaddr addr, unsigned size)
166
{
167
    TPCI200State *s = opaque;
168
    uint8_t ret = 0;
169
    if (addr < ARRAY_SIZE(local_config_regs)) {
170
        ret = local_config_regs[addr];
171
    }
172
    /* Endianness is stored in the first bit of these registers */
173
    if ((addr == 0x2b && s->big_endian[0]) ||
174
        (addr == 0x2f && s->big_endian[1]) ||
175
        (addr == 0x33 && s->big_endian[2])) {
176
        ret |= 1;
177
    }
178
    DPRINTF("Read from LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) ret);
179
    return ret;
180
}
181

    
182
static void tpci200_write_cfg(void *opaque, hwaddr addr, uint64_t val,
183
                              unsigned size)
184
{
185
    TPCI200State *s = opaque;
186
    /* Endianness is stored in the first bit of these registers */
187
    if (addr == 0x2b || addr == 0x2f || addr == 0x33) {
188
        unsigned las = (addr - 0x2b) / 4;
189
        s->big_endian[las] = val & 1;
190
        DPRINTF("LAS%u big endian mode: %u\n", las, (unsigned) val & 1);
191
    } else {
192
        DPRINTF("Write to LCR 0x%x: 0x%x\n", (unsigned) addr, (unsigned) val);
193
    }
194
}
195

    
196
static uint64_t tpci200_read_las0(void *opaque, hwaddr addr, unsigned size)
197
{
198
    TPCI200State *s = opaque;
199
    uint64_t ret = 0;
200

    
201
    switch (addr) {
202

    
203
    case REG_REV_ID:
204
        DPRINTF("Read REVISION ID\n"); /* Current value is 0x00 */
205
        break;
206

    
207
    case REG_IP_A_CTRL:
208
    case REG_IP_B_CTRL:
209
    case REG_IP_C_CTRL:
210
    case REG_IP_D_CTRL:
211
        {
212
            unsigned ip_n = IP_N_FROM_REG(addr);
213
            ret = s->ctrl[ip_n];
214
            DPRINTF("Read IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) ret);
215
        }
216
        break;
217

    
218
    case REG_RESET:
219
        DPRINTF("Read RESET\n"); /* Not implemented */
220
        break;
221

    
222
    case REG_STATUS:
223
        ret = s->status;
224
        DPRINTF("Read STATUS: 0x%x\n", (unsigned) ret);
225
        break;
226

    
227
    /* Reserved */
228
    default:
229
        DPRINTF("Unsupported read from LAS0 0x%x\n", (unsigned) addr);
230
        break;
231
    }
232

    
233
    return adjust_value(s->big_endian[0], &ret, size);
234
}
235

    
236
static void tpci200_write_las0(void *opaque, hwaddr addr, uint64_t val,
237
                               unsigned size)
238
{
239
    TPCI200State *s = opaque;
240

    
241
    adjust_value(s->big_endian[0], &val, size);
242

    
243
    switch (addr) {
244

    
245
    case REG_REV_ID:
246
        DPRINTF("Write Revision ID: 0x%x\n", (unsigned) val); /* No effect */
247
        break;
248

    
249
    case REG_IP_A_CTRL:
250
    case REG_IP_B_CTRL:
251
    case REG_IP_C_CTRL:
252
    case REG_IP_D_CTRL:
253
        {
254
            unsigned ip_n = IP_N_FROM_REG(addr);
255
            s->ctrl[ip_n] = val;
256
            DPRINTF("Write IP %c CONTROL: 0x%x\n", 'A' + ip_n, (unsigned) val);
257
        }
258
        break;
259

    
260
    case REG_RESET:
261
        DPRINTF("Write RESET: 0x%x\n", (unsigned) val); /* Not implemented */
262
        break;
263

    
264
    case REG_STATUS:
265
        {
266
            unsigned i;
267

    
268
            for (i = 0; i < N_MODULES; i++) {
269
                IPackDevice *ip = ipack_device_find(&s->bus, i);
270

    
271
                if (ip != NULL) {
272
                    if (val & STATUS_INT(i, 0)) {
273
                        DPRINTF("Clear IP %c INT0# status\n", 'A' + i);
274
                        qemu_irq_lower(ip->irq[0]);
275
                    }
276
                    if (val & STATUS_INT(i, 1)) {
277
                        DPRINTF("Clear IP %c INT1# status\n", 'A' + i);
278
                        qemu_irq_lower(ip->irq[1]);
279
                    }
280
                }
281

    
282
                if (val & STATUS_TIME(i)) {
283
                    DPRINTF("Clear IP %c timeout\n", 'A' + i);
284
                    s->status &= ~STATUS_TIME(i);
285
                }
286
            }
287

    
288
            if (val & STATUS_ERR_ANY) {
289
                DPRINTF("Unexpected write to STATUS register: 0x%x\n",
290
                        (unsigned) val);
291
            }
292
        }
293
        break;
294

    
295
    /* Reserved */
296
    default:
297
        DPRINTF("Unsupported write to LAS0 0x%x: 0x%x\n",
298
                (unsigned) addr, (unsigned) val);
299
        break;
300
    }
301
}
302

    
303
static uint64_t tpci200_read_las1(void *opaque, hwaddr addr, unsigned size)
304
{
305
    TPCI200State *s = opaque;
306
    IPackDevice *ip;
307
    uint64_t ret = 0;
308
    unsigned ip_n, space;
309
    uint8_t offset;
310

    
311
    adjust_addr(s->big_endian[1], &addr, size);
312

    
313
    /*
314
     * The address is divided into the IP module number (0-4), the IP
315
     * address space (I/O, ID, INT) and the offset within that space.
316
     */
317
    ip_n = addr >> 8;
318
    space = (addr >> 6) & 3;
319
    ip = ipack_device_find(&s->bus, ip_n);
320

    
321
    if (ip == NULL) {
322
        DPRINTF("Read LAS1: IP module %u not installed\n", ip_n);
323
    } else {
324
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
325
        switch (space) {
326

    
327
        case IP_ID_SPACE:
328
            offset = addr & IP_ID_SPACE_ADDR_MASK;
329
            if (k->id_read) {
330
                ret = k->id_read(ip, offset);
331
            }
332
            break;
333

    
334
        case IP_INT_SPACE:
335
            offset = addr & IP_INT_SPACE_ADDR_MASK;
336

    
337
            /* Read address 0 to ACK IP INT0# and address 2 to ACK IP INT1# */
338
            if (offset == 0 || offset == 2) {
339
                unsigned intno = offset / 2;
340
                bool int_set = s->status & STATUS_INT(ip_n, intno);
341
                bool int_edge_sensitive = s->ctrl[ip_n] & CTRL_INT_EDGE(intno);
342
                if (int_set && !int_edge_sensitive) {
343
                    qemu_irq_lower(ip->irq[intno]);
344
                }
345
            }
346

    
347
            if (k->int_read) {
348
                ret = k->int_read(ip, offset);
349
            }
350
            break;
351

    
352
        default:
353
            offset = addr & IP_IO_SPACE_ADDR_MASK;
354
            if (k->io_read) {
355
                ret = k->io_read(ip, offset);
356
            }
357
            break;
358
        }
359
    }
360

    
361
    return adjust_value(s->big_endian[1], &ret, size);
362
}
363

    
364
static void tpci200_write_las1(void *opaque, hwaddr addr, uint64_t val,
365
                               unsigned size)
366
{
367
    TPCI200State *s = opaque;
368
    IPackDevice *ip;
369
    unsigned ip_n, space;
370
    uint8_t offset;
371

    
372
    adjust_addr(s->big_endian[1], &addr, size);
373
    adjust_value(s->big_endian[1], &val, size);
374

    
375
    /*
376
     * The address is divided into the IP module number, the IP
377
     * address space (I/O, ID, INT) and the offset within that space.
378
     */
379
    ip_n = addr >> 8;
380
    space = (addr >> 6) & 3;
381
    ip = ipack_device_find(&s->bus, ip_n);
382

    
383
    if (ip == NULL) {
384
        DPRINTF("Write LAS1: IP module %u not installed\n", ip_n);
385
    } else {
386
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
387
        switch (space) {
388

    
389
        case IP_ID_SPACE:
390
            offset = addr & IP_ID_SPACE_ADDR_MASK;
391
            if (k->id_write) {
392
                k->id_write(ip, offset, val);
393
            }
394
            break;
395

    
396
        case IP_INT_SPACE:
397
            offset = addr & IP_INT_SPACE_ADDR_MASK;
398
            if (k->int_write) {
399
                k->int_write(ip, offset, val);
400
            }
401
            break;
402

    
403
        default:
404
            offset = addr & IP_IO_SPACE_ADDR_MASK;
405
            if (k->io_write) {
406
                k->io_write(ip, offset, val);
407
            }
408
            break;
409
        }
410
    }
411
}
412

    
413
static uint64_t tpci200_read_las2(void *opaque, hwaddr addr, unsigned size)
414
{
415
    TPCI200State *s = opaque;
416
    IPackDevice *ip;
417
    uint64_t ret = 0;
418
    unsigned ip_n;
419
    uint32_t offset;
420

    
421
    adjust_addr(s->big_endian[2], &addr, size);
422

    
423
    /*
424
     * The address is divided into the IP module number and the offset
425
     * within the IP module MEM space.
426
     */
427
    ip_n = addr >> 23;
428
    offset = addr & 0x7fffff;
429
    ip = ipack_device_find(&s->bus, ip_n);
430

    
431
    if (ip == NULL) {
432
        DPRINTF("Read LAS2: IP module %u not installed\n", ip_n);
433
    } else {
434
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
435
        if (k->mem_read16) {
436
            ret = k->mem_read16(ip, offset);
437
        }
438
    }
439

    
440
    return adjust_value(s->big_endian[2], &ret, size);
441
}
442

    
443
static void tpci200_write_las2(void *opaque, hwaddr addr, uint64_t val,
444
                               unsigned size)
445
{
446
    TPCI200State *s = opaque;
447
    IPackDevice *ip;
448
    unsigned ip_n;
449
    uint32_t offset;
450

    
451
    adjust_addr(s->big_endian[2], &addr, size);
452
    adjust_value(s->big_endian[2], &val, size);
453

    
454
    /*
455
     * The address is divided into the IP module number and the offset
456
     * within the IP module MEM space.
457
     */
458
    ip_n = addr >> 23;
459
    offset = addr & 0x7fffff;
460
    ip = ipack_device_find(&s->bus, ip_n);
461

    
462
    if (ip == NULL) {
463
        DPRINTF("Write LAS2: IP module %u not installed\n", ip_n);
464
    } else {
465
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
466
        if (k->mem_write16) {
467
            k->mem_write16(ip, offset, val);
468
        }
469
    }
470
}
471

    
472
static uint64_t tpci200_read_las3(void *opaque, hwaddr addr, unsigned size)
473
{
474
    TPCI200State *s = opaque;
475
    IPackDevice *ip;
476
    uint64_t ret = 0;
477
    /*
478
     * The address is divided into the IP module number and the offset
479
     * within the IP module MEM space.
480
     */
481
    unsigned ip_n = addr >> 22;
482
    uint32_t offset = addr & 0x3fffff;
483

    
484
    ip = ipack_device_find(&s->bus, ip_n);
485

    
486
    if (ip == NULL) {
487
        DPRINTF("Read LAS3: IP module %u not installed\n", ip_n);
488
    } else {
489
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
490
        if (k->mem_read8) {
491
            ret = k->mem_read8(ip, offset);
492
        }
493
    }
494

    
495
    return ret;
496
}
497

    
498
static void tpci200_write_las3(void *opaque, hwaddr addr, uint64_t val,
499
                               unsigned size)
500
{
501
    TPCI200State *s = opaque;
502
    IPackDevice *ip;
503
    /*
504
     * The address is divided into the IP module number and the offset
505
     * within the IP module MEM space.
506
     */
507
    unsigned ip_n = addr >> 22;
508
    uint32_t offset = addr & 0x3fffff;
509

    
510
    ip = ipack_device_find(&s->bus, ip_n);
511

    
512
    if (ip == NULL) {
513
        DPRINTF("Write LAS3: IP module %u not installed\n", ip_n);
514
    } else {
515
        IPackDeviceClass *k = IPACK_DEVICE_GET_CLASS(ip);
516
        if (k->mem_write8) {
517
            k->mem_write8(ip, offset, val);
518
        }
519
    }
520
}
521

    
522
static const MemoryRegionOps tpci200_cfg_ops = {
523
    .read = tpci200_read_cfg,
524
    .write = tpci200_write_cfg,
525
    .endianness = DEVICE_NATIVE_ENDIAN,
526
    .valid =  {
527
        .min_access_size = 1,
528
        .max_access_size = 4
529
    },
530
    .impl = {
531
        .min_access_size = 1,
532
        .max_access_size = 1
533
    }
534
};
535

    
536
static const MemoryRegionOps tpci200_las0_ops = {
537
    .read = tpci200_read_las0,
538
    .write = tpci200_write_las0,
539
    .endianness = DEVICE_NATIVE_ENDIAN,
540
    .valid =  {
541
        .min_access_size = 2,
542
        .max_access_size = 2
543
    }
544
};
545

    
546
static const MemoryRegionOps tpci200_las1_ops = {
547
    .read = tpci200_read_las1,
548
    .write = tpci200_write_las1,
549
    .endianness = DEVICE_NATIVE_ENDIAN,
550
    .valid =  {
551
        .min_access_size = 1,
552
        .max_access_size = 2
553
    }
554
};
555

    
556
static const MemoryRegionOps tpci200_las2_ops = {
557
    .read = tpci200_read_las2,
558
    .write = tpci200_write_las2,
559
    .endianness = DEVICE_NATIVE_ENDIAN,
560
    .valid =  {
561
        .min_access_size = 1,
562
        .max_access_size = 2
563
    }
564
};
565

    
566
static const MemoryRegionOps tpci200_las3_ops = {
567
    .read = tpci200_read_las3,
568
    .write = tpci200_write_las3,
569
    .endianness = DEVICE_NATIVE_ENDIAN,
570
    .valid =  {
571
        .min_access_size = 1,
572
        .max_access_size = 1
573
    }
574
};
575

    
576
static int tpci200_initfn(PCIDevice *pci_dev)
577
{
578
    TPCI200State *s = TPCI200(pci_dev);
579
    uint8_t *c = s->dev.config;
580

    
581
    pci_set_word(c + PCI_COMMAND, 0x0003);
582
    pci_set_word(c + PCI_STATUS,  0x0280);
583

    
584
    pci_set_byte(c + PCI_INTERRUPT_PIN, 0x01); /* Interrupt pin A */
585

    
586
    pci_set_byte(c + PCI_CAPABILITY_LIST, 0x40);
587
    pci_set_long(c + 0x40, 0x48014801);
588
    pci_set_long(c + 0x48, 0x00024C06);
589
    pci_set_long(c + 0x4C, 0x00000003);
590

    
591
    memory_region_init_io(&s->mmio, &tpci200_cfg_ops,
592
                          s, "tpci200_mmio", 128);
593
    memory_region_init_io(&s->io,   &tpci200_cfg_ops,
594
                          s, "tpci200_io",   128);
595
    memory_region_init_io(&s->las0, &tpci200_las0_ops,
596
                          s, "tpci200_las0", 256);
597
    memory_region_init_io(&s->las1, &tpci200_las1_ops,
598
                          s, "tpci200_las1", 1024);
599
    memory_region_init_io(&s->las2, &tpci200_las2_ops,
600
                          s, "tpci200_las2", 1024*1024*32);
601
    memory_region_init_io(&s->las3, &tpci200_las3_ops,
602
                          s, "tpci200_las3", 1024*1024*16);
603
    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio);
604
    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO,     &s->io);
605
    pci_register_bar(&s->dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las0);
606
    pci_register_bar(&s->dev, 3, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las1);
607
    pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las2);
608
    pci_register_bar(&s->dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->las3);
609

    
610
    ipack_bus_new_inplace(&s->bus, DEVICE(&s->dev), NULL,
611
                          N_MODULES, tpci200_set_irq);
612

    
613
    return 0;
614
}
615

    
616
static void tpci200_exitfn(PCIDevice *pci_dev)
617
{
618
    TPCI200State *s = TPCI200(pci_dev);
619

    
620
    memory_region_destroy(&s->mmio);
621
    memory_region_destroy(&s->io);
622
    memory_region_destroy(&s->las0);
623
    memory_region_destroy(&s->las1);
624
    memory_region_destroy(&s->las2);
625
    memory_region_destroy(&s->las3);
626
}
627

    
628
static const VMStateDescription vmstate_tpci200 = {
629
    .name = "tpci200",
630
    .version_id = 1,
631
    .minimum_version_id = 1,
632
    .minimum_version_id_old = 1,
633
    .fields      = (VMStateField[]) {
634
        VMSTATE_PCI_DEVICE(dev, TPCI200State),
635
        VMSTATE_BOOL_ARRAY(big_endian, TPCI200State, 3),
636
        VMSTATE_UINT8_ARRAY(ctrl, TPCI200State, N_MODULES),
637
        VMSTATE_UINT16(status, TPCI200State),
638
        VMSTATE_UINT8(int_set, TPCI200State),
639
        VMSTATE_END_OF_LIST()
640
    }
641
};
642

    
643
static void tpci200_class_init(ObjectClass *klass, void *data)
644
{
645
    DeviceClass *dc = DEVICE_CLASS(klass);
646
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
647

    
648
    k->init = tpci200_initfn;
649
    k->exit = tpci200_exitfn;
650
    k->vendor_id = PCI_VENDOR_ID_TEWS;
651
    k->device_id = PCI_DEVICE_ID_TEWS_TPCI200;
652
    k->class_id = PCI_CLASS_BRIDGE_OTHER;
653
    k->subsystem_vendor_id = PCI_VENDOR_ID_TEWS;
654
    k->subsystem_id = 0x300A;
655
    dc->desc = "TEWS TPCI200 IndustryPack carrier";
656
    dc->vmsd = &vmstate_tpci200;
657
}
658

    
659
static const TypeInfo tpci200_info = {
660
    .name          = TYPE_TPCI200,
661
    .parent        = TYPE_PCI_DEVICE,
662
    .instance_size = sizeof(TPCI200State),
663
    .class_init    = tpci200_class_init,
664
};
665

    
666
static void tpci200_register_types(void)
667
{
668
    type_register_static(&tpci200_info);
669
}
670

    
671
type_init(tpci200_register_types)