apb.c 17.2 KB
Newer Older
P
pbrook 已提交
1 2 3 4
/*
 * QEMU Ultrasparc APB PCI host
 *
 * Copyright (c) 2006 Fabrice Bellard
5
 * Copyright (c) 2012,2013 Artyom Tarasenko
6
 *
P
pbrook 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
pbrook 已提交
25

B
Fix APB  
blueswir1 已提交
26
/* XXX This file and most of its contents are somewhat misnamed.  The
P
pbrook 已提交
27 28 29
   Ultrasparc PCI host is called the PCI Bus Module (PBM).  The APB is
   the secondary PCI bridge.  */

30 31 32 33 34
#include "hw/sysbus.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_host.h"
#include "hw/pci/pci_bridge.h"
#include "hw/pci/pci_bus.h"
P
Paolo Bonzini 已提交
35
#include "hw/pci-host/apb.h"
36
#include "sysemu/sysemu.h"
37
#include "exec/address-spaces.h"
B
Fix APB  
blueswir1 已提交
38 39 40 41 42

/* debug APB */
//#define DEBUG_APB

#ifdef DEBUG_APB
43 44
#define APB_DPRINTF(fmt, ...) \
do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
B
Fix APB  
blueswir1 已提交
45
#else
46
#define APB_DPRINTF(fmt, ...)
B
Fix APB  
blueswir1 已提交
47 48
#endif

B
Blue Swirl 已提交
49 50 51 52 53 54 55 56 57
/*
 * Chipset docs:
 * PBM: "UltraSPARC IIi User's Manual",
 * http://www.sun.com/processors/manuals/805-0087.pdf
 *
 * APB: "Advanced PCI Bridge (APB) User's Manual",
 * http://www.sun.com/processors/manuals/805-1251.pdf
 */

58 59 60 61 62 63 64 65 66 67 68 69
#define PBM_PCI_IMR_MASK    0x7fffffff
#define PBM_PCI_IMR_ENABLED 0x80000000

#define POR          (1 << 31)
#define SOFT_POR     (1 << 30)
#define SOFT_XIR     (1 << 29)
#define BTN_POR      (1 << 28)
#define BTN_XIR      (1 << 27)
#define RESET_MASK   0xf8000000
#define RESET_WCMASK 0x98000000
#define RESET_WMASK  0x60000000

A
Artyom Tarasenko 已提交
70
#define MAX_IVEC 0x40
71
#define NO_IRQ_REQUEST (MAX_IVEC + 1)
B
Blue Swirl 已提交
72

P
Paolo Bonzini 已提交
73 74 75 76 77
#define TYPE_APB "pbm"

#define APB_DEVICE(obj) \
    OBJECT_CHECK(APBState, (obj), TYPE_APB)

B
Blue Swirl 已提交
78
typedef struct APBState {
P
Paolo Bonzini 已提交
79 80
    PCIHostState parent_obj;

A
Avi Kivity 已提交
81 82
    MemoryRegion apb_config;
    MemoryRegion pci_config;
83
    MemoryRegion pci_mmio;
A
Avi Kivity 已提交
84
    MemoryRegion pci_ioport;
85
    uint64_t pci_irq_in;
86 87 88 89
    uint32_t iommu[4];
    uint32_t pci_control[16];
    uint32_t pci_irq_map[8];
    uint32_t obio_irq_map[32];
B
Blue Swirl 已提交
90 91
    qemu_irq *pbm_irqs;
    qemu_irq *ivec_irqs;
92
    unsigned int irq_request;
93
    uint32_t reset_control;
B
Blue Swirl 已提交
94
    unsigned int nr_resets;
B
Blue Swirl 已提交
95
} APBState;
P
pbrook 已提交
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
static inline void pbm_set_request(APBState *s, unsigned int irq_num)
{
    APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);

    s->irq_request = irq_num;
    qemu_set_irq(s->ivec_irqs[irq_num], 1);
}

static inline void pbm_check_irqs(APBState *s)
{

    unsigned int i;

    /* Previous request is not acknowledged, resubmit */
    if (s->irq_request != NO_IRQ_REQUEST) {
        pbm_set_request(s, s->irq_request);
        return;
    }
    /* no request pending */
    if (s->pci_irq_in == 0ULL) {
        return;
    }
    for (i = 0; i < 32; i++) {
        if (s->pci_irq_in & (1ULL << i)) {
            if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
                pbm_set_request(s, i);
                return;
            }
        }
    }
    for (i = 32; i < 64; i++) {
        if (s->pci_irq_in & (1ULL << i)) {
            if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
                pbm_set_request(s, i);
                break;
            }
        }
    }
}

static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
{
    APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
    qemu_set_irq(s->ivec_irqs[irq_num], 0);
    s->irq_request = NO_IRQ_REQUEST;
}
143

A
Avi Kivity 已提交
144
static void apb_config_writel (void *opaque, hwaddr addr,
A
Avi Kivity 已提交
145
                               uint64_t val, unsigned size)
P
pbrook 已提交
146
{
147 148
    APBState *s = opaque;

149
    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
150 151 152 153 154 155 156 157 158 159 160 161

    switch (addr & 0xffff) {
    case 0x30 ... 0x4f: /* DMA error registers */
        /* XXX: not implemented yet */
        break;
    case 0x200 ... 0x20b: /* IOMMU */
        s->iommu[(addr & 0xf) >> 2] = val;
        break;
    case 0x20c ... 0x3ff: /* IOMMU flush */
        break;
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
        if (addr & 4) {
162 163 164 165 166 167 168
            unsigned int ino = (addr & 0x3f) >> 3;
            s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
            s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
            if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
                pbm_clear_request(s, ino);
            }
            pbm_check_irqs(s);
169 170
        }
        break;
B
Blue Swirl 已提交
171 172
    case 0x1000 ... 0x1080: /* OBIO interrupt control */
        if (addr & 4) {
173 174 175 176 177 178 179 180
            unsigned int ino = ((addr & 0xff) >> 3);
            s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
            s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
            if ((s->irq_request == (ino | 0x20))
                 && !(val & ~PBM_PCI_IMR_MASK)) {
                pbm_clear_request(s, ino | 0x20);
            }
            pbm_check_irqs(s);
B
Blue Swirl 已提交
181 182
        }
        break;
183
    case 0x1400 ... 0x14ff: /* PCI interrupt clear */
184
        if (addr & 4) {
185 186 187 188 189
            unsigned int ino = (addr & 0xff) >> 5;
            if ((s->irq_request / 4)  == ino) {
                pbm_clear_request(s, s->irq_request);
                pbm_check_irqs(s);
            }
190 191 192 193
        }
        break;
    case 0x1800 ... 0x1860: /* OBIO interrupt clear */
        if (addr & 4) {
194 195 196 197 198
            unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
            if (s->irq_request == ino) {
                pbm_clear_request(s, ino);
                pbm_check_irqs(s);
            }
199 200
        }
        break;
201 202 203 204 205 206 207 208 209
    case 0x2000 ... 0x202f: /* PCI control */
        s->pci_control[(addr & 0x3f) >> 2] = val;
        break;
    case 0xf020 ... 0xf027: /* Reset control */
        if (addr & 4) {
            val &= RESET_MASK;
            s->reset_control &= ~(val & RESET_WCMASK);
            s->reset_control |= val & RESET_WMASK;
            if (val & SOFT_POR) {
B
Blue Swirl 已提交
210
                s->nr_resets = 0;
211 212 213 214 215 216 217 218 219 220 221
                qemu_system_reset_request();
            } else if (val & SOFT_XIR) {
                qemu_system_reset_request();
            }
        }
        break;
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
        /* we don't care */
P
pbrook 已提交
222
    default:
B
blueswir1 已提交
223
        break;
P
pbrook 已提交
224 225 226
    }
}

A
Avi Kivity 已提交
227
static uint64_t apb_config_readl (void *opaque,
A
Avi Kivity 已提交
228
                                  hwaddr addr, unsigned size)
P
pbrook 已提交
229
{
230
    APBState *s = opaque;
P
pbrook 已提交
231 232
    uint32_t val;

233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    switch (addr & 0xffff) {
    case 0x30 ... 0x4f: /* DMA error registers */
        val = 0;
        /* XXX: not implemented yet */
        break;
    case 0x200 ... 0x20b: /* IOMMU */
        val = s->iommu[(addr & 0xf) >> 2];
        break;
    case 0x20c ... 0x3ff: /* IOMMU flush */
        val = 0;
        break;
    case 0xc00 ... 0xc3f: /* PCI interrupt control */
        if (addr & 4) {
            val = s->pci_irq_map[(addr & 0x3f) >> 3];
        } else {
            val = 0;
        }
        break;
B
Blue Swirl 已提交
251 252 253 254 255 256 257
    case 0x1000 ... 0x1080: /* OBIO interrupt control */
        if (addr & 4) {
            val = s->obio_irq_map[(addr & 0xff) >> 3];
        } else {
            val = 0;
        }
        break;
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
    case 0x2000 ... 0x202f: /* PCI control */
        val = s->pci_control[(addr & 0x3f) >> 2];
        break;
    case 0xf020 ... 0xf027: /* Reset control */
        if (addr & 4) {
            val = s->reset_control;
        } else {
            val = 0;
        }
        break;
    case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
    case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
    case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
    case 0xf000 ... 0xf01f: /* FFB config, memory control */
        /* we don't care */
P
pbrook 已提交
273
    default:
B
blueswir1 已提交
274 275
        val = 0;
        break;
P
pbrook 已提交
276
    }
277
    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
278

P
pbrook 已提交
279 280 281
    return val;
}

A
Avi Kivity 已提交
282 283 284 285
static const MemoryRegionOps apb_config_ops = {
    .read = apb_config_readl,
    .write = apb_config_writel,
    .endianness = DEVICE_NATIVE_ENDIAN,
P
pbrook 已提交
286 287
};

A
Avi Kivity 已提交
288
static void apb_pci_config_write(void *opaque, hwaddr addr,
A
Avi Kivity 已提交
289
                                 uint64_t val, unsigned size)
290
{
A
Avi Kivity 已提交
291
    APBState *s = opaque;
P
Paolo Bonzini 已提交
292
    PCIHostState *phb = PCI_HOST_BRIDGE(s);
293 294

    val = qemu_bswap_len(val, size);
295
    APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
P
Paolo Bonzini 已提交
296
    pci_data_write(phb->bus, addr, val, size);
297 298
}

A
Avi Kivity 已提交
299
static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
A
Avi Kivity 已提交
300
                                    unsigned size)
301 302
{
    uint32_t ret;
A
Avi Kivity 已提交
303
    APBState *s = opaque;
P
Paolo Bonzini 已提交
304
    PCIHostState *phb = PCI_HOST_BRIDGE(s);
305

P
Paolo Bonzini 已提交
306
    ret = pci_data_read(phb->bus, addr, size);
307
    ret = qemu_bswap_len(ret, size);
308
    APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
309 310 311
    return ret;
}

P
pbrook 已提交
312
/* The APB host has an IRQ line for each IRQ line of each slot.  */
313
static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
P
pbrook 已提交
314
{
P
pbrook 已提交
315 316 317 318 319 320 321 322 323 324
    return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
}

static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
{
    int bus_offset;
    if (pci_dev->devfn & 1)
        bus_offset = 16;
    else
        bus_offset = 0;
325
    return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
326 327
}

328
static void pci_apb_set_irq(void *opaque, int irq_num, int level)
329
{
330
    APBState *s = opaque;
331

332
    APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
P
pbrook 已提交
333
    /* PCI IRQ map onto the first 32 INO.  */
334
    if (irq_num < 32) {
335 336 337 338 339
        if (level) {
            s->pci_irq_in |= 1ULL << irq_num;
            if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
                pbm_set_request(s, irq_num);
            }
B
Blue Swirl 已提交
340
        } else {
341
            s->pci_irq_in &= ~(1ULL << irq_num);
B
Blue Swirl 已提交
342 343
        }
    } else {
344 345
        /* OBIO IRQ map onto the next 32 INO.  */
        if (level) {
B
Blue Swirl 已提交
346
            APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
347 348 349 350 351
            s->pci_irq_in |= 1ULL << irq_num;
            if ((s->irq_request == NO_IRQ_REQUEST)
                && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
                pbm_set_request(s, irq_num);
            }
352
        } else {
353
            s->pci_irq_in &= ~(1ULL << irq_num);
354 355
        }
    }
P
pbrook 已提交
356 357
}

358
static int apb_pci_bridge_initfn(PCIDevice *dev)
359
{
360 361
    int rc;

362
    rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
363 364 365 366
    if (rc < 0) {
        return rc;
    }

367 368 369 370 371 372 373 374 375 376
    /*
     * command register:
     * According to PCI bridge spec, after reset
     *   bus master bit is off
     *   memory space enable bit is off
     * According to manual (805-1251.pdf).
     *   the reset value should be zero unless the boot pin is tied high
     *   (which is true) and thus it should be PCI_COMMAND_MEMORY.
     */
    pci_set_word(dev->config + PCI_COMMAND,
377 378 379 380
                 PCI_COMMAND_MEMORY);
    pci_set_word(dev->config + PCI_STATUS,
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                 PCI_STATUS_DEVSEL_MEDIUM);
381
    return 0;
382 383
}

A
Avi Kivity 已提交
384 385
PCIBus *pci_apb_init(hwaddr special_base,
                     hwaddr mem_base,
B
Blue Swirl 已提交
386 387
                     qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
                     qemu_irq **pbm_irqs)
P
pbrook 已提交
388
{
B
Blue Swirl 已提交
389 390
    DeviceState *dev;
    SysBusDevice *s;
P
Paolo Bonzini 已提交
391
    PCIHostState *phb;
B
Blue Swirl 已提交
392
    APBState *d;
393 394
    PCIDevice *pci_dev;
    PCIBridge *br;
P
pbrook 已提交
395

P
pbrook 已提交
396
    /* Ultrasparc PBM main bus */
P
Paolo Bonzini 已提交
397
    dev = qdev_create(NULL, TYPE_APB);
M
Markus Armbruster 已提交
398
    qdev_init_nofail(dev);
399
    s = SYS_BUS_DEVICE(dev);
B
Blue Swirl 已提交
400
    /* apb_config */
401
    sysbus_mmio_map(s, 0, special_base);
402 403
    /* PCI configuration space */
    sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
B
Blue Swirl 已提交
404
    /* pci_ioport */
405
    sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
P
Paolo Bonzini 已提交
406
    d = APB_DEVICE(dev);
407

408
    memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
409 410
    memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);

P
Paolo Bonzini 已提交
411 412 413 414 415 416
    phb = PCI_HOST_BRIDGE(dev);
    phb->bus = pci_register_bus(DEVICE(phb), "pci",
                                pci_apb_set_irq, pci_pbm_map_irq, d,
                                &d->pci_mmio,
                                get_system_io(),
                                0, 32, TYPE_PCI_BUS);
417

B
Blue Swirl 已提交
418 419
    *pbm_irqs = d->pbm_irqs;
    d->ivec_irqs = ivec_irqs;
420

P
Paolo Bonzini 已提交
421
    pci_create_simple(phb->bus, 0, "pbm-pci");
422

B
Blue Swirl 已提交
423
    /* APB secondary busses */
P
Paolo Bonzini 已提交
424
    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
425 426 427 428 429 430 431
                                   "pbm-bridge");
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
                       pci_apb_map_irq);
    qdev_init_nofail(&pci_dev->qdev);
    *bus2 = pci_bridge_get_sec_bus(br);

P
Paolo Bonzini 已提交
432
    pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
433 434 435 436 437 438
                                   "pbm-bridge");
    br = DO_UPCAST(PCIBridge, dev, pci_dev);
    pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
                       pci_apb_map_irq);
    qdev_init_nofail(&pci_dev->qdev);
    *bus3 = pci_bridge_get_sec_bus(br);
P
pbrook 已提交
439

P
Paolo Bonzini 已提交
440
    return phb->bus;
B
Blue Swirl 已提交
441 442
}

443
static void pci_pbm_reset(DeviceState *d)
B
Blue Swirl 已提交
444
{
445
    unsigned int i;
P
Paolo Bonzini 已提交
446
    APBState *s = APB_DEVICE(d);
B
Blue Swirl 已提交
447

448 449 450
    for (i = 0; i < 8; i++) {
        s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
    }
451 452 453
    for (i = 0; i < 32; i++) {
        s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
    }
454

455 456 457
    s->irq_request = NO_IRQ_REQUEST;
    s->pci_irq_in = 0ULL;

B
Blue Swirl 已提交
458
    if (s->nr_resets++ == 0) {
459 460 461 462 463
        /* Power on reset */
        s->reset_control = POR;
    }
}

A
Avi Kivity 已提交
464 465 466 467 468 469
static const MemoryRegionOps pci_config_ops = {
    .read = apb_pci_config_read,
    .write = apb_pci_config_write,
    .endianness = DEVICE_NATIVE_ENDIAN,
};

470 471
static int pci_pbm_init_device(SysBusDevice *dev)
{
B
Blue Swirl 已提交
472
    APBState *s;
473
    unsigned int i;
B
Blue Swirl 已提交
474

P
Paolo Bonzini 已提交
475
    s = APB_DEVICE(dev);
476 477 478
    for (i = 0; i < 8; i++) {
        s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
    }
479 480 481
    for (i = 0; i < 32; i++) {
        s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
    }
B
Blue Swirl 已提交
482
    s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
483 484
    s->irq_request = NO_IRQ_REQUEST;
    s->pci_irq_in = 0ULL;
485

B
Blue Swirl 已提交
486
    /* apb_config */
487 488
    memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
                          "apb-config", 0x10000);
489
    /* at region 0 */
490
    sysbus_init_mmio(dev, &s->apb_config);
491

492 493
    memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
                          "apb-pci-config", 0x1000000);
494
    /* at region 1 */
495
    sysbus_init_mmio(dev, &s->pci_config);
496 497

    /* pci_ioport */
498 499
    memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport",
                             get_system_io(), 0, 0x10000);
500
    /* at region 2 */
501
    sysbus_init_mmio(dev, &s->pci_ioport);
502

503
    return 0;
B
Blue Swirl 已提交
504
}
P
pbrook 已提交
505

506
static int pbm_pci_host_init(PCIDevice *d)
B
Blue Swirl 已提交
507
{
508 509 510 511 512
    pci_set_word(d->config + PCI_COMMAND,
                 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
    pci_set_word(d->config + PCI_STATUS,
                 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
                 PCI_STATUS_DEVSEL_MEDIUM);
513
    return 0;
B
Blue Swirl 已提交
514
}
P
pbrook 已提交
515

516 517 518 519 520 521 522 523 524 525
static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
{
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = pbm_pci_host_init;
    k->vendor_id = PCI_VENDOR_ID_SUN;
    k->device_id = PCI_DEVICE_ID_SUN_SABRE;
    k->class_id = PCI_CLASS_BRIDGE_HOST;
}

526
static const TypeInfo pbm_pci_host_info = {
527 528 529 530
    .name          = "pbm-pci",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIDevice),
    .class_init    = pbm_pci_host_class_init,
B
Blue Swirl 已提交
531 532
};

533 534
static void pbm_host_class_init(ObjectClass *klass, void *data)
{
535
    DeviceClass *dc = DEVICE_CLASS(klass);
536 537 538
    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);

    k->init = pci_pbm_init_device;
539
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
540
    dc->reset = pci_pbm_reset;
541 542
}

543
static const TypeInfo pbm_host_info = {
P
Paolo Bonzini 已提交
544 545
    .name          = TYPE_APB,
    .parent        = TYPE_PCI_HOST_BRIDGE,
546 547
    .instance_size = sizeof(APBState),
    .class_init    = pbm_host_class_init,
548
};
549

550 551
static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
{
552
    DeviceClass *dc = DEVICE_CLASS(klass);
553 554 555 556 557 558 559 560 561
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);

    k->init = apb_pci_bridge_initfn;
    k->exit = pci_bridge_exitfn;
    k->vendor_id = PCI_VENDOR_ID_SUN;
    k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
    k->revision = 0x11;
    k->config_write = pci_bridge_write_config;
    k->is_bridge = 1;
562
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
563 564
    dc->reset = pci_bridge_reset;
    dc->vmsd = &vmstate_pci_device;
565 566
}

567
static const TypeInfo pbm_pci_bridge_info = {
568 569 570 571
    .name          = "pbm-bridge",
    .parent        = TYPE_PCI_DEVICE,
    .instance_size = sizeof(PCIBridge),
    .class_init    = pbm_pci_bridge_class_init,
572 573
};

A
Andreas Färber 已提交
574
static void pbm_register_types(void)
B
Blue Swirl 已提交
575
{
576 577 578
    type_register_static(&pbm_host_info);
    type_register_static(&pbm_pci_host_info);
    type_register_static(&pbm_pci_bridge_info);
P
pbrook 已提交
579
}
B
Blue Swirl 已提交
580

A
Andreas Färber 已提交
581
type_init(pbm_register_types)