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