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