]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/pci-host/apb.c
devices: Associate devices to their logical category
[thirdparty/qemu.git] / hw / pci-host / apb.c
CommitLineData
502a5395
PB
1/*
2 * QEMU Ultrasparc APB PCI host
3 *
4 * Copyright (c) 2006 Fabrice Bellard
9625036d 5 * Copyright (c) 2012,2013 Artyom Tarasenko
5fafdf24 6 *
502a5395
PB
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
80b3ada7 25
a94fd955 26/* XXX This file and most of its contents are somewhat misnamed. The
80b3ada7
PB
27 Ultrasparc PCI host is called the PCI Bus Module (PBM). The APB is
28 the secondary PCI bridge. */
29
83c9f4ca
PB
30#include "hw/sysbus.h"
31#include "hw/pci/pci.h"
32#include "hw/pci/pci_host.h"
33#include "hw/pci/pci_bridge.h"
34#include "hw/pci/pci_bus.h"
0d09e41a 35#include "hw/pci-host/apb.h"
9c17d615 36#include "sysemu/sysemu.h"
022c62cb 37#include "exec/address-spaces.h"
a94fd955
BS
38
39/* debug APB */
40//#define DEBUG_APB
41
42#ifdef DEBUG_APB
001faf32
BS
43#define APB_DPRINTF(fmt, ...) \
44do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
a94fd955 45#else
001faf32 46#define APB_DPRINTF(fmt, ...)
a94fd955
BS
47#endif
48
930f3fe1
BS
49/*
50 * Chipset docs:
51 * PBM: "UltraSPARC IIi User's Manual",
52 * http://www.sun.com/processors/manuals/805-0087.pdf
53 *
54 * APB: "Advanced PCI Bridge (APB) User's Manual",
55 * http://www.sun.com/processors/manuals/805-1251.pdf
56 */
57
95819af0
BS
58#define PBM_PCI_IMR_MASK 0x7fffffff
59#define PBM_PCI_IMR_ENABLED 0x80000000
60
61#define POR (1 << 31)
62#define SOFT_POR (1 << 30)
63#define SOFT_XIR (1 << 29)
64#define BTN_POR (1 << 28)
65#define BTN_XIR (1 << 27)
66#define RESET_MASK 0xf8000000
67#define RESET_WCMASK 0x98000000
68#define RESET_WMASK 0x60000000
69
852e82f3 70#define MAX_IVEC 0x40
9625036d 71#define NO_IRQ_REQUEST (MAX_IVEC + 1)
361dea40 72
2b8fbcd8
PB
73#define TYPE_APB "pbm"
74
75#define APB_DEVICE(obj) \
76 OBJECT_CHECK(APBState, (obj), TYPE_APB)
77
72f44c8c 78typedef struct APBState {
2b8fbcd8
PB
79 PCIHostState parent_obj;
80
3812ed0b
AK
81 MemoryRegion apb_config;
82 MemoryRegion pci_config;
f69539b1 83 MemoryRegion pci_mmio;
3812ed0b 84 MemoryRegion pci_ioport;
9625036d 85 uint64_t pci_irq_in;
95819af0
BS
86 uint32_t iommu[4];
87 uint32_t pci_control[16];
88 uint32_t pci_irq_map[8];
89 uint32_t obio_irq_map[32];
361dea40
BS
90 qemu_irq *pbm_irqs;
91 qemu_irq *ivec_irqs;
9625036d 92 unsigned int irq_request;
95819af0 93 uint32_t reset_control;
9c0afd0e 94 unsigned int nr_resets;
72f44c8c 95} APBState;
502a5395 96
9625036d
AT
97static inline void pbm_set_request(APBState *s, unsigned int irq_num)
98{
99 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
100
101 s->irq_request = irq_num;
102 qemu_set_irq(s->ivec_irqs[irq_num], 1);
103}
104
105static inline void pbm_check_irqs(APBState *s)
106{
107
108 unsigned int i;
109
110 /* Previous request is not acknowledged, resubmit */
111 if (s->irq_request != NO_IRQ_REQUEST) {
112 pbm_set_request(s, s->irq_request);
113 return;
114 }
115 /* no request pending */
116 if (s->pci_irq_in == 0ULL) {
117 return;
118 }
119 for (i = 0; i < 32; i++) {
120 if (s->pci_irq_in & (1ULL << i)) {
121 if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
122 pbm_set_request(s, i);
123 return;
124 }
125 }
126 }
127 for (i = 32; i < 64; i++) {
128 if (s->pci_irq_in & (1ULL << i)) {
129 if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
130 pbm_set_request(s, i);
131 break;
132 }
133 }
134 }
135}
136
137static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
138{
139 APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
140 qemu_set_irq(s->ivec_irqs[irq_num], 0);
141 s->irq_request = NO_IRQ_REQUEST;
142}
94d19914 143
a8170e5e 144static void apb_config_writel (void *opaque, hwaddr addr,
3812ed0b 145 uint64_t val, unsigned size)
502a5395 146{
95819af0
BS
147 APBState *s = opaque;
148
c0907c9e 149 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
95819af0
BS
150
151 switch (addr & 0xffff) {
152 case 0x30 ... 0x4f: /* DMA error registers */
153 /* XXX: not implemented yet */
154 break;
155 case 0x200 ... 0x20b: /* IOMMU */
156 s->iommu[(addr & 0xf) >> 2] = val;
157 break;
158 case 0x20c ... 0x3ff: /* IOMMU flush */
159 break;
160 case 0xc00 ... 0xc3f: /* PCI interrupt control */
161 if (addr & 4) {
9625036d
AT
162 unsigned int ino = (addr & 0x3f) >> 3;
163 s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
164 s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
165 if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
166 pbm_clear_request(s, ino);
167 }
168 pbm_check_irqs(s);
95819af0
BS
169 }
170 break;
361dea40
BS
171 case 0x1000 ... 0x1080: /* OBIO interrupt control */
172 if (addr & 4) {
9625036d
AT
173 unsigned int ino = ((addr & 0xff) >> 3);
174 s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
175 s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
176 if ((s->irq_request == (ino | 0x20))
177 && !(val & ~PBM_PCI_IMR_MASK)) {
178 pbm_clear_request(s, ino | 0x20);
179 }
180 pbm_check_irqs(s);
361dea40
BS
181 }
182 break;
9625036d 183 case 0x1400 ... 0x14ff: /* PCI interrupt clear */
94d19914 184 if (addr & 4) {
9625036d
AT
185 unsigned int ino = (addr & 0xff) >> 5;
186 if ((s->irq_request / 4) == ino) {
187 pbm_clear_request(s, s->irq_request);
188 pbm_check_irqs(s);
189 }
94d19914
AT
190 }
191 break;
192 case 0x1800 ... 0x1860: /* OBIO interrupt clear */
193 if (addr & 4) {
9625036d
AT
194 unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
195 if (s->irq_request == ino) {
196 pbm_clear_request(s, ino);
197 pbm_check_irqs(s);
198 }
94d19914
AT
199 }
200 break;
95819af0
BS
201 case 0x2000 ... 0x202f: /* PCI control */
202 s->pci_control[(addr & 0x3f) >> 2] = val;
203 break;
204 case 0xf020 ... 0xf027: /* Reset control */
205 if (addr & 4) {
206 val &= RESET_MASK;
207 s->reset_control &= ~(val & RESET_WCMASK);
208 s->reset_control |= val & RESET_WMASK;
209 if (val & SOFT_POR) {
9c0afd0e 210 s->nr_resets = 0;
95819af0
BS
211 qemu_system_reset_request();
212 } else if (val & SOFT_XIR) {
213 qemu_system_reset_request();
214 }
215 }
216 break;
217 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
218 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
219 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
220 case 0xf000 ... 0xf01f: /* FFB config, memory control */
221 /* we don't care */
502a5395 222 default:
f930d07e 223 break;
502a5395
PB
224 }
225}
226
3812ed0b 227static uint64_t apb_config_readl (void *opaque,
a8170e5e 228 hwaddr addr, unsigned size)
502a5395 229{
95819af0 230 APBState *s = opaque;
502a5395
PB
231 uint32_t val;
232
95819af0
BS
233 switch (addr & 0xffff) {
234 case 0x30 ... 0x4f: /* DMA error registers */
235 val = 0;
236 /* XXX: not implemented yet */
237 break;
238 case 0x200 ... 0x20b: /* IOMMU */
239 val = s->iommu[(addr & 0xf) >> 2];
240 break;
241 case 0x20c ... 0x3ff: /* IOMMU flush */
242 val = 0;
243 break;
244 case 0xc00 ... 0xc3f: /* PCI interrupt control */
245 if (addr & 4) {
246 val = s->pci_irq_map[(addr & 0x3f) >> 3];
247 } else {
248 val = 0;
249 }
250 break;
361dea40
BS
251 case 0x1000 ... 0x1080: /* OBIO interrupt control */
252 if (addr & 4) {
253 val = s->obio_irq_map[(addr & 0xff) >> 3];
254 } else {
255 val = 0;
256 }
257 break;
95819af0
BS
258 case 0x2000 ... 0x202f: /* PCI control */
259 val = s->pci_control[(addr & 0x3f) >> 2];
260 break;
261 case 0xf020 ... 0xf027: /* Reset control */
262 if (addr & 4) {
263 val = s->reset_control;
264 } else {
265 val = 0;
266 }
267 break;
268 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
269 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
270 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
271 case 0xf000 ... 0xf01f: /* FFB config, memory control */
272 /* we don't care */
502a5395 273 default:
f930d07e
BS
274 val = 0;
275 break;
502a5395 276 }
c0907c9e 277 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
95819af0 278
502a5395
PB
279 return val;
280}
281
3812ed0b
AK
282static const MemoryRegionOps apb_config_ops = {
283 .read = apb_config_readl,
284 .write = apb_config_writel,
285 .endianness = DEVICE_NATIVE_ENDIAN,
502a5395
PB
286};
287
a8170e5e 288static void apb_pci_config_write(void *opaque, hwaddr addr,
3812ed0b 289 uint64_t val, unsigned size)
5a5d4a76 290{
3812ed0b 291 APBState *s = opaque;
2b8fbcd8 292 PCIHostState *phb = PCI_HOST_BRIDGE(s);
63e6f31d
MT
293
294 val = qemu_bswap_len(val, size);
c0907c9e 295 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
2b8fbcd8 296 pci_data_write(phb->bus, addr, val, size);
5a5d4a76
BS
297}
298
a8170e5e 299static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
3812ed0b 300 unsigned size)
5a5d4a76
BS
301{
302 uint32_t ret;
3812ed0b 303 APBState *s = opaque;
2b8fbcd8 304 PCIHostState *phb = PCI_HOST_BRIDGE(s);
5a5d4a76 305
2b8fbcd8 306 ret = pci_data_read(phb->bus, addr, size);
63e6f31d 307 ret = qemu_bswap_len(ret, size);
c0907c9e 308 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
5a5d4a76
BS
309 return ret;
310}
311
80b3ada7 312/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 313static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 314{
80b3ada7
PB
315 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
316}
317
318static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
319{
320 int bus_offset;
321 if (pci_dev->devfn & 1)
322 bus_offset = 16;
323 else
324 bus_offset = 0;
903ce9fe 325 return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
d2b59317
PB
326}
327
5d4e84c8 328static void pci_apb_set_irq(void *opaque, int irq_num, int level)
d2b59317 329{
95819af0 330 APBState *s = opaque;
5d4e84c8 331
9625036d 332 APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
80b3ada7 333 /* PCI IRQ map onto the first 32 INO. */
95819af0 334 if (irq_num < 32) {
9625036d
AT
335 if (level) {
336 s->pci_irq_in |= 1ULL << irq_num;
337 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
338 pbm_set_request(s, irq_num);
339 }
361dea40 340 } else {
9625036d 341 s->pci_irq_in &= ~(1ULL << irq_num);
361dea40
BS
342 }
343 } else {
9625036d
AT
344 /* OBIO IRQ map onto the next 32 INO. */
345 if (level) {
361dea40 346 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
9625036d
AT
347 s->pci_irq_in |= 1ULL << irq_num;
348 if ((s->irq_request == NO_IRQ_REQUEST)
349 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
350 pbm_set_request(s, irq_num);
351 }
95819af0 352 } else {
9625036d 353 s->pci_irq_in &= ~(1ULL << irq_num);
95819af0
BS
354 }
355 }
502a5395
PB
356}
357
68f79994 358static int apb_pci_bridge_initfn(PCIDevice *dev)
d6318738 359{
68f79994
IY
360 int rc;
361
60a0e443 362 rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
68f79994
IY
363 if (rc < 0) {
364 return rc;
365 }
366
d6318738
MT
367 /*
368 * command register:
369 * According to PCI bridge spec, after reset
370 * bus master bit is off
371 * memory space enable bit is off
372 * According to manual (805-1251.pdf).
373 * the reset value should be zero unless the boot pin is tied high
374 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
375 */
376 pci_set_word(dev->config + PCI_COMMAND,
9fe52c7f
BS
377 PCI_COMMAND_MEMORY);
378 pci_set_word(dev->config + PCI_STATUS,
379 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
380 PCI_STATUS_DEVSEL_MEDIUM);
68f79994 381 return 0;
d6318738
MT
382}
383
a8170e5e
AK
384PCIBus *pci_apb_init(hwaddr special_base,
385 hwaddr mem_base,
361dea40
BS
386 qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
387 qemu_irq **pbm_irqs)
502a5395 388{
72f44c8c
BS
389 DeviceState *dev;
390 SysBusDevice *s;
2b8fbcd8 391 PCIHostState *phb;
72f44c8c 392 APBState *d;
68f79994
IY
393 PCIDevice *pci_dev;
394 PCIBridge *br;
502a5395 395
80b3ada7 396 /* Ultrasparc PBM main bus */
2b8fbcd8 397 dev = qdev_create(NULL, TYPE_APB);
e23a1b33 398 qdev_init_nofail(dev);
1356b98d 399 s = SYS_BUS_DEVICE(dev);
72f44c8c 400 /* apb_config */
bae7b517 401 sysbus_mmio_map(s, 0, special_base);
d63baf92
IK
402 /* PCI configuration space */
403 sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
72f44c8c 404 /* pci_ioport */
d63baf92 405 sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
2b8fbcd8 406 d = APB_DEVICE(dev);
d63baf92 407
40c5dce9 408 memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
f69539b1
BS
409 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
410
2b8fbcd8
PB
411 phb = PCI_HOST_BRIDGE(dev);
412 phb->bus = pci_register_bus(DEVICE(phb), "pci",
413 pci_apb_set_irq, pci_pbm_map_irq, d,
414 &d->pci_mmio,
415 get_system_io(),
416 0, 32, TYPE_PCI_BUS);
f6b6f1bc 417
361dea40
BS
418 *pbm_irqs = d->pbm_irqs;
419 d->ivec_irqs = ivec_irqs;
95819af0 420
2b8fbcd8 421 pci_create_simple(phb->bus, 0, "pbm-pci");
d63baf92 422
72f44c8c 423 /* APB secondary busses */
2b8fbcd8 424 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
68f79994
IY
425 "pbm-bridge");
426 br = DO_UPCAST(PCIBridge, dev, pci_dev);
427 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
428 pci_apb_map_irq);
429 qdev_init_nofail(&pci_dev->qdev);
430 *bus2 = pci_bridge_get_sec_bus(br);
431
2b8fbcd8 432 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
68f79994
IY
433 "pbm-bridge");
434 br = DO_UPCAST(PCIBridge, dev, pci_dev);
435 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
436 pci_apb_map_irq);
437 qdev_init_nofail(&pci_dev->qdev);
438 *bus3 = pci_bridge_get_sec_bus(br);
502a5395 439
2b8fbcd8 440 return phb->bus;
72f44c8c
BS
441}
442
95819af0 443static void pci_pbm_reset(DeviceState *d)
72f44c8c 444{
95819af0 445 unsigned int i;
2b8fbcd8 446 APBState *s = APB_DEVICE(d);
72f44c8c 447
95819af0
BS
448 for (i = 0; i < 8; i++) {
449 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
450 }
d1d80055
AT
451 for (i = 0; i < 32; i++) {
452 s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
453 }
95819af0 454
9625036d
AT
455 s->irq_request = NO_IRQ_REQUEST;
456 s->pci_irq_in = 0ULL;
457
9c0afd0e 458 if (s->nr_resets++ == 0) {
95819af0
BS
459 /* Power on reset */
460 s->reset_control = POR;
461 }
462}
463
3812ed0b
AK
464static const MemoryRegionOps pci_config_ops = {
465 .read = apb_pci_config_read,
466 .write = apb_pci_config_write,
467 .endianness = DEVICE_NATIVE_ENDIAN,
468};
469
95819af0
BS
470static int pci_pbm_init_device(SysBusDevice *dev)
471{
72f44c8c 472 APBState *s;
95819af0 473 unsigned int i;
72f44c8c 474
2b8fbcd8 475 s = APB_DEVICE(dev);
95819af0
BS
476 for (i = 0; i < 8; i++) {
477 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
478 }
d1d80055
AT
479 for (i = 0; i < 32; i++) {
480 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
481 }
361dea40 482 s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
9625036d
AT
483 s->irq_request = NO_IRQ_REQUEST;
484 s->pci_irq_in = 0ULL;
95819af0 485
72f44c8c 486 /* apb_config */
40c5dce9
PB
487 memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
488 "apb-config", 0x10000);
d63baf92 489 /* at region 0 */
750ecd44 490 sysbus_init_mmio(dev, &s->apb_config);
d63baf92 491
40c5dce9
PB
492 memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
493 "apb-pci-config", 0x1000000);
d63baf92 494 /* at region 1 */
750ecd44 495 sysbus_init_mmio(dev, &s->pci_config);
d63baf92
IK
496
497 /* pci_ioport */
5519ad0c
PB
498 memory_region_init_alias(&s->pci_ioport, OBJECT(s), "apb-pci-ioport",
499 get_system_io(), 0, 0x10000);
d63baf92 500 /* at region 2 */
750ecd44 501 sysbus_init_mmio(dev, &s->pci_ioport);
d63baf92 502
81a322d4 503 return 0;
72f44c8c 504}
502a5395 505
81a322d4 506static int pbm_pci_host_init(PCIDevice *d)
72f44c8c 507{
9fe52c7f
BS
508 pci_set_word(d->config + PCI_COMMAND,
509 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
510 pci_set_word(d->config + PCI_STATUS,
511 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
512 PCI_STATUS_DEVSEL_MEDIUM);
81a322d4 513 return 0;
72f44c8c 514}
80b3ada7 515
40021f08
AL
516static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
517{
518 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
519
520 k->init = pbm_pci_host_init;
521 k->vendor_id = PCI_VENDOR_ID_SUN;
522 k->device_id = PCI_DEVICE_ID_SUN_SABRE;
523 k->class_id = PCI_CLASS_BRIDGE_HOST;
40021f08
AL
524}
525
8c43a6f0 526static const TypeInfo pbm_pci_host_info = {
39bffca2
AL
527 .name = "pbm-pci",
528 .parent = TYPE_PCI_DEVICE,
529 .instance_size = sizeof(PCIDevice),
530 .class_init = pbm_pci_host_class_init,
72f44c8c
BS
531};
532
999e12bb
AL
533static void pbm_host_class_init(ObjectClass *klass, void *data)
534{
39bffca2 535 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
536 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
537
538 k->init = pci_pbm_init_device;
125ee0ed 539 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39bffca2 540 dc->reset = pci_pbm_reset;
999e12bb
AL
541}
542
8c43a6f0 543static const TypeInfo pbm_host_info = {
2b8fbcd8
PB
544 .name = TYPE_APB,
545 .parent = TYPE_PCI_HOST_BRIDGE,
39bffca2
AL
546 .instance_size = sizeof(APBState),
547 .class_init = pbm_host_class_init,
95819af0 548};
68f79994 549
40021f08
AL
550static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
551{
39bffca2 552 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
553 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
554
555 k->init = apb_pci_bridge_initfn;
556 k->exit = pci_bridge_exitfn;
557 k->vendor_id = PCI_VENDOR_ID_SUN;
558 k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
559 k->revision = 0x11;
560 k->config_write = pci_bridge_write_config;
561 k->is_bridge = 1;
125ee0ed 562 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39bffca2
AL
563 dc->reset = pci_bridge_reset;
564 dc->vmsd = &vmstate_pci_device;
40021f08
AL
565}
566
8c43a6f0 567static const TypeInfo pbm_pci_bridge_info = {
39bffca2
AL
568 .name = "pbm-bridge",
569 .parent = TYPE_PCI_DEVICE,
570 .instance_size = sizeof(PCIBridge),
571 .class_init = pbm_pci_bridge_class_init,
68f79994
IY
572};
573
83f7d43a 574static void pbm_register_types(void)
72f44c8c 575{
39bffca2
AL
576 type_register_static(&pbm_host_info);
577 type_register_static(&pbm_pci_host_info);
578 type_register_static(&pbm_pci_bridge_info);
502a5395 579}
72f44c8c 580
83f7d43a 581type_init(pbm_register_types)