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