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