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