1 /* 2 * PowerMac MacIO device emulation 3 * 4 * Copyright (c) 2005-2007 Fabrice Bellard 5 * Copyright (c) 2007 Jocelyn Mayer 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 #include "qemu/osdep.h" 26 #include "qapi/error.h" 27 #include "hw/hw.h" 28 #include "hw/ppc/mac.h" 29 #include "hw/misc/macio/cuda.h" 30 #include "hw/pci/pci.h" 31 #include "hw/ppc/mac_dbdma.h" 32 #include "hw/char/escc.h" 33 34 #define TYPE_MACIO "macio" 35 #define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO) 36 37 typedef struct MacIOState 38 { 39 /*< private >*/ 40 PCIDevice parent; 41 /*< public >*/ 42 43 MemoryRegion bar; 44 CUDAState cuda; 45 DBDMAState dbdma; 46 ESCCState escc; 47 MemoryRegion *pic_mem; 48 uint64_t frequency; 49 } MacIOState; 50 51 #define OLDWORLD_MACIO(obj) \ 52 OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO) 53 54 typedef struct OldWorldMacIOState { 55 /*< private >*/ 56 MacIOState parent_obj; 57 /*< public >*/ 58 59 qemu_irq irqs[7]; 60 61 MacIONVRAMState nvram; 62 MACIOIDEState ide[2]; 63 } OldWorldMacIOState; 64 65 #define NEWWORLD_MACIO(obj) \ 66 OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO) 67 68 typedef struct NewWorldMacIOState { 69 /*< private >*/ 70 MacIOState parent_obj; 71 /*< public >*/ 72 qemu_irq irqs[7]; 73 MACIOIDEState ide[2]; 74 } NewWorldMacIOState; 75 76 /* 77 * The mac-io has two interfaces to the ESCC. One is called "escc-legacy", 78 * while the other one is the normal, current ESCC interface. 79 * 80 * The magic below creates memory aliases to spawn the escc-legacy device 81 * purely by rerouting the respective registers to our escc region. This 82 * works because the only difference between the two memory regions is the 83 * register layout, not their semantics. 84 * 85 * Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf 86 */ 87 static void macio_escc_legacy_setup(MacIOState *s) 88 { 89 ESCCState *escc = ESCC(&s->escc); 90 SysBusDevice *sbd = SYS_BUS_DEVICE(escc); 91 MemoryRegion *escc_legacy = g_new(MemoryRegion, 1); 92 MemoryRegion *bar = &s->bar; 93 int i; 94 static const int maps[] = { 95 0x00, 0x00, /* Command B */ 96 0x02, 0x20, /* Command A */ 97 0x04, 0x10, /* Data B */ 98 0x06, 0x30, /* Data A */ 99 0x08, 0x40, /* Enhancement B */ 100 0x0A, 0x50, /* Enhancement A */ 101 0x80, 0x80, /* Recovery count */ 102 0x90, 0x90, /* Start A */ 103 0xa0, 0xa0, /* Start B */ 104 0xb0, 0xb0, /* Detect AB */ 105 }; 106 107 memory_region_init(escc_legacy, OBJECT(s), "escc-legacy", 256); 108 for (i = 0; i < ARRAY_SIZE(maps); i += 2) { 109 MemoryRegion *port = g_new(MemoryRegion, 1); 110 memory_region_init_alias(port, OBJECT(s), "escc-legacy-port", 111 sysbus_mmio_get_region(sbd, 0), 112 maps[i + 1], 0x2); 113 memory_region_add_subregion(escc_legacy, maps[i], port); 114 } 115 116 memory_region_add_subregion(bar, 0x12000, escc_legacy); 117 } 118 119 static void macio_bar_setup(MacIOState *s) 120 { 121 ESCCState *escc = ESCC(&s->escc); 122 SysBusDevice *sbd = SYS_BUS_DEVICE(escc); 123 MemoryRegion *bar = &s->bar; 124 125 memory_region_add_subregion(bar, 0x13000, sysbus_mmio_get_region(sbd, 0)); 126 macio_escc_legacy_setup(s); 127 } 128 129 static void macio_common_realize(PCIDevice *d, Error **errp) 130 { 131 MacIOState *s = MACIO(d); 132 SysBusDevice *sysbus_dev; 133 Error *err = NULL; 134 135 object_property_set_bool(OBJECT(&s->dbdma), true, "realized", &err); 136 if (err) { 137 error_propagate(errp, err); 138 return; 139 } 140 sysbus_dev = SYS_BUS_DEVICE(&s->dbdma); 141 memory_region_add_subregion(&s->bar, 0x08000, 142 sysbus_mmio_get_region(sysbus_dev, 0)); 143 144 object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err); 145 if (err) { 146 error_propagate(errp, err); 147 return; 148 } 149 sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 150 memory_region_add_subregion(&s->bar, 0x16000, 151 sysbus_mmio_get_region(sysbus_dev, 0)); 152 153 object_property_set_bool(OBJECT(&s->escc), true, "realized", &err); 154 if (err) { 155 error_propagate(errp, err); 156 return; 157 } 158 159 macio_bar_setup(s); 160 pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar); 161 } 162 163 static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide, 164 qemu_irq irq0, qemu_irq irq1, int dmaid, 165 Error **errp) 166 { 167 SysBusDevice *sysbus_dev; 168 169 sysbus_dev = SYS_BUS_DEVICE(ide); 170 sysbus_connect_irq(sysbus_dev, 0, irq0); 171 sysbus_connect_irq(sysbus_dev, 1, irq1); 172 qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid); 173 object_property_set_link(OBJECT(ide), OBJECT(&s->dbdma), "dbdma", errp); 174 macio_ide_register_dma(ide); 175 176 object_property_set_bool(OBJECT(ide), true, "realized", errp); 177 } 178 179 static void macio_oldworld_realize(PCIDevice *d, Error **errp) 180 { 181 MacIOState *s = MACIO(d); 182 OldWorldMacIOState *os = OLDWORLD_MACIO(d); 183 Error *err = NULL; 184 SysBusDevice *sysbus_dev; 185 int i; 186 int cur_irq = 0; 187 188 macio_common_realize(d, &err); 189 if (err) { 190 error_propagate(errp, err); 191 return; 192 } 193 194 sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 195 sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); 196 197 sysbus_dev = SYS_BUS_DEVICE(&s->escc); 198 sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); 199 sysbus_connect_irq(sysbus_dev, 1, os->irqs[cur_irq++]); 200 201 object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err); 202 if (err) { 203 error_propagate(errp, err); 204 return; 205 } 206 sysbus_dev = SYS_BUS_DEVICE(&os->nvram); 207 memory_region_add_subregion(&s->bar, 0x60000, 208 sysbus_mmio_get_region(sysbus_dev, 0)); 209 pmac_format_nvram_partition(&os->nvram, os->nvram.size); 210 211 if (s->pic_mem) { 212 /* Heathrow PIC */ 213 memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); 214 } 215 216 /* IDE buses */ 217 for (i = 0; i < ARRAY_SIZE(os->ide); i++) { 218 qemu_irq irq0 = os->irqs[cur_irq++]; 219 qemu_irq irq1 = os->irqs[cur_irq++]; 220 221 macio_realize_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4), &err); 222 if (err) { 223 error_propagate(errp, err); 224 return; 225 } 226 } 227 } 228 229 static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, size_t ide_size, 230 int index) 231 { 232 gchar *name; 233 234 object_initialize(ide, ide_size, TYPE_MACIO_IDE); 235 qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); 236 memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), 237 &ide->mem); 238 name = g_strdup_printf("ide[%i]", index); 239 object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL); 240 g_free(name); 241 } 242 243 static void macio_oldworld_init(Object *obj) 244 { 245 MacIOState *s = MACIO(obj); 246 OldWorldMacIOState *os = OLDWORLD_MACIO(obj); 247 DeviceState *dev; 248 int i; 249 250 qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); 251 252 object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM); 253 dev = DEVICE(&os->nvram); 254 qdev_prop_set_uint32(dev, "size", 0x2000); 255 qdev_prop_set_uint32(dev, "it_shift", 4); 256 257 for (i = 0; i < 2; i++) { 258 macio_init_ide(s, &os->ide[i], sizeof(os->ide[i]), i); 259 } 260 } 261 262 static void timer_write(void *opaque, hwaddr addr, uint64_t value, 263 unsigned size) 264 { 265 } 266 267 static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) 268 { 269 uint32_t value = 0; 270 uint64_t systime = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); 271 uint64_t kltime; 272 273 kltime = muldiv64(systime, 4194300, NANOSECONDS_PER_SECOND * 4); 274 kltime = muldiv64(kltime, 18432000, 1048575); 275 276 switch (addr) { 277 case 0x38: 278 value = kltime; 279 break; 280 case 0x3c: 281 value = kltime >> 32; 282 break; 283 } 284 285 return value; 286 } 287 288 static const MemoryRegionOps timer_ops = { 289 .read = timer_read, 290 .write = timer_write, 291 .endianness = DEVICE_LITTLE_ENDIAN, 292 }; 293 294 static void macio_newworld_realize(PCIDevice *d, Error **errp) 295 { 296 MacIOState *s = MACIO(d); 297 NewWorldMacIOState *ns = NEWWORLD_MACIO(d); 298 Error *err = NULL; 299 SysBusDevice *sysbus_dev; 300 MemoryRegion *timer_memory = NULL; 301 int i; 302 int cur_irq = 0; 303 304 macio_common_realize(d, &err); 305 if (err) { 306 error_propagate(errp, err); 307 return; 308 } 309 310 sysbus_dev = SYS_BUS_DEVICE(&s->cuda); 311 sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); 312 313 sysbus_dev = SYS_BUS_DEVICE(&s->escc); 314 sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); 315 sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]); 316 317 if (s->pic_mem) { 318 /* OpenPIC */ 319 memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); 320 } 321 322 /* IDE buses */ 323 for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { 324 qemu_irq irq0 = ns->irqs[cur_irq++]; 325 qemu_irq irq1 = ns->irqs[cur_irq++]; 326 327 macio_realize_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4), &err); 328 if (err) { 329 error_propagate(errp, err); 330 return; 331 } 332 } 333 334 /* Timer */ 335 timer_memory = g_new(MemoryRegion, 1); 336 memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", 337 0x1000); 338 memory_region_add_subregion(&s->bar, 0x15000, timer_memory); 339 } 340 341 static void macio_newworld_init(Object *obj) 342 { 343 MacIOState *s = MACIO(obj); 344 NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); 345 int i; 346 347 qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); 348 349 for (i = 0; i < 2; i++) { 350 macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i); 351 } 352 } 353 354 static void macio_instance_init(Object *obj) 355 { 356 MacIOState *s = MACIO(obj); 357 358 memory_region_init(&s->bar, obj, "macio", 0x80000); 359 360 object_initialize(&s->cuda, sizeof(s->cuda), TYPE_CUDA); 361 qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); 362 object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL); 363 364 object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA); 365 qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default()); 366 object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL); 367 368 object_initialize(&s->escc, sizeof(s->escc), TYPE_ESCC); 369 qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0); 370 qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK); 371 qdev_prop_set_uint32(DEVICE(&s->escc), "it_shift", 4); 372 qdev_prop_set_chr(DEVICE(&s->escc), "chrA", serial_hds[0]); 373 qdev_prop_set_chr(DEVICE(&s->escc), "chrB", serial_hds[1]); 374 qdev_prop_set_uint32(DEVICE(&s->escc), "chnBtype", escc_serial); 375 qdev_prop_set_uint32(DEVICE(&s->escc), "chnAtype", escc_serial); 376 qdev_set_parent_bus(DEVICE(&s->escc), sysbus_get_default()); 377 object_property_add_child(obj, "escc", OBJECT(&s->escc), NULL); 378 } 379 380 static const VMStateDescription vmstate_macio_oldworld = { 381 .name = "macio-oldworld", 382 .version_id = 0, 383 .minimum_version_id = 0, 384 .fields = (VMStateField[]) { 385 VMSTATE_PCI_DEVICE(parent_obj.parent, OldWorldMacIOState), 386 VMSTATE_END_OF_LIST() 387 } 388 }; 389 390 static void macio_oldworld_class_init(ObjectClass *oc, void *data) 391 { 392 PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); 393 DeviceClass *dc = DEVICE_CLASS(oc); 394 395 pdc->realize = macio_oldworld_realize; 396 pdc->device_id = PCI_DEVICE_ID_APPLE_343S1201; 397 dc->vmsd = &vmstate_macio_oldworld; 398 } 399 400 static const VMStateDescription vmstate_macio_newworld = { 401 .name = "macio-newworld", 402 .version_id = 0, 403 .minimum_version_id = 0, 404 .fields = (VMStateField[]) { 405 VMSTATE_PCI_DEVICE(parent_obj.parent, NewWorldMacIOState), 406 VMSTATE_END_OF_LIST() 407 } 408 }; 409 410 static void macio_newworld_class_init(ObjectClass *oc, void *data) 411 { 412 PCIDeviceClass *pdc = PCI_DEVICE_CLASS(oc); 413 DeviceClass *dc = DEVICE_CLASS(oc); 414 415 pdc->realize = macio_newworld_realize; 416 pdc->device_id = PCI_DEVICE_ID_APPLE_UNI_N_KEYL; 417 dc->vmsd = &vmstate_macio_newworld; 418 } 419 420 static Property macio_properties[] = { 421 DEFINE_PROP_UINT64("frequency", MacIOState, frequency, 0), 422 DEFINE_PROP_END_OF_LIST() 423 }; 424 425 static void macio_class_init(ObjectClass *klass, void *data) 426 { 427 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 428 DeviceClass *dc = DEVICE_CLASS(klass); 429 430 k->vendor_id = PCI_VENDOR_ID_APPLE; 431 k->class_id = PCI_CLASS_OTHERS << 8; 432 dc->props = macio_properties; 433 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); 434 } 435 436 static const TypeInfo macio_oldworld_type_info = { 437 .name = TYPE_OLDWORLD_MACIO, 438 .parent = TYPE_MACIO, 439 .instance_size = sizeof(OldWorldMacIOState), 440 .instance_init = macio_oldworld_init, 441 .class_init = macio_oldworld_class_init, 442 }; 443 444 static const TypeInfo macio_newworld_type_info = { 445 .name = TYPE_NEWWORLD_MACIO, 446 .parent = TYPE_MACIO, 447 .instance_size = sizeof(NewWorldMacIOState), 448 .instance_init = macio_newworld_init, 449 .class_init = macio_newworld_class_init, 450 }; 451 452 static const TypeInfo macio_type_info = { 453 .name = TYPE_MACIO, 454 .parent = TYPE_PCI_DEVICE, 455 .instance_size = sizeof(MacIOState), 456 .instance_init = macio_instance_init, 457 .abstract = true, 458 .class_init = macio_class_init, 459 .interfaces = (InterfaceInfo[]) { 460 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 461 { }, 462 }, 463 }; 464 465 static void macio_register_types(void) 466 { 467 type_register_static(&macio_type_info); 468 type_register_static(&macio_oldworld_type_info); 469 type_register_static(&macio_newworld_type_info); 470 } 471 472 type_init(macio_register_types) 473 474 void macio_init(PCIDevice *d, 475 MemoryRegion *pic_mem) 476 { 477 MacIOState *macio_state = MACIO(d); 478 479 macio_state->pic_mem = pic_mem; 480 /* Note: this code is strongly inspirated from the corresponding code 481 in PearPC */ 482 qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency", 483 macio_state->frequency); 484 485 qdev_init_nofail(DEVICE(d)); 486 } 487