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