2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2010 Nathan Whitehorn
5 * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <sys/param.h>
34 #include <sys/module.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
40 #include <sys/kthread.h>
42 #include <sys/malloc.h>
43 #include <sys/mutex.h>
48 #include <machine/pio.h>
49 #include <machine/bus.h>
50 #include <machine/platform.h>
51 #include <machine/resource.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/cam_sim.h>
58 #include <cam/cam_xpt_sim.h>
59 #include <cam/cam_debug.h>
60 #include <cam/scsi/scsi_all.h>
63 #include "ps3-hvcall.h"
65 #define PS3CDROM_LOCK_INIT(_sc) \
66 mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \
68 #define PS3CDROM_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
69 #define PS3CDROM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
70 #define PS3CDROM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
71 #define PS3CDROM_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
72 #define PS3CDROM_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
74 #define PS3CDROM_MAX_XFERS 3
76 #define LV1_STORAGE_SEND_ATAPI_COMMAND 0x01
78 struct ps3cdrom_softc;
80 struct ps3cdrom_xfer {
81 TAILQ_ENTRY(ps3cdrom_xfer) x_queue;
82 struct ps3cdrom_softc *x_sc;
84 bus_dmamap_t x_dmamap;
88 TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer);
90 struct ps3cdrom_softc {
99 struct resource *sc_irq;
102 bus_dma_tag_t sc_dmatag;
104 struct cam_sim *sc_sim;
105 struct cam_path *sc_path;
107 struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS];
108 struct ps3cdrom_xferq sc_active_xferq;
109 struct ps3cdrom_xferq sc_free_xferq;
113 NON_DATA_PROTO = 0x00,
114 PIO_DATA_IN_PROTO = 0x01,
115 PIO_DATA_OUT_PROTO = 0x02,
119 enum lv1_ata_in_out {
124 struct lv1_atapi_cmd {
129 uint32_t proto; /* enum lv1_ata_proto */
130 uint32_t in_out; /* enum lv1_ata_in_out */
135 static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb);
136 static void ps3cdrom_poll(struct cam_sim *sim);
137 static void ps3cdrom_async(void *callback_arg, u_int32_t code,
138 struct cam_path* path, void *arg);
140 static void ps3cdrom_intr(void *arg);
142 static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
145 static int ps3cdrom_decode_lv1_status(uint64_t status,
146 u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq);
149 ps3cdrom_probe(device_t dev)
151 if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
152 ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM)
155 device_set_desc(dev, "Playstation 3 CDROM");
157 return (BUS_PROBE_SPECIFIC);
161 ps3cdrom_attach(device_t dev)
163 struct ps3cdrom_softc *sc = device_get_softc(dev);
164 struct cam_devq *devq;
165 struct ps3cdrom_xfer *xp;
166 struct ccb_setasync csa;
171 PS3CDROM_LOCK_INIT(sc);
173 /* Setup interrupt handler */
176 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
179 device_printf(dev, "Could not allocate IRQ\n");
181 goto fail_destroy_lock;
184 err = bus_setup_intr(dev, sc->sc_irq,
185 INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY,
186 NULL, ps3cdrom_intr, sc, &sc->sc_irqctx);
188 device_printf(dev, "Could not setup IRQ\n");
190 goto fail_release_intr;
195 err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
196 BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
197 BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
198 busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
200 device_printf(dev, "Could not create DMA tag\n");
202 goto fail_teardown_intr;
205 /* Setup transfer queues */
207 TAILQ_INIT(&sc->sc_active_xferq);
208 TAILQ_INIT(&sc->sc_free_xferq);
210 for (i = 0; i < PS3CDROM_MAX_XFERS; i++) {
211 xp = &sc->sc_xfer[i];
214 err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
217 device_printf(dev, "Could not create DMA map (%d)\n",
219 goto fail_destroy_dmamap;
222 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
227 devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1);
229 device_printf(dev, "Could not allocate SIM queue\n");
231 goto fail_destroy_dmatag;
234 sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom",
235 sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0,
238 device_printf(dev, "Could not allocate SIM\n");
241 goto fail_destroy_dmatag;
248 err = xpt_bus_register(sc->sc_sim, dev, 0);
249 if (err != CAM_SUCCESS) {
250 device_printf(dev, "Could not register XPT bus\n");
256 err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim),
257 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
258 if (err != CAM_REQ_CMP) {
259 device_printf(dev, "Could not create XPT path\n");
262 goto fail_unregister_xpt_bus;
265 xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5);
266 csa.ccb_h.func_code = XPT_SASYNC_CB;
267 csa.event_enable = AC_LOST_DEVICE;
268 csa.callback = ps3cdrom_async;
269 csa.callback_arg = sc->sc_sim;
270 xpt_action((union ccb *) &csa);
272 CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE,
273 ("registered SIM for ps3cdrom%d\n", device_get_unit(dev)));
277 return (BUS_PROBE_SPECIFIC);
279 fail_unregister_xpt_bus:
281 xpt_bus_deregister(cam_sim_path(sc->sc_sim));
285 cam_sim_free(sc->sc_sim, TRUE);
289 while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) {
290 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
291 bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap);
296 bus_dma_tag_destroy(sc->sc_dmatag);
300 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
304 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
308 PS3CDROM_LOCK_DESTROY(sc);
314 ps3cdrom_detach(device_t dev)
316 struct ps3cdrom_softc *sc = device_get_softc(dev);
319 xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL);
320 xpt_free_path(sc->sc_path);
321 xpt_bus_deregister(cam_sim_path(sc->sc_sim));
322 cam_sim_free(sc->sc_sim, TRUE);
324 for (i = 0; i < PS3CDROM_MAX_XFERS; i++)
325 bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap);
327 bus_dma_tag_destroy(sc->sc_dmatag);
329 bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
330 bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
332 PS3CDROM_LOCK_DESTROY(sc);
338 ps3cdrom_action(struct cam_sim *sim, union ccb *ccb)
340 struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim);
341 device_t dev = sc->sc_dev;
342 struct ps3cdrom_xfer *xp;
345 PS3CDROM_ASSERT_LOCKED(sc);
347 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
348 ("function code 0x%02x\n", ccb->ccb_h.func_code));
350 switch (ccb->ccb_h.func_code) {
352 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
355 if(ccb->ccb_h.target_id > 0) {
356 ccb->ccb_h.status = CAM_TID_INVALID;
360 if(ccb->ccb_h.target_lun > 0) {
361 ccb->ccb_h.status = CAM_LUN_INVALID;
365 xp = TAILQ_FIRST(&sc->sc_free_xferq);
367 KASSERT(xp != NULL, ("no free transfers"));
371 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
373 err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap,
374 ccb, ps3cdrom_transfer, xp, 0);
375 if (err && err != EINPROGRESS) {
376 device_printf(dev, "Could not load DMA map (%d)\n",
380 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
381 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
385 case XPT_SET_TRAN_SETTINGS:
386 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
388 case XPT_GET_TRAN_SETTINGS:
390 struct ccb_trans_settings *cts = &ccb->cts;
392 cts->protocol = PROTO_SCSI;
393 cts->protocol_version = SCSI_REV_2;
394 cts->transport = XPORT_SPI;
395 cts->transport_version = 2;
396 cts->proto_specific.valid = 0;
397 cts->xport_specific.valid = 0;
398 ccb->ccb_h.status = CAM_REQ_CMP;
403 ccb->ccb_h.status = CAM_REQ_CMP;
405 case XPT_CALC_GEOMETRY:
406 cam_calc_geometry(&ccb->ccg, 1);
410 struct ccb_pathinq *cpi = &ccb->cpi;
412 cpi->version_num = 1;
413 cpi->hba_inquiry = 0;
414 cpi->target_sprt = 0;
415 cpi->hba_inquiry = PI_SDTR_ABLE;
416 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE;
417 cpi->hba_eng_cnt = 0;
418 bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
421 cpi->initiator_id = 7;
422 cpi->bus_id = cam_sim_bus(sim);
423 cpi->unit_number = cam_sim_unit(sim);
424 cpi->base_transfer_speed = 150000;
425 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
426 strlcpy(cpi->hba_vid, "Sony", HBA_IDLEN);
427 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
428 cpi->transport = XPORT_SPI;
429 cpi->transport_version = 2;
430 cpi->protocol = PROTO_SCSI;
431 cpi->protocol_version = SCSI_REV_2;
432 cpi->maxio = PAGE_SIZE;
433 cpi->ccb_h.status = CAM_REQ_CMP;
437 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
438 ("unsupported function code 0x%02x\n",
439 ccb->ccb_h.func_code));
440 ccb->ccb_h.status = CAM_REQ_INVALID;
448 ps3cdrom_poll(struct cam_sim *sim)
450 ps3cdrom_intr(cam_sim_softc(sim));
454 ps3cdrom_async(void *callback_arg, u_int32_t code,
455 struct cam_path* path, void *arg)
459 xpt_print_path(path);
467 ps3cdrom_intr(void *arg)
469 struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg;
470 device_t dev = sc->sc_dev;
471 uint64_t devid = ps3bus_get_device(dev);
472 struct ps3cdrom_xfer *xp;
474 u_int8_t *cdb, sense_key, asc, ascq;
475 uint64_t tag, status;
477 if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
482 /* Find transfer with the returned tag */
484 TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) {
485 if (xp->x_tag == tag)
491 cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
492 ccb->csio.cdb_io.cdb_ptr :
493 ccb->csio.cdb_io.cdb_bytes;
495 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
496 ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n",
497 cdb[0], tag, status));
500 ccb->csio.scsi_status = SCSI_STATUS_OK;
502 ccb->ccb_h.status = CAM_REQ_CMP;
504 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
505 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
507 if (!ps3cdrom_decode_lv1_status(status, &sense_key,
509 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
510 ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n",
511 sense_key, asc, ascq));
513 scsi_set_sense_data(&ccb->csio.sense_data,
514 /*sense_format*/ SSD_TYPE_NONE,
520 ccb->csio.sense_len = SSD_FULL_SIZE;
521 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
525 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
526 ccb->csio.resid = ccb->csio.dxfer_len;
529 if (ccb->ccb_h.flags & CAM_DIR_IN)
530 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
531 BUS_DMASYNC_POSTREAD);
533 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
536 TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue);
537 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
542 "Could not find transfer with tag 0x%016lx\n", tag);
549 ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
551 struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg;
552 struct ps3cdrom_softc *sc = xp->x_sc;
553 device_t dev = sc->sc_dev;
554 uint64_t devid = ps3bus_get_device(dev);
555 union ccb *ccb = xp->x_ccb;
557 uint64_t start_sector, block_count;
560 KASSERT(nsegs == 1 || nsegs == 0,
561 ("ps3cdrom_transfer: invalid number of DMA segments %d", nsegs));
562 KASSERT(error == 0, ("ps3cdrom_transfer: DMA error %d", error));
564 PS3CDROM_ASSERT_LOCKED(sc);
567 device_printf(dev, "Could not load DMA map (%d)\n", error);
570 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
571 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
576 cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
577 ccb->csio.cdb_io.cdb_ptr :
578 ccb->csio.cdb_io.cdb_bytes;
580 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
581 ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0],
582 ccb->csio.cdb_len, ccb->csio.dxfer_len));
586 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to read"));
587 start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
588 (cdb[4] << 8) | cdb[5];
589 block_count = (cdb[7] << 8) | cdb[8];
591 err = lv1_storage_read(devid, 0 /* region id */,
592 start_sector, block_count, 0 /* flags */, segs[0].ds_addr,
594 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
595 BUS_DMASYNC_POSTREAD);
598 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to write"));
599 start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
600 (cdb[4] << 8) | cdb[5];
601 block_count = (cdb[7] << 8) | cdb[8];
603 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
604 BUS_DMASYNC_PREWRITE);
605 err = lv1_storage_write(devid, 0 /* region id */,
606 start_sector, block_count, 0 /* flags */,
607 segs[0].ds_addr, &xp->x_tag);
611 struct lv1_atapi_cmd atapi_cmd;
613 bzero(&atapi_cmd, sizeof(atapi_cmd));
614 atapi_cmd.pktlen = 12;
615 bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len);
617 if (ccb->ccb_h.flags & CAM_DIR_IN) {
618 atapi_cmd.in_out = DIR_READ;
619 atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
620 DMA_PROTO : PIO_DATA_IN_PROTO;
621 } else if (ccb->ccb_h.flags & CAM_DIR_OUT) {
622 atapi_cmd.in_out = DIR_WRITE;
623 atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
624 DMA_PROTO : PIO_DATA_OUT_PROTO;
626 atapi_cmd.proto = NON_DATA_PROTO;
629 atapi_cmd.nblocks = atapi_cmd.arglen =
630 (nsegs == 0) ? 0 : segs[0].ds_len;
631 atapi_cmd.blksize = 1;
632 atapi_cmd.buf = (nsegs == 0) ? 0 : segs[0].ds_addr;
634 if (ccb->ccb_h.flags & CAM_DIR_OUT)
635 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
636 BUS_DMASYNC_PREWRITE);
638 err = lv1_storage_send_device_command(devid,
639 LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd),
640 sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen,
648 device_printf(dev, "ATAPI command 0x%02x failed (%d)\n",
651 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
654 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
656 bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
657 /* Invalid field in parameter list */
658 scsi_set_sense_data(&ccb->csio.sense_data,
659 /*sense_format*/ SSD_TYPE_NONE,
661 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
666 ccb->csio.sense_len = SSD_FULL_SIZE;
667 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
668 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
671 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
672 ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0],
675 TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue);
676 ccb->ccb_h.status |= CAM_SIM_QUEUED;
681 ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc,
684 if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND)
687 *sense_key = (status >> 16) & 0xff;
688 *asc = (status >> 8) & 0xff;
689 *ascq = status & 0xff;
694 static device_method_t ps3cdrom_methods[] = {
695 DEVMETHOD(device_probe, ps3cdrom_probe),
696 DEVMETHOD(device_attach, ps3cdrom_attach),
697 DEVMETHOD(device_detach, ps3cdrom_detach),
701 static driver_t ps3cdrom_driver = {
704 sizeof(struct ps3cdrom_softc),
707 static devclass_t ps3cdrom_devclass;
709 DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0);
710 MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1);