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