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