]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/powerpc/ps3/ps3disk.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.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 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);