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 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, 0, 0); 145 146 static void 147 ps3bus_identify(driver_t *driver, device_t parent) 148 { 149 if (strcmp(installed_platform(), "ps3") != 0) 150 return; 151 152 if (device_find_child(parent, "ps3bus", -1) == NULL) 153 BUS_ADD_CHILD(parent, 0, "ps3bus", 0); 154 } 155 156 static int 157 ps3bus_probe(device_t dev) 158 { 159 /* Do not attach to any OF nodes that may be present */ 160 161 device_set_desc(dev, "Playstation 3 System Bus"); 162 163 return (BUS_PROBE_NOWILDCARD); 164 } 165 166 static void 167 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index, 168 struct ps3bus_devinfo *dinfo) 169 { 170 uint64_t irq_type, irq, outlet; 171 uint64_t reg_type, paddr, len; 172 uint64_t ppe, junk; 173 int i, result; 174 int thread; 175 176 resource_list_init(&dinfo->resources); 177 178 lv1_get_logical_ppe_id(&ppe); 179 thread = 32 - fls(mfctrl()); 180 181 /* Scan for interrupts */ 182 for (i = 0; i < 10; i++) { 183 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 184 (lv1_repository_string("bus") >> 32) | bus_index, 185 lv1_repository_string("dev") | dev_index, 186 lv1_repository_string("intr") | i, 0, &irq_type, &irq); 187 188 if (result != 0) 189 break; 190 191 switch (irq_type) { 192 case SB_IRQ: 193 lv1_construct_event_receive_port(&outlet); 194 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 195 0); 196 lv1_connect_interrupt_event_receive_port(dinfo->bus, 197 dinfo->dev, outlet, irq); 198 break; 199 case OHCI_IRQ: 200 case EHCI_IRQ: 201 lv1_construct_io_irq_outlet(irq, &outlet); 202 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 203 0); 204 break; 205 default: 206 printf("Unknown IRQ type %ld for device %d.%d\n", 207 irq_type, dinfo->bus, dinfo->dev); 208 break; 209 } 210 211 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, 212 outlet, outlet, 1); 213 } 214 215 /* Scan for registers */ 216 for (i = 0; i < 10; i++) { 217 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 218 (lv1_repository_string("bus") >> 32) | bus_index, 219 lv1_repository_string("dev") | dev_index, 220 lv1_repository_string("reg") | i, 221 lv1_repository_string("type"), ®_type, &junk); 222 223 if (result != 0) 224 break; 225 226 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 227 (lv1_repository_string("bus") >> 32) | bus_index, 228 lv1_repository_string("dev") | dev_index, 229 lv1_repository_string("reg") | i, 230 lv1_repository_string("data"), &paddr, &len); 231 232 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, 233 paddr, len, 12 /* log_2(4 KB) */, &paddr); 234 235 if (result != 0) { 236 printf("Mapping registers failed for device " 237 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, 238 dinfo->bustype, dinfo->devtype, result); 239 continue; 240 } 241 242 rman_manage_region(rm, paddr, paddr + len - 1); 243 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, 244 paddr, paddr + len, len); 245 } 246 } 247 248 static void 249 ps3bus_resources_init_by_type(struct rman *rm, int bus_index, int dev_index, 250 uint64_t irq_type, uint64_t reg_type, struct ps3bus_devinfo *dinfo) 251 { 252 uint64_t _irq_type, irq, outlet; 253 uint64_t _reg_type, paddr, len; 254 uint64_t ppe, junk; 255 int i, result; 256 int thread; 257 258 resource_list_init(&dinfo->resources); 259 260 lv1_get_logical_ppe_id(&ppe); 261 thread = 32 - fls(mfctrl()); 262 263 /* Scan for interrupts */ 264 for (i = 0; i < 10; i++) { 265 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 266 (lv1_repository_string("bus") >> 32) | bus_index, 267 lv1_repository_string("dev") | dev_index, 268 lv1_repository_string("intr") | i, 0, &_irq_type, &irq); 269 270 if (result != 0) 271 break; 272 273 if (_irq_type != irq_type) 274 continue; 275 276 lv1_construct_io_irq_outlet(irq, &outlet); 277 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet, 278 0); 279 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i, 280 outlet, outlet, 1); 281 } 282 283 /* Scan for registers */ 284 for (i = 0; i < 10; i++) { 285 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 286 (lv1_repository_string("bus") >> 32) | bus_index, 287 lv1_repository_string("dev") | dev_index, 288 lv1_repository_string("reg") | i, 289 lv1_repository_string("type"), &_reg_type, &junk); 290 291 if (result != 0) 292 break; 293 294 if (_reg_type != reg_type) 295 continue; 296 297 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 298 (lv1_repository_string("bus") >> 32) | bus_index, 299 lv1_repository_string("dev") | dev_index, 300 lv1_repository_string("reg") | i, 301 lv1_repository_string("data"), &paddr, &len); 302 303 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev, 304 paddr, len, 12 /* log_2(4 KB) */, &paddr); 305 306 if (result != 0) { 307 printf("Mapping registers failed for device " 308 "%d.%d (%ld.%ld): %d\n", dinfo->bus, dinfo->dev, 309 dinfo->bustype, dinfo->devtype, result); 310 break; 311 } 312 313 rman_manage_region(rm, paddr, paddr + len - 1); 314 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, 315 paddr, paddr + len, len); 316 } 317 } 318 319 static int 320 ps3bus_attach(device_t self) 321 { 322 struct ps3bus_softc *sc; 323 struct ps3bus_devinfo *dinfo; 324 int bus_index, dev_index, result; 325 uint64_t bustype, bus, devs; 326 uint64_t dev, devtype; 327 uint64_t junk; 328 device_t cdev; 329 330 sc = device_get_softc(self); 331 sc->sc_mem_rman.rm_type = RMAN_ARRAY; 332 sc->sc_mem_rman.rm_descr = "PS3Bus Memory Mapped I/O"; 333 sc->sc_intr_rman.rm_type = RMAN_ARRAY; 334 sc->sc_intr_rman.rm_descr = "PS3Bus Interrupts"; 335 rman_init(&sc->sc_mem_rman); 336 rman_init(&sc->sc_intr_rman); 337 rman_manage_region(&sc->sc_intr_rman, 0, ~0); 338 339 /* Get memory regions for DMA */ 340 mem_regions(&sc->regions, &sc->rcount, NULL, NULL); 341 342 /* 343 * Probe all the PS3's buses. 344 */ 345 346 for (bus_index = 0; bus_index < 5; bus_index++) { 347 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 348 (lv1_repository_string("bus") >> 32) | bus_index, 349 lv1_repository_string("type"), 0, 0, &bustype, &junk); 350 351 if (result != 0) 352 continue; 353 354 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 355 (lv1_repository_string("bus") >> 32) | bus_index, 356 lv1_repository_string("id"), 0, 0, &bus, &junk); 357 358 if (result != 0) 359 continue; 360 361 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 362 (lv1_repository_string("bus") >> 32) | bus_index, 363 lv1_repository_string("num_dev"), 0, 0, &devs, &junk); 364 365 for (dev_index = 0; dev_index < devs; dev_index++) { 366 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 367 (lv1_repository_string("bus") >> 32) | bus_index, 368 lv1_repository_string("dev") | dev_index, 369 lv1_repository_string("type"), 0, &devtype, &junk); 370 371 if (result != 0) 372 continue; 373 374 result = lv1_get_repository_node_value(PS3_LPAR_ID_PME, 375 (lv1_repository_string("bus") >> 32) | bus_index, 376 lv1_repository_string("dev") | dev_index, 377 lv1_repository_string("id"), 0, &dev, &junk); 378 379 if (result != 0) 380 continue; 381 382 switch (devtype) { 383 case PS3_DEVTYPE_USB: 384 /* USB device has OHCI and EHCI USB host controllers */ 385 386 lv1_open_device(bus, dev, 0); 387 388 /* OHCI host controller */ 389 390 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 391 M_WAITOK | M_ZERO); 392 393 dinfo->bus = bus; 394 dinfo->dev = dev; 395 dinfo->bustype = bustype; 396 dinfo->devtype = devtype; 397 dinfo->busidx = bus_index; 398 dinfo->devidx = dev_index; 399 400 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, 401 dev_index, OHCI_IRQ, OHCI_REG, dinfo); 402 403 cdev = device_add_child(self, "ohci", -1); 404 if (cdev == NULL) { 405 device_printf(self, 406 "device_add_child failed\n"); 407 free(dinfo, M_PS3BUS); 408 continue; 409 } 410 411 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 412 device_set_ivars(cdev, dinfo); 413 414 /* EHCI host controller */ 415 416 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 417 M_WAITOK | M_ZERO); 418 419 dinfo->bus = bus; 420 dinfo->dev = dev; 421 dinfo->bustype = bustype; 422 dinfo->devtype = devtype; 423 dinfo->busidx = bus_index; 424 dinfo->devidx = dev_index; 425 426 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index, 427 dev_index, EHCI_IRQ, EHCI_REG, dinfo); 428 429 cdev = device_add_child(self, "ehci", -1); 430 if (cdev == NULL) { 431 device_printf(self, 432 "device_add_child failed\n"); 433 free(dinfo, M_PS3BUS); 434 continue; 435 } 436 437 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 438 device_set_ivars(cdev, dinfo); 439 break; 440 default: 441 dinfo = malloc(sizeof(*dinfo), M_PS3BUS, 442 M_WAITOK | M_ZERO); 443 444 dinfo->bus = bus; 445 dinfo->dev = dev; 446 dinfo->bustype = bustype; 447 dinfo->devtype = devtype; 448 dinfo->busidx = bus_index; 449 dinfo->devidx = dev_index; 450 451 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS || 452 dinfo->bustype == PS3_BUSTYPE_STORAGE) 453 lv1_open_device(bus, dev, 0); 454 455 ps3bus_resources_init(&sc->sc_mem_rman, bus_index, 456 dev_index, dinfo); 457 458 cdev = device_add_child(self, NULL, -1); 459 if (cdev == NULL) { 460 device_printf(self, 461 "device_add_child failed\n"); 462 free(dinfo, M_PS3BUS); 463 continue; 464 } 465 466 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF); 467 device_set_ivars(cdev, dinfo); 468 } 469 } 470 } 471 472 clock_register(self, 1000); 473 474 return (bus_generic_attach(self)); 475 } 476 477 static int 478 ps3bus_print_child(device_t dev, device_t child) 479 { 480 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 481 int retval = 0; 482 483 retval += bus_print_child_header(dev, child); 484 retval += resource_list_print_type(&dinfo->resources, "mem", 485 SYS_RES_MEMORY, "%#jx"); 486 retval += resource_list_print_type(&dinfo->resources, "irq", 487 SYS_RES_IRQ, "%jd"); 488 489 retval += bus_print_child_footer(dev, child); 490 491 return (retval); 492 } 493 494 static int 495 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result) 496 { 497 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 498 499 switch (which) { 500 case PS3BUS_IVAR_BUS: 501 *result = dinfo->bus; 502 break; 503 case PS3BUS_IVAR_DEVICE: 504 *result = dinfo->dev; 505 break; 506 case PS3BUS_IVAR_BUSTYPE: 507 *result = dinfo->bustype; 508 break; 509 case PS3BUS_IVAR_DEVTYPE: 510 *result = dinfo->devtype; 511 break; 512 case PS3BUS_IVAR_BUSIDX: 513 *result = dinfo->busidx; 514 break; 515 case PS3BUS_IVAR_DEVIDX: 516 *result = dinfo->devidx; 517 break; 518 default: 519 return (EINVAL); 520 } 521 522 return (0); 523 } 524 525 static struct resource * 526 ps3bus_alloc_resource(device_t bus, device_t child, int type, int *rid, 527 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) 528 { 529 struct ps3bus_devinfo *dinfo; 530 struct ps3bus_softc *sc; 531 int needactivate; 532 struct resource *rv; 533 struct rman *rm; 534 rman_res_t adjstart, adjend, adjcount; 535 struct resource_list_entry *rle; 536 537 sc = device_get_softc(bus); 538 dinfo = device_get_ivars(child); 539 needactivate = flags & RF_ACTIVE; 540 flags &= ~RF_ACTIVE; 541 542 switch (type) { 543 case SYS_RES_MEMORY: 544 rle = resource_list_find(&dinfo->resources, SYS_RES_MEMORY, 545 *rid); 546 if (rle == NULL) { 547 device_printf(bus, "no rle for %s memory %d\n", 548 device_get_nameunit(child), *rid); 549 return (NULL); 550 } 551 552 if (start < rle->start) 553 adjstart = rle->start; 554 else if (start > rle->end) 555 adjstart = rle->end; 556 else 557 adjstart = start; 558 559 if (end < rle->start) 560 adjend = rle->start; 561 else if (end > rle->end) 562 adjend = rle->end; 563 else 564 adjend = end; 565 566 adjcount = adjend - adjstart; 567 568 rm = &sc->sc_mem_rman; 569 break; 570 case SYS_RES_IRQ: 571 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, 572 *rid); 573 rm = &sc->sc_intr_rman; 574 adjstart = rle->start; 575 adjcount = ulmax(count, rle->count); 576 adjend = ulmax(rle->end, rle->start + adjcount - 1); 577 break; 578 default: 579 device_printf(bus, "unknown resource request from %s\n", 580 device_get_nameunit(child)); 581 return (NULL); 582 } 583 584 rv = rman_reserve_resource(rm, adjstart, adjend, adjcount, flags, 585 child); 586 if (rv == NULL) { 587 device_printf(bus, 588 "failed to reserve resource %#lx - %#lx (%#lx)" 589 " for %s\n", adjstart, adjend, adjcount, 590 device_get_nameunit(child)); 591 return (NULL); 592 } 593 594 rman_set_rid(rv, *rid); 595 596 if (needactivate) { 597 if (bus_activate_resource(child, type, *rid, rv) != 0) { 598 device_printf(bus, 599 "failed to activate resource for %s\n", 600 device_get_nameunit(child)); 601 rman_release_resource(rv); 602 return (NULL); 603 } 604 } 605 606 return (rv); 607 } 608 609 static int 610 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid, 611 struct resource *res) 612 { 613 void *p; 614 615 if (type == SYS_RES_IRQ) 616 return (bus_activate_resource(bus, type, rid, res)); 617 618 if (type == SYS_RES_MEMORY) { 619 vm_offset_t start; 620 621 start = (vm_offset_t) rman_get_start(res); 622 623 if (bootverbose) 624 printf("ps3 mapdev: start %zx, len %ld\n", start, 625 rman_get_size(res)); 626 627 p = pmap_mapdev(start, (vm_size_t) rman_get_size(res)); 628 if (p == NULL) 629 return (ENOMEM); 630 rman_set_virtual(res, p); 631 rman_set_bustag(res, &bs_be_tag); 632 rman_set_bushandle(res, (rman_res_t)p); 633 } 634 635 return (rman_activate_resource(res)); 636 } 637 638 static bus_dma_tag_t 639 ps3bus_get_dma_tag(device_t dev, device_t child) 640 { 641 struct ps3bus_devinfo *dinfo = device_get_ivars(child); 642 struct ps3bus_softc *sc = device_get_softc(dev); 643 int i, err, flags, pagesize; 644 645 if (dinfo->bustype != PS3_BUSTYPE_SYSBUS && 646 dinfo->bustype != PS3_BUSTYPE_STORAGE) 647 return (bus_get_dma_tag(dev)); 648 649 mtx_lock(&dinfo->iommu_mtx); 650 if (dinfo->dma_tag != NULL) { 651 mtx_unlock(&dinfo->iommu_mtx); 652 return (dinfo->dma_tag); 653 } 654 655 flags = 0; /* 32-bit mode */ 656 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS && 657 dinfo->devtype == PS3_DEVTYPE_USB) 658 flags = 2; /* 8-bit mode */ 659 660 pagesize = 24; /* log_2(16 MB) */ 661 if (dinfo->bustype == PS3_BUSTYPE_STORAGE) 662 pagesize = 12; /* 4 KB */ 663 664 for (i = 0; i < sc->rcount; i++) { 665 err = lv1_allocate_device_dma_region(dinfo->bus, dinfo->dev, 666 sc->regions[i].mr_size, pagesize, flags, 667 &dinfo->dma_base[i]); 668 if (err != 0) { 669 device_printf(child, 670 "could not allocate DMA region %d: %d\n", i, err); 671 goto fail; 672 } 673 674 err = lv1_map_device_dma_region(dinfo->bus, dinfo->dev, 675 sc->regions[i].mr_start, dinfo->dma_base[i], 676 sc->regions[i].mr_size, 677 0xf800000000000800UL /* Cell Handbook Figure 7.3.4.1 */); 678 if (err != 0) { 679 device_printf(child, 680 "could not map DMA region %d: %d\n", i, err); 681 goto fail; 682 } 683 } 684 685 err = bus_dma_tag_create(bus_get_dma_tag(dev), 686 1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, 687 NULL, NULL, BUS_SPACE_MAXSIZE, 0, BUS_SPACE_MAXSIZE, 688 0, NULL, NULL, &dinfo->dma_tag); 689 690 /* 691 * Note: storage devices have IOMMU mappings set up by the hypervisor, 692 * but use physical, non-translated addresses. The above IOMMU 693 * initialization is necessary for the hypervisor to be able to set up 694 * the mappings, but actual DMA mappings should not use the IOMMU 695 * routines. 696 */ 697 if (dinfo->bustype != PS3_BUSTYPE_STORAGE) 698 bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo); 699 700 fail: 701 mtx_unlock(&dinfo->iommu_mtx); 702 703 if (err) 704 return (NULL); 705 706 return (dinfo->dma_tag); 707 } 708 709 static int 710 ps3_iommu_map(device_t dev, bus_dma_segment_t *segs, int *nsegs, 711 bus_addr_t min, bus_addr_t max, bus_size_t alignment, bus_addr_t boundary, 712 void *cookie) 713 { 714 struct ps3bus_devinfo *dinfo = cookie; 715 struct ps3bus_softc *sc = device_get_softc(dev); 716 int i, j; 717 718 for (i = 0; i < *nsegs; i++) { 719 for (j = 0; j < sc->rcount; j++) { 720 if (segs[i].ds_addr >= sc->regions[j].mr_start && 721 segs[i].ds_addr < sc->regions[j].mr_start + 722 sc->regions[j].mr_size) 723 break; 724 } 725 KASSERT(j < sc->rcount, 726 ("Trying to map address %#lx not in physical memory", 727 segs[i].ds_addr)); 728 729 segs[i].ds_addr = dinfo->dma_base[j] + 730 (segs[i].ds_addr - sc->regions[j].mr_start); 731 } 732 733 return (0); 734 } 735 736 static int 737 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie) 738 { 739 740 return (0); 741 } 742 743 #define Y2K 946684800 744 745 static int 746 ps3_gettime(device_t dev, struct timespec *ts) 747 { 748 uint64_t rtc, tb; 749 int result; 750 751 result = lv1_get_rtc(&rtc, &tb); 752 if (result) 753 return (result); 754 755 ts->tv_sec = rtc + Y2K; 756 ts->tv_nsec = 0; 757 return (0); 758 } 759 760 static int 761 ps3_settime(device_t dev, struct timespec *ts) 762 { 763 return (-1); 764 } 765