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