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