]> git.proxmox.com Git - mirror_qemu.git/blame - hw/pci-host/apb.c
memory: add owner argument to initialization functions
[mirror_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
72f44c8c
BS
73typedef struct APBState {
74 SysBusDevice busdev;
d63baf92 75 PCIBus *bus;
3812ed0b
AK
76 MemoryRegion apb_config;
77 MemoryRegion pci_config;
f69539b1 78 MemoryRegion pci_mmio;
3812ed0b 79 MemoryRegion pci_ioport;
9625036d 80 uint64_t pci_irq_in;
95819af0
BS
81 uint32_t iommu[4];
82 uint32_t pci_control[16];
83 uint32_t pci_irq_map[8];
84 uint32_t obio_irq_map[32];
361dea40
BS
85 qemu_irq *pbm_irqs;
86 qemu_irq *ivec_irqs;
9625036d 87 unsigned int irq_request;
95819af0 88 uint32_t reset_control;
9c0afd0e 89 unsigned int nr_resets;
72f44c8c 90} APBState;
502a5395 91
9625036d
AT
92static inline void pbm_set_request(APBState *s, unsigned int irq_num)
93{
94 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
95
96 s->irq_request = irq_num;
97 qemu_set_irq(s->ivec_irqs[irq_num], 1);
98}
99
100static inline void pbm_check_irqs(APBState *s)
101{
102
103 unsigned int i;
104
105 /* Previous request is not acknowledged, resubmit */
106 if (s->irq_request != NO_IRQ_REQUEST) {
107 pbm_set_request(s, s->irq_request);
108 return;
109 }
110 /* no request pending */
111 if (s->pci_irq_in == 0ULL) {
112 return;
113 }
114 for (i = 0; i < 32; i++) {
115 if (s->pci_irq_in & (1ULL << i)) {
116 if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
117 pbm_set_request(s, i);
118 return;
119 }
120 }
121 }
122 for (i = 32; i < 64; i++) {
123 if (s->pci_irq_in & (1ULL << i)) {
124 if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
125 pbm_set_request(s, i);
126 break;
127 }
128 }
129 }
130}
131
132static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
133{
134 APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
135 qemu_set_irq(s->ivec_irqs[irq_num], 0);
136 s->irq_request = NO_IRQ_REQUEST;
137}
94d19914 138
a8170e5e 139static void apb_config_writel (void *opaque, hwaddr addr,
3812ed0b 140 uint64_t val, unsigned size)
502a5395 141{
95819af0
BS
142 APBState *s = opaque;
143
c0907c9e 144 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
95819af0
BS
145
146 switch (addr & 0xffff) {
147 case 0x30 ... 0x4f: /* DMA error registers */
148 /* XXX: not implemented yet */
149 break;
150 case 0x200 ... 0x20b: /* IOMMU */
151 s->iommu[(addr & 0xf) >> 2] = val;
152 break;
153 case 0x20c ... 0x3ff: /* IOMMU flush */
154 break;
155 case 0xc00 ... 0xc3f: /* PCI interrupt control */
156 if (addr & 4) {
9625036d
AT
157 unsigned int ino = (addr & 0x3f) >> 3;
158 s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
159 s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
160 if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
161 pbm_clear_request(s, ino);
162 }
163 pbm_check_irqs(s);
95819af0
BS
164 }
165 break;
361dea40
BS
166 case 0x1000 ... 0x1080: /* OBIO interrupt control */
167 if (addr & 4) {
9625036d
AT
168 unsigned int ino = ((addr & 0xff) >> 3);
169 s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
170 s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
171 if ((s->irq_request == (ino | 0x20))
172 && !(val & ~PBM_PCI_IMR_MASK)) {
173 pbm_clear_request(s, ino | 0x20);
174 }
175 pbm_check_irqs(s);
361dea40
BS
176 }
177 break;
9625036d 178 case 0x1400 ... 0x14ff: /* PCI interrupt clear */
94d19914 179 if (addr & 4) {
9625036d
AT
180 unsigned int ino = (addr & 0xff) >> 5;
181 if ((s->irq_request / 4) == ino) {
182 pbm_clear_request(s, s->irq_request);
183 pbm_check_irqs(s);
184 }
94d19914
AT
185 }
186 break;
187 case 0x1800 ... 0x1860: /* OBIO interrupt clear */
188 if (addr & 4) {
9625036d
AT
189 unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
190 if (s->irq_request == ino) {
191 pbm_clear_request(s, ino);
192 pbm_check_irqs(s);
193 }
94d19914
AT
194 }
195 break;
95819af0
BS
196 case 0x2000 ... 0x202f: /* PCI control */
197 s->pci_control[(addr & 0x3f) >> 2] = val;
198 break;
199 case 0xf020 ... 0xf027: /* Reset control */
200 if (addr & 4) {
201 val &= RESET_MASK;
202 s->reset_control &= ~(val & RESET_WCMASK);
203 s->reset_control |= val & RESET_WMASK;
204 if (val & SOFT_POR) {
9c0afd0e 205 s->nr_resets = 0;
95819af0
BS
206 qemu_system_reset_request();
207 } else if (val & SOFT_XIR) {
208 qemu_system_reset_request();
209 }
210 }
211 break;
212 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
213 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
214 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
215 case 0xf000 ... 0xf01f: /* FFB config, memory control */
216 /* we don't care */
502a5395 217 default:
f930d07e 218 break;
502a5395
PB
219 }
220}
221
3812ed0b 222static uint64_t apb_config_readl (void *opaque,
a8170e5e 223 hwaddr addr, unsigned size)
502a5395 224{
95819af0 225 APBState *s = opaque;
502a5395
PB
226 uint32_t val;
227
95819af0
BS
228 switch (addr & 0xffff) {
229 case 0x30 ... 0x4f: /* DMA error registers */
230 val = 0;
231 /* XXX: not implemented yet */
232 break;
233 case 0x200 ... 0x20b: /* IOMMU */
234 val = s->iommu[(addr & 0xf) >> 2];
235 break;
236 case 0x20c ... 0x3ff: /* IOMMU flush */
237 val = 0;
238 break;
239 case 0xc00 ... 0xc3f: /* PCI interrupt control */
240 if (addr & 4) {
241 val = s->pci_irq_map[(addr & 0x3f) >> 3];
242 } else {
243 val = 0;
244 }
245 break;
361dea40
BS
246 case 0x1000 ... 0x1080: /* OBIO interrupt control */
247 if (addr & 4) {
248 val = s->obio_irq_map[(addr & 0xff) >> 3];
249 } else {
250 val = 0;
251 }
252 break;
95819af0
BS
253 case 0x2000 ... 0x202f: /* PCI control */
254 val = s->pci_control[(addr & 0x3f) >> 2];
255 break;
256 case 0xf020 ... 0xf027: /* Reset control */
257 if (addr & 4) {
258 val = s->reset_control;
259 } else {
260 val = 0;
261 }
262 break;
263 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
264 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
265 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
266 case 0xf000 ... 0xf01f: /* FFB config, memory control */
267 /* we don't care */
502a5395 268 default:
f930d07e
BS
269 val = 0;
270 break;
502a5395 271 }
c0907c9e 272 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
95819af0 273
502a5395
PB
274 return val;
275}
276
3812ed0b
AK
277static const MemoryRegionOps apb_config_ops = {
278 .read = apb_config_readl,
279 .write = apb_config_writel,
280 .endianness = DEVICE_NATIVE_ENDIAN,
502a5395
PB
281};
282
a8170e5e 283static void apb_pci_config_write(void *opaque, hwaddr addr,
3812ed0b 284 uint64_t val, unsigned size)
5a5d4a76 285{
3812ed0b 286 APBState *s = opaque;
63e6f31d
MT
287
288 val = qemu_bswap_len(val, size);
c0907c9e 289 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
d63baf92 290 pci_data_write(s->bus, addr, val, size);
5a5d4a76
BS
291}
292
a8170e5e 293static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
3812ed0b 294 unsigned size)
5a5d4a76
BS
295{
296 uint32_t ret;
3812ed0b 297 APBState *s = opaque;
5a5d4a76 298
d63baf92 299 ret = pci_data_read(s->bus, addr, size);
63e6f31d 300 ret = qemu_bswap_len(ret, size);
c0907c9e 301 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
5a5d4a76
BS
302 return ret;
303}
304
a8170e5e 305static void pci_apb_iowriteb (void *opaque, hwaddr addr,
502a5395
PB
306 uint32_t val)
307{
afcea8cb 308 cpu_outb(addr & IOPORTS_MASK, val);
502a5395
PB
309}
310
a8170e5e 311static void pci_apb_iowritew (void *opaque, hwaddr addr,
502a5395
PB
312 uint32_t val)
313{
a4d5f62c 314 cpu_outw(addr & IOPORTS_MASK, bswap16(val));
502a5395
PB
315}
316
a8170e5e 317static void pci_apb_iowritel (void *opaque, hwaddr addr,
502a5395
PB
318 uint32_t val)
319{
a4d5f62c 320 cpu_outl(addr & IOPORTS_MASK, bswap32(val));
502a5395
PB
321}
322
a8170e5e 323static uint32_t pci_apb_ioreadb (void *opaque, hwaddr addr)
502a5395
PB
324{
325 uint32_t val;
326
afcea8cb 327 val = cpu_inb(addr & IOPORTS_MASK);
502a5395
PB
328 return val;
329}
330
a8170e5e 331static uint32_t pci_apb_ioreadw (void *opaque, hwaddr addr)
502a5395
PB
332{
333 uint32_t val;
334
a4d5f62c 335 val = bswap16(cpu_inw(addr & IOPORTS_MASK));
502a5395
PB
336 return val;
337}
338
a8170e5e 339static uint32_t pci_apb_ioreadl (void *opaque, hwaddr addr)
502a5395
PB
340{
341 uint32_t val;
342
a4d5f62c 343 val = bswap32(cpu_inl(addr & IOPORTS_MASK));
502a5395
PB
344 return val;
345}
346
3812ed0b
AK
347static const MemoryRegionOps pci_ioport_ops = {
348 .old_mmio = {
349 .read = { pci_apb_ioreadb, pci_apb_ioreadw, pci_apb_ioreadl },
350 .write = { pci_apb_iowriteb, pci_apb_iowritew, pci_apb_iowritel, },
351 },
352 .endianness = DEVICE_NATIVE_ENDIAN,
502a5395
PB
353};
354
80b3ada7 355/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 356static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 357{
80b3ada7
PB
358 return ((pci_dev->devfn & 0x18) >> 1) + irq_num;
359}
360
361static int pci_pbm_map_irq(PCIDevice *pci_dev, int irq_num)
362{
363 int bus_offset;
364 if (pci_dev->devfn & 1)
365 bus_offset = 16;
366 else
367 bus_offset = 0;
903ce9fe 368 return (bus_offset + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
d2b59317
PB
369}
370
5d4e84c8 371static void pci_apb_set_irq(void *opaque, int irq_num, int level)
d2b59317 372{
95819af0 373 APBState *s = opaque;
5d4e84c8 374
9625036d 375 APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
80b3ada7 376 /* PCI IRQ map onto the first 32 INO. */
95819af0 377 if (irq_num < 32) {
9625036d
AT
378 if (level) {
379 s->pci_irq_in |= 1ULL << irq_num;
380 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
381 pbm_set_request(s, irq_num);
382 }
361dea40 383 } else {
9625036d 384 s->pci_irq_in &= ~(1ULL << irq_num);
361dea40
BS
385 }
386 } else {
9625036d
AT
387 /* OBIO IRQ map onto the next 32 INO. */
388 if (level) {
361dea40 389 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
9625036d
AT
390 s->pci_irq_in |= 1ULL << irq_num;
391 if ((s->irq_request == NO_IRQ_REQUEST)
392 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
393 pbm_set_request(s, irq_num);
394 }
95819af0 395 } else {
9625036d 396 s->pci_irq_in &= ~(1ULL << irq_num);
95819af0
BS
397 }
398 }
502a5395
PB
399}
400
68f79994 401static int apb_pci_bridge_initfn(PCIDevice *dev)
d6318738 402{
68f79994
IY
403 int rc;
404
60a0e443 405 rc = pci_bridge_initfn(dev, TYPE_PCI_BUS);
68f79994
IY
406 if (rc < 0) {
407 return rc;
408 }
409
d6318738
MT
410 /*
411 * command register:
412 * According to PCI bridge spec, after reset
413 * bus master bit is off
414 * memory space enable bit is off
415 * According to manual (805-1251.pdf).
416 * the reset value should be zero unless the boot pin is tied high
417 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
418 */
419 pci_set_word(dev->config + PCI_COMMAND,
9fe52c7f
BS
420 PCI_COMMAND_MEMORY);
421 pci_set_word(dev->config + PCI_STATUS,
422 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
423 PCI_STATUS_DEVSEL_MEDIUM);
68f79994 424 return 0;
d6318738
MT
425}
426
a8170e5e
AK
427PCIBus *pci_apb_init(hwaddr special_base,
428 hwaddr mem_base,
361dea40
BS
429 qemu_irq *ivec_irqs, PCIBus **bus2, PCIBus **bus3,
430 qemu_irq **pbm_irqs)
502a5395 431{
72f44c8c
BS
432 DeviceState *dev;
433 SysBusDevice *s;
434 APBState *d;
68f79994
IY
435 PCIDevice *pci_dev;
436 PCIBridge *br;
502a5395 437
80b3ada7 438 /* Ultrasparc PBM main bus */
72f44c8c 439 dev = qdev_create(NULL, "pbm");
e23a1b33 440 qdev_init_nofail(dev);
1356b98d 441 s = SYS_BUS_DEVICE(dev);
72f44c8c 442 /* apb_config */
bae7b517 443 sysbus_mmio_map(s, 0, special_base);
d63baf92
IK
444 /* PCI configuration space */
445 sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
72f44c8c 446 /* pci_ioport */
d63baf92 447 sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
72f44c8c 448 d = FROM_SYSBUS(APBState, s);
d63baf92 449
2c9b15ca 450 memory_region_init(&d->pci_mmio, NULL, "pci-mmio", 0x100000000ULL);
f69539b1
BS
451 memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
452
d63baf92 453 d->bus = pci_register_bus(&d->busdev.qdev, "pci",
f69539b1
BS
454 pci_apb_set_irq, pci_pbm_map_irq, d,
455 &d->pci_mmio,
456 get_system_io(),
60a0e443 457 0, 32, TYPE_PCI_BUS);
f6b6f1bc 458
361dea40
BS
459 *pbm_irqs = d->pbm_irqs;
460 d->ivec_irqs = ivec_irqs;
95819af0 461
73093354 462 pci_create_simple(d->bus, 0, "pbm-pci");
d63baf92 463
72f44c8c 464 /* APB secondary busses */
68f79994
IY
465 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 0), true,
466 "pbm-bridge");
467 br = DO_UPCAST(PCIBridge, dev, pci_dev);
468 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 1",
469 pci_apb_map_irq);
470 qdev_init_nofail(&pci_dev->qdev);
471 *bus2 = pci_bridge_get_sec_bus(br);
472
473 pci_dev = pci_create_multifunction(d->bus, PCI_DEVFN(1, 1), true,
474 "pbm-bridge");
475 br = DO_UPCAST(PCIBridge, dev, pci_dev);
476 pci_bridge_map_irq(br, "Advanced PCI Bus secondary bridge 2",
477 pci_apb_map_irq);
478 qdev_init_nofail(&pci_dev->qdev);
479 *bus3 = pci_bridge_get_sec_bus(br);
502a5395 480
d63baf92 481 return d->bus;
72f44c8c
BS
482}
483
95819af0 484static void pci_pbm_reset(DeviceState *d)
72f44c8c 485{
95819af0
BS
486 unsigned int i;
487 APBState *s = container_of(d, APBState, busdev.qdev);
72f44c8c 488
95819af0
BS
489 for (i = 0; i < 8; i++) {
490 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
491 }
d1d80055
AT
492 for (i = 0; i < 32; i++) {
493 s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
494 }
95819af0 495
9625036d
AT
496 s->irq_request = NO_IRQ_REQUEST;
497 s->pci_irq_in = 0ULL;
498
9c0afd0e 499 if (s->nr_resets++ == 0) {
95819af0
BS
500 /* Power on reset */
501 s->reset_control = POR;
502 }
503}
504
3812ed0b
AK
505static const MemoryRegionOps pci_config_ops = {
506 .read = apb_pci_config_read,
507 .write = apb_pci_config_write,
508 .endianness = DEVICE_NATIVE_ENDIAN,
509};
510
95819af0
BS
511static int pci_pbm_init_device(SysBusDevice *dev)
512{
72f44c8c 513 APBState *s;
95819af0 514 unsigned int i;
72f44c8c
BS
515
516 s = FROM_SYSBUS(APBState, dev);
95819af0
BS
517 for (i = 0; i < 8; i++) {
518 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
519 }
d1d80055
AT
520 for (i = 0; i < 32; i++) {
521 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
522 }
361dea40 523 s->pbm_irqs = qemu_allocate_irqs(pci_apb_set_irq, s, MAX_IVEC);
9625036d
AT
524 s->irq_request = NO_IRQ_REQUEST;
525 s->pci_irq_in = 0ULL;
95819af0 526
72f44c8c 527 /* apb_config */
2c9b15ca 528 memory_region_init_io(&s->apb_config, NULL, &apb_config_ops, s, "apb-config",
3812ed0b 529 0x10000);
d63baf92 530 /* at region 0 */
750ecd44 531 sysbus_init_mmio(dev, &s->apb_config);
d63baf92 532
2c9b15ca 533 memory_region_init_io(&s->pci_config, NULL, &pci_config_ops, s, "apb-pci-config",
3812ed0b 534 0x1000000);
d63baf92 535 /* at region 1 */
750ecd44 536 sysbus_init_mmio(dev, &s->pci_config);
d63baf92
IK
537
538 /* pci_ioport */
2c9b15ca 539 memory_region_init_io(&s->pci_ioport, NULL, &pci_ioport_ops, s,
3812ed0b 540 "apb-pci-ioport", 0x10000);
d63baf92 541 /* at region 2 */
750ecd44 542 sysbus_init_mmio(dev, &s->pci_ioport);
d63baf92 543
81a322d4 544 return 0;
72f44c8c 545}
502a5395 546
81a322d4 547static int pbm_pci_host_init(PCIDevice *d)
72f44c8c 548{
9fe52c7f
BS
549 pci_set_word(d->config + PCI_COMMAND,
550 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
551 pci_set_word(d->config + PCI_STATUS,
552 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
553 PCI_STATUS_DEVSEL_MEDIUM);
81a322d4 554 return 0;
72f44c8c 555}
80b3ada7 556
40021f08
AL
557static void pbm_pci_host_class_init(ObjectClass *klass, void *data)
558{
559 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
560
561 k->init = pbm_pci_host_init;
562 k->vendor_id = PCI_VENDOR_ID_SUN;
563 k->device_id = PCI_DEVICE_ID_SUN_SABRE;
564 k->class_id = PCI_CLASS_BRIDGE_HOST;
40021f08
AL
565}
566
8c43a6f0 567static const TypeInfo pbm_pci_host_info = {
39bffca2
AL
568 .name = "pbm-pci",
569 .parent = TYPE_PCI_DEVICE,
570 .instance_size = sizeof(PCIDevice),
571 .class_init = pbm_pci_host_class_init,
72f44c8c
BS
572};
573
999e12bb
AL
574static void pbm_host_class_init(ObjectClass *klass, void *data)
575{
39bffca2 576 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
577 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
578
579 k->init = pci_pbm_init_device;
39bffca2 580 dc->reset = pci_pbm_reset;
999e12bb
AL
581}
582
8c43a6f0 583static const TypeInfo pbm_host_info = {
39bffca2
AL
584 .name = "pbm",
585 .parent = TYPE_SYS_BUS_DEVICE,
586 .instance_size = sizeof(APBState),
587 .class_init = pbm_host_class_init,
95819af0 588};
68f79994 589
40021f08
AL
590static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
591{
39bffca2 592 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
593 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
594
595 k->init = apb_pci_bridge_initfn;
596 k->exit = pci_bridge_exitfn;
597 k->vendor_id = PCI_VENDOR_ID_SUN;
598 k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
599 k->revision = 0x11;
600 k->config_write = pci_bridge_write_config;
601 k->is_bridge = 1;
39bffca2
AL
602 dc->reset = pci_bridge_reset;
603 dc->vmsd = &vmstate_pci_device;
40021f08
AL
604}
605
8c43a6f0 606static const TypeInfo pbm_pci_bridge_info = {
39bffca2
AL
607 .name = "pbm-bridge",
608 .parent = TYPE_PCI_DEVICE,
609 .instance_size = sizeof(PCIBridge),
610 .class_init = pbm_pci_bridge_class_init,
68f79994
IY
611};
612
83f7d43a 613static void pbm_register_types(void)
72f44c8c 614{
39bffca2
AL
615 type_register_static(&pbm_host_info);
616 type_register_static(&pbm_pci_host_info);
617 type_register_static(&pbm_pci_bridge_info);
502a5395 618}
72f44c8c 619
83f7d43a 620type_init(pbm_register_types)