xref: /freebsd/sys/powerpc/ps3/ps3bus.c (revision 4b9d6057)
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"), &reg_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