19f2c359fSNathan Whitehorn /*- 29f2c359fSNathan Whitehorn * Copyright (C) 2010 Nathan Whitehorn 39f2c359fSNathan Whitehorn * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru> 49f2c359fSNathan Whitehorn * All rights reserved. 59f2c359fSNathan Whitehorn * 69f2c359fSNathan Whitehorn * Redistribution and use in source and binary forms, with or without 79f2c359fSNathan Whitehorn * modification, are permitted provided that the following conditions 89f2c359fSNathan Whitehorn * are met: 99f2c359fSNathan Whitehorn * 1. Redistributions of source code must retain the above copyright 109f2c359fSNathan Whitehorn * notice, this list of conditions and the following disclaimer, 119f2c359fSNathan Whitehorn * without modification, immediately at the beginning of the file. 129f2c359fSNathan Whitehorn * 2. Redistributions in binary form must reproduce the above copyright 139f2c359fSNathan Whitehorn * notice, this list of conditions and the following disclaimer in the 149f2c359fSNathan Whitehorn * documentation and/or other materials provided with the distribution. 159f2c359fSNathan Whitehorn * 169f2c359fSNathan Whitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 179f2c359fSNathan Whitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 189f2c359fSNathan Whitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 199f2c359fSNathan Whitehorn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 209f2c359fSNathan Whitehorn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 219f2c359fSNathan Whitehorn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 229f2c359fSNathan Whitehorn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 239f2c359fSNathan Whitehorn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 249f2c359fSNathan Whitehorn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 259f2c359fSNathan Whitehorn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 269f2c359fSNathan Whitehorn */ 279f2c359fSNathan Whitehorn 289f2c359fSNathan Whitehorn #include <sys/cdefs.h> 299f2c359fSNathan Whitehorn __FBSDID("$FreeBSD$"); 309f2c359fSNathan Whitehorn 319f2c359fSNathan Whitehorn #include <sys/param.h> 329f2c359fSNathan Whitehorn #include <sys/module.h> 339f2c359fSNathan Whitehorn #include <sys/systm.h> 349f2c359fSNathan Whitehorn #include <sys/kernel.h> 359f2c359fSNathan Whitehorn #include <sys/ata.h> 369f2c359fSNathan Whitehorn #include <sys/bus.h> 379f2c359fSNathan Whitehorn #include <sys/conf.h> 389f2c359fSNathan Whitehorn #include <sys/kthread.h> 399f2c359fSNathan Whitehorn #include <sys/lock.h> 409f2c359fSNathan Whitehorn #include <sys/malloc.h> 419f2c359fSNathan Whitehorn #include <sys/mutex.h> 429f2c359fSNathan Whitehorn 439f2c359fSNathan Whitehorn #include <vm/vm.h> 449f2c359fSNathan Whitehorn #include <vm/pmap.h> 459f2c359fSNathan Whitehorn 469f2c359fSNathan Whitehorn #include <machine/pio.h> 479f2c359fSNathan Whitehorn #include <machine/bus.h> 489f2c359fSNathan Whitehorn #include <machine/platform.h> 499f2c359fSNathan Whitehorn #include <machine/pmap.h> 509f2c359fSNathan Whitehorn #include <machine/resource.h> 519f2c359fSNathan Whitehorn #include <sys/bus.h> 529f2c359fSNathan Whitehorn #include <sys/rman.h> 539f2c359fSNathan Whitehorn 549f2c359fSNathan Whitehorn #include <cam/cam.h> 559f2c359fSNathan Whitehorn #include <cam/cam_ccb.h> 569f2c359fSNathan Whitehorn #include <cam/cam_sim.h> 579f2c359fSNathan Whitehorn #include <cam/cam_xpt_sim.h> 589f2c359fSNathan Whitehorn #include <cam/cam_debug.h> 599f2c359fSNathan Whitehorn #include <cam/scsi/scsi_all.h> 609f2c359fSNathan Whitehorn 619f2c359fSNathan Whitehorn #include "ps3bus.h" 629f2c359fSNathan Whitehorn #include "ps3-hvcall.h" 639f2c359fSNathan Whitehorn 649f2c359fSNathan Whitehorn #define PS3CDROM_LOCK_INIT(_sc) \ 659f2c359fSNathan Whitehorn mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \ 669f2c359fSNathan Whitehorn MTX_DEF) 679f2c359fSNathan Whitehorn #define PS3CDROM_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx); 689f2c359fSNathan Whitehorn #define PS3CDROM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) 699f2c359fSNathan Whitehorn #define PS3CDROM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) 709f2c359fSNathan Whitehorn #define PS3CDROM_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED); 719f2c359fSNathan Whitehorn #define PS3CDROM_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED); 729f2c359fSNathan Whitehorn 739f2c359fSNathan Whitehorn #define PS3CDROM_MAX_XFERS 3 749f2c359fSNathan Whitehorn 759f2c359fSNathan Whitehorn #define LV1_STORAGE_SEND_ATAPI_COMMAND 0x01 769f2c359fSNathan Whitehorn 779f2c359fSNathan Whitehorn struct ps3cdrom_softc; 789f2c359fSNathan Whitehorn 799f2c359fSNathan Whitehorn struct ps3cdrom_xfer { 809f2c359fSNathan Whitehorn TAILQ_ENTRY(ps3cdrom_xfer) x_queue; 819f2c359fSNathan Whitehorn struct ps3cdrom_softc *x_sc; 829f2c359fSNathan Whitehorn union ccb *x_ccb; 839f2c359fSNathan Whitehorn bus_dmamap_t x_dmamap; 849f2c359fSNathan Whitehorn uint64_t x_tag; 859f2c359fSNathan Whitehorn }; 869f2c359fSNathan Whitehorn 879f2c359fSNathan Whitehorn TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer); 889f2c359fSNathan Whitehorn 899f2c359fSNathan Whitehorn struct ps3cdrom_softc { 909f2c359fSNathan Whitehorn device_t sc_dev; 919f2c359fSNathan Whitehorn 929f2c359fSNathan Whitehorn struct mtx sc_mtx; 939f2c359fSNathan Whitehorn 949f2c359fSNathan Whitehorn uint64_t sc_blksize; 959f2c359fSNathan Whitehorn uint64_t sc_nblocks; 969f2c359fSNathan Whitehorn 979f2c359fSNathan Whitehorn int sc_irqid; 989f2c359fSNathan Whitehorn struct resource *sc_irq; 999f2c359fSNathan Whitehorn void *sc_irqctx; 1009f2c359fSNathan Whitehorn 1019f2c359fSNathan Whitehorn bus_dma_tag_t sc_dmatag; 1029f2c359fSNathan Whitehorn 1039f2c359fSNathan Whitehorn struct cam_sim *sc_sim; 1049f2c359fSNathan Whitehorn struct cam_path *sc_path; 1059f2c359fSNathan Whitehorn 1069f2c359fSNathan Whitehorn struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS]; 1079f2c359fSNathan Whitehorn struct ps3cdrom_xferq sc_active_xferq; 1089f2c359fSNathan Whitehorn struct ps3cdrom_xferq sc_free_xferq; 1099f2c359fSNathan Whitehorn }; 1109f2c359fSNathan Whitehorn 1119f2c359fSNathan Whitehorn enum lv1_ata_proto { 1129f2c359fSNathan Whitehorn NON_DATA_PROTO = 0x00, 1139f2c359fSNathan Whitehorn PIO_DATA_IN_PROTO = 0x01, 1149f2c359fSNathan Whitehorn PIO_DATA_OUT_PROTO = 0x02, 1159f2c359fSNathan Whitehorn DMA_PROTO = 0x03 1169f2c359fSNathan Whitehorn }; 1179f2c359fSNathan Whitehorn 1189f2c359fSNathan Whitehorn enum lv1_ata_in_out { 1199f2c359fSNathan Whitehorn DIR_WRITE = 0x00, 1209f2c359fSNathan Whitehorn DIR_READ = 0x01 1219f2c359fSNathan Whitehorn }; 1229f2c359fSNathan Whitehorn 1239f2c359fSNathan Whitehorn struct lv1_atapi_cmd { 1249f2c359fSNathan Whitehorn uint8_t pkt[32]; 1259f2c359fSNathan Whitehorn uint32_t pktlen; 1269f2c359fSNathan Whitehorn uint32_t nblocks; 1279f2c359fSNathan Whitehorn uint32_t blksize; 1289f2c359fSNathan Whitehorn uint32_t proto; /* enum lv1_ata_proto */ 1299f2c359fSNathan Whitehorn uint32_t in_out; /* enum lv1_ata_in_out */ 1309f2c359fSNathan Whitehorn uint64_t buf; 1319f2c359fSNathan Whitehorn uint32_t arglen; 1329f2c359fSNathan Whitehorn }; 1339f2c359fSNathan Whitehorn 1349f2c359fSNathan Whitehorn static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb); 1359f2c359fSNathan Whitehorn static void ps3cdrom_poll(struct cam_sim *sim); 1369f2c359fSNathan Whitehorn static void ps3cdrom_async(void *callback_arg, u_int32_t code, 1379f2c359fSNathan Whitehorn struct cam_path* path, void *arg); 1389f2c359fSNathan Whitehorn 1399f2c359fSNathan Whitehorn static void ps3cdrom_intr(void *arg); 1409f2c359fSNathan Whitehorn 1419f2c359fSNathan Whitehorn static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, 1429f2c359fSNathan Whitehorn int error); 1439f2c359fSNathan Whitehorn 1449f2c359fSNathan Whitehorn static int ps3cdrom_decode_lv1_status(uint64_t status, 1459f2c359fSNathan Whitehorn u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq); 1469f2c359fSNathan Whitehorn 1479f2c359fSNathan Whitehorn static int 1489f2c359fSNathan Whitehorn ps3cdrom_probe(device_t dev) 1499f2c359fSNathan Whitehorn { 1509f2c359fSNathan Whitehorn if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE || 1519f2c359fSNathan Whitehorn ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM) 1529f2c359fSNathan Whitehorn return (ENXIO); 1539f2c359fSNathan Whitehorn 1549f2c359fSNathan Whitehorn device_set_desc(dev, "Playstation 3 CDROM"); 1559f2c359fSNathan Whitehorn 1569f2c359fSNathan Whitehorn return (BUS_PROBE_SPECIFIC); 1579f2c359fSNathan Whitehorn } 1589f2c359fSNathan Whitehorn 1599f2c359fSNathan Whitehorn static int 1609f2c359fSNathan Whitehorn ps3cdrom_attach(device_t dev) 1619f2c359fSNathan Whitehorn { 1629f2c359fSNathan Whitehorn struct ps3cdrom_softc *sc = device_get_softc(dev); 1639f2c359fSNathan Whitehorn struct cam_devq *devq; 1649f2c359fSNathan Whitehorn struct ps3cdrom_xfer *xp; 1659f2c359fSNathan Whitehorn struct ccb_setasync csa; 1669f2c359fSNathan Whitehorn int i, err; 1679f2c359fSNathan Whitehorn 1689f2c359fSNathan Whitehorn sc->sc_dev = dev; 1699f2c359fSNathan Whitehorn 1709f2c359fSNathan Whitehorn PS3CDROM_LOCK_INIT(sc); 1719f2c359fSNathan Whitehorn 1729f2c359fSNathan Whitehorn /* Setup interrupt handler */ 1739f2c359fSNathan Whitehorn 1749f2c359fSNathan Whitehorn sc->sc_irqid = 0; 1759f2c359fSNathan Whitehorn sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid, 1769f2c359fSNathan Whitehorn RF_ACTIVE); 1779f2c359fSNathan Whitehorn if (!sc->sc_irq) { 1789f2c359fSNathan Whitehorn device_printf(dev, "Could not allocate IRQ\n"); 1799f2c359fSNathan Whitehorn err = ENXIO; 1809f2c359fSNathan Whitehorn goto fail_destroy_lock; 1819f2c359fSNathan Whitehorn } 1829f2c359fSNathan Whitehorn 1839f2c359fSNathan Whitehorn err = bus_setup_intr(dev, sc->sc_irq, 1849f2c359fSNathan Whitehorn INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY, 1859f2c359fSNathan Whitehorn NULL, ps3cdrom_intr, sc, &sc->sc_irqctx); 1869f2c359fSNathan Whitehorn if (err) { 1879f2c359fSNathan Whitehorn device_printf(dev, "Could not setup IRQ\n"); 1889f2c359fSNathan Whitehorn err = ENXIO; 1899f2c359fSNathan Whitehorn goto fail_release_intr; 1909f2c359fSNathan Whitehorn } 1919f2c359fSNathan Whitehorn 1929f2c359fSNathan Whitehorn /* Setup DMA */ 1939f2c359fSNathan Whitehorn 1949f2c359fSNathan Whitehorn err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0, 1959f2c359fSNathan Whitehorn BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, 1969f2c359fSNathan Whitehorn BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0, 1979f2c359fSNathan Whitehorn busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag); 1989f2c359fSNathan Whitehorn if (err) { 1999f2c359fSNathan Whitehorn device_printf(dev, "Could not create DMA tag\n"); 2009f2c359fSNathan Whitehorn err = ENXIO; 2019f2c359fSNathan Whitehorn goto fail_teardown_intr; 2029f2c359fSNathan Whitehorn } 2039f2c359fSNathan Whitehorn 2049f2c359fSNathan Whitehorn /* Setup transfer queues */ 2059f2c359fSNathan Whitehorn 2069f2c359fSNathan Whitehorn TAILQ_INIT(&sc->sc_active_xferq); 2079f2c359fSNathan Whitehorn TAILQ_INIT(&sc->sc_free_xferq); 2089f2c359fSNathan Whitehorn 2099f2c359fSNathan Whitehorn for (i = 0; i < PS3CDROM_MAX_XFERS; i++) { 2109f2c359fSNathan Whitehorn xp = &sc->sc_xfer[i]; 2119f2c359fSNathan Whitehorn xp->x_sc = sc; 2129f2c359fSNathan Whitehorn 2139f2c359fSNathan Whitehorn err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT, 2149f2c359fSNathan Whitehorn &xp->x_dmamap); 2159f2c359fSNathan Whitehorn if (err) { 2169f2c359fSNathan Whitehorn device_printf(dev, "Could not create DMA map (%d)\n", 2179f2c359fSNathan Whitehorn err); 2189f2c359fSNathan Whitehorn goto fail_destroy_dmamap; 2199f2c359fSNathan Whitehorn } 2209f2c359fSNathan Whitehorn 2219f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 2229f2c359fSNathan Whitehorn } 2239f2c359fSNathan Whitehorn 2249f2c359fSNathan Whitehorn /* Setup CAM */ 2259f2c359fSNathan Whitehorn 2269f2c359fSNathan Whitehorn devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1); 2279f2c359fSNathan Whitehorn if (!devq) { 2289f2c359fSNathan Whitehorn device_printf(dev, "Could not allocate SIM queue\n"); 2299f2c359fSNathan Whitehorn err = ENOMEM; 2309f2c359fSNathan Whitehorn goto fail_destroy_dmatag; 2319f2c359fSNathan Whitehorn } 2329f2c359fSNathan Whitehorn 2339f2c359fSNathan Whitehorn sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom", 2349f2c359fSNathan Whitehorn sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0, 2359f2c359fSNathan Whitehorn devq); 2369f2c359fSNathan Whitehorn if (!sc->sc_sim) { 2379f2c359fSNathan Whitehorn device_printf(dev, "Could not allocate SIM\n"); 2389f2c359fSNathan Whitehorn cam_simq_free(devq); 2399f2c359fSNathan Whitehorn err = ENOMEM; 2409f2c359fSNathan Whitehorn goto fail_destroy_dmatag; 2419f2c359fSNathan Whitehorn } 2429f2c359fSNathan Whitehorn 2439f2c359fSNathan Whitehorn /* Setup XPT */ 2449f2c359fSNathan Whitehorn 2459f2c359fSNathan Whitehorn PS3CDROM_LOCK(sc); 2469f2c359fSNathan Whitehorn 2479f2c359fSNathan Whitehorn err = xpt_bus_register(sc->sc_sim, dev, 0); 2489f2c359fSNathan Whitehorn if (err != CAM_SUCCESS) { 2499f2c359fSNathan Whitehorn device_printf(dev, "Could not register XPT bus\n"); 2509f2c359fSNathan Whitehorn err = ENXIO; 2519f2c359fSNathan Whitehorn PS3CDROM_UNLOCK(sc); 2529f2c359fSNathan Whitehorn goto fail_free_sim; 2539f2c359fSNathan Whitehorn } 2549f2c359fSNathan Whitehorn 2559f2c359fSNathan Whitehorn err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim), 2569f2c359fSNathan Whitehorn CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); 2579f2c359fSNathan Whitehorn if (err != CAM_REQ_CMP) { 2589f2c359fSNathan Whitehorn device_printf(dev, "Could not create XPT path\n"); 2599f2c359fSNathan Whitehorn err = ENOMEM; 2609f2c359fSNathan Whitehorn PS3CDROM_UNLOCK(sc); 2619f2c359fSNathan Whitehorn goto fail_unregister_xpt_bus; 2629f2c359fSNathan Whitehorn } 2639f2c359fSNathan Whitehorn 2649f2c359fSNathan Whitehorn xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5); 2659f2c359fSNathan Whitehorn csa.ccb_h.func_code = XPT_SASYNC_CB; 2669f2c359fSNathan Whitehorn csa.event_enable = AC_LOST_DEVICE; 2679f2c359fSNathan Whitehorn csa.callback = ps3cdrom_async; 2689f2c359fSNathan Whitehorn csa.callback_arg = sc->sc_sim; 2699f2c359fSNathan Whitehorn xpt_action((union ccb *) &csa); 2709f2c359fSNathan Whitehorn 2719f2c359fSNathan Whitehorn CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE, 2729f2c359fSNathan Whitehorn ("registered SIM for ps3cdrom%d\n", device_get_unit(dev))); 2739f2c359fSNathan Whitehorn 2749f2c359fSNathan Whitehorn PS3CDROM_UNLOCK(sc); 2759f2c359fSNathan Whitehorn 2769f2c359fSNathan Whitehorn return (BUS_PROBE_SPECIFIC); 2779f2c359fSNathan Whitehorn 2789f2c359fSNathan Whitehorn fail_unregister_xpt_bus: 2799f2c359fSNathan Whitehorn 2809f2c359fSNathan Whitehorn xpt_bus_deregister(cam_sim_path(sc->sc_sim)); 2819f2c359fSNathan Whitehorn 2829f2c359fSNathan Whitehorn fail_free_sim: 2839f2c359fSNathan Whitehorn 2849f2c359fSNathan Whitehorn cam_sim_free(sc->sc_sim, TRUE); 2859f2c359fSNathan Whitehorn 2869f2c359fSNathan Whitehorn fail_destroy_dmamap: 2879f2c359fSNathan Whitehorn 2889f2c359fSNathan Whitehorn while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) { 2899f2c359fSNathan Whitehorn TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue); 2909f2c359fSNathan Whitehorn bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap); 2919f2c359fSNathan Whitehorn } 2929f2c359fSNathan Whitehorn 2939f2c359fSNathan Whitehorn fail_destroy_dmatag: 2949f2c359fSNathan Whitehorn 2959f2c359fSNathan Whitehorn bus_dma_tag_destroy(sc->sc_dmatag); 2969f2c359fSNathan Whitehorn 2979f2c359fSNathan Whitehorn fail_teardown_intr: 2989f2c359fSNathan Whitehorn 2999f2c359fSNathan Whitehorn bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); 3009f2c359fSNathan Whitehorn 3019f2c359fSNathan Whitehorn fail_release_intr: 3029f2c359fSNathan Whitehorn 3039f2c359fSNathan Whitehorn bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); 3049f2c359fSNathan Whitehorn 3059f2c359fSNathan Whitehorn fail_destroy_lock: 3069f2c359fSNathan Whitehorn 3079f2c359fSNathan Whitehorn PS3CDROM_LOCK_DESTROY(sc); 3089f2c359fSNathan Whitehorn 3099f2c359fSNathan Whitehorn return (err); 3109f2c359fSNathan Whitehorn } 3119f2c359fSNathan Whitehorn 3129f2c359fSNathan Whitehorn static int 3139f2c359fSNathan Whitehorn ps3cdrom_detach(device_t dev) 3149f2c359fSNathan Whitehorn { 3159f2c359fSNathan Whitehorn struct ps3cdrom_softc *sc = device_get_softc(dev); 3169f2c359fSNathan Whitehorn int i; 3179f2c359fSNathan Whitehorn 3189f2c359fSNathan Whitehorn xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL); 3199f2c359fSNathan Whitehorn xpt_free_path(sc->sc_path); 3209f2c359fSNathan Whitehorn xpt_bus_deregister(cam_sim_path(sc->sc_sim)); 3219f2c359fSNathan Whitehorn cam_sim_free(sc->sc_sim, TRUE); 3229f2c359fSNathan Whitehorn 3239f2c359fSNathan Whitehorn for (i = 0; i < PS3CDROM_MAX_XFERS; i++) 3249f2c359fSNathan Whitehorn bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap); 3259f2c359fSNathan Whitehorn 3269f2c359fSNathan Whitehorn bus_dma_tag_destroy(sc->sc_dmatag); 3279f2c359fSNathan Whitehorn 3289f2c359fSNathan Whitehorn bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx); 3299f2c359fSNathan Whitehorn bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq); 3309f2c359fSNathan Whitehorn 3319f2c359fSNathan Whitehorn PS3CDROM_LOCK_DESTROY(sc); 3329f2c359fSNathan Whitehorn 3339f2c359fSNathan Whitehorn return (0); 3349f2c359fSNathan Whitehorn } 3359f2c359fSNathan Whitehorn 3369f2c359fSNathan Whitehorn static void 3379f2c359fSNathan Whitehorn ps3cdrom_action(struct cam_sim *sim, union ccb *ccb) 3389f2c359fSNathan Whitehorn { 3399f2c359fSNathan Whitehorn struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim); 3409f2c359fSNathan Whitehorn device_t dev = sc->sc_dev; 3419f2c359fSNathan Whitehorn struct ps3cdrom_xfer *xp; 3429f2c359fSNathan Whitehorn int err; 3439f2c359fSNathan Whitehorn 3449f2c359fSNathan Whitehorn PS3CDROM_ASSERT_LOCKED(sc); 3459f2c359fSNathan Whitehorn 3469f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 3479f2c359fSNathan Whitehorn ("function code 0x%02x\n", ccb->ccb_h.func_code)); 3489f2c359fSNathan Whitehorn 3499f2c359fSNathan Whitehorn switch (ccb->ccb_h.func_code) { 3509f2c359fSNathan Whitehorn case XPT_SCSI_IO: 3519f2c359fSNathan Whitehorn if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG) 3529f2c359fSNathan Whitehorn break; 3539f2c359fSNathan Whitehorn 3549f2c359fSNathan Whitehorn if(ccb->ccb_h.target_id > 0) { 3559f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_TID_INVALID; 3569f2c359fSNathan Whitehorn break; 3579f2c359fSNathan Whitehorn } 3589f2c359fSNathan Whitehorn 3599f2c359fSNathan Whitehorn if(ccb->ccb_h.target_lun > 0) { 3609f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_LUN_INVALID; 3619f2c359fSNathan Whitehorn break; 3629f2c359fSNathan Whitehorn } 3639f2c359fSNathan Whitehorn 3649f2c359fSNathan Whitehorn xp = TAILQ_FIRST(&sc->sc_free_xferq); 3659f2c359fSNathan Whitehorn 3669f2c359fSNathan Whitehorn KASSERT(xp != NULL, ("no free transfers")); 3679f2c359fSNathan Whitehorn 3689f2c359fSNathan Whitehorn xp->x_ccb = ccb; 3699f2c359fSNathan Whitehorn 3709f2c359fSNathan Whitehorn TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue); 3719f2c359fSNathan Whitehorn 372*dd0b4fb6SKonstantin Belousov err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap, 373*dd0b4fb6SKonstantin Belousov ccb, ps3cdrom_transfer, xp, 0); 3749f2c359fSNathan Whitehorn if (err && err != EINPROGRESS) { 3759f2c359fSNathan Whitehorn device_printf(dev, "Could not load DMA map (%d)\n", 3769f2c359fSNathan Whitehorn err); 3779f2c359fSNathan Whitehorn 3789f2c359fSNathan Whitehorn xp->x_ccb = NULL; 3799f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 3809f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 3819f2c359fSNathan Whitehorn break; 3829f2c359fSNathan Whitehorn } 3839f2c359fSNathan Whitehorn return; 3849f2c359fSNathan Whitehorn case XPT_SET_TRAN_SETTINGS: 3859f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 3869f2c359fSNathan Whitehorn break; 3879f2c359fSNathan Whitehorn case XPT_GET_TRAN_SETTINGS: 3889f2c359fSNathan Whitehorn { 3899f2c359fSNathan Whitehorn struct ccb_trans_settings *cts = &ccb->cts; 3909f2c359fSNathan Whitehorn 3919f2c359fSNathan Whitehorn cts->protocol = PROTO_SCSI; 3929f2c359fSNathan Whitehorn cts->protocol_version = SCSI_REV_2; 3939f2c359fSNathan Whitehorn cts->transport = XPORT_SPI; 3949f2c359fSNathan Whitehorn cts->transport_version = 2; 3959f2c359fSNathan Whitehorn cts->proto_specific.valid = 0; 3969f2c359fSNathan Whitehorn cts->xport_specific.valid = 0; 3979f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_REQ_CMP; 3989f2c359fSNathan Whitehorn break; 3999f2c359fSNathan Whitehorn } 4009f2c359fSNathan Whitehorn case XPT_RESET_BUS: 4019f2c359fSNathan Whitehorn case XPT_RESET_DEV: 4029f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_REQ_CMP; 4039f2c359fSNathan Whitehorn break; 4049f2c359fSNathan Whitehorn case XPT_CALC_GEOMETRY: 4059f2c359fSNathan Whitehorn cam_calc_geometry(&ccb->ccg, 1); 4069f2c359fSNathan Whitehorn break; 4079f2c359fSNathan Whitehorn case XPT_PATH_INQ: 4089f2c359fSNathan Whitehorn { 4099f2c359fSNathan Whitehorn struct ccb_pathinq *cpi = &ccb->cpi; 4109f2c359fSNathan Whitehorn 4119f2c359fSNathan Whitehorn cpi->version_num = 1; 4129f2c359fSNathan Whitehorn cpi->hba_inquiry = 0; 4139f2c359fSNathan Whitehorn cpi->target_sprt = 0; 4149f2c359fSNathan Whitehorn cpi->hba_inquiry = PI_SDTR_ABLE; 4159f2c359fSNathan Whitehorn cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE; 4169f2c359fSNathan Whitehorn cpi->hba_eng_cnt = 0; 4179f2c359fSNathan Whitehorn bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags)); 4189f2c359fSNathan Whitehorn cpi->max_target = 0; 4199f2c359fSNathan Whitehorn cpi->max_lun = 0; 4209f2c359fSNathan Whitehorn cpi->initiator_id = 7; 4219f2c359fSNathan Whitehorn cpi->bus_id = cam_sim_bus(sim); 4229f2c359fSNathan Whitehorn cpi->unit_number = cam_sim_unit(sim); 4239f2c359fSNathan Whitehorn cpi->base_transfer_speed = 150000; 4249f2c359fSNathan Whitehorn strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 4259f2c359fSNathan Whitehorn strncpy(cpi->hba_vid, "Sony", HBA_IDLEN); 4269f2c359fSNathan Whitehorn strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 4279f2c359fSNathan Whitehorn cpi->transport = XPORT_SPI; 4289f2c359fSNathan Whitehorn cpi->transport_version = 2; 4299f2c359fSNathan Whitehorn cpi->protocol = PROTO_SCSI; 4309f2c359fSNathan Whitehorn cpi->protocol_version = SCSI_REV_2; 4319f2c359fSNathan Whitehorn cpi->maxio = PAGE_SIZE; 4329f2c359fSNathan Whitehorn cpi->ccb_h.status = CAM_REQ_CMP; 4339f2c359fSNathan Whitehorn break; 4349f2c359fSNathan Whitehorn } 4359f2c359fSNathan Whitehorn default: 4369f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 4379f2c359fSNathan Whitehorn ("unsupported function code 0x%02x\n", 4389f2c359fSNathan Whitehorn ccb->ccb_h.func_code)); 4399f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_REQ_INVALID; 4409f2c359fSNathan Whitehorn break; 4419f2c359fSNathan Whitehorn } 4429f2c359fSNathan Whitehorn 4439f2c359fSNathan Whitehorn xpt_done(ccb); 4449f2c359fSNathan Whitehorn } 4459f2c359fSNathan Whitehorn 4469f2c359fSNathan Whitehorn static void 4479f2c359fSNathan Whitehorn ps3cdrom_poll(struct cam_sim *sim) 4489f2c359fSNathan Whitehorn { 4499f2c359fSNathan Whitehorn ps3cdrom_intr(cam_sim_softc(sim)); 4509f2c359fSNathan Whitehorn } 4519f2c359fSNathan Whitehorn 4529f2c359fSNathan Whitehorn static void 4539f2c359fSNathan Whitehorn ps3cdrom_async(void *callback_arg, u_int32_t code, 4549f2c359fSNathan Whitehorn struct cam_path* path, void *arg) 4559f2c359fSNathan Whitehorn { 4569f2c359fSNathan Whitehorn switch (code) { 4579f2c359fSNathan Whitehorn case AC_LOST_DEVICE: 4589f2c359fSNathan Whitehorn xpt_print_path(path); 4599f2c359fSNathan Whitehorn break; 4609f2c359fSNathan Whitehorn default: 4619f2c359fSNathan Whitehorn break; 4629f2c359fSNathan Whitehorn } 4639f2c359fSNathan Whitehorn } 4649f2c359fSNathan Whitehorn 4659f2c359fSNathan Whitehorn static void 4669f2c359fSNathan Whitehorn ps3cdrom_intr(void *arg) 4679f2c359fSNathan Whitehorn { 4689f2c359fSNathan Whitehorn struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg; 4699f2c359fSNathan Whitehorn device_t dev = sc->sc_dev; 4709f2c359fSNathan Whitehorn uint64_t devid = ps3bus_get_device(dev); 4719f2c359fSNathan Whitehorn struct ps3cdrom_xfer *xp; 4729f2c359fSNathan Whitehorn union ccb *ccb; 4739f2c359fSNathan Whitehorn u_int8_t *cdb, sense_key, asc, ascq; 4749f2c359fSNathan Whitehorn uint64_t tag, status; 4759f2c359fSNathan Whitehorn 4769f2c359fSNathan Whitehorn if (lv1_storage_get_async_status(devid, &tag, &status) != 0) 4779f2c359fSNathan Whitehorn return; 4789f2c359fSNathan Whitehorn 4799f2c359fSNathan Whitehorn PS3CDROM_LOCK(sc); 4809f2c359fSNathan Whitehorn 4819f2c359fSNathan Whitehorn /* Find transfer with the returned tag */ 4829f2c359fSNathan Whitehorn 4839f2c359fSNathan Whitehorn TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) { 4849f2c359fSNathan Whitehorn if (xp->x_tag == tag) 4859f2c359fSNathan Whitehorn break; 4869f2c359fSNathan Whitehorn } 4879f2c359fSNathan Whitehorn 4889f2c359fSNathan Whitehorn if (xp) { 4899f2c359fSNathan Whitehorn ccb = xp->x_ccb; 4909f2c359fSNathan Whitehorn cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 4919f2c359fSNathan Whitehorn ccb->csio.cdb_io.cdb_ptr : 4929f2c359fSNathan Whitehorn ccb->csio.cdb_io.cdb_bytes; 4939f2c359fSNathan Whitehorn 4949f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 4959f2c359fSNathan Whitehorn ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n", 4969f2c359fSNathan Whitehorn cdb[0], tag, status)); 4979f2c359fSNathan Whitehorn 4989f2c359fSNathan Whitehorn if (!status) { 4999f2c359fSNathan Whitehorn ccb->csio.scsi_status = SCSI_STATUS_OK; 5009f2c359fSNathan Whitehorn ccb->csio.resid = 0; 5019f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_REQ_CMP; 5029f2c359fSNathan Whitehorn } else { 5039f2c359fSNathan Whitehorn ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 5049f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 5059f2c359fSNathan Whitehorn 5069f2c359fSNathan Whitehorn if (!ps3cdrom_decode_lv1_status(status, &sense_key, 5079f2c359fSNathan Whitehorn &asc, &ascq)) { 5089f2c359fSNathan Whitehorn 5099f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 5109f2c359fSNathan Whitehorn ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n", 5119f2c359fSNathan Whitehorn sense_key, asc, ascq)); 5129f2c359fSNathan Whitehorn 5131cc052e8SKenneth D. Merry scsi_set_sense_data(&ccb->csio.sense_data, 5141cc052e8SKenneth D. Merry /*sense_format*/ SSD_TYPE_NONE, 5151cc052e8SKenneth D. Merry /*current_error*/ 1, 5161cc052e8SKenneth D. Merry sense_key, 5171cc052e8SKenneth D. Merry asc, 5181cc052e8SKenneth D. Merry ascq, 5191cc052e8SKenneth D. Merry SSD_ELEM_NONE); 5201cc052e8SKenneth D. Merry ccb->csio.sense_len = SSD_FULL_SIZE; 5219f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | 5229f2c359fSNathan Whitehorn CAM_AUTOSNS_VALID; 5239f2c359fSNathan Whitehorn } 5249f2c359fSNathan Whitehorn 5259f2c359fSNathan Whitehorn if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 5269f2c359fSNathan Whitehorn ccb->csio.resid = ccb->csio.dxfer_len; 5279f2c359fSNathan Whitehorn } 5289f2c359fSNathan Whitehorn 5299f2c359fSNathan Whitehorn if (ccb->ccb_h.flags & CAM_DIR_IN) 5309f2c359fSNathan Whitehorn bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 5319f2c359fSNathan Whitehorn BUS_DMASYNC_POSTREAD); 5329f2c359fSNathan Whitehorn 5339f2c359fSNathan Whitehorn bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap); 5349f2c359fSNathan Whitehorn 5359f2c359fSNathan Whitehorn xp->x_ccb = NULL; 5369f2c359fSNathan Whitehorn TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue); 5379f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 5389f2c359fSNathan Whitehorn 5399f2c359fSNathan Whitehorn xpt_done(ccb); 5409f2c359fSNathan Whitehorn } else { 5419f2c359fSNathan Whitehorn device_printf(dev, 5429f2c359fSNathan Whitehorn "Could not find transfer with tag 0x%016lx\n", tag); 5439f2c359fSNathan Whitehorn } 5449f2c359fSNathan Whitehorn 5459f2c359fSNathan Whitehorn PS3CDROM_UNLOCK(sc); 5469f2c359fSNathan Whitehorn } 5479f2c359fSNathan Whitehorn 5489f2c359fSNathan Whitehorn static void 5499f2c359fSNathan Whitehorn ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error) 5509f2c359fSNathan Whitehorn { 5519f2c359fSNathan Whitehorn struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg; 5529f2c359fSNathan Whitehorn struct ps3cdrom_softc *sc = xp->x_sc; 5539f2c359fSNathan Whitehorn device_t dev = sc->sc_dev; 5549f2c359fSNathan Whitehorn uint64_t devid = ps3bus_get_device(dev); 5559f2c359fSNathan Whitehorn union ccb *ccb = xp->x_ccb; 5569f2c359fSNathan Whitehorn u_int8_t *cdb; 5579f2c359fSNathan Whitehorn uint64_t start_sector, block_count; 5589f2c359fSNathan Whitehorn int err; 5599f2c359fSNathan Whitehorn 5609f2c359fSNathan Whitehorn KASSERT(nsegs == 1, ("invalid number of DMA segments")); 5619f2c359fSNathan Whitehorn 5629f2c359fSNathan Whitehorn PS3CDROM_ASSERT_LOCKED(sc); 5639f2c359fSNathan Whitehorn 5649f2c359fSNathan Whitehorn if (error) { 5659f2c359fSNathan Whitehorn device_printf(dev, "Could not load DMA map (%d)\n", error); 5669f2c359fSNathan Whitehorn 5679f2c359fSNathan Whitehorn xp->x_ccb = NULL; 5689f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 5699f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 5709f2c359fSNathan Whitehorn xpt_done(ccb); 5719f2c359fSNathan Whitehorn return; 5729f2c359fSNathan Whitehorn } 5739f2c359fSNathan Whitehorn 5749f2c359fSNathan Whitehorn cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ? 5759f2c359fSNathan Whitehorn ccb->csio.cdb_io.cdb_ptr : 5769f2c359fSNathan Whitehorn ccb->csio.cdb_io.cdb_bytes; 5779f2c359fSNathan Whitehorn 5789f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 5799f2c359fSNathan Whitehorn ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0], 5809f2c359fSNathan Whitehorn ccb->csio.cdb_len, ccb->csio.dxfer_len)); 5819f2c359fSNathan Whitehorn 5829f2c359fSNathan Whitehorn switch (cdb[0]) { 5839f2c359fSNathan Whitehorn case READ_10: 5849f2c359fSNathan Whitehorn start_sector = (cdb[2] << 24) | (cdb[3] << 16) | 5859f2c359fSNathan Whitehorn (cdb[4] << 8) | cdb[5]; 5869f2c359fSNathan Whitehorn block_count = (cdb[7] << 8) | cdb[8]; 5879f2c359fSNathan Whitehorn 5889f2c359fSNathan Whitehorn err = lv1_storage_read(devid, 0 /* region id */, 5899f2c359fSNathan Whitehorn start_sector, block_count, 0 /* flags */, segs[0].ds_addr, 5909f2c359fSNathan Whitehorn &xp->x_tag); 5919f2c359fSNathan Whitehorn bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 5929f2c359fSNathan Whitehorn BUS_DMASYNC_POSTREAD); 5939f2c359fSNathan Whitehorn break; 5949f2c359fSNathan Whitehorn case WRITE_10: 5959f2c359fSNathan Whitehorn start_sector = (cdb[2] << 24) | (cdb[3] << 16) | 5969f2c359fSNathan Whitehorn (cdb[4] << 8) | cdb[5]; 5979f2c359fSNathan Whitehorn block_count = (cdb[7] << 8) | cdb[8]; 5989f2c359fSNathan Whitehorn 5999f2c359fSNathan Whitehorn bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 6009f2c359fSNathan Whitehorn BUS_DMASYNC_PREWRITE); 6019f2c359fSNathan Whitehorn err = lv1_storage_write(devid, 0 /* region id */, 6029f2c359fSNathan Whitehorn start_sector, block_count, 0 /* flags */, 6039f2c359fSNathan Whitehorn segs[0].ds_addr, &xp->x_tag); 6049f2c359fSNathan Whitehorn break; 6059f2c359fSNathan Whitehorn default: 6069f2c359fSNathan Whitehorn { 6079f2c359fSNathan Whitehorn struct lv1_atapi_cmd atapi_cmd; 6089f2c359fSNathan Whitehorn 6099f2c359fSNathan Whitehorn bzero(&atapi_cmd, sizeof(atapi_cmd)); 6109f2c359fSNathan Whitehorn atapi_cmd.pktlen = 12; 6119f2c359fSNathan Whitehorn bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len); 6129f2c359fSNathan Whitehorn 6139f2c359fSNathan Whitehorn if (ccb->ccb_h.flags & CAM_DIR_IN) { 6149f2c359fSNathan Whitehorn atapi_cmd.in_out = DIR_READ; 6159f2c359fSNathan Whitehorn atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ? 6169f2c359fSNathan Whitehorn DMA_PROTO : PIO_DATA_IN_PROTO; 6179f2c359fSNathan Whitehorn } else if (ccb->ccb_h.flags & CAM_DIR_OUT) { 6189f2c359fSNathan Whitehorn atapi_cmd.in_out = DIR_WRITE; 6199f2c359fSNathan Whitehorn atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ? 6209f2c359fSNathan Whitehorn DMA_PROTO : PIO_DATA_OUT_PROTO; 6219f2c359fSNathan Whitehorn } else { 6229f2c359fSNathan Whitehorn atapi_cmd.proto = NON_DATA_PROTO; 6239f2c359fSNathan Whitehorn } 6249f2c359fSNathan Whitehorn 6259f2c359fSNathan Whitehorn atapi_cmd.nblocks = atapi_cmd.arglen = segs[0].ds_len; 6269f2c359fSNathan Whitehorn atapi_cmd.blksize = 1; 6279f2c359fSNathan Whitehorn atapi_cmd.buf = segs[0].ds_addr; 6289f2c359fSNathan Whitehorn 6299f2c359fSNathan Whitehorn if (ccb->ccb_h.flags & CAM_DIR_OUT) 6309f2c359fSNathan Whitehorn bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap, 6319f2c359fSNathan Whitehorn BUS_DMASYNC_PREWRITE); 6329f2c359fSNathan Whitehorn 6339f2c359fSNathan Whitehorn err = lv1_storage_send_device_command(devid, 6349f2c359fSNathan Whitehorn LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd), 6359f2c359fSNathan Whitehorn sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen, 6369f2c359fSNathan Whitehorn &xp->x_tag); 6379f2c359fSNathan Whitehorn 6389f2c359fSNathan Whitehorn break; 6399f2c359fSNathan Whitehorn } 6409f2c359fSNathan Whitehorn } 6419f2c359fSNathan Whitehorn 6429f2c359fSNathan Whitehorn if (err) { 6439f2c359fSNathan Whitehorn device_printf(dev, "ATAPI command 0x%02x failed (%d)\n", 6449f2c359fSNathan Whitehorn cdb[0], err); 6459f2c359fSNathan Whitehorn 6469f2c359fSNathan Whitehorn bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap); 6479f2c359fSNathan Whitehorn 6489f2c359fSNathan Whitehorn xp->x_ccb = NULL; 6499f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue); 6509f2c359fSNathan Whitehorn 6511cc052e8SKenneth D. Merry bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data)); 6521cc052e8SKenneth D. Merry /* Invalid field in parameter list */ 6531cc052e8SKenneth D. Merry scsi_set_sense_data(&ccb->csio.sense_data, 6541cc052e8SKenneth D. Merry /*sense_format*/ SSD_TYPE_NONE, 6551cc052e8SKenneth D. Merry /*current_error*/ 1, 6561cc052e8SKenneth D. Merry /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 6571cc052e8SKenneth D. Merry /*asc*/ 0x26, 6581cc052e8SKenneth D. Merry /*ascq*/ 0x00, 6591cc052e8SKenneth D. Merry SSD_ELEM_NONE); 6601cc052e8SKenneth D. Merry 6611cc052e8SKenneth D. Merry ccb->csio.sense_len = SSD_FULL_SIZE; 6621cc052e8SKenneth D. Merry ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 6639f2c359fSNathan Whitehorn ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 6649f2c359fSNathan Whitehorn xpt_done(ccb); 6659f2c359fSNathan Whitehorn } else { 6669f2c359fSNathan Whitehorn CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, 6679f2c359fSNathan Whitehorn ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0], 6689f2c359fSNathan Whitehorn xp->x_tag)); 6699f2c359fSNathan Whitehorn 6709f2c359fSNathan Whitehorn TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue); 6719f2c359fSNathan Whitehorn ccb->ccb_h.status |= CAM_SIM_QUEUED; 6729f2c359fSNathan Whitehorn } 6739f2c359fSNathan Whitehorn } 6749f2c359fSNathan Whitehorn 6759f2c359fSNathan Whitehorn static int 6769f2c359fSNathan Whitehorn ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc, 6779f2c359fSNathan Whitehorn u_int8_t *ascq) 6789f2c359fSNathan Whitehorn { 6799f2c359fSNathan Whitehorn if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND) 6809f2c359fSNathan Whitehorn return -1; 6819f2c359fSNathan Whitehorn 6829f2c359fSNathan Whitehorn *sense_key = (status >> 16) & 0xff; 6839f2c359fSNathan Whitehorn *asc = (status >> 8) & 0xff; 6849f2c359fSNathan Whitehorn *ascq = status & 0xff; 6859f2c359fSNathan Whitehorn 6869f2c359fSNathan Whitehorn return (0); 6879f2c359fSNathan Whitehorn } 6889f2c359fSNathan Whitehorn 6899f2c359fSNathan Whitehorn static device_method_t ps3cdrom_methods[] = { 6909f2c359fSNathan Whitehorn DEVMETHOD(device_probe, ps3cdrom_probe), 6919f2c359fSNathan Whitehorn DEVMETHOD(device_attach, ps3cdrom_attach), 6929f2c359fSNathan Whitehorn DEVMETHOD(device_detach, ps3cdrom_detach), 6939f2c359fSNathan Whitehorn {0, 0}, 6949f2c359fSNathan Whitehorn }; 6959f2c359fSNathan Whitehorn 6969f2c359fSNathan Whitehorn static driver_t ps3cdrom_driver = { 6979f2c359fSNathan Whitehorn "ps3cdrom", 6989f2c359fSNathan Whitehorn ps3cdrom_methods, 6999f2c359fSNathan Whitehorn sizeof(struct ps3cdrom_softc), 7009f2c359fSNathan Whitehorn }; 7019f2c359fSNathan Whitehorn 7029f2c359fSNathan Whitehorn static devclass_t ps3cdrom_devclass; 7039f2c359fSNathan Whitehorn 7049f2c359fSNathan Whitehorn DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0); 7059f2c359fSNathan Whitehorn MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1); 706