1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (C) 2010 Nathan Whitehorn 5 * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru) 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/module.h> 36 #include <sys/malloc.h> 37 #include <sys/bus.h> 38 #include <sys/clock.h> 39 #include <sys/cpu.h> 40 #include <sys/lock.h> 41 #include <sys/mutex.h> 42 #include <sys/resource.h> 43 #include <sys/rman.h> 44 45 #include <vm/vm.h> 46 #include <vm/pmap.h> 47 48 #include <machine/bus.h> 49 #include <machine/platform.h> 50 #include <machine/resource.h> 51 52 #include "ps3bus.h" 53 #include "ps3-hvcall.h" 54 #include "iommu_if.h" 55 #include "clock_if.h" 56 57 static void ps3bus_identify(driver_t *, device_t); 58 static int ps3bus_probe(device_t); 59 static int ps3bus_attach(device_t); 60 static int ps3bus_print_child(device_t dev, device_t child); 61 static int ps3bus_read_ivar(device_t bus, device_t child, int which, 62 uintptr_t *result); 63 static struct resource *ps3bus_alloc_resource(device_t bus, device_t child, 64 int type, int *rid, rman_res_t start, rman_res_t end, 65 rman_res_t count, u_int flags); 66 static int ps3bus_activate_resource(device_t bus, device_t child, int type, 67 int rid, struct resource *res); 68 static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child); 69 static int ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, bus_addr_t min, bus_addr_t max, bus_size_t alignment, 70 bus_addr_t boundary, void *cookie); 71 static int ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, 72 int nsegs, void *cookie); 73 static int ps3_gettime(device_t dev, struct timespec *ts); 74 static int ps3_settime(device_t dev, struct timespec *ts); 75 76 struct ps3bus_devinfo { 77 int bus; 78 int dev; 79 uint64_t bustype; 80 uint64_t devtype; 81 int busidx; 82 int devidx; 83 84 struct resource_list resources; 85 bus_dma_tag_t dma_tag; 86 87 struct mtx iommu_mtx; 88 bus_addr_t dma_base[4]; 89 }; 90 91 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information"); 92 93 enum ps3bus_irq_type { 94 SB_IRQ = 2, 95 OHCI_IRQ = 3, 96 EHCI_IRQ = 4, 97 }; 98 99 enum ps3bus_reg_type { 100 OHCI_REG = 3, 101 EHCI_REG = 4, 102 }; 103 104 static device_method_t ps3bus_methods[] = { 105 /* Device interface */ 106 DEVMETHOD(device_identify, ps3bus_identify), 107 DEVMETHOD(device_probe, ps3bus_probe), 108 DEVMETHOD(device_attach, ps3bus_attach), 109 110 /* Bus interface */ 111 DEVMETHOD(bus_add_child, bus_generic_add_child), 112 DEVMETHOD(bus_get_dma_tag, ps3bus_get_dma_tag), 113 DEVMETHOD(bus_print_child, ps3bus_print_child), 114 DEVMETHOD(bus_read_ivar, ps3bus_read_ivar), 115 DEVMETHOD(bus_alloc_resource, ps3bus_alloc_resource), 116 DEVMETHOD(bus_activate_resource, ps3bus_activate_resource), 117 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), 118 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), 119 120 /* IOMMU interface */ 121 DEVMETHOD(iommu_map, ps3_iommu_map), 122 DEVMETHOD(iommu_unmap, ps3_iommu_unmap), 123 124 /* Clock interface */ 125 DEVMETHOD(clock_gettime, ps3_gettime), 126 DEVMETHOD(clock_settime, ps3_settime), 127 128 DEVMETHOD_END 129 }; 130 131 struct ps3bus_softc { 132 struct rman sc_mem_rman; 133 struct rman sc_intr_rman; 134 struct mem_region *regions; 135 int rcount; 136 }; 137 138 static driver_t ps3bus_driver = { 139 "ps3bus", 140 ps3bus_methods, 141 sizeof(struct ps3bus_softc) 142 }; 143 144 static devclass_t ps3bus_devclass; 145 146 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0); 147 148 static void 149 ps3bus_identify(driver_t *driver, device_t parent) 150 { 151 if (strcmp(installed_platform(), "ps3") != 0) 152 return; 153 154 if (device_find_child(parent, "ps3bus", -1) == NULL) 155 BUS_ADD_CHILD(parent, 0, "ps3bus", 0); 156 } 157 158 static int 159 ps3bus_probe(device_t dev) 160 { 161 /* Do not attach to any OF nodes that may be present */ 162 163 device_set_desc(dev, "Playstation 3 System Bus"); 164 165 return (BUS_PROBE_NOWILDCARD); 166 } 167 168 static void 169 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index, 170 struct ps3bus_devinfo *dinfo) 171 { 172 uint64_t irq_type, irq, outlet; 173 uint64_t reg_type, paddr, len; 174 uint64_t ppe, junk; 175 int i, result; 176 int thread; 177 178 resource_list_init(&dinfo->resources); 179 180 lv1_get_logical_ppe_id(&ppe); 181 thread = 32 - fls(mfctrl()); 182 183 /* Scan for interrupts */ 184 for (i = 0; i < 10; i++) { 185 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 186 (lv1_repository_string("bus") >> 32) | bus_index, 187 lv1_repository_string("dev") | dev_index, 188 lv1_repository_string("intr") | i, 0, &irq_type, &irq); 189 190 if (result != 0) 191 break; 192 193 switch (irq_type) { 194 case SB_IRQ: 195 lv1_construct_event_receive_port(&outlet); 196 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 197 0); 198 lv1_connect_interrupt_event_receive_port(dinfo->bus, 199 dinfo->dev, outlet, irq); 200 break; 201 case OHCI_IRQ: 202 case EHCI_IRQ: 203 lv1_construct_io_irq_outlet(irq, &outlet); 204 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 205 0); 206 break; 207 default: 208 printf("Unknown IRQ type %ld for device %d.%d\n", 209 irq_type, dinfo->bus, dinfo->dev); 210 break; 211 } 212 213 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, 214 outlet, outlet, 1); 215 } 216 217 /* Scan for registers */ 218 for (i = 0; i < 10; i++) { 219 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 220 (lv1_repository_string("bus") >> 32) | bus_index, 221 lv1_repository_string("dev") | dev_index, 222 lv1_repository_string("reg") | i, 223 lv1_repository_string("type"), ®_type, &junk); 224 225 if (result != 0) 226 break; 227 228 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 229 (lv1_repository_string("bus") >> 32) | bus_index, 230 lv1_repository_string("dev") | dev_index, 231 lv1_repository_string("reg") | i, 232 lv1_repository_string("data"), &paddr, &len); 233 234 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, 235 paddr, len, 12 /* log_2(4 KB) */, &paddr); 236 237 if (result != 0) { 238 printf("Mapping registers failed for device " 239 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, 240 dinfo->bustype, dinfo->devtype, result); 241 continue; 242 } 243 244 rman_manage_region(rm, paddr, paddr + len - 1); 245 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, 246 paddr, paddr + len, len); 247 } 248 } 249 250 static void 251 ps3bus_resources_init_by_type(struct rman *rm, int bus_index, int dev_index, 252 uint64_t irq_type, uint64_t reg_type, struct ps3bus_devinfo *dinfo) 253 { 254 uint64_t _irq_type, irq, outlet; 255 uint64_t _reg_type, paddr, len; 256 uint64_t ppe, junk; 257 int i, result; 258 int thread; 259 260 resource_list_init(&dinfo->resources); 261 262 lv1_get_logical_ppe_id(&ppe); 263 thread = 32 - fls(mfctrl()); 264 265 /* Scan for interrupts */ 266 for (i = 0; i < 10; i++) { 267 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 268 (lv1_repository_string("bus") >> 32) | bus_index, 269 lv1_repository_string("dev") | dev_index, 270 lv1_repository_string("intr") | i, 0, &_irq_type, &irq); 271 272 if (result != 0) 273 break; 274 275 if (_irq_type != irq_type) 276 continue; 277 278 lv1_construct_io_irq_outlet(irq, &outlet); 279 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 280 0); 281 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, 282 outlet, outlet, 1); 283 } 284 285 /* Scan for registers */ 286 for (i = 0; i < 10; i++) { 287 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 288 (lv1_repository_string("bus") >> 32) | bus_index, 289 lv1_repository_string("dev") | dev_index, 290 lv1_repository_string("reg") | i, 291 lv1_repository_string("type"), &_reg_type, &junk); 292 293 if (result != 0) 294 break; 295 296 if (_reg_type != reg_type) 297 continue; 298 299 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 300 (lv1_repository_string("bus") >> 32) | bus_index, 301 lv1_repository_string("dev") | dev_index, 302 lv1_repository_string("reg") | i, 303 lv1_repository_string("data"), &paddr, &len); 304 305 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, 306 paddr, len, 12 /* log_2(4 KB) */, &paddr); 307 308 if (result != 0) { 309 printf("Mapping registers failed for device " 310 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, 311 dinfo->bustype, dinfo->devtype, result); 312 break; 313 } 314 315 rman_manage_region(rm, paddr, paddr + len - 1); 316 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, 317 paddr, paddr + len, len); 318 } 319 } 320 321 static int 322 ps3bus_attach(device_t self) 323 { 324 struct ps3bus_softc *sc; 325 struct ps3bus_devinfo *dinfo; 326 int bus_index, dev_index, result; 327 uint64_t bustype, bus, devs; 328 uint64_t dev, devtype; 329 uint64_t junk; 330 device_t cdev; 331 332 sc = device_get_softc(self); 333 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 334 sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O"; 335 sc->sc_intr_rman.rm_type = RMAN_ARRAY; 336 sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts"; 337 rman_init(&sc->sc_mem_rman); 338 rman_init(&sc->sc_intr_rman); 339 rman_manage_region(&sc->sc_intr_rman, 0, ~0); 340 341 /* Get memory regions for DMA */ 342 mem_regions(&sc->regions, &sc->rcount, NULL, NULL); 343 344 /* 345 * Probe all the PS3's buses. 346 */ 347 348 for (bus_index = 0; bus_index < 5; bus_index++) { 349 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 350 (lv1_repository_string("bus") >> 32) | bus_index, 351 lv1_repository_string("type"), 0, 0, &bustype, &junk); 352 353 if (result != 0) 354 continue; 355 356 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 357 (lv1_repository_string("bus") >> 32) | bus_index, 358 lv1_repository_string("id"), 0, 0, &bus, &junk); 359 360 if (result != 0) 361 continue; 362 363 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 364 (lv1_repository_string("bus") >> 32) | bus_index, 365 lv1_repository_string("num_dev"), 0, 0, &devs, &junk); 366 367 for (dev_index = 0; dev_index < devs; dev_index++) { 368 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 369 (lv1_repository_string("bus") >> 32) | bus_index, 370 lv1_repository_string("dev") | dev_index, 371 lv1_repository_string("type"), 0, &devtype, &junk); 372 373 if (result != 0) 374 continue; 375 376 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 377 (lv1_repository_string("bus") >> 32) | bus_index, 378 lv1_repository_string("dev") | dev_index, 379 lv1_repository_string("id"), 0, &dev, &junk); 380 381 if (result != 0) 382 continue; 383 384 switch (devtype) { 385 case PS3_DEVTYPE_USB: 386 /* USB device has OHCI and EHCI USB host controllers */ 387 388 lv1_open_device(bus, dev, 0); 389 390 /* OHCI host controller */ 391 392 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 393 M_WAITOK | M_ZERO); 394 395 dinfo->bus = bus; 396 dinfo->dev = dev; 397 dinfo->bustype = bustype; 398 dinfo->devtype = devtype; 399 dinfo->busidx = bus_index; 400 dinfo->devidx = dev_index; 401 402 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, 403 dev_index, OHCI_IRQ, OHCI_REG, dinfo); 404 405 cdev = device_add_child(self, "ohci", -1); 406 if (cdev == NULL) { 407 device_printf(self, 408 "device_add_child failed\n"); 409 free(dinfo, M_PS3BUS); 410 continue; 411 } 412 413 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 414 device_set_ivars(cdev, dinfo); 415 416 /* EHCI host controller */ 417 418 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 419 M_WAITOK | M_ZERO); 420 421 dinfo->bus = bus; 422 dinfo->dev = dev; 423 dinfo->bustype = bustype; 424 dinfo->devtype = devtype; 425 dinfo->busidx = bus_index; 426 dinfo->devidx = dev_index; 427 428 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, 429 dev_index, EHCI_IRQ, EHCI_REG, dinfo); 430 431 cdev = device_add_child(self, "ehci", -1); 432 if (cdev == NULL) { 433 device_printf(self, 434 "device_add_child failed\n"); 435 free(dinfo, M_PS3BUS); 436 continue; 437 } 438 439 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 440 device_set_ivars(cdev, dinfo); 441 break; 442 default: 443 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 444 M_WAITOK | M_ZERO); 445 446 dinfo->bus = bus; 447 dinfo->dev = dev; 448 dinfo->bustype = bustype; 449 dinfo->devtype = devtype; 450 dinfo->busidx = bus_index; 451 dinfo->devidx = dev_index; 452 453 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS || 454 dinfo->bustype == PS3_BUSTYPE_STORAGE) 455 lv1_open_device(bus, dev, 0); 456 457 ps3bus_resources_init(&sc->sc_mem_rman, bus_index, 458 dev_index, dinfo); 459 460 cdev = device_add_child(self, NULL, -1); 461 if (cdev == NULL) { 462 device_printf(self, 463 "device_add_child failed\n"); 464 free(dinfo, M_PS3BUS); 465 continue; 466 } 467 468 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 469 device_set_ivars(cdev, dinfo); 470 } 471 } 472 } 473 474 clock_register(self, 1000); 475 476 return (bus_generic_attach(self)); 477 } 478 479 static int 480 ps3bus_print_child(device_t dev, device_t child) 481 { 482 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 483 int retval = 0; 484 485 retval += bus_print_child_header(dev, child); 486 retval += resource_list_print_type(&dinfo->resources, "mem", 487 SYS_RES_MEMORY, "%#jx"); 488 retval += resource_list_print_type(&dinfo->resources, "irq", 489 SYS_RES_IRQ, "%jd"); 490 491 retval += bus_print_child_footer(dev, child); 492 493 return (retval); 494 } 495 496 static int 497 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) 498 { 499 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 500 501 switch (which) { 502 case PS3BUS_IVAR_BUS: 503 *result = dinfo->bus; 504 break; 505 case PS3BUS_IVAR_DEVICE: 506 *result = dinfo->dev; 507 break; 508 case PS3BUS_IVAR_BUSTYPE: 509 *result = dinfo->bustype; 510 break; 511 case PS3BUS_IVAR_DEVTYPE: 512 *result = dinfo->devtype; 513 break; 514 case PS3BUS_IVAR_BUSIDX: 515 *result = dinfo->busidx; 516 break; 517 case PS3BUS_IVAR_DEVIDX: 518 *result = dinfo->devidx; 519 break; 520 default: 521 return (EINVAL); 522 } 523 524 return (0); 525 } 526 527 static struct resource * 528 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid, 529 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 530 { 531 struct ps3bus_devinfo *dinfo; 532 struct ps3bus_softc *sc; 533 int needactivate; 534 struct resource *rv; 535 struct rman *rm; 536 rman_res_t adjstart, adjend, adjcount; 537 struct resource_list_entry *rle; 538 539 sc = device_get_softc(bus); 540 dinfo = device_get_ivars(child); 541 needactivate = flags & RF_ACTIVE; 542 flags &= ~RF_ACTIVE; 543 544 switch (type) { 545 case SYS_RES_MEMORY: 546 rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, 547 *rid); 548 if (rle == NULL) { 549 device_printf(bus, "no rle for %s memory %d\n", 550 device_get_nameunit(child), *rid); 551 return (NULL); 552 } 553 554 if (start < rle->start) 555 adjstart = rle->start; 556 else if (start > rle->end) 557 adjstart = rle->end; 558 else 559 adjstart = start; 560 561 if (end < rle->start) 562 adjend = rle->start; 563 else if (end > rle->end) 564 adjend = rle->end; 565 else 566 adjend = end; 567 568 adjcount = adjend - adjstart; 569 570 rm = &sc->sc_mem_rman; 571 break; 572 case SYS_RES_IRQ: 573 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 574 *rid); 575 rm = &sc->sc_intr_rman; 576 adjstart = rle->start; 577 adjcount = ulmax(count, rle->count); 578 adjend = ulmax(rle->end, rle->start + adjcount - 1); 579 break; 580 default: 581 device_printf(bus, "unknown resource request from %s\n", 582 device_get_nameunit(child)); 583 return (NULL); 584 } 585 586 rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, 587 child); 588 if (rv == NULL) { 589 device_printf(bus, 590 "failed to reserve resource %#lx - %#lx (%#lx)" 591 " for %s\n", adjstart, adjend, adjcount, 592 device_get_nameunit(child)); 593 return (NULL); 594 } 595 596 rman_set_rid(rv, *rid); 597 598 if (needactivate) { 599 if (bus_activate_resource(child, type, *rid, rv) != 0) { 600 device_printf(bus, 601 "failed to activate resource for %s\n", 602 device_get_nameunit(child)); 603 rman_release_resource(rv); 604 return (NULL); 605 } 606 } 607 608 return (rv); 609 } 610 611 static int 612 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid, 613 struct resource *res) 614 { 615 void *p; 616 617 if (type == SYS_RES_IRQ) 618 return (bus_activate_resource(bus, type, rid, res)); 619 620 if (type == SYS_RES_MEMORY) { 621 vm_offset_t start; 622 623 start = (vm_offset_t) rman_get_start(res); 624 625 if (bootverbose) 626 printf("ps3 mapdev: start %zx, len %ld\n", start, 627 rman_get_size(res)); 628 629 p = pmap_mapdev(start, (vm_size_t) rman_get_size(res)); 630 if (p == NULL) 631 return (ENOMEM); 632 rman_set_virtual(res, p); 633 rman_set_bustag(res, &bs_be_tag); 634 rman_set_bushandle(res, (rman_res_t)p); 635 } 636 637 return (rman_activate_resource(res)); 638 } 639 640 static bus_dma_tag_t 641 ps3bus_get_dma_tag(device_t dev, device_t child) 642 { 643 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 644 struct ps3bus_softc *sc = device_get_softc(dev); 645 int i, err, flags, pagesize; 646 647 if (dinfo->bustype != PS3_BUSTYPE_SYSBUS && 648 dinfo->bustype != PS3_BUSTYPE_STORAGE) 649 return (bus_get_dma_tag(dev)); 650 651 mtx_lock(&dinfo->iommu_mtx); 652 if (dinfo->dma_tag != NULL) { 653 mtx_unlock(&dinfo->iommu_mtx); 654 return (dinfo->dma_tag); 655 } 656 657 flags = 0; /* 32-bit mode */ 658 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS && 659 dinfo->devtype == PS3_DEVTYPE_USB) 660 flags = 2; /* 8-bit mode */ 661 662 pagesize = 24; /* log_2(16 MB) */ 663 if (dinfo->bustype == PS3_BUSTYPE_STORAGE) 664 pagesize = 12; /* 4 KB */ 665 666 for (i = 0; i < sc->rcount; i++) { 667 err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev, 668 sc->regions[i].mr_size, pagesize, flags, 669 &dinfo->dma_base[i]); 670 if (err != 0) { 671 device_printf(child, 672 "could not allocate DMA region %d: %d\n", i, err); 673 goto fail; 674 } 675 676 err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev, 677 sc->regions[i].mr_start, dinfo->dma_base[i], 678 sc->regions[i].mr_size, 679 0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */); 680 if (err != 0) { 681 device_printf(child, 682 "could not map DMA region %d: %d\n", i, err); 683 goto fail; 684 } 685 } 686 687 err = bus_dma_tag_create(bus_get_dma_tag(dev), 688 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 689 NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE, 690 0, NULL, NULL, &dinfo->dma_tag); 691 692 /* 693 * Note: storage devices have IOMMU mappings set up by the hypervisor, 694 * but use physical, non-translated addresses. The above IOMMU 695 * initialization is necessary for the hypervisor to be able to set up 696 * the mappings, but actual DMA mappings should not use the IOMMU 697 * routines. 698 */ 699 if (dinfo->bustype != PS3_BUSTYPE_STORAGE) 700 bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo); 701 702 fail: 703 mtx_unlock(&dinfo->iommu_mtx); 704 705 if (err) 706 return (NULL); 707 708 return (dinfo->dma_tag); 709 } 710 711 static int 712 ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, 713 bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary, 714 void *cookie) 715 { 716 struct ps3bus_devinfo *dinfo = cookie; 717 struct ps3bus_softc *sc = device_get_softc(dev); 718 int i, j; 719 720 for (i = 0; i < *nsegs; i++) { 721 for (j = 0; j < sc->rcount; j++) { 722 if (segs[i].ds_addr >= sc->regions[j].mr_start && 723 segs[i].ds_addr < sc->regions[j].mr_start + 724 sc->regions[j].mr_size) 725 break; 726 } 727 KASSERT(j < sc->rcount, 728 ("Trying to map address %#lx not in physical memory", 729 segs[i].ds_addr)); 730 731 segs[i].ds_addr = dinfo->dma_base[j] + 732 (segs[i].ds_addr - sc->regions[j].mr_start); 733 } 734 735 return (0); 736 } 737 738 static int 739 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie) 740 { 741 742 return (0); 743 } 744 745 #define Y2K 946684800 746 747 static int 748 ps3_gettime(device_t dev, struct timespec *ts) 749 { 750 uint64_t rtc, tb; 751 int result; 752 753 result = lv1_get_rtc(&rtc, &tb); 754 if (result) 755 return (result); 756 757 ts->tv_sec = rtc + Y2K; 758 ts->tv_nsec = 0; 759 return (0); 760 } 761 762 static int 763 ps3_settime(device_t dev, struct timespec *ts) 764 { 765 return (-1); 766 } 767 768