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