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