ps3disk.c revision 331722
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: stable/11/sys/powerpc/ps3/ps3disk.c 331722 2018-03-29 02:50:57Z eadler $");
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
69static SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD, 0,
70    "PS3 Disk driver parameters");
71
72#ifdef PS3DISK_DEBUG
73static int ps3disk_debug = 0;
74SYSCTL_INT(_hw_ps3disk, OID_AUTO, debug, CTLFLAG_RW, &ps3disk_debug,
75	0, "control debugging printfs");
76TUNABLE_INT("hw.ps3disk.debug", &ps3disk_debug);
77enum {
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, ...)				\
86do {								\
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
94struct ps3disk_region {
95	uint64_t r_id;
96	uint64_t r_start;
97	uint64_t r_size;
98	uint64_t r_flags;
99};
100
101struct 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
128static int ps3disk_open(struct disk *dp);
129static int ps3disk_close(struct disk *dp);
130static void ps3disk_strategy(struct bio *bp);
131
132static void ps3disk_task(void *arg);
133static void ps3disk_intr(void *arg);
134static int ps3disk_get_disk_geometry(struct ps3disk_softc *sc);
135static int ps3disk_enum_regions(struct ps3disk_softc *sc);
136static void ps3disk_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
137    int error);
138
139static void ps3disk_sysctlattach(struct ps3disk_softc *sc);
140
141static MALLOC_DEFINE(M_PS3DISK, "ps3disk", "PS3 Disk");
142
143static int
144ps3disk_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
155static int
156ps3disk_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
276fail_teardown_intr:
277	bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
278fail_release_intr:
279	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
280fail_free_regions:
281	free(sc->sc_reg, M_PS3DISK);
282fail_destroy_lock:
283	PS3DISK_LOCK_DESTROY(sc);
284	return (err);
285}
286
287static int
288ps3disk_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
309static int
310ps3disk_open(struct disk *dp)
311{
312	return (0);
313}
314
315static int
316ps3disk_close(struct disk *dp)
317{
318	return (0);
319}
320
321/* Process deferred blocks */
322static void
323ps3disk_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
353static void
354ps3disk_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
411static void
412ps3disk_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
466static int
467ps3disk_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
497static int
498ps3disk_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
578fail:
579
580	sc->sc_nregs = 0;
581	if (sc->sc_reg)
582		free(sc->sc_reg, M_PS3DISK);
583
584	return (err);
585}
586
587static void
588ps3disk_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
654static int
655ps3disk_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
672static void
673ps3disk_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
687static 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
694static driver_t ps3disk_driver = {
695	"ps3disk",
696	ps3disk_methods,
697	sizeof(struct ps3disk_softc),
698};
699
700static devclass_t ps3disk_devclass;
701
702DRIVER_MODULE(ps3disk, ps3bus, ps3disk_driver, ps3disk_devclass, 0, 0);
703