Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/powerpc/ps3/ps3cdrom.c
39507 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (C) 2010 Nathan Whitehorn
5
* Copyright (C) 2011 glevand <[email protected]>
6
* All rights reserved.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer,
13
* without modification, immediately at the beginning of the file.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
*/
29
30
#include <sys/param.h>
31
#include <sys/module.h>
32
#include <sys/systm.h>
33
#include <sys/kernel.h>
34
#include <sys/ata.h>
35
#include <sys/bus.h>
36
#include <sys/conf.h>
37
#include <sys/kthread.h>
38
#include <sys/lock.h>
39
#include <sys/malloc.h>
40
#include <sys/mutex.h>
41
42
#include <vm/vm.h>
43
#include <vm/pmap.h>
44
45
#include <machine/pio.h>
46
#include <machine/bus.h>
47
#include <machine/platform.h>
48
#include <machine/resource.h>
49
#include <sys/bus.h>
50
#include <sys/rman.h>
51
52
#include <cam/cam.h>
53
#include <cam/cam_ccb.h>
54
#include <cam/cam_sim.h>
55
#include <cam/cam_xpt_sim.h>
56
#include <cam/cam_debug.h>
57
#include <cam/scsi/scsi_all.h>
58
59
#include "ps3bus.h"
60
#include "ps3-hvcall.h"
61
62
#define PS3CDROM_LOCK_INIT(_sc) \
63
mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \
64
MTX_DEF)
65
#define PS3CDROM_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
66
#define PS3CDROM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
67
#define PS3CDROM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
68
#define PS3CDROM_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
69
#define PS3CDROM_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
70
71
#define PS3CDROM_MAX_XFERS 3
72
73
#define LV1_STORAGE_SEND_ATAPI_COMMAND 0x01
74
75
struct ps3cdrom_softc;
76
77
struct ps3cdrom_xfer {
78
TAILQ_ENTRY(ps3cdrom_xfer) x_queue;
79
struct ps3cdrom_softc *x_sc;
80
union ccb *x_ccb;
81
bus_dmamap_t x_dmamap;
82
uint64_t x_tag;
83
};
84
85
TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer);
86
87
struct ps3cdrom_softc {
88
device_t sc_dev;
89
90
struct mtx sc_mtx;
91
92
uint64_t sc_blksize;
93
uint64_t sc_nblocks;
94
95
int sc_irqid;
96
struct resource *sc_irq;
97
void *sc_irqctx;
98
99
bus_dma_tag_t sc_dmatag;
100
101
struct cam_sim *sc_sim;
102
struct cam_path *sc_path;
103
104
struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS];
105
struct ps3cdrom_xferq sc_active_xferq;
106
struct ps3cdrom_xferq sc_free_xferq;
107
};
108
109
enum lv1_ata_proto {
110
NON_DATA_PROTO = 0x00,
111
PIO_DATA_IN_PROTO = 0x01,
112
PIO_DATA_OUT_PROTO = 0x02,
113
DMA_PROTO = 0x03
114
};
115
116
enum lv1_ata_in_out {
117
DIR_WRITE = 0x00,
118
DIR_READ = 0x01
119
};
120
121
struct lv1_atapi_cmd {
122
uint8_t pkt[32];
123
uint32_t pktlen;
124
uint32_t nblocks;
125
uint32_t blksize;
126
uint32_t proto; /* enum lv1_ata_proto */
127
uint32_t in_out; /* enum lv1_ata_in_out */
128
uint64_t buf;
129
uint32_t arglen;
130
};
131
132
static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb);
133
static void ps3cdrom_poll(struct cam_sim *sim);
134
static void ps3cdrom_async(void *callback_arg, u_int32_t code,
135
struct cam_path* path, void *arg);
136
137
static void ps3cdrom_intr(void *arg);
138
139
static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
140
int error);
141
142
static int ps3cdrom_decode_lv1_status(uint64_t status,
143
u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq);
144
145
static int
146
ps3cdrom_probe(device_t dev)
147
{
148
if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
149
ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM)
150
return (ENXIO);
151
152
device_set_desc(dev, "Playstation 3 CDROM");
153
154
return (BUS_PROBE_SPECIFIC);
155
}
156
157
static int
158
ps3cdrom_attach(device_t dev)
159
{
160
struct ps3cdrom_softc *sc = device_get_softc(dev);
161
struct cam_devq *devq;
162
struct ps3cdrom_xfer *xp;
163
struct ccb_setasync csa;
164
int i, err;
165
166
sc->sc_dev = dev;
167
168
PS3CDROM_LOCK_INIT(sc);
169
170
/* Setup interrupt handler */
171
172
sc->sc_irqid = 0;
173
sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
174
RF_ACTIVE);
175
if (!sc->sc_irq) {
176
device_printf(dev, "Could not allocate IRQ\n");
177
err = ENXIO;
178
goto fail_destroy_lock;
179
}
180
181
err = bus_setup_intr(dev, sc->sc_irq,
182
INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY,
183
NULL, ps3cdrom_intr, sc, &sc->sc_irqctx);
184
if (err) {
185
device_printf(dev, "Could not setup IRQ\n");
186
err = ENXIO;
187
goto fail_release_intr;
188
}
189
190
/* Setup DMA */
191
192
err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
193
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
194
BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
195
busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
196
if (err) {
197
device_printf(dev, "Could not create DMA tag\n");
198
err = ENXIO;
199
goto fail_teardown_intr;
200
}
201
202
/* Setup transfer queues */
203
204
TAILQ_INIT(&sc->sc_active_xferq);
205
TAILQ_INIT(&sc->sc_free_xferq);
206
207
for (i = 0; i < PS3CDROM_MAX_XFERS; i++) {
208
xp = &sc->sc_xfer[i];
209
xp->x_sc = sc;
210
211
err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
212
&xp->x_dmamap);
213
if (err) {
214
device_printf(dev, "Could not create DMA map (%d)\n",
215
err);
216
goto fail_destroy_dmamap;
217
}
218
219
TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
220
}
221
222
/* Setup CAM */
223
224
devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1);
225
if (!devq) {
226
device_printf(dev, "Could not allocate SIM queue\n");
227
err = ENOMEM;
228
goto fail_destroy_dmatag;
229
}
230
231
sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom",
232
sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0,
233
devq);
234
if (!sc->sc_sim) {
235
device_printf(dev, "Could not allocate SIM\n");
236
cam_simq_free(devq);
237
err = ENOMEM;
238
goto fail_destroy_dmatag;
239
}
240
241
/* Setup XPT */
242
243
PS3CDROM_LOCK(sc);
244
245
err = xpt_bus_register(sc->sc_sim, dev, 0);
246
if (err != CAM_SUCCESS) {
247
device_printf(dev, "Could not register XPT bus\n");
248
err = ENXIO;
249
PS3CDROM_UNLOCK(sc);
250
goto fail_free_sim;
251
}
252
253
err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim),
254
CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
255
if (err != CAM_REQ_CMP) {
256
device_printf(dev, "Could not create XPT path\n");
257
err = ENOMEM;
258
PS3CDROM_UNLOCK(sc);
259
goto fail_unregister_xpt_bus;
260
}
261
262
memset(&csa, 0, sizeof(csa));
263
xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5);
264
csa.ccb_h.func_code = XPT_SASYNC_CB;
265
csa.event_enable = AC_LOST_DEVICE;
266
csa.callback = ps3cdrom_async;
267
csa.callback_arg = sc->sc_sim;
268
xpt_action((union ccb *) &csa);
269
270
CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE,
271
("registered SIM for ps3cdrom%d\n", device_get_unit(dev)));
272
273
PS3CDROM_UNLOCK(sc);
274
275
return (BUS_PROBE_SPECIFIC);
276
277
fail_unregister_xpt_bus:
278
279
xpt_bus_deregister(cam_sim_path(sc->sc_sim));
280
281
fail_free_sim:
282
283
cam_sim_free(sc->sc_sim, TRUE);
284
285
fail_destroy_dmamap:
286
287
while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) {
288
TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
289
bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap);
290
}
291
292
fail_destroy_dmatag:
293
294
bus_dma_tag_destroy(sc->sc_dmatag);
295
296
fail_teardown_intr:
297
298
bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
299
300
fail_release_intr:
301
302
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
303
304
fail_destroy_lock:
305
306
PS3CDROM_LOCK_DESTROY(sc);
307
308
return (err);
309
}
310
311
static int
312
ps3cdrom_detach(device_t dev)
313
{
314
struct ps3cdrom_softc *sc = device_get_softc(dev);
315
int i;
316
317
xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL);
318
xpt_free_path(sc->sc_path);
319
xpt_bus_deregister(cam_sim_path(sc->sc_sim));
320
cam_sim_free(sc->sc_sim, TRUE);
321
322
for (i = 0; i < PS3CDROM_MAX_XFERS; i++)
323
bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap);
324
325
bus_dma_tag_destroy(sc->sc_dmatag);
326
327
bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
328
bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
329
330
PS3CDROM_LOCK_DESTROY(sc);
331
332
return (0);
333
}
334
335
static void
336
ps3cdrom_action(struct cam_sim *sim, union ccb *ccb)
337
{
338
struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim);
339
device_t dev = sc->sc_dev;
340
struct ps3cdrom_xfer *xp;
341
int err;
342
343
PS3CDROM_ASSERT_LOCKED(sc);
344
345
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
346
("function code 0x%02x\n", ccb->ccb_h.func_code));
347
348
switch (ccb->ccb_h.func_code) {
349
case XPT_SCSI_IO:
350
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
351
break;
352
353
if(ccb->ccb_h.target_id > 0) {
354
ccb->ccb_h.status = CAM_TID_INVALID;
355
break;
356
}
357
358
if(ccb->ccb_h.target_lun > 0) {
359
ccb->ccb_h.status = CAM_LUN_INVALID;
360
break;
361
}
362
363
xp = TAILQ_FIRST(&sc->sc_free_xferq);
364
365
KASSERT(xp != NULL, ("no free transfers"));
366
367
xp->x_ccb = ccb;
368
369
TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
370
371
err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap,
372
ccb, ps3cdrom_transfer, xp, 0);
373
if (err && err != EINPROGRESS) {
374
device_printf(dev, "Could not load DMA map (%d)\n",
375
err);
376
377
xp->x_ccb = NULL;
378
TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
379
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
380
break;
381
}
382
return;
383
case XPT_SET_TRAN_SETTINGS:
384
ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
385
break;
386
case XPT_GET_TRAN_SETTINGS:
387
{
388
struct ccb_trans_settings *cts = &ccb->cts;
389
390
cts->protocol = PROTO_SCSI;
391
cts->protocol_version = SCSI_REV_2;
392
cts->transport = XPORT_SPI;
393
cts->transport_version = 2;
394
cts->proto_specific.valid = 0;
395
cts->xport_specific.valid = 0;
396
ccb->ccb_h.status = CAM_REQ_CMP;
397
break;
398
}
399
case XPT_RESET_BUS:
400
case XPT_RESET_DEV:
401
ccb->ccb_h.status = CAM_REQ_CMP;
402
break;
403
case XPT_CALC_GEOMETRY:
404
cam_calc_geometry(&ccb->ccg, 1);
405
break;
406
case XPT_PATH_INQ:
407
{
408
struct ccb_pathinq *cpi = &ccb->cpi;
409
410
cpi->version_num = 1;
411
cpi->hba_inquiry = 0;
412
cpi->target_sprt = 0;
413
cpi->hba_inquiry = PI_SDTR_ABLE;
414
cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE;
415
cpi->hba_eng_cnt = 0;
416
bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
417
cpi->max_target = 0;
418
cpi->max_lun = 0;
419
cpi->initiator_id = 7;
420
cpi->bus_id = cam_sim_bus(sim);
421
cpi->unit_number = cam_sim_unit(sim);
422
cpi->base_transfer_speed = 150000;
423
strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
424
strlcpy(cpi->hba_vid, "Sony", HBA_IDLEN);
425
strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
426
cpi->transport = XPORT_SPI;
427
cpi->transport_version = 2;
428
cpi->protocol = PROTO_SCSI;
429
cpi->protocol_version = SCSI_REV_2;
430
cpi->maxio = PAGE_SIZE;
431
cpi->ccb_h.status = CAM_REQ_CMP;
432
break;
433
}
434
default:
435
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
436
("unsupported function code 0x%02x\n",
437
ccb->ccb_h.func_code));
438
ccb->ccb_h.status = CAM_REQ_INVALID;
439
break;
440
}
441
442
xpt_done(ccb);
443
}
444
445
static void
446
ps3cdrom_poll(struct cam_sim *sim)
447
{
448
ps3cdrom_intr(cam_sim_softc(sim));
449
}
450
451
static void
452
ps3cdrom_async(void *callback_arg, u_int32_t code,
453
struct cam_path* path, void *arg)
454
{
455
switch (code) {
456
case AC_LOST_DEVICE:
457
xpt_print_path(path);
458
break;
459
default:
460
break;
461
}
462
}
463
464
static void
465
ps3cdrom_intr(void *arg)
466
{
467
struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg;
468
device_t dev = sc->sc_dev;
469
uint64_t devid = ps3bus_get_device(dev);
470
struct ps3cdrom_xfer *xp;
471
union ccb *ccb;
472
u_int8_t *cdb, sense_key, asc, ascq;
473
uint64_t tag, status;
474
475
if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
476
return;
477
478
PS3CDROM_LOCK(sc);
479
480
/* Find transfer with the returned tag */
481
482
TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) {
483
if (xp->x_tag == tag)
484
break;
485
}
486
487
if (xp) {
488
ccb = xp->x_ccb;
489
cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
490
ccb->csio.cdb_io.cdb_ptr :
491
ccb->csio.cdb_io.cdb_bytes;
492
493
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
494
("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n",
495
cdb[0], tag, status));
496
497
if (!status) {
498
ccb->csio.scsi_status = SCSI_STATUS_OK;
499
ccb->csio.resid = 0;
500
ccb->ccb_h.status = CAM_REQ_CMP;
501
} else {
502
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
503
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
504
505
if (!ps3cdrom_decode_lv1_status(status, &sense_key,
506
&asc, &ascq)) {
507
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
508
("sense key 0x%02x asc 0x%02x ascq 0x%02x\n",
509
sense_key, asc, ascq));
510
511
scsi_set_sense_data(&ccb->csio.sense_data,
512
/*sense_format*/ SSD_TYPE_NONE,
513
/*current_error*/ 1,
514
sense_key,
515
asc,
516
ascq,
517
SSD_ELEM_NONE);
518
ccb->csio.sense_len = SSD_FULL_SIZE;
519
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
520
CAM_AUTOSNS_VALID;
521
}
522
523
if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
524
ccb->csio.resid = ccb->csio.dxfer_len;
525
}
526
527
if (ccb->ccb_h.flags & CAM_DIR_IN)
528
bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
529
BUS_DMASYNC_POSTREAD);
530
531
bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
532
533
xp->x_ccb = NULL;
534
TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue);
535
TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
536
537
xpt_done(ccb);
538
} else {
539
device_printf(dev,
540
"Could not find transfer with tag 0x%016lx\n", tag);
541
}
542
543
PS3CDROM_UNLOCK(sc);
544
}
545
546
static void
547
ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
548
{
549
struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg;
550
struct ps3cdrom_softc *sc = xp->x_sc;
551
device_t dev = sc->sc_dev;
552
uint64_t devid = ps3bus_get_device(dev);
553
union ccb *ccb = xp->x_ccb;
554
u_int8_t *cdb;
555
uint64_t start_sector, block_count;
556
int err;
557
558
KASSERT(nsegs == 1 || nsegs == 0,
559
("ps3cdrom_transfer: invalid number of DMA segments %d", nsegs));
560
KASSERT(error == 0, ("ps3cdrom_transfer: DMA error %d", error));
561
562
PS3CDROM_ASSERT_LOCKED(sc);
563
564
if (error) {
565
device_printf(dev, "Could not load DMA map (%d)\n", error);
566
567
xp->x_ccb = NULL;
568
TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
569
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
570
xpt_done(ccb);
571
return;
572
}
573
574
cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
575
ccb->csio.cdb_io.cdb_ptr :
576
ccb->csio.cdb_io.cdb_bytes;
577
578
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
579
("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0],
580
ccb->csio.cdb_len, ccb->csio.dxfer_len));
581
582
switch (cdb[0]) {
583
case READ_10:
584
KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to read"));
585
start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
586
(cdb[4] << 8) | cdb[5];
587
block_count = (cdb[7] << 8) | cdb[8];
588
589
err = lv1_storage_read(devid, 0 /* region id */,
590
start_sector, block_count, 0 /* flags */, segs[0].ds_addr,
591
&xp->x_tag);
592
bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
593
BUS_DMASYNC_POSTREAD);
594
break;
595
case WRITE_10:
596
KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to write"));
597
start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
598
(cdb[4] << 8) | cdb[5];
599
block_count = (cdb[7] << 8) | cdb[8];
600
601
bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
602
BUS_DMASYNC_PREWRITE);
603
err = lv1_storage_write(devid, 0 /* region id */,
604
start_sector, block_count, 0 /* flags */,
605
segs[0].ds_addr, &xp->x_tag);
606
break;
607
default:
608
{
609
struct lv1_atapi_cmd atapi_cmd;
610
611
bzero(&atapi_cmd, sizeof(atapi_cmd));
612
atapi_cmd.pktlen = 12;
613
bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len);
614
615
if (ccb->ccb_h.flags & CAM_DIR_IN) {
616
atapi_cmd.in_out = DIR_READ;
617
atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
618
DMA_PROTO : PIO_DATA_IN_PROTO;
619
} else if (ccb->ccb_h.flags & CAM_DIR_OUT) {
620
atapi_cmd.in_out = DIR_WRITE;
621
atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
622
DMA_PROTO : PIO_DATA_OUT_PROTO;
623
} else {
624
atapi_cmd.proto = NON_DATA_PROTO;
625
}
626
627
atapi_cmd.nblocks = atapi_cmd.arglen =
628
(nsegs == 0) ? 0 : segs[0].ds_len;
629
atapi_cmd.blksize = 1;
630
atapi_cmd.buf = (nsegs == 0) ? 0 : segs[0].ds_addr;
631
632
if (ccb->ccb_h.flags & CAM_DIR_OUT)
633
bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
634
BUS_DMASYNC_PREWRITE);
635
636
err = lv1_storage_send_device_command(devid,
637
LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd),
638
sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen,
639
&xp->x_tag);
640
641
break;
642
}
643
}
644
645
if (err) {
646
device_printf(dev, "ATAPI command 0x%02x failed (%d)\n",
647
cdb[0], err);
648
649
bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
650
651
xp->x_ccb = NULL;
652
TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
653
654
bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
655
/* Invalid field in parameter list */
656
scsi_set_sense_data(&ccb->csio.sense_data,
657
/*sense_format*/ SSD_TYPE_NONE,
658
/*current_error*/ 1,
659
/*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
660
/*asc*/ 0x26,
661
/*ascq*/ 0x00,
662
SSD_ELEM_NONE);
663
664
ccb->csio.sense_len = SSD_FULL_SIZE;
665
ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
666
ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
667
xpt_done(ccb);
668
} else {
669
CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
670
("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0],
671
xp->x_tag));
672
673
TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue);
674
ccb->ccb_h.status |= CAM_SIM_QUEUED;
675
}
676
}
677
678
static int
679
ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc,
680
u_int8_t *ascq)
681
{
682
if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND)
683
return -1;
684
685
*sense_key = (status >> 16) & 0xff;
686
*asc = (status >> 8) & 0xff;
687
*ascq = status & 0xff;
688
689
return (0);
690
}
691
692
static device_method_t ps3cdrom_methods[] = {
693
DEVMETHOD(device_probe, ps3cdrom_probe),
694
DEVMETHOD(device_attach, ps3cdrom_attach),
695
DEVMETHOD(device_detach, ps3cdrom_detach),
696
{0, 0},
697
};
698
699
static driver_t ps3cdrom_driver = {
700
"ps3cdrom",
701
ps3cdrom_methods,
702
sizeof(struct ps3cdrom_softc),
703
};
704
705
DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, 0, 0);
706
MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1);
707
708