]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - sys/powerpc/ps3/ps3disk.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / sys / powerpc / ps3 / ps3disk.c
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 SYSCTL_NODE(_hw, OID_AUTO, ps3disk, CTLFLAG_RD, 0, "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);