2 * QEMU Uninorth PCI host (for all Mac99 and newer machines)
4 * Copyright (c) 2006 Fabrice Bellard
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 #include "qemu/osdep.h"
26 #include "hw/ppc/mac.h"
27 #include "hw/pci/pci.h"
28 #include "hw/pci/pci_host.h"
29 #include "hw/pci-host/uninorth.h"
32 static const int unin_irq_line
[] = { 0x1b, 0x1c, 0x1d, 0x1e };
34 static int pci_unin_map_irq(PCIDevice
*pci_dev
, int irq_num
)
36 return (irq_num
+ (pci_dev
->devfn
>> 3)) & 3;
39 static void pci_unin_set_irq(void *opaque
, int irq_num
, int level
)
41 UNINHostState
*s
= opaque
;
43 trace_unin_set_irq(unin_irq_line
[irq_num
], level
);
44 qemu_set_irq(s
->irqs
[irq_num
], level
);
47 static uint32_t unin_get_config_reg(uint32_t reg
, uint32_t addr
)
51 if (reg
& (1u << 31)) {
52 /* XXX OpenBIOS compatibility hack */
53 retval
= reg
| (addr
& 3);
56 retval
= (reg
& ~7u) | (addr
& 7);
60 /* Grab CFA0 style values */
61 slot
= ctz32(reg
& 0xfffff800);
63 slot
= -1; /* XXX: should this be 0? */
65 func
= (reg
>> 8) & 7;
67 /* ... and then convert them to x86 format */
69 retval
= (reg
& (0xff - 7)) | (addr
& 7);
76 trace_unin_get_config_reg(reg
, addr
, retval
);
81 static void unin_data_write(void *opaque
, hwaddr addr
,
82 uint64_t val
, unsigned len
)
84 UNINHostState
*s
= opaque
;
85 PCIHostState
*phb
= PCI_HOST_BRIDGE(s
);
86 trace_unin_data_write(addr
, len
, val
);
87 pci_data_write(phb
->bus
,
88 unin_get_config_reg(phb
->config_reg
, addr
),
92 static uint64_t unin_data_read(void *opaque
, hwaddr addr
,
95 UNINHostState
*s
= opaque
;
96 PCIHostState
*phb
= PCI_HOST_BRIDGE(s
);
99 val
= pci_data_read(phb
->bus
,
100 unin_get_config_reg(phb
->config_reg
, addr
),
102 trace_unin_data_read(addr
, len
, val
);
106 static const MemoryRegionOps unin_data_ops
= {
107 .read
= unin_data_read
,
108 .write
= unin_data_write
,
109 .endianness
= DEVICE_LITTLE_ENDIAN
,
112 static void pci_unin_init_irqs(UNINHostState
*s
)
116 for (i
= 0; i
< ARRAY_SIZE(s
->irqs
); i
++) {
117 s
->irqs
[i
] = qdev_get_gpio_in(DEVICE(s
->pic
), unin_irq_line
[i
]);
121 static char *pci_unin_main_ofw_unit_address(const SysBusDevice
*dev
)
123 UNINHostState
*s
= UNI_NORTH_PCI_HOST_BRIDGE(dev
);
125 return g_strdup_printf("%x", s
->ofw_addr
);
128 static void pci_unin_main_realize(DeviceState
*dev
, Error
**errp
)
130 UNINHostState
*s
= UNI_NORTH_PCI_HOST_BRIDGE(dev
);
131 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
133 h
->bus
= pci_register_root_bus(dev
, NULL
,
134 pci_unin_set_irq
, pci_unin_map_irq
,
138 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS
);
140 pci_create_simple(h
->bus
, PCI_DEVFN(11, 0), "uni-north-pci");
141 pci_unin_init_irqs(s
);
143 /* DEC 21154 bridge */
145 /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
146 pci_create_simple(h
->bus
, PCI_DEVFN(12, 0), "dec-21154");
150 static void pci_unin_main_init(Object
*obj
)
152 UNINHostState
*s
= UNI_NORTH_PCI_HOST_BRIDGE(obj
);
153 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
154 PCIHostState
*h
= PCI_HOST_BRIDGE(obj
);
156 /* Use values found on a real PowerMac */
157 /* Uninorth main bus */
158 memory_region_init_io(&h
->conf_mem
, OBJECT(h
), &pci_host_conf_le_ops
,
159 obj
, "unin-pci-conf-idx", 0x1000);
160 memory_region_init_io(&h
->data_mem
, OBJECT(h
), &unin_data_ops
, obj
,
161 "unin-pci-conf-data", 0x1000);
163 memory_region_init(&s
->pci_mmio
, OBJECT(s
), "unin-pci-mmio",
165 memory_region_init_io(&s
->pci_io
, OBJECT(s
), &unassigned_io_ops
, obj
,
166 "unin-pci-isa-mmio", 0x00800000);
168 memory_region_init_alias(&s
->pci_hole
, OBJECT(s
),
169 "unin-pci-hole", &s
->pci_mmio
,
170 0x80000000ULL
, 0x10000000ULL
);
172 object_property_add_link(obj
, "pic", TYPE_OPENPIC
,
174 qdev_prop_allow_set_link_before_realize
,
177 sysbus_init_mmio(sbd
, &h
->conf_mem
);
178 sysbus_init_mmio(sbd
, &h
->data_mem
);
179 sysbus_init_mmio(sbd
, &s
->pci_hole
);
180 sysbus_init_mmio(sbd
, &s
->pci_io
);
183 static void pci_u3_agp_realize(DeviceState
*dev
, Error
**errp
)
185 UNINHostState
*s
= U3_AGP_HOST_BRIDGE(dev
);
186 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
188 h
->bus
= pci_register_root_bus(dev
, NULL
,
189 pci_unin_set_irq
, pci_unin_map_irq
,
193 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS
);
195 pci_create_simple(h
->bus
, PCI_DEVFN(11, 0), "u3-agp");
196 pci_unin_init_irqs(s
);
199 static void pci_u3_agp_init(Object
*obj
)
201 UNINHostState
*s
= U3_AGP_HOST_BRIDGE(obj
);
202 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
203 PCIHostState
*h
= PCI_HOST_BRIDGE(obj
);
205 /* Uninorth U3 AGP bus */
206 memory_region_init_io(&h
->conf_mem
, OBJECT(h
), &pci_host_conf_le_ops
,
207 obj
, "unin-pci-conf-idx", 0x1000);
208 memory_region_init_io(&h
->data_mem
, OBJECT(h
), &unin_data_ops
, obj
,
209 "unin-pci-conf-data", 0x1000);
211 memory_region_init(&s
->pci_mmio
, OBJECT(s
), "unin-pci-mmio",
213 memory_region_init_io(&s
->pci_io
, OBJECT(s
), &unassigned_io_ops
, obj
,
214 "unin-pci-isa-mmio", 0x00800000);
216 memory_region_init_alias(&s
->pci_hole
, OBJECT(s
),
217 "unin-pci-hole", &s
->pci_mmio
,
218 0x80000000ULL
, 0x70000000ULL
);
220 object_property_add_link(obj
, "pic", TYPE_OPENPIC
,
222 qdev_prop_allow_set_link_before_realize
,
225 sysbus_init_mmio(sbd
, &h
->conf_mem
);
226 sysbus_init_mmio(sbd
, &h
->data_mem
);
227 sysbus_init_mmio(sbd
, &s
->pci_hole
);
228 sysbus_init_mmio(sbd
, &s
->pci_io
);
231 static void pci_unin_agp_realize(DeviceState
*dev
, Error
**errp
)
233 UNINHostState
*s
= UNI_NORTH_AGP_HOST_BRIDGE(dev
);
234 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
236 h
->bus
= pci_register_root_bus(dev
, NULL
,
237 pci_unin_set_irq
, pci_unin_map_irq
,
241 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS
);
243 pci_create_simple(h
->bus
, PCI_DEVFN(11, 0), "uni-north-agp");
244 pci_unin_init_irqs(s
);
247 static void pci_unin_agp_init(Object
*obj
)
249 UNINHostState
*s
= UNI_NORTH_AGP_HOST_BRIDGE(obj
);
250 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
251 PCIHostState
*h
= PCI_HOST_BRIDGE(obj
);
253 /* Uninorth AGP bus */
254 memory_region_init_io(&h
->conf_mem
, OBJECT(h
), &pci_host_conf_le_ops
,
255 obj
, "unin-agp-conf-idx", 0x1000);
256 memory_region_init_io(&h
->data_mem
, OBJECT(h
), &pci_host_data_le_ops
,
257 obj
, "unin-agp-conf-data", 0x1000);
259 object_property_add_link(obj
, "pic", TYPE_OPENPIC
,
261 qdev_prop_allow_set_link_before_realize
,
264 sysbus_init_mmio(sbd
, &h
->conf_mem
);
265 sysbus_init_mmio(sbd
, &h
->data_mem
);
268 static void pci_unin_internal_realize(DeviceState
*dev
, Error
**errp
)
270 UNINHostState
*s
= UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(dev
);
271 PCIHostState
*h
= PCI_HOST_BRIDGE(dev
);
273 h
->bus
= pci_register_root_bus(dev
, NULL
,
274 pci_unin_set_irq
, pci_unin_map_irq
,
278 PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS
);
280 pci_create_simple(h
->bus
, PCI_DEVFN(14, 0), "uni-north-internal-pci");
281 pci_unin_init_irqs(s
);
284 static void pci_unin_internal_init(Object
*obj
)
286 UNINHostState
*s
= UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj
);
287 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
288 PCIHostState
*h
= PCI_HOST_BRIDGE(obj
);
290 /* Uninorth internal bus */
291 memory_region_init_io(&h
->conf_mem
, OBJECT(h
), &pci_host_conf_le_ops
,
292 obj
, "unin-pci-conf-idx", 0x1000);
293 memory_region_init_io(&h
->data_mem
, OBJECT(h
), &pci_host_data_le_ops
,
294 obj
, "unin-pci-conf-data", 0x1000);
296 object_property_add_link(obj
, "pic", TYPE_OPENPIC
,
298 qdev_prop_allow_set_link_before_realize
,
301 sysbus_init_mmio(sbd
, &h
->conf_mem
);
302 sysbus_init_mmio(sbd
, &h
->data_mem
);
305 static void unin_main_pci_host_realize(PCIDevice
*d
, Error
**errp
)
307 /* cache_line_size */
308 d
->config
[0x0C] = 0x08;
310 d
->config
[0x0D] = 0x10;
311 /* capabilities_pointer */
312 d
->config
[0x34] = 0x00;
315 * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI
316 * memory space with base 0x80000000, size 0x10000000 for Apple's
317 * AppleMacRiscPCI driver
319 d
->config
[0x48] = 0x0;
320 d
->config
[0x49] = 0x0;
321 d
->config
[0x4a] = 0x0;
322 d
->config
[0x4b] = 0x1;
325 static void unin_agp_pci_host_realize(PCIDevice
*d
, Error
**errp
)
327 /* cache_line_size */
328 d
->config
[0x0C] = 0x08;
330 d
->config
[0x0D] = 0x10;
331 /* capabilities_pointer
332 d->config[0x34] = 0x80; */
335 static void u3_agp_pci_host_realize(PCIDevice
*d
, Error
**errp
)
337 /* cache line size */
338 d
->config
[0x0C] = 0x08;
340 d
->config
[0x0D] = 0x10;
343 static void unin_internal_pci_host_realize(PCIDevice
*d
, Error
**errp
)
345 /* cache_line_size */
346 d
->config
[0x0C] = 0x08;
348 d
->config
[0x0D] = 0x10;
349 /* capabilities_pointer */
350 d
->config
[0x34] = 0x00;
353 static void unin_main_pci_host_class_init(ObjectClass
*klass
, void *data
)
355 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
356 DeviceClass
*dc
= DEVICE_CLASS(klass
);
358 k
->realize
= unin_main_pci_host_realize
;
359 k
->vendor_id
= PCI_VENDOR_ID_APPLE
;
360 k
->device_id
= PCI_DEVICE_ID_APPLE_UNI_N_PCI
;
362 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
364 * PCI-facing part of the host bridge, not usable without the
365 * host-facing part, which can't be device_add'ed, yet.
367 dc
->user_creatable
= false;
370 static const TypeInfo unin_main_pci_host_info
= {
371 .name
= "uni-north-pci",
372 .parent
= TYPE_PCI_DEVICE
,
373 .instance_size
= sizeof(PCIDevice
),
374 .class_init
= unin_main_pci_host_class_init
,
375 .interfaces
= (InterfaceInfo
[]) {
376 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
381 static void u3_agp_pci_host_class_init(ObjectClass
*klass
, void *data
)
383 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
384 DeviceClass
*dc
= DEVICE_CLASS(klass
);
386 k
->realize
= u3_agp_pci_host_realize
;
387 k
->vendor_id
= PCI_VENDOR_ID_APPLE
;
388 k
->device_id
= PCI_DEVICE_ID_APPLE_U3_AGP
;
390 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
392 * PCI-facing part of the host bridge, not usable without the
393 * host-facing part, which can't be device_add'ed, yet.
395 dc
->user_creatable
= false;
398 static const TypeInfo u3_agp_pci_host_info
= {
400 .parent
= TYPE_PCI_DEVICE
,
401 .instance_size
= sizeof(PCIDevice
),
402 .class_init
= u3_agp_pci_host_class_init
,
403 .interfaces
= (InterfaceInfo
[]) {
404 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
409 static void unin_agp_pci_host_class_init(ObjectClass
*klass
, void *data
)
411 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
412 DeviceClass
*dc
= DEVICE_CLASS(klass
);
414 k
->realize
= unin_agp_pci_host_realize
;
415 k
->vendor_id
= PCI_VENDOR_ID_APPLE
;
416 k
->device_id
= PCI_DEVICE_ID_APPLE_UNI_N_AGP
;
418 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
420 * PCI-facing part of the host bridge, not usable without the
421 * host-facing part, which can't be device_add'ed, yet.
423 dc
->user_creatable
= false;
426 static const TypeInfo unin_agp_pci_host_info
= {
427 .name
= "uni-north-agp",
428 .parent
= TYPE_PCI_DEVICE
,
429 .instance_size
= sizeof(PCIDevice
),
430 .class_init
= unin_agp_pci_host_class_init
,
431 .interfaces
= (InterfaceInfo
[]) {
432 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
437 static void unin_internal_pci_host_class_init(ObjectClass
*klass
, void *data
)
439 PCIDeviceClass
*k
= PCI_DEVICE_CLASS(klass
);
440 DeviceClass
*dc
= DEVICE_CLASS(klass
);
442 k
->realize
= unin_internal_pci_host_realize
;
443 k
->vendor_id
= PCI_VENDOR_ID_APPLE
;
444 k
->device_id
= PCI_DEVICE_ID_APPLE_UNI_N_I_PCI
;
446 k
->class_id
= PCI_CLASS_BRIDGE_HOST
;
448 * PCI-facing part of the host bridge, not usable without the
449 * host-facing part, which can't be device_add'ed, yet.
451 dc
->user_creatable
= false;
454 static const TypeInfo unin_internal_pci_host_info
= {
455 .name
= "uni-north-internal-pci",
456 .parent
= TYPE_PCI_DEVICE
,
457 .instance_size
= sizeof(PCIDevice
),
458 .class_init
= unin_internal_pci_host_class_init
,
459 .interfaces
= (InterfaceInfo
[]) {
460 { INTERFACE_CONVENTIONAL_PCI_DEVICE
},
465 static Property pci_unin_main_pci_host_props
[] = {
466 DEFINE_PROP_UINT32("ofw-addr", UNINHostState
, ofw_addr
, -1),
467 DEFINE_PROP_END_OF_LIST()
470 static void pci_unin_main_class_init(ObjectClass
*klass
, void *data
)
472 DeviceClass
*dc
= DEVICE_CLASS(klass
);
473 SysBusDeviceClass
*sbc
= SYS_BUS_DEVICE_CLASS(klass
);
475 dc
->realize
= pci_unin_main_realize
;
476 dc
->props
= pci_unin_main_pci_host_props
;
477 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
479 sbc
->explicit_ofw_unit_address
= pci_unin_main_ofw_unit_address
;
482 static const TypeInfo pci_unin_main_info
= {
483 .name
= TYPE_UNI_NORTH_PCI_HOST_BRIDGE
,
484 .parent
= TYPE_PCI_HOST_BRIDGE
,
485 .instance_size
= sizeof(UNINHostState
),
486 .instance_init
= pci_unin_main_init
,
487 .class_init
= pci_unin_main_class_init
,
490 static void pci_u3_agp_class_init(ObjectClass
*klass
, void *data
)
492 DeviceClass
*dc
= DEVICE_CLASS(klass
);
494 dc
->realize
= pci_u3_agp_realize
;
495 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
498 static const TypeInfo pci_u3_agp_info
= {
499 .name
= TYPE_U3_AGP_HOST_BRIDGE
,
500 .parent
= TYPE_PCI_HOST_BRIDGE
,
501 .instance_size
= sizeof(UNINHostState
),
502 .instance_init
= pci_u3_agp_init
,
503 .class_init
= pci_u3_agp_class_init
,
506 static void pci_unin_agp_class_init(ObjectClass
*klass
, void *data
)
508 DeviceClass
*dc
= DEVICE_CLASS(klass
);
510 dc
->realize
= pci_unin_agp_realize
;
511 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
514 static const TypeInfo pci_unin_agp_info
= {
515 .name
= TYPE_UNI_NORTH_AGP_HOST_BRIDGE
,
516 .parent
= TYPE_PCI_HOST_BRIDGE
,
517 .instance_size
= sizeof(UNINHostState
),
518 .instance_init
= pci_unin_agp_init
,
519 .class_init
= pci_unin_agp_class_init
,
522 static void pci_unin_internal_class_init(ObjectClass
*klass
, void *data
)
524 DeviceClass
*dc
= DEVICE_CLASS(klass
);
526 dc
->realize
= pci_unin_internal_realize
;
527 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
530 static const TypeInfo pci_unin_internal_info
= {
531 .name
= TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE
,
532 .parent
= TYPE_PCI_HOST_BRIDGE
,
533 .instance_size
= sizeof(UNINHostState
),
534 .instance_init
= pci_unin_internal_init
,
535 .class_init
= pci_unin_internal_class_init
,
539 static void unin_write(void *opaque
, hwaddr addr
, uint64_t value
,
542 trace_unin_write(addr
, value
);
545 static uint64_t unin_read(void *opaque
, hwaddr addr
, unsigned size
)
551 value
= UNINORTH_VERSION_10A
;
557 trace_unin_read(addr
, value
);
562 static const MemoryRegionOps unin_ops
= {
565 .endianness
= DEVICE_BIG_ENDIAN
,
568 static void unin_init(Object
*obj
)
570 UNINState
*s
= UNI_NORTH(obj
);
571 SysBusDevice
*sbd
= SYS_BUS_DEVICE(obj
);
573 memory_region_init_io(&s
->mem
, obj
, &unin_ops
, s
, "unin", 0x1000);
575 sysbus_init_mmio(sbd
, &s
->mem
);
578 static void unin_class_init(ObjectClass
*klass
, void *data
)
580 DeviceClass
*dc
= DEVICE_CLASS(klass
);
582 set_bit(DEVICE_CATEGORY_BRIDGE
, dc
->categories
);
585 static const TypeInfo unin_info
= {
586 .name
= TYPE_UNI_NORTH
,
587 .parent
= TYPE_SYS_BUS_DEVICE
,
588 .instance_size
= sizeof(UNINState
),
589 .instance_init
= unin_init
,
590 .class_init
= unin_class_init
,
593 static void unin_register_types(void)
595 type_register_static(&unin_main_pci_host_info
);
596 type_register_static(&u3_agp_pci_host_info
);
597 type_register_static(&unin_agp_pci_host_info
);
598 type_register_static(&unin_internal_pci_host_info
);
600 type_register_static(&pci_unin_main_info
);
601 type_register_static(&pci_u3_agp_info
);
602 type_register_static(&pci_unin_agp_info
);
603 type_register_static(&pci_unin_internal_info
);
605 type_register_static(&unin_info
);
608 type_init(unin_register_types
)