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