uninorth.c (18270B)
1/* 2 * QEMU Uninorth PCI host (for all Mac99 and newer machines) 3 * 4 * Copyright (c) 2006 Fabrice Bellard 5 * 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: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 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 22 * THE SOFTWARE. 23 */ 24 25#include "qemu/osdep.h" 26#include "hw/irq.h" 27#include "hw/ppc/mac.h" 28#include "hw/qdev-properties.h" 29#include "qemu/module.h" 30#include "hw/pci/pci.h" 31#include "hw/pci/pci_host.h" 32#include "hw/pci-host/uninorth.h" 33#include "trace.h" 34 35static int pci_unin_map_irq(PCIDevice *pci_dev, int irq_num) 36{ 37 return (irq_num + (pci_dev->devfn >> 3)) & 3; 38} 39 40static void pci_unin_set_irq(void *opaque, int irq_num, int level) 41{ 42 UNINHostState *s = opaque; 43 44 trace_unin_set_irq(irq_num, level); 45 qemu_set_irq(s->irqs[irq_num], level); 46} 47 48static uint32_t unin_get_config_reg(uint32_t reg, uint32_t addr) 49{ 50 uint32_t retval; 51 52 if (reg & (1u << 31)) { 53 /* XXX OpenBIOS compatibility hack */ 54 retval = reg | (addr & 3); 55 } else if (reg & 1) { 56 /* CFA1 style */ 57 retval = (reg & ~7u) | (addr & 7); 58 } else { 59 uint32_t slot, func; 60 61 /* Grab CFA0 style values */ 62 slot = ctz32(reg & 0xfffff800); 63 if (slot == 32) { 64 slot = -1; /* XXX: should this be 0? */ 65 } 66 func = PCI_FUNC(reg >> 8); 67 68 /* ... and then convert them to x86 format */ 69 /* config pointer */ 70 retval = (reg & (0xff - 7)) | (addr & 7); 71 /* slot, fn */ 72 retval |= PCI_DEVFN(slot, func) << 8; 73 } 74 75 trace_unin_get_config_reg(reg, addr, retval); 76 77 return retval; 78} 79 80static void unin_data_write(void *opaque, hwaddr addr, 81 uint64_t val, unsigned len) 82{ 83 UNINHostState *s = opaque; 84 PCIHostState *phb = PCI_HOST_BRIDGE(s); 85 trace_unin_data_write(addr, len, val); 86 pci_data_write(phb->bus, 87 unin_get_config_reg(phb->config_reg, addr), 88 val, len); 89} 90 91static uint64_t unin_data_read(void *opaque, hwaddr addr, 92 unsigned len) 93{ 94 UNINHostState *s = opaque; 95 PCIHostState *phb = PCI_HOST_BRIDGE(s); 96 uint32_t val; 97 98 val = pci_data_read(phb->bus, 99 unin_get_config_reg(phb->config_reg, addr), 100 len); 101 trace_unin_data_read(addr, len, val); 102 return val; 103} 104 105static const MemoryRegionOps unin_data_ops = { 106 .read = unin_data_read, 107 .write = unin_data_write, 108 .endianness = DEVICE_LITTLE_ENDIAN, 109}; 110 111static char *pci_unin_main_ofw_unit_address(const SysBusDevice *dev) 112{ 113 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev); 114 115 return g_strdup_printf("%x", s->ofw_addr); 116} 117 118static void pci_unin_main_realize(DeviceState *dev, Error **errp) 119{ 120 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(dev); 121 PCIHostState *h = PCI_HOST_BRIDGE(dev); 122 123 h->bus = pci_register_root_bus(dev, NULL, 124 pci_unin_set_irq, pci_unin_map_irq, 125 s, 126 &s->pci_mmio, 127 &s->pci_io, 128 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); 129 130 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-pci"); 131 132 /* DEC 21154 bridge */ 133#if 0 134 /* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */ 135 pci_create_simple(h->bus, PCI_DEVFN(12, 0), "dec-21154"); 136#endif 137} 138 139static void pci_unin_main_init(Object *obj) 140{ 141 UNINHostState *s = UNI_NORTH_PCI_HOST_BRIDGE(obj); 142 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 143 PCIHostState *h = PCI_HOST_BRIDGE(obj); 144 145 /* Use values found on a real PowerMac */ 146 /* Uninorth main bus */ 147 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, 148 obj, "unin-pci-conf-idx", 0x1000); 149 memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj, 150 "unin-pci-conf-data", 0x1000); 151 152 memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio", 153 0x100000000ULL); 154 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, 155 "unin-pci-isa-mmio", 0x00800000); 156 157 memory_region_init_alias(&s->pci_hole, OBJECT(s), 158 "unin-pci-hole", &s->pci_mmio, 159 0x80000000ULL, 0x10000000ULL); 160 161 sysbus_init_mmio(sbd, &h->conf_mem); 162 sysbus_init_mmio(sbd, &h->data_mem); 163 sysbus_init_mmio(sbd, &s->pci_hole); 164 sysbus_init_mmio(sbd, &s->pci_io); 165 166 qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); 167} 168 169static void pci_u3_agp_realize(DeviceState *dev, Error **errp) 170{ 171 UNINHostState *s = U3_AGP_HOST_BRIDGE(dev); 172 PCIHostState *h = PCI_HOST_BRIDGE(dev); 173 174 h->bus = pci_register_root_bus(dev, NULL, 175 pci_unin_set_irq, pci_unin_map_irq, 176 s, 177 &s->pci_mmio, 178 &s->pci_io, 179 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); 180 181 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "u3-agp"); 182} 183 184static void pci_u3_agp_init(Object *obj) 185{ 186 UNINHostState *s = U3_AGP_HOST_BRIDGE(obj); 187 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 188 PCIHostState *h = PCI_HOST_BRIDGE(obj); 189 190 /* Uninorth U3 AGP bus */ 191 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, 192 obj, "unin-pci-conf-idx", 0x1000); 193 memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, obj, 194 "unin-pci-conf-data", 0x1000); 195 196 memory_region_init(&s->pci_mmio, OBJECT(s), "unin-pci-mmio", 197 0x100000000ULL); 198 memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj, 199 "unin-pci-isa-mmio", 0x00800000); 200 201 memory_region_init_alias(&s->pci_hole, OBJECT(s), 202 "unin-pci-hole", &s->pci_mmio, 203 0x80000000ULL, 0x70000000ULL); 204 205 sysbus_init_mmio(sbd, &h->conf_mem); 206 sysbus_init_mmio(sbd, &h->data_mem); 207 sysbus_init_mmio(sbd, &s->pci_hole); 208 sysbus_init_mmio(sbd, &s->pci_io); 209 210 qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); 211} 212 213static void pci_unin_agp_realize(DeviceState *dev, Error **errp) 214{ 215 UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(dev); 216 PCIHostState *h = PCI_HOST_BRIDGE(dev); 217 218 h->bus = pci_register_root_bus(dev, NULL, 219 pci_unin_set_irq, pci_unin_map_irq, 220 s, 221 &s->pci_mmio, 222 &s->pci_io, 223 PCI_DEVFN(11, 0), 4, TYPE_PCI_BUS); 224 225 pci_create_simple(h->bus, PCI_DEVFN(11, 0), "uni-north-agp"); 226} 227 228static void pci_unin_agp_init(Object *obj) 229{ 230 UNINHostState *s = UNI_NORTH_AGP_HOST_BRIDGE(obj); 231 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 232 PCIHostState *h = PCI_HOST_BRIDGE(obj); 233 234 /* Uninorth AGP bus */ 235 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, 236 obj, "unin-agp-conf-idx", 0x1000); 237 memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, 238 obj, "unin-agp-conf-data", 0x1000); 239 240 sysbus_init_mmio(sbd, &h->conf_mem); 241 sysbus_init_mmio(sbd, &h->data_mem); 242 243 qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); 244} 245 246static void pci_unin_internal_realize(DeviceState *dev, Error **errp) 247{ 248 UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(dev); 249 PCIHostState *h = PCI_HOST_BRIDGE(dev); 250 251 h->bus = pci_register_root_bus(dev, NULL, 252 pci_unin_set_irq, pci_unin_map_irq, 253 s, 254 &s->pci_mmio, 255 &s->pci_io, 256 PCI_DEVFN(14, 0), 4, TYPE_PCI_BUS); 257 258 pci_create_simple(h->bus, PCI_DEVFN(14, 0), "uni-north-internal-pci"); 259} 260 261static void pci_unin_internal_init(Object *obj) 262{ 263 UNINHostState *s = UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE(obj); 264 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 265 PCIHostState *h = PCI_HOST_BRIDGE(obj); 266 267 /* Uninorth internal bus */ 268 memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, 269 obj, "unin-pci-conf-idx", 0x1000); 270 memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, 271 obj, "unin-pci-conf-data", 0x1000); 272 273 sysbus_init_mmio(sbd, &h->conf_mem); 274 sysbus_init_mmio(sbd, &h->data_mem); 275 276 qdev_init_gpio_out(DEVICE(obj), s->irqs, ARRAY_SIZE(s->irqs)); 277} 278 279static void unin_main_pci_host_realize(PCIDevice *d, Error **errp) 280{ 281 /* cache_line_size */ 282 d->config[0x0C] = 0x08; 283 /* latency_timer */ 284 d->config[0x0D] = 0x10; 285 /* capabilities_pointer */ 286 d->config[0x34] = 0x00; 287 288 /* 289 * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI 290 * memory space with base 0x80000000, size 0x10000000 for Apple's 291 * AppleMacRiscPCI driver 292 */ 293 d->config[0x48] = 0x0; 294 d->config[0x49] = 0x0; 295 d->config[0x4a] = 0x0; 296 d->config[0x4b] = 0x1; 297} 298 299static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp) 300{ 301 /* cache_line_size */ 302 d->config[0x0C] = 0x08; 303 /* latency_timer */ 304 d->config[0x0D] = 0x10; 305 /* capabilities_pointer 306 d->config[0x34] = 0x80; */ 307} 308 309static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp) 310{ 311 /* cache line size */ 312 d->config[0x0C] = 0x08; 313 /* latency timer */ 314 d->config[0x0D] = 0x10; 315} 316 317static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp) 318{ 319 /* cache_line_size */ 320 d->config[0x0C] = 0x08; 321 /* latency_timer */ 322 d->config[0x0D] = 0x10; 323 /* capabilities_pointer */ 324 d->config[0x34] = 0x00; 325} 326 327static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) 328{ 329 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 330 DeviceClass *dc = DEVICE_CLASS(klass); 331 332 k->realize = unin_main_pci_host_realize; 333 k->vendor_id = PCI_VENDOR_ID_APPLE; 334 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; 335 k->revision = 0x00; 336 k->class_id = PCI_CLASS_BRIDGE_HOST; 337 /* 338 * PCI-facing part of the host bridge, not usable without the 339 * host-facing part, which can't be device_add'ed, yet. 340 */ 341 dc->user_creatable = false; 342} 343 344static const TypeInfo unin_main_pci_host_info = { 345 .name = "uni-north-pci", 346 .parent = TYPE_PCI_DEVICE, 347 .instance_size = sizeof(PCIDevice), 348 .class_init = unin_main_pci_host_class_init, 349 .interfaces = (InterfaceInfo[]) { 350 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 351 { }, 352 }, 353}; 354 355static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) 356{ 357 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 358 DeviceClass *dc = DEVICE_CLASS(klass); 359 360 k->realize = u3_agp_pci_host_realize; 361 k->vendor_id = PCI_VENDOR_ID_APPLE; 362 k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; 363 k->revision = 0x00; 364 k->class_id = PCI_CLASS_BRIDGE_HOST; 365 /* 366 * PCI-facing part of the host bridge, not usable without the 367 * host-facing part, which can't be device_add'ed, yet. 368 */ 369 dc->user_creatable = false; 370} 371 372static const TypeInfo u3_agp_pci_host_info = { 373 .name = "u3-agp", 374 .parent = TYPE_PCI_DEVICE, 375 .instance_size = sizeof(PCIDevice), 376 .class_init = u3_agp_pci_host_class_init, 377 .interfaces = (InterfaceInfo[]) { 378 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 379 { }, 380 }, 381}; 382 383static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) 384{ 385 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 386 DeviceClass *dc = DEVICE_CLASS(klass); 387 388 k->realize = unin_agp_pci_host_realize; 389 k->vendor_id = PCI_VENDOR_ID_APPLE; 390 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; 391 k->revision = 0x00; 392 k->class_id = PCI_CLASS_BRIDGE_HOST; 393 /* 394 * PCI-facing part of the host bridge, not usable without the 395 * host-facing part, which can't be device_add'ed, yet. 396 */ 397 dc->user_creatable = false; 398} 399 400static const TypeInfo unin_agp_pci_host_info = { 401 .name = "uni-north-agp", 402 .parent = TYPE_PCI_DEVICE, 403 .instance_size = sizeof(PCIDevice), 404 .class_init = unin_agp_pci_host_class_init, 405 .interfaces = (InterfaceInfo[]) { 406 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 407 { }, 408 }, 409}; 410 411static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) 412{ 413 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 414 DeviceClass *dc = DEVICE_CLASS(klass); 415 416 k->realize = unin_internal_pci_host_realize; 417 k->vendor_id = PCI_VENDOR_ID_APPLE; 418 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; 419 k->revision = 0x00; 420 k->class_id = PCI_CLASS_BRIDGE_HOST; 421 /* 422 * PCI-facing part of the host bridge, not usable without the 423 * host-facing part, which can't be device_add'ed, yet. 424 */ 425 dc->user_creatable = false; 426} 427 428static const TypeInfo unin_internal_pci_host_info = { 429 .name = "uni-north-internal-pci", 430 .parent = TYPE_PCI_DEVICE, 431 .instance_size = sizeof(PCIDevice), 432 .class_init = unin_internal_pci_host_class_init, 433 .interfaces = (InterfaceInfo[]) { 434 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 435 { }, 436 }, 437}; 438 439static Property pci_unin_main_pci_host_props[] = { 440 DEFINE_PROP_UINT32("ofw-addr", UNINHostState, ofw_addr, -1), 441 DEFINE_PROP_END_OF_LIST() 442}; 443 444static void pci_unin_main_class_init(ObjectClass *klass, void *data) 445{ 446 DeviceClass *dc = DEVICE_CLASS(klass); 447 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 448 449 dc->realize = pci_unin_main_realize; 450 device_class_set_props(dc, pci_unin_main_pci_host_props); 451 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 452 dc->fw_name = "pci"; 453 sbc->explicit_ofw_unit_address = pci_unin_main_ofw_unit_address; 454} 455 456static const TypeInfo pci_unin_main_info = { 457 .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, 458 .parent = TYPE_PCI_HOST_BRIDGE, 459 .instance_size = sizeof(UNINHostState), 460 .instance_init = pci_unin_main_init, 461 .class_init = pci_unin_main_class_init, 462}; 463 464static void pci_u3_agp_class_init(ObjectClass *klass, void *data) 465{ 466 DeviceClass *dc = DEVICE_CLASS(klass); 467 468 dc->realize = pci_u3_agp_realize; 469 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 470} 471 472static const TypeInfo pci_u3_agp_info = { 473 .name = TYPE_U3_AGP_HOST_BRIDGE, 474 .parent = TYPE_PCI_HOST_BRIDGE, 475 .instance_size = sizeof(UNINHostState), 476 .instance_init = pci_u3_agp_init, 477 .class_init = pci_u3_agp_class_init, 478}; 479 480static void pci_unin_agp_class_init(ObjectClass *klass, void *data) 481{ 482 DeviceClass *dc = DEVICE_CLASS(klass); 483 484 dc->realize = pci_unin_agp_realize; 485 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 486} 487 488static const TypeInfo pci_unin_agp_info = { 489 .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, 490 .parent = TYPE_PCI_HOST_BRIDGE, 491 .instance_size = sizeof(UNINHostState), 492 .instance_init = pci_unin_agp_init, 493 .class_init = pci_unin_agp_class_init, 494}; 495 496static void pci_unin_internal_class_init(ObjectClass *klass, void *data) 497{ 498 DeviceClass *dc = DEVICE_CLASS(klass); 499 500 dc->realize = pci_unin_internal_realize; 501 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 502} 503 504static const TypeInfo pci_unin_internal_info = { 505 .name = TYPE_UNI_NORTH_INTERNAL_PCI_HOST_BRIDGE, 506 .parent = TYPE_PCI_HOST_BRIDGE, 507 .instance_size = sizeof(UNINHostState), 508 .instance_init = pci_unin_internal_init, 509 .class_init = pci_unin_internal_class_init, 510}; 511 512/* UniN device */ 513static void unin_write(void *opaque, hwaddr addr, uint64_t value, 514 unsigned size) 515{ 516 trace_unin_write(addr, value); 517} 518 519static uint64_t unin_read(void *opaque, hwaddr addr, unsigned size) 520{ 521 uint32_t value; 522 523 switch (addr) { 524 case 0: 525 value = UNINORTH_VERSION_10A; 526 break; 527 default: 528 value = 0; 529 } 530 531 trace_unin_read(addr, value); 532 533 return value; 534} 535 536static const MemoryRegionOps unin_ops = { 537 .read = unin_read, 538 .write = unin_write, 539 .endianness = DEVICE_BIG_ENDIAN, 540}; 541 542static void unin_init(Object *obj) 543{ 544 UNINState *s = UNI_NORTH(obj); 545 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 546 547 memory_region_init_io(&s->mem, obj, &unin_ops, s, "unin", 0x1000); 548 549 sysbus_init_mmio(sbd, &s->mem); 550} 551 552static void unin_class_init(ObjectClass *klass, void *data) 553{ 554 DeviceClass *dc = DEVICE_CLASS(klass); 555 556 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 557} 558 559static const TypeInfo unin_info = { 560 .name = TYPE_UNI_NORTH, 561 .parent = TYPE_SYS_BUS_DEVICE, 562 .instance_size = sizeof(UNINState), 563 .instance_init = unin_init, 564 .class_init = unin_class_init, 565}; 566 567static void unin_register_types(void) 568{ 569 type_register_static(&unin_main_pci_host_info); 570 type_register_static(&u3_agp_pci_host_info); 571 type_register_static(&unin_agp_pci_host_info); 572 type_register_static(&unin_internal_pci_host_info); 573 574 type_register_static(&pci_unin_main_info); 575 type_register_static(&pci_u3_agp_info); 576 type_register_static(&pci_unin_agp_info); 577 type_register_static(&pci_unin_internal_info); 578 579 type_register_static(&unin_info); 580} 581 582type_init(unin_register_types)