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