xref: /freebsd/sys/powerpc/ps3/ps3disk.c (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (C) 2011 glevand (geoffrey.levand@mail.ru)
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/sysctl.h>
32 #include <sys/disk.h>
33 #include <sys/bio.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/kernel.h>
37 #include <sys/kthread.h>
38 #include <sys/lock.h>
39 #include <sys/malloc.h>
40 #include <sys/module.h>
41 #include <sys/mutex.h>
42 
43 #include <vm/vm.h>
44 #include <vm/pmap.h>
45 
46 #include <machine/pio.h>
47 #include <machine/bus.h>
48 #include <machine/platform.h>
49 #include <machine/resource.h>
50 #include <sys/bus.h>
51 #include <sys/rman.h>
52 
53 #include <geom/geom_disk.h>
54 
55 #include "ps3bus.h"
56 #include "ps3-hvcall.h"
57 
58 #define PS3DISK_LOCK_INIT(_sc)		\
59 	mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3disk", MTX_DEF)
60 #define PS3DISK_LOCK_DESTROY(_sc)	mtx_destroy(&_sc->sc_mtx);
61 #define PS3DISK_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
62 #define	PS3DISK_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
63 #define PS3DISK_ASSERT_LOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_OWNED);
64 #define PS3DISK_ASSERT_UNLOCKED(_sc)	mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
65 
66 #define LV1_STORAGE_ATA_HDDOUT 		0x23
67 
68 static SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
69     "PS3 Disk driver parameters");
70 
71 #ifdef PS3DISK_DEBUG
72 static int ps3disk_debug = 0;
73 SYSCTL_INT(_hw_ps3disk, OID_AUTO, debug, CTLFLAG_RW, &ps3disk_debug,
74 	0, "control debugging printfs");
75 TUNABLE_INT("hw.ps3disk.debug", &ps3disk_debug);
76 enum {
77 	PS3DISK_DEBUG_INTR	= 0x00000001,
78 	PS3DISK_DEBUG_TASK	= 0x00000002,
79 	PS3DISK_DEBUG_READ	= 0x00000004,
80 	PS3DISK_DEBUG_WRITE	= 0x00000008,
81 	PS3DISK_DEBUG_FLUSH	= 0x00000010,
82 	PS3DISK_DEBUG_ANY	= 0xffffffff
83 };
84 #define	DPRINTF(sc, m, fmt, ...)				\
85 do {								\
86 	if (sc->sc_debug & (m))					\
87 		printf(fmt, __VA_ARGS__);			\
88 } while (0)
89 #else
90 #define	DPRINTF(sc, m, fmt, ...)
91 #endif
92 
93 struct ps3disk_region {
94 	uint64_t r_id;
95 	uint64_t r_start;
96 	uint64_t r_size;
97 	uint64_t r_flags;
98 };
99 
100 struct ps3disk_softc {
101 	device_t sc_dev;
102 
103 	struct mtx sc_mtx;
104 
105 	uint64_t sc_blksize;
106 	uint64_t sc_nblocks;
107 
108 	uint64_t sc_nregs;
109 	struct ps3disk_region *sc_reg;
110 
111 	int sc_irqid;
112 	struct resource	*sc_irq;
113 	void *sc_irqctx;
114 
115 	struct disk **sc_disk;
116 
117 	struct bio_queue_head sc_bioq;
118 	struct bio_queue_head sc_deferredq;
119 	struct proc *sc_task;
120 
121 	bus_dma_tag_t sc_dmatag;
122 
123 	int sc_running;
124 	int sc_debug;
125 };
126 
127 static int ps3disk_open(struct disk *dp);
128 static int ps3disk_close(struct disk *dp);
129 static void ps3disk_strategy(struct bio *bp);
130 
131 static void ps3disk_task(void *arg);
132 static void ps3disk_intr(void *arg);
133 static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc);
134 static int ps3disk_enum_regions(struct ps3disk_softc *sc);
135 static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
136     int error);
137 
138 static void ps3disk_sysctlattach(struct ps3disk_softc *sc);
139 
140 static MALLOC_DEFINE(M_PS3DISK, "ps3disk", "PS3 Disk");
141 
142 static int
143 ps3disk_probe(device_t dev)
144 {
145 	if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
146 	    ps3bus_get_devtype(dev) != PS3_DEVTYPE_DISK)
147 		return (ENXIO);
148 
149 	device_set_desc(dev, "Playstation 3 Disk");
150 
151 	return (BUS_PROBE_SPECIFIC);
152 }
153 
154 static int
155 ps3disk_attach(device_t dev)
156 {
157 	struct ps3disk_softc *sc;
158 	struct disk *d;
159 	intmax_t mb;
160 	uint64_t junk;
161 	char unit;
162 	int i, err;
163 
164 	sc = device_get_softc(dev);
165 	sc->sc_dev = dev;
166 
167 	PS3DISK_LOCK_INIT(sc);
168 
169 	err = ps3disk_get_disk_geometry(sc);
170 	if (err) {
171 		device_printf(dev, "Could not get disk geometry\n");
172 		err = ENXIO;
173 		goto fail_destroy_lock;
174 	}
175 
176 	device_printf(dev, "block size %lu total blocks %lu\n",
177 	    sc->sc_blksize, sc->sc_nblocks);
178 
179 	err = ps3disk_enum_regions(sc);
180 	if (err) {
181 		device_printf(dev, "Could not enumerate disk regions\n");
182 		err = ENXIO;
183 		goto fail_destroy_lock;
184 	}
185 
186 	device_printf(dev, "Found %lu regions\n", sc->sc_nregs);
187 
188 	if (!sc->sc_nregs) {
189 		err = ENXIO;
190 		goto fail_destroy_lock;
191 	}
192 
193 	/* Setup interrupt handler */
194 	sc->sc_irqid = 0;
195 	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
196 	    RF_ACTIVE);
197 	if (!sc->sc_irq) {
198 		device_printf(dev, "Could not allocate IRQ\n");
199 		err = ENXIO;
200 		goto fail_free_regions;
201 	}
202 
203 	err = bus_setup_intr(dev, sc->sc_irq,
204 	    INTR_TYPE_BIO | INTR_MPSAFE | INTR_ENTROPY,
205 	    NULL, ps3disk_intr, sc, &sc->sc_irqctx);
206 	if (err) {
207 		device_printf(dev, "Could not setup IRQ\n");
208 		err = ENXIO;
209 		goto fail_release_intr;
210 	}
211 
212 	/* Setup DMA */
213 	err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
214 	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
215 	    BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
216 	    busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
217 	if (err) {
218 		device_printf(dev, "Could not create DMA tag\n");
219 		err = ENXIO;
220 		goto fail_teardown_intr;
221 	}
222 
223 	/* Setup disks */
224 
225 	sc->sc_disk = malloc(sc->sc_nregs * sizeof(struct disk *),
226 	    M_PS3DISK, M_ZERO | M_WAITOK);
227 	if (!sc->sc_disk) {
228 		device_printf(dev, "Could not allocate disk(s)\n");
229 		err = ENOMEM;
230 		goto fail_teardown_intr;
231 	}
232 
233 	for (i = 0; i < sc->sc_nregs; i++) {
234 		struct ps3disk_region *rp = &sc->sc_reg[i];
235 
236 		d = sc->sc_disk[i] = disk_alloc();
237 		d->d_open = ps3disk_open;
238 		d->d_close = ps3disk_close;
239 		d->d_strategy = ps3disk_strategy;
240 		d->d_name = "ps3disk";
241 		d->d_drv1 = sc;
242 		d->d_maxsize = PAGE_SIZE;
243 		d->d_sectorsize = sc->sc_blksize;
244 		d->d_unit = i;
245 		d->d_mediasize = sc->sc_reg[i].r_size * sc->sc_blksize;
246 		d->d_flags |= DISKFLAG_CANFLUSHCACHE;
247 
248 		mb = d->d_mediasize >> 20;
249 		unit = 'M';
250 		if (mb >= 10240) {
251 			unit = 'G';
252 			mb /= 1024;
253 		}
254 
255 		/* Test to see if we can read this region */
256 		err = lv1_storage_read(ps3bus_get_device(dev), d->d_unit,
257 		    0, 0, rp->r_flags, 0, &junk);
258 		device_printf(dev, "region %d %ju%cB%s\n", i, mb, unit,
259 		    (err == LV1_DENIED_BY_POLICY) ?  " (hypervisor protected)"
260 		    : "");
261 
262 		if (err != LV1_DENIED_BY_POLICY)
263 			disk_create(d, DISK_VERSION);
264 	}
265 	err = 0;
266 
267 	bioq_init(&sc->sc_bioq);
268 	bioq_init(&sc->sc_deferredq);
269 	kproc_create(&ps3disk_task, sc, &sc->sc_task, 0, 0, "ps3disk");
270 
271 	ps3disk_sysctlattach(sc);
272 	sc->sc_running = 1;
273 	return (0);
274 
275 fail_teardown_intr:
276 	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
277 fail_release_intr:
278 	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
279 fail_free_regions:
280 	free(sc->sc_reg, M_PS3DISK);
281 fail_destroy_lock:
282 	PS3DISK_LOCK_DESTROY(sc);
283 	return (err);
284 }
285 
286 static int
287 ps3disk_detach(device_t dev)
288 {
289 	struct ps3disk_softc *sc = device_get_softc(dev);
290 	int i;
291 
292 	for (i = 0; i < sc->sc_nregs; i++)
293 		disk_destroy(sc->sc_disk[i]);
294 
295 	bus_dma_tag_destroy(sc->sc_dmatag);
296 
297 	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
298 	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
299 
300 	free(sc->sc_disk, M_PS3DISK);
301 	free(sc->sc_reg, M_PS3DISK);
302 
303 	PS3DISK_LOCK_DESTROY(sc);
304 
305 	return (0);
306 }
307 
308 static int
309 ps3disk_open(struct disk *dp)
310 {
311 	return (0);
312 }
313 
314 static int
315 ps3disk_close(struct disk *dp)
316 {
317 	return (0);
318 }
319 
320 /* Process deferred blocks */
321 static void
322 ps3disk_task(void *arg)
323 {
324 	struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
325 	struct bio *bp;
326 
327 	while (1) {
328 		kproc_suspend_check(sc->sc_task);
329 		tsleep(&sc->sc_deferredq, PRIBIO, "ps3disk", 10);
330 
331 		PS3DISK_LOCK(sc);
332 		bp = bioq_takefirst(&sc->sc_deferredq);
333 		PS3DISK_UNLOCK(sc);
334 
335 		if (bp == NULL)
336 			continue;
337 
338 		if (bp->bio_driver1 != NULL) {
339 			bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
340 			    bp->bio_driver1);
341 			bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
342 			    bp->bio_driver1);
343 		}
344 
345 		ps3disk_strategy(bp);
346 	}
347 
348 	kproc_exit(0);
349 }
350 
351 static void
352 ps3disk_strategy(struct bio *bp)
353 {
354 	struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
355 	int err;
356 
357 	if (sc == NULL) {
358 		bp->bio_flags |= BIO_ERROR;
359 		bp->bio_error = EINVAL;
360 		biodone(bp);
361 		return;
362 	}
363 
364 	PS3DISK_LOCK(sc);
365 	bp->bio_resid = bp->bio_bcount;
366 	bioq_insert_tail(&sc->sc_bioq, bp);
367 
368 	DPRINTF(sc, PS3DISK_DEBUG_TASK, "%s: bio_cmd 0x%02x\n",
369 	    __func__, bp->bio_cmd);
370 
371 	err = 0;
372 	if (bp->bio_cmd == BIO_FLUSH) {
373 		bp->bio_driver1 = 0;
374 		err = lv1_storage_send_device_command(
375 		    ps3bus_get_device(sc->sc_dev), LV1_STORAGE_ATA_HDDOUT,
376 		    0, 0, 0, 0, (uint64_t *)&bp->bio_driver2);
377 		if (err == LV1_BUSY)
378 			err = EAGAIN;
379 	} else if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
380 		if (bp->bio_bcount % sc->sc_blksize != 0) {
381 			err = EINVAL;
382 		} else {
383 			bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
384 			    (bus_dmamap_t *)(&bp->bio_driver1));
385 			err = bus_dmamap_load(sc->sc_dmatag,
386 			    (bus_dmamap_t)(bp->bio_driver1), bp->bio_data,
387 			    bp->bio_bcount, ps3disk_transfer, bp, 0);
388 			if (err == EINPROGRESS)
389 				err = 0;
390 		}
391 	} else {
392 		err = EINVAL;
393 	}
394 
395 	if (err == EAGAIN) {
396 		bioq_remove(&sc->sc_bioq, bp);
397 		bioq_insert_tail(&sc->sc_deferredq, bp);
398 	} else if (err != 0) {
399 		bp->bio_error = err;
400 		bp->bio_flags |= BIO_ERROR;
401 		bioq_remove(&sc->sc_bioq, bp);
402 		disk_err(bp, "hard error", -1, 1);
403 		biodone(bp);
404 	}
405 
406 	PS3DISK_UNLOCK(sc);
407 }
408 
409 static void
410 ps3disk_intr(void *arg)
411 {
412 	struct ps3disk_softc *sc = (struct ps3disk_softc *) arg;
413 	device_t dev = sc->sc_dev;
414 	uint64_t devid = ps3bus_get_device(dev);
415 	struct bio *bp;
416 	uint64_t tag, status;
417 
418 	if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
419 		return;
420 
421 	PS3DISK_LOCK(sc);
422 
423 	DPRINTF(sc, PS3DISK_DEBUG_INTR, "%s: tag 0x%016lx "
424 	    "status 0x%016lx\n", __func__, tag, status);
425 
426 	/* Locate the matching request */
427 	TAILQ_FOREACH(bp, &sc->sc_bioq.queue, bio_queue) {
428 		if ((uint64_t)bp->bio_driver2 != tag)
429 			continue;
430 
431 		if (status != 0) {
432 			device_printf(sc->sc_dev, "%s error (%#lx)\n",
433 			    (bp->bio_cmd == BIO_READ) ? "Read" : "Write",
434 			    status);
435 			bp->bio_error = EIO;
436 			bp->bio_flags |= BIO_ERROR;
437 		} else {
438 			bp->bio_error = 0;
439 			bp->bio_resid = 0;
440 			bp->bio_flags |= BIO_DONE;
441 		}
442 
443 		if (bp->bio_driver1 != NULL) {
444 			if (bp->bio_cmd == BIO_READ)
445 				bus_dmamap_sync(sc->sc_dmatag, (bus_dmamap_t)
446 				    bp->bio_driver1, BUS_DMASYNC_POSTREAD);
447 			bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
448 			    bp->bio_driver1);
449 			bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
450 			    bp->bio_driver1);
451 		}
452 
453 		bioq_remove(&sc->sc_bioq, bp);
454 		biodone(bp);
455 		break;
456 	}
457 
458 	if (bioq_first(&sc->sc_deferredq) != NULL)
459 		wakeup(&sc->sc_deferredq);
460 
461 	PS3DISK_UNLOCK(sc);
462 }
463 
464 static int
465 ps3disk_get_disk_geometry(struct ps3disk_softc *sc)
466 {
467 	device_t dev = sc->sc_dev;
468 	uint64_t bus_index = ps3bus_get_busidx(dev);
469 	uint64_t dev_index = ps3bus_get_devidx(dev);
470 	uint64_t junk;
471 	int err;
472 
473 	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
474 	    (lv1_repository_string("bus") >> 32) | bus_index,
475 	    lv1_repository_string("dev") | dev_index,
476 	    lv1_repository_string("blk_size"), 0, &sc->sc_blksize, &junk);
477 	if (err) {
478 		device_printf(dev, "Could not get block size (0x%08x)\n", err);
479 		return (ENXIO);
480 	}
481 
482 	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
483 	    (lv1_repository_string("bus") >> 32) | bus_index,
484 	    lv1_repository_string("dev") | dev_index,
485 	    lv1_repository_string("n_blocks"), 0, &sc->sc_nblocks, &junk);
486 	if (err) {
487 		device_printf(dev, "Could not get total number of blocks "
488 		    "(0x%08x)\n", err);
489 		err = ENXIO;
490 	}
491 
492 	return (err);
493 }
494 
495 static int
496 ps3disk_enum_regions(struct ps3disk_softc *sc)
497 {
498 	device_t dev = sc->sc_dev;
499 	uint64_t bus_index = ps3bus_get_busidx(dev);
500 	uint64_t dev_index = ps3bus_get_devidx(dev);
501 	uint64_t junk;
502 	int i, err;
503 
504 	/* Read number of regions */
505 
506 	err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
507 	    (lv1_repository_string("bus") >> 32) | bus_index,
508 	    lv1_repository_string("dev") | dev_index,
509 	    lv1_repository_string("n_regs"), 0, &sc->sc_nregs, &junk);
510 	if (err) {
511 		device_printf(dev, "Could not get number of regions (0x%08x)\n",
512 		    err);
513 		err = ENXIO;
514 		goto fail;
515 	}
516 
517 	if (!sc->sc_nregs)
518 		return 0;
519 
520 	sc->sc_reg = malloc(sc->sc_nregs * sizeof(struct ps3disk_region),
521 	    M_PS3DISK, M_ZERO | M_WAITOK);
522 	if (!sc->sc_reg) {
523 		err = ENOMEM;
524 		goto fail;
525 	}
526 
527 	/* Setup regions */
528 
529 	for (i = 0; i < sc->sc_nregs; i++) {
530 		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
531 		    (lv1_repository_string("bus") >> 32) | bus_index,
532 		    lv1_repository_string("dev") | dev_index,
533 		    lv1_repository_string("region") | i,
534 		    lv1_repository_string("id"), &sc->sc_reg[i].r_id, &junk);
535 		if (err) {
536 			device_printf(dev, "Could not get region id (0x%08x)\n",
537 			    err);
538 			err = ENXIO;
539 			goto fail;
540 		}
541 
542 		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
543 		    (lv1_repository_string("bus") >> 32) | bus_index,
544 		    lv1_repository_string("dev") | dev_index,
545 		    lv1_repository_string("region") | i,
546 		    lv1_repository_string("start"), &sc->sc_reg[i].r_start,
547 		    &junk);
548 		if (err) {
549 			device_printf(dev, "Could not get region start "
550 			    "(0x%08x)\n", err);
551 			err = ENXIO;
552 			goto fail;
553 		}
554 
555 		err = lv1_get_repository_node_value(PS3_LPAR_ID_PME,
556 		    (lv1_repository_string("bus") >> 32) | bus_index,
557 		    lv1_repository_string("dev") | dev_index,
558 		    lv1_repository_string("region") | i,
559 		    lv1_repository_string("size"), &sc->sc_reg[i].r_size,
560 		    &junk);
561 		if (err) {
562 			device_printf(dev, "Could not get region size "
563 			    "(0x%08x)\n", err);
564 			err = ENXIO;
565 			goto fail;
566 		}
567 
568 		if (i == 0)
569 			sc->sc_reg[i].r_flags = 0x2;
570 		else
571 			sc->sc_reg[i].r_flags = 0;
572 	}
573 
574 	return (0);
575 
576 fail:
577 
578 	sc->sc_nregs = 0;
579 	if (sc->sc_reg)
580 		free(sc->sc_reg, M_PS3DISK);
581 
582 	return (err);
583 }
584 
585 static void
586 ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
587 {
588 	struct bio *bp = (struct bio *)(arg);
589 	struct ps3disk_softc *sc = (struct ps3disk_softc *)bp->bio_disk->d_drv1;
590 	struct ps3disk_region *rp = &sc->sc_reg[bp->bio_disk->d_unit];
591 	uint64_t devid = ps3bus_get_device(sc->sc_dev);
592 	uint64_t block;
593 	int i, err;
594 
595 	/* Locks already held by busdma */
596 	PS3DISK_ASSERT_LOCKED(sc);
597 
598 	if (error) {
599 		bp->bio_error = error;
600 		bp->bio_flags |= BIO_ERROR;
601 		bioq_remove(&sc->sc_bioq, bp);
602 		biodone(bp);
603 		return;
604 	}
605 
606 	block = bp->bio_pblkno;
607 	for (i = 0; i < nsegs; i++) {
608 		KASSERT((segs[i].ds_len % sc->sc_blksize) == 0,
609 		    ("DMA fragments not blocksize multiples"));
610 
611 		if (bp->bio_cmd == BIO_READ) {
612 			err = lv1_storage_read(devid, rp->r_id,
613 			    block, segs[i].ds_len/sc->sc_blksize,
614 			    rp->r_flags, segs[i].ds_addr,
615 			    (uint64_t *)&bp->bio_driver2);
616 		} else {
617 			bus_dmamap_sync(sc->sc_dmatag,
618 			    (bus_dmamap_t)bp->bio_driver1,
619 			    BUS_DMASYNC_PREWRITE);
620 			err = lv1_storage_write(devid, rp->r_id,
621 			    block, segs[i].ds_len/sc->sc_blksize,
622 			    rp->r_flags, segs[i].ds_addr,
623 			    (uint64_t *)&bp->bio_driver2);
624 		}
625 
626 		if (err) {
627 			if (err == LV1_BUSY) {
628 				bioq_remove(&sc->sc_bioq, bp);
629 				bioq_insert_tail(&sc->sc_deferredq, bp);
630 			} else {
631 				bus_dmamap_unload(sc->sc_dmatag, (bus_dmamap_t)
632 				    bp->bio_driver1);
633 				bus_dmamap_destroy(sc->sc_dmatag, (bus_dmamap_t)
634 				    bp->bio_driver1);
635 				device_printf(sc->sc_dev, "Could not read "
636 				    "sectors (0x%08x)\n", err);
637 				bp->bio_error = EINVAL;
638 				bp->bio_flags |= BIO_ERROR;
639 				bioq_remove(&sc->sc_bioq, bp);
640 				biodone(bp);
641 			}
642 
643 			break;
644 		}
645 
646 		DPRINTF(sc, PS3DISK_DEBUG_READ, "%s: tag 0x%016lx\n",
647 		    __func__, sc->sc_bounce_tag);
648 	}
649 }
650 
651 #ifdef PS3DISK_DEBUG
652 static int
653 ps3disk_sysctl_debug(SYSCTL_HANDLER_ARGS)
654 {
655 	struct ps3disk_softc *sc = arg1;
656 	int debug, error;
657 
658 	debug = sc->sc_debug;
659 
660 	error = sysctl_handle_int(oidp, &debug, 0, req);
661 	if (error || !req->newptr)
662 		return error;
663 
664 	sc->sc_debug = debug;
665 
666 	return 0;
667 }
668 #endif
669 
670 static void
671 ps3disk_sysctlattach(struct ps3disk_softc *sc)
672 {
673 #ifdef PS3DISK_DEBUG
674 	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
675 	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
676 
677 	sc->sc_debug = ps3disk_debug;
678 
679 	SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
680 	    "debug", CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, sc, 0,
681 	    ps3disk_sysctl_debug, "I", "control debugging printfs");
682 #endif
683 }
684 
685 static device_method_t ps3disk_methods[] = {
686 	DEVMETHOD(device_probe,		ps3disk_probe),
687 	DEVMETHOD(device_attach,	ps3disk_attach),
688 	DEVMETHOD(device_detach,	ps3disk_detach),
689 	{0, 0},
690 };
691 
692 static driver_t ps3disk_driver = {
693 	"ps3disk",
694 	ps3disk_methods,
695 	sizeof(struct ps3disk_softc),
696 };
697 
698 DRIVER_MODULE(ps3disk, ps3bus, ps3disk_driver, 0, 0);
699