cxgbe/t4_tom: Read the chip's DDP page sizes and save them in a
[freebsd-src.git] / sys / powerpc / ps3 / ps3bus.c
blob37ea0b747e2126b171876f15b249b8d8cc0a3db5
1 /*-
2 * Copyright (C) 2010 Nathan Whitehorn
3 * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
4 * All rights reserved.
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.
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.
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
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>
41 #include <vm/vm.h>
42 #include <vm/pmap.h>
44 #include <machine/bus.h>
45 #include <machine/platform.h>
46 #include <machine/resource.h>
48 #include "ps3bus.h"
49 #include "ps3-hvcall.h"
50 #include "iommu_if.h"
51 #include "clock_if.h"
53 static void ps3bus_identify(driver_t *, device_t);
54 static int ps3bus_probe(device_t);
55 static int ps3bus_attach(device_t);
56 static int ps3bus_print_child(device_t dev, device_t child);
57 static int ps3bus_read_ivar(device_t bus, device_t child, int which,
58 uintptr_t *result);
59 static struct resource *ps3bus_alloc_resource(device_t bus, device_t child,
60 int type, int *rid, rman_res_t start, rman_res_t end,
61 rman_res_t count, u_int flags);
62 static int ps3bus_activate_resource(device_t bus, device_t child, int type,
63 int rid, struct resource *res);
64 static bus_dma_tag_t ps3bus_get_dma_tag(device_t dev, device_t child);
65 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,
66 bus_addr_t boundary, void *cookie);
67 static int ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs,
68 int nsegs, void *cookie);
69 static int ps3_gettime(device_t dev, struct timespec *ts);
70 static int ps3_settime(device_t dev, struct timespec *ts);
72 struct ps3bus_devinfo {
73 int bus;
74 int dev;
75 uint64_t bustype;
76 uint64_t devtype;
77 int busidx;
78 int devidx;
80 struct resource_list resources;
81 bus_dma_tag_t dma_tag;
83 struct mtx iommu_mtx;
84 bus_addr_t dma_base[4];
87 static MALLOC_DEFINE(M_PS3BUS, "ps3bus", "PS3 system bus device information");
89 enum ps3bus_irq_type {
90 SB_IRQ = 2,
91 OHCI_IRQ = 3,
92 EHCI_IRQ = 4,
95 enum ps3bus_reg_type {
96 OHCI_REG = 3,
97 EHCI_REG = 4,
100 static device_method_t ps3bus_methods[] = {
101 /* Device interface */
102 DEVMETHOD(device_identify, ps3bus_identify),
103 DEVMETHOD(device_probe, ps3bus_probe),
104 DEVMETHOD(device_attach, ps3bus_attach),
106 /* Bus interface */
107 DEVMETHOD(bus_add_child, bus_generic_add_child),
108 DEVMETHOD(bus_get_dma_tag, ps3bus_get_dma_tag),
109 DEVMETHOD(bus_print_child, ps3bus_print_child),
110 DEVMETHOD(bus_read_ivar, ps3bus_read_ivar),
111 DEVMETHOD(bus_alloc_resource, ps3bus_alloc_resource),
112 DEVMETHOD(bus_activate_resource, ps3bus_activate_resource),
113 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
114 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
116 /* IOMMU interface */
117 DEVMETHOD(iommu_map, ps3_iommu_map),
118 DEVMETHOD(iommu_unmap, ps3_iommu_unmap),
120 /* Clock interface */
121 DEVMETHOD(clock_gettime, ps3_gettime),
122 DEVMETHOD(clock_settime, ps3_settime),
124 DEVMETHOD_END
127 struct ps3bus_softc {
128 struct rman sc_mem_rman;
129 struct rman sc_intr_rman;
130 struct mem_region *regions;
131 int rcount;
134 static driver_t ps3bus_driver = {
135 "ps3bus",
136 ps3bus_methods,
137 sizeof(struct ps3bus_softc)
140 static devclass_t ps3bus_devclass;
142 DRIVER_MODULE(ps3bus, nexus, ps3bus_driver, ps3bus_devclass, 0, 0);
144 static void
145 ps3bus_identify(driver_t *driver, device_t parent)
147 if (strcmp(installed_platform(), "ps3") != 0)
148 return;
150 if (device_find_child(parent, "ps3bus", -1) == NULL)
151 BUS_ADD_CHILD(parent, 0, "ps3bus", 0);
154 static int
155 ps3bus_probe(device_t dev)
157 /* Do not attach to any OF nodes that may be present */
159 device_set_desc(dev, "Playstation 3 System Bus");
161 return (BUS_PROBE_NOWILDCARD);
164 static void
165 ps3bus_resources_init(struct rman *rm, int bus_index, int dev_index,
166 struct ps3bus_devinfo *dinfo)
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;
174 resource_list_init(&dinfo->resources);
176 lv1_get_logical_ppe_id(&ppe);
177 thread = 32 - fls(mfctrl());
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);
186 if (result != 0)
187 break;
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,
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,
202 break;
203 default:
204 printf("Unknown IRQ type %ld for device %d.%d\n",
205 irq_type, dinfo->bus, dinfo->dev);
206 break;
209 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
210 outlet, outlet, 1);
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"), &reg_type, &junk);
221 if (result != 0)
222 break;
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);
230 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
231 paddr, len, 12 /* log_2(4 KB) */, &paddr);
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;
240 rman_manage_region(rm, paddr, paddr + len - 1);
241 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
242 paddr, paddr + len, len);
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)
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;
256 resource_list_init(&dinfo->resources);
258 lv1_get_logical_ppe_id(&ppe);
259 thread = 32 - fls(mfctrl());
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);
268 if (result != 0)
269 break;
271 if (_irq_type != irq_type)
272 continue;
274 lv1_construct_io_irq_outlet(irq, &outlet);
275 lv1_connect_irq_plug_ext(ppe, thread, outlet, outlet,
277 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i,
278 outlet, outlet, 1);
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);
289 if (result != 0)
290 break;
292 if (_reg_type != reg_type)
293 continue;
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);
301 result = lv1_map_device_mmio_region(dinfo->bus, dinfo->dev,
302 paddr, len, 12 /* log_2(4 KB) */, &paddr);
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;
311 rman_manage_region(rm, paddr, paddr + len - 1);
312 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i,
313 paddr, paddr + len, len);
317 static int
318 ps3bus_attach(device_t self)
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;
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);
337 /* Get memory regions for DMA */
338 mem_regions(&sc->regions, &sc->rcount, &sc->regions, &sc->rcount);
341 * Probe all the PS3's buses.
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);
349 if (result != 0)
350 continue;
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);
356 if (result != 0)
357 continue;
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);
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);
369 if (result != 0)
370 continue;
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);
377 if (result != 0)
378 continue;
380 switch (devtype) {
381 case PS3_DEVTYPE_USB:
382 /* USB device has OHCI and EHCI USB host controllers */
384 lv1_open_device(bus, dev, 0);
386 /* OHCI host controller */
388 dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
389 M_WAITOK | M_ZERO);
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;
398 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
399 dev_index, OHCI_IRQ, OHCI_REG, dinfo);
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;
409 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
410 device_set_ivars(cdev, dinfo);
412 /* EHCI host controller */
414 dinfo = malloc(sizeof(*dinfo), M_PS3BUS,
415 M_WAITOK | M_ZERO);
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;
424 ps3bus_resources_init_by_type(&sc->sc_mem_rman, bus_index,
425 dev_index, EHCI_IRQ, EHCI_REG, dinfo);
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;
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);
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;
449 if (dinfo->bustype == PS3_BUSTYPE_SYSBUS ||
450 dinfo->bustype == PS3_BUSTYPE_STORAGE)
451 lv1_open_device(bus, dev, 0);
453 ps3bus_resources_init(&sc->sc_mem_rman, bus_index,
454 dev_index, dinfo);
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;
464 mtx_init(&dinfo->iommu_mtx, "iommu", NULL, MTX_DEF);
465 device_set_ivars(cdev, dinfo);
470 clock_register(self, 1000);
472 return (bus_generic_attach(self));
475 static int
476 ps3bus_print_child(device_t dev, device_t child)
478 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
479 int retval = 0;
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");
487 retval += bus_print_child_footer(dev, child);
489 return (retval);
492 static int
493 ps3bus_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
495 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
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);
520 return (0);
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)
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;
535 sc = device_get_softc(bus);
536 dinfo = device_get_ivars(child);
537 needactivate = flags & RF_ACTIVE;
538 flags &= ~RF_ACTIVE;
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);
550 if (start < rle->start)
551 adjstart = rle->start;
552 else if (start > rle->end)
553 adjstart = rle->end;
554 else
555 adjstart = start;
557 if (end < rle->start)
558 adjend = rle->start;
559 else if (end > rle->end)
560 adjend = rle->end;
561 else
562 adjend = end;
564 adjcount = adjend - adjstart;
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);
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);
592 rman_set_rid(rv, *rid);
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);
604 return (rv);
607 static int
608 ps3bus_activate_resource(device_t bus, device_t child, int type, int rid,
609 struct resource *res)
611 void *p;
613 if (type == SYS_RES_IRQ)
614 return (bus_activate_resource(bus, type, rid, res));
616 if (type == SYS_RES_MEMORY) {
617 vm_offset_t start;
619 start = (vm_offset_t) rman_get_start(res);
621 if (bootverbose)
622 printf("ps3 mapdev: start %zx, len %ld\n", start,
623 rman_get_size(res));
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);
633 return (rman_activate_resource(res));
636 static bus_dma_tag_t
637 ps3bus_get_dma_tag(device_t dev, device_t child)
639 struct ps3bus_devinfo *dinfo = device_get_ivars(child);
640 struct ps3bus_softc *sc = device_get_softc(dev);
641 int i, err, flags, pagesize;
643 if (dinfo->bustype != PS3_BUSTYPE_SYSBUS &&
644 dinfo->bustype != PS3_BUSTYPE_STORAGE)
645 return (bus_get_dma_tag(dev));
647 mtx_lock(&dinfo->iommu_mtx);
648 if (dinfo->dma_tag != NULL) {
649 mtx_unlock(&dinfo->iommu_mtx);
650 return (dinfo->dma_tag);
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 */
658 pagesize = 24; /* log_2(16 MB) */
659 if (dinfo->bustype == PS3_BUSTYPE_STORAGE)
660 pagesize = 12; /* 4 KB */
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;
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;
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);
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.
695 if (dinfo->bustype != PS3_BUSTYPE_STORAGE)
696 bus_dma_tag_set_iommu(dinfo->dma_tag, dev, dinfo);
698 fail:
699 mtx_unlock(&dinfo->iommu_mtx);
701 if (err)
702 return (NULL);
704 return (dinfo->dma_tag);
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)
712 struct ps3bus_devinfo *dinfo = cookie;
713 struct ps3bus_softc *sc = device_get_softc(dev);
714 int i, j;
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;
723 KASSERT(j < sc->rcount,
724 ("Trying to map address %#lx not in physical memory",
725 segs[i].ds_addr));
727 segs[i].ds_addr = dinfo->dma_base[j] +
728 (segs[i].ds_addr - sc->regions[j].mr_start);
731 return (0);
734 static int
735 ps3_iommu_unmap(device_t dev, bus_dma_segment_t *segs, int nsegs, void *cookie)
738 return (0);
741 #define Y2K 946684800
743 static int
744 ps3_gettime(device_t dev, struct timespec *ts)
746 uint64_t rtc, tb;
747 int result;
749 result = lv1_get_rtc(&rtc, &tb);
750 if (result)
751 return (result);
753 ts->tv_sec = rtc + Y2K;
754 ts->tv_nsec = 0;
755 return (0);
758 static int
759 ps3_settime(device_t dev, struct timespec *ts)
761 return (-1);