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 336 static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp) 337 { 338 /* cache line size */ 339 d->config[0x0C] = 0x08; 340 /* latency timer */ 341 d->config[0x0D] = 0x10; 342 } 343 344 static void unin_internal_pci_host_realize(PCIDevice *d, Error **errp) 345 { 346 d->config[0x0C] = 0x08; // cache_line_size 347 d->config[0x0D] = 0x10; // latency_timer 348 d->config[0x34] = 0x00; // capabilities_pointer 349 } 350 351 static void unin_main_pci_host_class_init(ObjectClass *klass, void *data) 352 { 353 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 354 DeviceClass *dc = DEVICE_CLASS(klass); 355 356 k->realize = unin_main_pci_host_realize; 357 k->vendor_id = PCI_VENDOR_ID_APPLE; 358 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_PCI; 359 k->revision = 0x00; 360 k->class_id = PCI_CLASS_BRIDGE_HOST; 361 /* 362 * PCI-facing part of the host bridge, not usable without the 363 * host-facing part, which can't be device_add'ed, yet. 364 */ 365 dc->cannot_instantiate_with_device_add_yet = true; 366 } 367 368 static const TypeInfo unin_main_pci_host_info = { 369 .name = "uni-north-pci", 370 .parent = TYPE_PCI_DEVICE, 371 .instance_size = sizeof(PCIDevice), 372 .class_init = unin_main_pci_host_class_init, 373 }; 374 375 static void u3_agp_pci_host_class_init(ObjectClass *klass, void *data) 376 { 377 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 378 DeviceClass *dc = DEVICE_CLASS(klass); 379 380 k->realize = u3_agp_pci_host_realize; 381 k->vendor_id = PCI_VENDOR_ID_APPLE; 382 k->device_id = PCI_DEVICE_ID_APPLE_U3_AGP; 383 k->revision = 0x00; 384 k->class_id = PCI_CLASS_BRIDGE_HOST; 385 /* 386 * PCI-facing part of the host bridge, not usable without the 387 * host-facing part, which can't be device_add'ed, yet. 388 */ 389 dc->cannot_instantiate_with_device_add_yet = true; 390 } 391 392 static const TypeInfo u3_agp_pci_host_info = { 393 .name = "u3-agp", 394 .parent = TYPE_PCI_DEVICE, 395 .instance_size = sizeof(PCIDevice), 396 .class_init = u3_agp_pci_host_class_init, 397 }; 398 399 static void unin_agp_pci_host_class_init(ObjectClass *klass, void *data) 400 { 401 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 402 DeviceClass *dc = DEVICE_CLASS(klass); 403 404 k->realize = unin_agp_pci_host_realize; 405 k->vendor_id = PCI_VENDOR_ID_APPLE; 406 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP; 407 k->revision = 0x00; 408 k->class_id = PCI_CLASS_BRIDGE_HOST; 409 /* 410 * PCI-facing part of the host bridge, not usable without the 411 * host-facing part, which can't be device_add'ed, yet. 412 */ 413 dc->cannot_instantiate_with_device_add_yet = true; 414 } 415 416 static const TypeInfo unin_agp_pci_host_info = { 417 .name = "uni-north-agp", 418 .parent = TYPE_PCI_DEVICE, 419 .instance_size = sizeof(PCIDevice), 420 .class_init = unin_agp_pci_host_class_init, 421 }; 422 423 static void unin_internal_pci_host_class_init(ObjectClass *klass, void *data) 424 { 425 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 426 DeviceClass *dc = DEVICE_CLASS(klass); 427 428 k->realize = unin_internal_pci_host_realize; 429 k->vendor_id = PCI_VENDOR_ID_APPLE; 430 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_I_PCI; 431 k->revision = 0x00; 432 k->class_id = PCI_CLASS_BRIDGE_HOST; 433 /* 434 * PCI-facing part of the host bridge, not usable without the 435 * host-facing part, which can't be device_add'ed, yet. 436 */ 437 dc->cannot_instantiate_with_device_add_yet = true; 438 } 439 440 static const TypeInfo unin_internal_pci_host_info = { 441 .name = "uni-north-internal-pci", 442 .parent = TYPE_PCI_DEVICE, 443 .instance_size = sizeof(PCIDevice), 444 .class_init = unin_internal_pci_host_class_init, 445 }; 446 447 static void pci_unin_main_class_init(ObjectClass *klass, void *data) 448 { 449 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 450 DeviceClass *dc = DEVICE_CLASS(klass); 451 452 sbc->init = pci_unin_main_init_device; 453 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 454 } 455 456 static const TypeInfo pci_unin_main_info = { 457 .name = TYPE_UNI_NORTH_PCI_HOST_BRIDGE, 458 .parent = TYPE_PCI_HOST_BRIDGE, 459 .instance_size = sizeof(UNINState), 460 .class_init = pci_unin_main_class_init, 461 }; 462 463 static void pci_u3_agp_class_init(ObjectClass *klass, void *data) 464 { 465 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 466 DeviceClass *dc = DEVICE_CLASS(klass); 467 468 sbc->init = pci_u3_agp_init_device; 469 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 470 } 471 472 static const TypeInfo pci_u3_agp_info = { 473 .name = TYPE_U3_AGP_HOST_BRIDGE, 474 .parent = TYPE_PCI_HOST_BRIDGE, 475 .instance_size = sizeof(UNINState), 476 .class_init = pci_u3_agp_class_init, 477 }; 478 479 static void pci_unin_agp_class_init(ObjectClass *klass, void *data) 480 { 481 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 482 DeviceClass *dc = DEVICE_CLASS(klass); 483 484 sbc->init = pci_unin_agp_init_device; 485 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 486 } 487 488 static const TypeInfo pci_unin_agp_info = { 489 .name = TYPE_UNI_NORTH_AGP_HOST_BRIDGE, 490 .parent = TYPE_PCI_HOST_BRIDGE, 491 .instance_size = sizeof(UNINState), 492 .class_init = pci_unin_agp_class_init, 493 }; 494 495 static void pci_unin_internal_class_init(ObjectClass *klass, void *data) 496 { 497 SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass); 498 DeviceClass *dc = DEVICE_CLASS(klass); 499 500 sbc->init = pci_unin_internal_init_device; 501 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 502 } 503 504 static 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(UNINState), 508 .class_init = pci_unin_internal_class_init, 509 }; 510 511 static void unin_register_types(void) 512 { 513 type_register_static(&unin_main_pci_host_info); 514 type_register_static(&u3_agp_pci_host_info); 515 type_register_static(&unin_agp_pci_host_info); 516 type_register_static(&unin_internal_pci_host_info); 517 518 type_register_static(&pci_unin_main_info); 519 type_register_static(&pci_u3_agp_info); 520 type_register_static(&pci_unin_agp_info); 521 type_register_static(&pci_unin_internal_info); 522 } 523 524 type_init(unin_register_types) 525