1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (C) 2010 Nathan Whitehorn
5 * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
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
ps3cdrom_probe(device_t dev)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
ps3cdrom_attach(device_t dev)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
ps3cdrom_detach(device_t dev)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
ps3cdrom_action(struct cam_sim * sim,union ccb * ccb)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
ps3cdrom_poll(struct cam_sim * sim)446 ps3cdrom_poll(struct cam_sim *sim)
447 {
448 ps3cdrom_intr(cam_sim_softc(sim));
449 }
450
451 static void
ps3cdrom_async(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)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
ps3cdrom_intr(void * arg)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
ps3cdrom_transfer(void * arg,bus_dma_segment_t * segs,int nsegs,int error)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
ps3cdrom_decode_lv1_status(uint64_t status,u_int8_t * sense_key,u_int8_t * asc,u_int8_t * ascq)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