]> git.proxmox.com Git - mirror_qemu.git/blame - hw/pci-host/apb.c
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20180111' into...
[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
97d5408f 30#include "qemu/osdep.h"
83c9f4ca
PB
31#include "hw/sysbus.h"
32#include "hw/pci/pci.h"
33#include "hw/pci/pci_host.h"
34#include "hw/pci/pci_bridge.h"
35#include "hw/pci/pci_bus.h"
0d09e41a 36#include "hw/pci-host/apb.h"
9c17d615 37#include "sysemu/sysemu.h"
022c62cb 38#include "exec/address-spaces.h"
aea5b071 39#include "qapi/error.h"
03dd024f 40#include "qemu/log.h"
a94fd955
BS
41
42/* debug APB */
43//#define DEBUG_APB
44
45#ifdef DEBUG_APB
001faf32
BS
46#define APB_DPRINTF(fmt, ...) \
47do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
a94fd955 48#else
001faf32 49#define APB_DPRINTF(fmt, ...)
a94fd955
BS
50#endif
51
930f3fe1
BS
52/*
53 * Chipset docs:
54 * PBM: "UltraSPARC IIi User's Manual",
55 * http://www.sun.com/processors/manuals/805-0087.pdf
56 *
57 * APB: "Advanced PCI Bridge (APB) User's Manual",
58 * http://www.sun.com/processors/manuals/805-1251.pdf
59 */
60
95819af0
BS
61#define PBM_PCI_IMR_MASK 0x7fffffff
62#define PBM_PCI_IMR_ENABLED 0x80000000
63
af23906d
PM
64#define POR (1U << 31)
65#define SOFT_POR (1U << 30)
66#define SOFT_XIR (1U << 29)
67#define BTN_POR (1U << 28)
68#define BTN_XIR (1U << 27)
95819af0
BS
69#define RESET_MASK 0xf8000000
70#define RESET_WCMASK 0x98000000
71#define RESET_WMASK 0x60000000
72
9625036d 73#define NO_IRQ_REQUEST (MAX_IVEC + 1)
361dea40 74
9625036d
AT
75static inline void pbm_set_request(APBState *s, unsigned int irq_num)
76{
77 APB_DPRINTF("%s: request irq %d\n", __func__, irq_num);
78
79 s->irq_request = irq_num;
80 qemu_set_irq(s->ivec_irqs[irq_num], 1);
81}
82
83static inline void pbm_check_irqs(APBState *s)
84{
85
86 unsigned int i;
87
88 /* Previous request is not acknowledged, resubmit */
89 if (s->irq_request != NO_IRQ_REQUEST) {
90 pbm_set_request(s, s->irq_request);
91 return;
92 }
93 /* no request pending */
94 if (s->pci_irq_in == 0ULL) {
95 return;
96 }
97 for (i = 0; i < 32; i++) {
98 if (s->pci_irq_in & (1ULL << i)) {
99 if (s->pci_irq_map[i >> 2] & PBM_PCI_IMR_ENABLED) {
100 pbm_set_request(s, i);
101 return;
102 }
103 }
104 }
105 for (i = 32; i < 64; i++) {
106 if (s->pci_irq_in & (1ULL << i)) {
107 if (s->obio_irq_map[i - 32] & PBM_PCI_IMR_ENABLED) {
108 pbm_set_request(s, i);
109 break;
110 }
111 }
112 }
113}
114
115static inline void pbm_clear_request(APBState *s, unsigned int irq_num)
116{
117 APB_DPRINTF("%s: clear request irq %d\n", __func__, irq_num);
118 qemu_set_irq(s->ivec_irqs[irq_num], 0);
119 s->irq_request = NO_IRQ_REQUEST;
120}
94d19914 121
ae74bbe7
MCA
122static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
123{
124 IOMMUState *is = opaque;
125
126 return &is->iommu_as;
127}
128
a8170e5e 129static void apb_config_writel (void *opaque, hwaddr addr,
3812ed0b 130 uint64_t val, unsigned size)
502a5395 131{
95819af0
BS
132 APBState *s = opaque;
133
c0907c9e 134 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
95819af0
BS
135
136 switch (addr & 0xffff) {
137 case 0x30 ... 0x4f: /* DMA error registers */
138 /* XXX: not implemented yet */
139 break;
95819af0
BS
140 case 0xc00 ... 0xc3f: /* PCI interrupt control */
141 if (addr & 4) {
9625036d
AT
142 unsigned int ino = (addr & 0x3f) >> 3;
143 s->pci_irq_map[ino] &= PBM_PCI_IMR_MASK;
144 s->pci_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
145 if ((s->irq_request == ino) && !(val & ~PBM_PCI_IMR_MASK)) {
146 pbm_clear_request(s, ino);
147 }
148 pbm_check_irqs(s);
95819af0
BS
149 }
150 break;
de739df8 151 case 0x1000 ... 0x107f: /* OBIO interrupt control */
361dea40 152 if (addr & 4) {
9625036d
AT
153 unsigned int ino = ((addr & 0xff) >> 3);
154 s->obio_irq_map[ino] &= PBM_PCI_IMR_MASK;
155 s->obio_irq_map[ino] |= val & ~PBM_PCI_IMR_MASK;
156 if ((s->irq_request == (ino | 0x20))
157 && !(val & ~PBM_PCI_IMR_MASK)) {
158 pbm_clear_request(s, ino | 0x20);
159 }
160 pbm_check_irqs(s);
361dea40
BS
161 }
162 break;
9625036d 163 case 0x1400 ... 0x14ff: /* PCI interrupt clear */
94d19914 164 if (addr & 4) {
9625036d
AT
165 unsigned int ino = (addr & 0xff) >> 5;
166 if ((s->irq_request / 4) == ino) {
167 pbm_clear_request(s, s->irq_request);
168 pbm_check_irqs(s);
169 }
94d19914
AT
170 }
171 break;
172 case 0x1800 ... 0x1860: /* OBIO interrupt clear */
173 if (addr & 4) {
9625036d
AT
174 unsigned int ino = ((addr & 0xff) >> 3) | 0x20;
175 if (s->irq_request == ino) {
176 pbm_clear_request(s, ino);
177 pbm_check_irqs(s);
178 }
94d19914
AT
179 }
180 break;
95819af0
BS
181 case 0x2000 ... 0x202f: /* PCI control */
182 s->pci_control[(addr & 0x3f) >> 2] = val;
183 break;
184 case 0xf020 ... 0xf027: /* Reset control */
185 if (addr & 4) {
186 val &= RESET_MASK;
187 s->reset_control &= ~(val & RESET_WCMASK);
188 s->reset_control |= val & RESET_WMASK;
189 if (val & SOFT_POR) {
9c0afd0e 190 s->nr_resets = 0;
cf83f140 191 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
95819af0 192 } else if (val & SOFT_XIR) {
cf83f140 193 qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
95819af0
BS
194 }
195 }
196 break;
197 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
198 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
199 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
200 case 0xf000 ... 0xf01f: /* FFB config, memory control */
201 /* we don't care */
502a5395 202 default:
f930d07e 203 break;
502a5395
PB
204 }
205}
206
3812ed0b 207static uint64_t apb_config_readl (void *opaque,
a8170e5e 208 hwaddr addr, unsigned size)
502a5395 209{
95819af0 210 APBState *s = opaque;
502a5395
PB
211 uint32_t val;
212
95819af0
BS
213 switch (addr & 0xffff) {
214 case 0x30 ... 0x4f: /* DMA error registers */
215 val = 0;
216 /* XXX: not implemented yet */
217 break;
95819af0
BS
218 case 0xc00 ... 0xc3f: /* PCI interrupt control */
219 if (addr & 4) {
220 val = s->pci_irq_map[(addr & 0x3f) >> 3];
221 } else {
222 val = 0;
223 }
224 break;
de739df8 225 case 0x1000 ... 0x107f: /* OBIO interrupt control */
361dea40
BS
226 if (addr & 4) {
227 val = s->obio_irq_map[(addr & 0xff) >> 3];
228 } else {
229 val = 0;
230 }
231 break;
de739df8
MCA
232 case 0x1080 ... 0x108f: /* PCI bus error */
233 if (addr & 4) {
234 val = s->pci_err_irq_map[(addr & 0xf) >> 3];
235 } else {
236 val = 0;
237 }
238 break;
95819af0
BS
239 case 0x2000 ... 0x202f: /* PCI control */
240 val = s->pci_control[(addr & 0x3f) >> 2];
241 break;
242 case 0xf020 ... 0xf027: /* Reset control */
243 if (addr & 4) {
244 val = s->reset_control;
245 } else {
246 val = 0;
247 }
248 break;
249 case 0x5000 ... 0x51cf: /* PIO/DMA diagnostics */
250 case 0xa400 ... 0xa67f: /* IOMMU diagnostics */
251 case 0xa800 ... 0xa80f: /* Interrupt diagnostics */
252 case 0xf000 ... 0xf01f: /* FFB config, memory control */
253 /* we don't care */
502a5395 254 default:
f930d07e
BS
255 val = 0;
256 break;
502a5395 257 }
c0907c9e 258 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, val);
95819af0 259
502a5395
PB
260 return val;
261}
262
3812ed0b
AK
263static const MemoryRegionOps apb_config_ops = {
264 .read = apb_config_readl,
265 .write = apb_config_writel,
b2f9005a 266 .endianness = DEVICE_BIG_ENDIAN,
502a5395
PB
267};
268
a8170e5e 269static void apb_pci_config_write(void *opaque, hwaddr addr,
3812ed0b 270 uint64_t val, unsigned size)
5a5d4a76 271{
3812ed0b 272 APBState *s = opaque;
2b8fbcd8 273 PCIHostState *phb = PCI_HOST_BRIDGE(s);
63e6f31d 274
c0907c9e 275 APB_DPRINTF("%s: addr " TARGET_FMT_plx " val %" PRIx64 "\n", __func__, addr, val);
2b8fbcd8 276 pci_data_write(phb->bus, addr, val, size);
5a5d4a76
BS
277}
278
a8170e5e 279static uint64_t apb_pci_config_read(void *opaque, hwaddr addr,
3812ed0b 280 unsigned size)
5a5d4a76
BS
281{
282 uint32_t ret;
3812ed0b 283 APBState *s = opaque;
2b8fbcd8 284 PCIHostState *phb = PCI_HOST_BRIDGE(s);
5a5d4a76 285
2b8fbcd8 286 ret = pci_data_read(phb->bus, addr, size);
c0907c9e 287 APB_DPRINTF("%s: addr " TARGET_FMT_plx " -> %x\n", __func__, addr, ret);
5a5d4a76
BS
288 return ret;
289}
290
80b3ada7 291/* The APB host has an IRQ line for each IRQ line of each slot. */
d2b59317 292static int pci_apb_map_irq(PCIDevice *pci_dev, int irq_num)
502a5395 293{
6864fa38
MCA
294 /* Return the irq as swizzled by the PBM */
295 return irq_num;
80b3ada7
PB
296}
297
d9e4d682 298static int pci_pbmA_map_irq(PCIDevice *pci_dev, int irq_num)
80b3ada7 299{
d9e4d682
MCA
300 /* The on-board devices have fixed (legacy) OBIO intnos */
301 switch (PCI_SLOT(pci_dev->devfn)) {
302 case 1:
303 /* Onboard NIC */
a5546222 304 return OBIO_NIC_IRQ;
d9e4d682
MCA
305 case 3:
306 /* Onboard IDE */
a5546222 307 return OBIO_HDD_IRQ;
d9e4d682
MCA
308 default:
309 /* Normal intno, fall through */
310 break;
311 }
6864fa38 312
d9e4d682
MCA
313 return ((PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
314}
6864fa38 315
d9e4d682
MCA
316static int pci_pbmB_map_irq(PCIDevice *pci_dev, int irq_num)
317{
318 return (0x10 + (PCI_SLOT(pci_dev->devfn) << 2) + irq_num) & 0x1f;
d2b59317
PB
319}
320
5d4e84c8 321static void pci_apb_set_irq(void *opaque, int irq_num, int level)
d2b59317 322{
95819af0 323 APBState *s = opaque;
5d4e84c8 324
9625036d 325 APB_DPRINTF("%s: set irq_in %d level %d\n", __func__, irq_num, level);
80b3ada7 326 /* PCI IRQ map onto the first 32 INO. */
95819af0 327 if (irq_num < 32) {
9625036d
AT
328 if (level) {
329 s->pci_irq_in |= 1ULL << irq_num;
330 if (s->pci_irq_map[irq_num >> 2] & PBM_PCI_IMR_ENABLED) {
331 pbm_set_request(s, irq_num);
332 }
361dea40 333 } else {
9625036d 334 s->pci_irq_in &= ~(1ULL << irq_num);
361dea40
BS
335 }
336 } else {
9625036d
AT
337 /* OBIO IRQ map onto the next 32 INO. */
338 if (level) {
361dea40 339 APB_DPRINTF("%s: set irq %d level %d\n", __func__, irq_num, level);
9625036d
AT
340 s->pci_irq_in |= 1ULL << irq_num;
341 if ((s->irq_request == NO_IRQ_REQUEST)
342 && (s->obio_irq_map[irq_num - 32] & PBM_PCI_IMR_ENABLED)) {
343 pbm_set_request(s, irq_num);
344 }
95819af0 345 } else {
9625036d 346 s->pci_irq_in &= ~(1ULL << irq_num);
95819af0
BS
347 }
348 }
502a5395
PB
349}
350
be0d9760 351static void apb_pci_bridge_realize(PCIDevice *dev, Error **errp)
d6318738 352{
d6318738
MT
353 /*
354 * command register:
355 * According to PCI bridge spec, after reset
356 * bus master bit is off
357 * memory space enable bit is off
358 * According to manual (805-1251.pdf).
359 * the reset value should be zero unless the boot pin is tied high
360 * (which is true) and thus it should be PCI_COMMAND_MEMORY.
361 */
e5fd1eb0
MCA
362 PBMPCIBridge *br = PBM_PCI_BRIDGE(dev);
363
364 pci_bridge_initfn(dev, TYPE_PCI_BUS);
365
33c5eb02 366 pci_set_word(dev->config + PCI_COMMAND, PCI_COMMAND_MEMORY);
9fe52c7f
BS
367 pci_set_word(dev->config + PCI_STATUS,
368 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
369 PCI_STATUS_DEVSEL_MEDIUM);
e5fd1eb0 370
6864fa38
MCA
371 /* Allow 32-bit IO addresses */
372 pci_set_word(dev->config + PCI_IO_BASE, PCI_IO_RANGE_TYPE_32);
373 pci_set_word(dev->config + PCI_IO_LIMIT, PCI_IO_RANGE_TYPE_32);
374 pci_set_word(dev->wmask + PCI_IO_BASE_UPPER16, 0xffff);
375 pci_set_word(dev->wmask + PCI_IO_LIMIT_UPPER16, 0xffff);
376
e5fd1eb0 377 pci_bridge_update_mappings(PCI_BRIDGE(br));
d6318738
MT
378}
379
cacd0580 380static void pci_pbm_reset(DeviceState *d)
502a5395 381{
cacd0580 382 APBState *s = APB_DEVICE(d);
33c5eb02
MCA
383 PCIDevice *pci_dev;
384 unsigned int i;
385 uint16_t cmd;
cacd0580
MCA
386
387 for (i = 0; i < 8; i++) {
388 s->pci_irq_map[i] &= PBM_PCI_IMR_MASK;
389 }
390 for (i = 0; i < 32; i++) {
391 s->obio_irq_map[i] &= PBM_PCI_IMR_MASK;
392 }
393
394 s->irq_request = NO_IRQ_REQUEST;
395 s->pci_irq_in = 0ULL;
396
397 if (s->nr_resets++ == 0) {
398 /* Power on reset */
399 s->reset_control = POR;
400 }
33c5eb02
MCA
401
402 /* As this is the busA PCI bridge which contains the on-board devices
403 * attached to the ebus, ensure that we initially allow IO transactions
404 * so that we get the early serial console until OpenBIOS can properly
405 * configure the PCI bridge itself */
406 pci_dev = PCI_DEVICE(s->bridgeA);
407 cmd = pci_get_word(pci_dev->config + PCI_COMMAND);
408 pci_set_word(pci_dev->config + PCI_COMMAND, cmd | PCI_COMMAND_IO);
409 pci_bridge_update_mappings(PCI_BRIDGE(pci_dev));
cacd0580
MCA
410}
411
412static const MemoryRegionOps pci_config_ops = {
413 .read = apb_pci_config_read,
414 .write = apb_pci_config_write,
415 .endianness = DEVICE_LITTLE_ENDIAN,
416};
417
418static void pci_pbm_realize(DeviceState *dev, Error **errp)
419{
420 APBState *s = APB_DEVICE(dev);
421 PCIHostState *phb = PCI_HOST_BRIDGE(dev);
422 SysBusDevice *sbd = SYS_BUS_DEVICE(s);
68f79994 423 PCIDevice *pci_dev;
502a5395 424
72f44c8c 425 /* apb_config */
cacd0580 426 sysbus_mmio_map(sbd, 0, s->special_base);
d63baf92 427 /* PCI configuration space */
cacd0580 428 sysbus_mmio_map(sbd, 1, s->special_base + 0x1000000ULL);
72f44c8c 429 /* pci_ioport */
cacd0580 430 sysbus_mmio_map(sbd, 2, s->special_base + 0x2000000ULL);
d63baf92 431
cacd0580
MCA
432 memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL);
433 memory_region_add_subregion(get_system_memory(), s->mem_base,
434 &s->pci_mmio);
435
436 phb->bus = pci_register_bus(dev, "pci",
437 pci_apb_set_irq, pci_apb_map_irq, s,
438 &s->pci_mmio,
439 &s->pci_ioport,
440 0, 32, TYPE_PCI_BUS);
f69539b1 441
2b8fbcd8 442 pci_create_simple(phb->bus, 0, "pbm-pci");
d63baf92 443
ea9a6606 444 /* APB IOMMU */
aea5b071
MCA
445 memory_region_add_subregion_overlap(&s->apb_config, 0x200,
446 sysbus_mmio_get_region(SYS_BUS_DEVICE(s->iommu), 0), 1);
447 pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, s->iommu);
ae74bbe7 448
72f44c8c 449 /* APB secondary busses */
2b8fbcd8 450 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 0), true,
e5fd1eb0 451 TYPE_PBM_PCI_BRIDGE);
cacd0580 452 s->bridgeB = PCI_BRIDGE(pci_dev);
d9e4d682 453 pci_bridge_map_irq(s->bridgeB, "pciB", pci_pbmB_map_irq);
68f79994 454 qdev_init_nofail(&pci_dev->qdev);
68f79994 455
2b8fbcd8 456 pci_dev = pci_create_multifunction(phb->bus, PCI_DEVFN(1, 1), true,
e5fd1eb0 457 TYPE_PBM_PCI_BRIDGE);
cacd0580 458 s->bridgeA = PCI_BRIDGE(pci_dev);
d9e4d682 459 pci_bridge_map_irq(s->bridgeA, "pciA", pci_pbmA_map_irq);
68f79994 460 qdev_init_nofail(&pci_dev->qdev);
95819af0
BS
461}
462
cacd0580 463static void pci_pbm_init(Object *obj)
95819af0 464{
cacd0580
MCA
465 APBState *s = APB_DEVICE(obj);
466 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
95819af0 467 unsigned int i;
72f44c8c 468
95819af0
BS
469 for (i = 0; i < 8; i++) {
470 s->pci_irq_map[i] = (0x1f << 6) | (i << 2);
471 }
de739df8
MCA
472 for (i = 0; i < 2; i++) {
473 s->pci_err_irq_map[i] = (0x1f << 6) | 0x30;
474 }
d1d80055
AT
475 for (i = 0; i < 32; i++) {
476 s->obio_irq_map[i] = ((0x1f << 6) | 0x20) + i;
477 }
4b10c8d7 478 qdev_init_gpio_in_named(DEVICE(s), pci_apb_set_irq, "pbm-irq", MAX_IVEC);
2a4d6af5 479 qdev_init_gpio_out_named(DEVICE(s), s->ivec_irqs, "ivec-irq", MAX_IVEC);
9625036d
AT
480 s->irq_request = NO_IRQ_REQUEST;
481 s->pci_irq_in = 0ULL;
95819af0 482
aea5b071
MCA
483 /* IOMMU */
484 object_property_add_link(obj, "iommu", TYPE_SUN4U_IOMMU,
485 (Object **) &s->iommu,
486 qdev_prop_allow_set_link_before_realize,
487 0, NULL);
488
72f44c8c 489 /* apb_config */
40c5dce9
PB
490 memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s,
491 "apb-config", 0x10000);
d63baf92 492 /* at region 0 */
b26f4419 493 sysbus_init_mmio(sbd, &s->apb_config);
d63baf92 494
40c5dce9
PB
495 memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s,
496 "apb-pci-config", 0x1000000);
d63baf92 497 /* at region 1 */
b26f4419 498 sysbus_init_mmio(sbd, &s->pci_config);
d63baf92
IK
499
500 /* pci_ioport */
6864fa38
MCA
501 memory_region_init(&s->pci_ioport, OBJECT(s), "apb-pci-ioport", 0x1000000);
502
d63baf92 503 /* at region 2 */
b26f4419 504 sysbus_init_mmio(sbd, &s->pci_ioport);
72f44c8c 505}
502a5395 506
9af21dbe 507static void pbm_pci_host_realize(PCIDevice *d, Error **errp)
72f44c8c 508{
9fe52c7f
BS
509 pci_set_word(d->config + PCI_COMMAND,
510 PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
511 pci_set_word(d->config + PCI_STATUS,
512 PCI_STATUS_FAST_BACK | PCI_STATUS_66MHZ |
513 PCI_STATUS_DEVSEL_MEDIUM);
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);
08c58f92 519 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08 520
9af21dbe 521 k->realize = pbm_pci_host_realize;
40021f08
AL
522 k->vendor_id = PCI_VENDOR_ID_SUN;
523 k->device_id = PCI_DEVICE_ID_SUN_SABRE;
524 k->class_id = PCI_CLASS_BRIDGE_HOST;
08c58f92
MA
525 /*
526 * PCI-facing part of the host bridge, not usable without the
527 * host-facing part, which can't be device_add'ed, yet.
528 */
e90f2a8c 529 dc->user_creatable = false;
40021f08
AL
530}
531
8c43a6f0 532static const TypeInfo pbm_pci_host_info = {
39bffca2
AL
533 .name = "pbm-pci",
534 .parent = TYPE_PCI_DEVICE,
535 .instance_size = sizeof(PCIDevice),
536 .class_init = pbm_pci_host_class_init,
fd3b02c8
EH
537 .interfaces = (InterfaceInfo[]) {
538 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
539 { },
540 },
72f44c8c
BS
541};
542
cacd0580
MCA
543static Property pbm_pci_host_properties[] = {
544 DEFINE_PROP_UINT64("special-base", APBState, special_base, 0),
545 DEFINE_PROP_UINT64("mem-base", APBState, mem_base, 0),
546 DEFINE_PROP_END_OF_LIST(),
547};
548
999e12bb
AL
549static void pbm_host_class_init(ObjectClass *klass, void *data)
550{
39bffca2 551 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb 552
cacd0580 553 dc->realize = pci_pbm_realize;
39bffca2 554 dc->reset = pci_pbm_reset;
cacd0580 555 dc->props = pbm_pci_host_properties;
b26f4419 556 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
999e12bb
AL
557}
558
8c43a6f0 559static const TypeInfo pbm_host_info = {
2b8fbcd8
PB
560 .name = TYPE_APB,
561 .parent = TYPE_PCI_HOST_BRIDGE,
39bffca2 562 .instance_size = sizeof(APBState),
cacd0580 563 .instance_init = pci_pbm_init,
39bffca2 564 .class_init = pbm_host_class_init,
95819af0 565};
68f79994 566
40021f08
AL
567static void pbm_pci_bridge_class_init(ObjectClass *klass, void *data)
568{
39bffca2 569 DeviceClass *dc = DEVICE_CLASS(klass);
40021f08
AL
570 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
571
be0d9760 572 k->realize = apb_pci_bridge_realize;
40021f08
AL
573 k->exit = pci_bridge_exitfn;
574 k->vendor_id = PCI_VENDOR_ID_SUN;
575 k->device_id = PCI_DEVICE_ID_SUN_SIMBA;
576 k->revision = 0x11;
577 k->config_write = pci_bridge_write_config;
578 k->is_bridge = 1;
125ee0ed 579 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
39bffca2
AL
580 dc->reset = pci_bridge_reset;
581 dc->vmsd = &vmstate_pci_device;
40021f08
AL
582}
583
8c43a6f0 584static const TypeInfo pbm_pci_bridge_info = {
e5fd1eb0 585 .name = TYPE_PBM_PCI_BRIDGE,
f055e96b 586 .parent = TYPE_PCI_BRIDGE,
39bffca2 587 .class_init = pbm_pci_bridge_class_init,
e5fd1eb0 588 .instance_size = sizeof(PBMPCIBridge),
fd3b02c8
EH
589 .interfaces = (InterfaceInfo[]) {
590 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
591 { },
592 },
68f79994
IY
593};
594
83f7d43a 595static void pbm_register_types(void)
72f44c8c 596{
39bffca2
AL
597 type_register_static(&pbm_host_info);
598 type_register_static(&pbm_pci_host_info);
599 type_register_static(&pbm_pci_bridge_info);
502a5395 600}
72f44c8c 601
83f7d43a 602type_init(pbm_register_types)