The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/powerpc/ps3/ps3cdrom.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (C) 2010 Nathan Whitehorn
    3  * Copyright (C) 2011 glevand <geoffrey.levand@mail.ru>
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer,
   11  *    without modification, immediately at the beginning of the file.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   26  */
   27 
   28 #include <sys/cdefs.h>
   29 __FBSDID("$FreeBSD: releng/11.2/sys/powerpc/ps3/ps3cdrom.c 331722 2018-03-29 02:50:57Z eadler $");
   30 
   31 #include <sys/param.h>
   32 #include <sys/module.h>
   33 #include <sys/systm.h>
   34 #include <sys/kernel.h>
   35 #include <sys/ata.h>
   36 #include <sys/bus.h>
   37 #include <sys/conf.h>
   38 #include <sys/kthread.h>
   39 #include <sys/lock.h>
   40 #include <sys/malloc.h>
   41 #include <sys/mutex.h>
   42 
   43 #include <vm/vm.h>
   44 #include <vm/pmap.h>
   45 
   46 #include <machine/pio.h>
   47 #include <machine/bus.h>
   48 #include <machine/platform.h>
   49 #include <machine/resource.h>
   50 #include <sys/bus.h>
   51 #include <sys/rman.h>
   52 
   53 #include <cam/cam.h>
   54 #include <cam/cam_ccb.h>
   55 #include <cam/cam_sim.h>
   56 #include <cam/cam_xpt_sim.h>
   57 #include <cam/cam_debug.h>
   58 #include <cam/scsi/scsi_all.h>
   59 
   60 #include "ps3bus.h"
   61 #include "ps3-hvcall.h"
   62 
   63 #define PS3CDROM_LOCK_INIT(_sc)         \
   64         mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->sc_dev), "ps3cdrom", \
   65             MTX_DEF)
   66 #define PS3CDROM_LOCK_DESTROY(_sc)      mtx_destroy(&_sc->sc_mtx);
   67 #define PS3CDROM_LOCK(_sc)              mtx_lock(&(_sc)->sc_mtx)
   68 #define PS3CDROM_UNLOCK(_sc)            mtx_unlock(&(_sc)->sc_mtx)
   69 #define PS3CDROM_ASSERT_LOCKED(_sc)     mtx_assert(&_sc->sc_mtx, MA_OWNED);
   70 #define PS3CDROM_ASSERT_UNLOCKED(_sc)   mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
   71 
   72 #define PS3CDROM_MAX_XFERS              3
   73 
   74 #define LV1_STORAGE_SEND_ATAPI_COMMAND  0x01
   75 
   76 struct ps3cdrom_softc;
   77 
   78 struct ps3cdrom_xfer {
   79         TAILQ_ENTRY(ps3cdrom_xfer) x_queue;
   80         struct ps3cdrom_softc *x_sc;
   81         union ccb *x_ccb;
   82         bus_dmamap_t x_dmamap;
   83         uint64_t x_tag;
   84 };
   85 
   86 TAILQ_HEAD(ps3cdrom_xferq, ps3cdrom_xfer);
   87 
   88 struct ps3cdrom_softc {
   89         device_t sc_dev;
   90 
   91         struct mtx sc_mtx;
   92 
   93         uint64_t sc_blksize;
   94         uint64_t sc_nblocks;
   95 
   96         int sc_irqid;
   97         struct resource *sc_irq;
   98         void *sc_irqctx;
   99 
  100         bus_dma_tag_t sc_dmatag;
  101 
  102         struct cam_sim *sc_sim;
  103         struct cam_path *sc_path;
  104 
  105         struct ps3cdrom_xfer sc_xfer[PS3CDROM_MAX_XFERS];
  106         struct ps3cdrom_xferq sc_active_xferq;
  107         struct ps3cdrom_xferq sc_free_xferq;
  108 };
  109 
  110 enum lv1_ata_proto {
  111         NON_DATA_PROTO          = 0x00,
  112         PIO_DATA_IN_PROTO       = 0x01,
  113         PIO_DATA_OUT_PROTO      = 0x02,
  114         DMA_PROTO               = 0x03
  115 };
  116 
  117 enum lv1_ata_in_out {
  118         DIR_WRITE               = 0x00,
  119         DIR_READ                = 0x01
  120 };
  121 
  122 struct lv1_atapi_cmd {
  123         uint8_t pkt[32];
  124         uint32_t pktlen;
  125         uint32_t nblocks;
  126         uint32_t blksize;
  127         uint32_t proto;         /* enum lv1_ata_proto */
  128         uint32_t in_out;        /* enum lv1_ata_in_out */
  129         uint64_t buf;
  130         uint32_t arglen;
  131 };
  132 
  133 static void ps3cdrom_action(struct cam_sim *sim, union ccb *ccb);
  134 static void ps3cdrom_poll(struct cam_sim *sim);
  135 static void ps3cdrom_async(void *callback_arg, u_int32_t code,
  136     struct cam_path* path, void *arg);
  137 
  138 static void ps3cdrom_intr(void *arg);
  139 
  140 static void ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs,
  141     int error);
  142 
  143 static int ps3cdrom_decode_lv1_status(uint64_t status,
  144         u_int8_t *sense_key, u_int8_t *asc, u_int8_t *ascq);
  145 
  146 static int
  147 ps3cdrom_probe(device_t dev)
  148 {
  149         if (ps3bus_get_bustype(dev) != PS3_BUSTYPE_STORAGE ||
  150             ps3bus_get_devtype(dev) != PS3_DEVTYPE_CDROM)
  151                 return (ENXIO);
  152 
  153         device_set_desc(dev, "Playstation 3 CDROM");
  154 
  155         return (BUS_PROBE_SPECIFIC);
  156 }
  157 
  158 static int
  159 ps3cdrom_attach(device_t dev)
  160 {
  161         struct ps3cdrom_softc *sc = device_get_softc(dev);
  162         struct cam_devq *devq;
  163         struct ps3cdrom_xfer *xp;
  164         struct ccb_setasync csa;
  165         int i, err;
  166 
  167         sc->sc_dev = dev;
  168 
  169         PS3CDROM_LOCK_INIT(sc);
  170 
  171         /* Setup interrupt handler */
  172 
  173         sc->sc_irqid = 0;
  174         sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid,
  175             RF_ACTIVE);
  176         if (!sc->sc_irq) {
  177                 device_printf(dev, "Could not allocate IRQ\n");
  178                 err = ENXIO;
  179                 goto fail_destroy_lock;
  180         }
  181 
  182         err = bus_setup_intr(dev, sc->sc_irq,
  183             INTR_TYPE_CAM | INTR_MPSAFE | INTR_ENTROPY,
  184             NULL, ps3cdrom_intr, sc, &sc->sc_irqctx);
  185         if (err) {
  186                 device_printf(dev, "Could not setup IRQ\n");
  187                 err = ENXIO;
  188                 goto fail_release_intr;
  189         }
  190 
  191         /* Setup DMA */
  192 
  193         err = bus_dma_tag_create(bus_get_dma_tag(dev), 4096, 0,
  194             BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
  195             BUS_SPACE_UNRESTRICTED, 1, PAGE_SIZE, 0,
  196             busdma_lock_mutex, &sc->sc_mtx, &sc->sc_dmatag);
  197         if (err) {
  198                 device_printf(dev, "Could not create DMA tag\n");
  199                 err = ENXIO;
  200                 goto fail_teardown_intr;
  201         }
  202 
  203         /* Setup transfer queues */
  204 
  205         TAILQ_INIT(&sc->sc_active_xferq);
  206         TAILQ_INIT(&sc->sc_free_xferq);
  207 
  208         for (i = 0; i < PS3CDROM_MAX_XFERS; i++) {
  209                 xp = &sc->sc_xfer[i];
  210                 xp->x_sc = sc;
  211 
  212                 err = bus_dmamap_create(sc->sc_dmatag, BUS_DMA_COHERENT,
  213                     &xp->x_dmamap);
  214                 if (err) {
  215                         device_printf(dev, "Could not create DMA map (%d)\n",
  216                             err);
  217                         goto fail_destroy_dmamap;
  218                 }
  219 
  220                 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
  221         }
  222 
  223         /* Setup CAM */
  224 
  225         devq = cam_simq_alloc(PS3CDROM_MAX_XFERS - 1);
  226         if (!devq) {
  227                 device_printf(dev, "Could not allocate SIM queue\n");
  228                 err = ENOMEM;
  229                 goto fail_destroy_dmatag;
  230         }
  231 
  232         sc->sc_sim = cam_sim_alloc(ps3cdrom_action, ps3cdrom_poll, "ps3cdrom",
  233             sc, device_get_unit(dev), &sc->sc_mtx, PS3CDROM_MAX_XFERS - 1, 0,
  234             devq);
  235         if (!sc->sc_sim) {
  236                 device_printf(dev, "Could not allocate SIM\n");
  237                 cam_simq_free(devq);
  238                 err = ENOMEM;
  239                 goto fail_destroy_dmatag;
  240         }
  241 
  242         /* Setup XPT */
  243 
  244         PS3CDROM_LOCK(sc);
  245 
  246         err = xpt_bus_register(sc->sc_sim, dev, 0);
  247         if (err != CAM_SUCCESS) {
  248                 device_printf(dev, "Could not register XPT bus\n");
  249                 err = ENXIO;
  250                 PS3CDROM_UNLOCK(sc);
  251                 goto fail_free_sim;
  252         }
  253 
  254         err = xpt_create_path(&sc->sc_path, NULL, cam_sim_path(sc->sc_sim),
  255             CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD);
  256         if (err != CAM_REQ_CMP) {
  257                 device_printf(dev, "Could not create XPT path\n");
  258                 err = ENOMEM;
  259                 PS3CDROM_UNLOCK(sc);
  260                 goto fail_unregister_xpt_bus;
  261         }
  262 
  263         xpt_setup_ccb(&csa.ccb_h, sc->sc_path, 5);
  264         csa.ccb_h.func_code = XPT_SASYNC_CB;
  265         csa.event_enable = AC_LOST_DEVICE;
  266         csa.callback = ps3cdrom_async;
  267         csa.callback_arg = sc->sc_sim;
  268         xpt_action((union ccb *) &csa);
  269 
  270         CAM_DEBUG(sc->sc_path, CAM_DEBUG_TRACE,
  271             ("registered SIM for ps3cdrom%d\n", device_get_unit(dev)));
  272 
  273         PS3CDROM_UNLOCK(sc);
  274 
  275         return (BUS_PROBE_SPECIFIC);
  276 
  277 fail_unregister_xpt_bus:
  278 
  279         xpt_bus_deregister(cam_sim_path(sc->sc_sim));
  280 
  281 fail_free_sim:
  282 
  283         cam_sim_free(sc->sc_sim, TRUE);
  284 
  285 fail_destroy_dmamap:
  286 
  287         while ((xp = TAILQ_FIRST(&sc->sc_free_xferq))) {
  288                 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
  289                 bus_dmamap_destroy(sc->sc_dmatag, xp->x_dmamap);
  290         }
  291 
  292 fail_destroy_dmatag:
  293 
  294         bus_dma_tag_destroy(sc->sc_dmatag);
  295 
  296 fail_teardown_intr:
  297 
  298         bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
  299 
  300 fail_release_intr:
  301 
  302         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
  303 
  304 fail_destroy_lock:
  305 
  306         PS3CDROM_LOCK_DESTROY(sc);
  307 
  308         return (err);
  309 }
  310 
  311 static int
  312 ps3cdrom_detach(device_t dev)
  313 {
  314         struct ps3cdrom_softc *sc = device_get_softc(dev);
  315         int i;
  316 
  317         xpt_async(AC_LOST_DEVICE, sc->sc_path, NULL);
  318         xpt_free_path(sc->sc_path);
  319         xpt_bus_deregister(cam_sim_path(sc->sc_sim));
  320         cam_sim_free(sc->sc_sim, TRUE);
  321 
  322         for (i = 0; i < PS3CDROM_MAX_XFERS; i++)
  323                 bus_dmamap_destroy(sc->sc_dmatag, sc->sc_xfer[i].x_dmamap);
  324 
  325         bus_dma_tag_destroy(sc->sc_dmatag);
  326 
  327         bus_teardown_intr(dev, sc->sc_irq, sc->sc_irqctx);
  328         bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqid, sc->sc_irq);
  329 
  330         PS3CDROM_LOCK_DESTROY(sc);
  331 
  332         return (0);
  333 }
  334 
  335 static void
  336 ps3cdrom_action(struct cam_sim *sim, union ccb *ccb)
  337 {
  338         struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *)cam_sim_softc(sim);
  339         device_t dev = sc->sc_dev;
  340         struct ps3cdrom_xfer *xp;
  341         int err;
  342 
  343         PS3CDROM_ASSERT_LOCKED(sc);
  344 
  345         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  346            ("function code 0x%02x\n", ccb->ccb_h.func_code));
  347 
  348         switch (ccb->ccb_h.func_code) {
  349         case XPT_SCSI_IO:
  350                 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG)
  351                         break;
  352 
  353                 if(ccb->ccb_h.target_id > 0) {
  354                         ccb->ccb_h.status = CAM_TID_INVALID;
  355                         break;
  356                 }
  357 
  358                 if(ccb->ccb_h.target_lun > 0) {
  359                         ccb->ccb_h.status = CAM_LUN_INVALID;
  360                         break;
  361                 }
  362 
  363                 xp = TAILQ_FIRST(&sc->sc_free_xferq);
  364                 
  365                 KASSERT(xp != NULL, ("no free transfers"));
  366 
  367                 xp->x_ccb = ccb;
  368 
  369                 TAILQ_REMOVE(&sc->sc_free_xferq, xp, x_queue);
  370 
  371                 err = bus_dmamap_load_ccb(sc->sc_dmatag, xp->x_dmamap,
  372                     ccb, ps3cdrom_transfer, xp, 0);
  373                 if (err && err != EINPROGRESS) {
  374                         device_printf(dev, "Could not load DMA map (%d)\n",
  375                             err);
  376 
  377                         xp->x_ccb = NULL;
  378                         TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
  379                         ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  380                         break;
  381                 }
  382                 return;
  383         case XPT_SET_TRAN_SETTINGS:
  384                 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
  385                 break;
  386         case XPT_GET_TRAN_SETTINGS:
  387         {
  388                 struct ccb_trans_settings *cts = &ccb->cts;
  389 
  390                 cts->protocol = PROTO_SCSI;
  391                 cts->protocol_version = SCSI_REV_2;
  392                 cts->transport = XPORT_SPI;
  393                 cts->transport_version = 2;
  394                 cts->proto_specific.valid = 0;
  395                 cts->xport_specific.valid = 0;
  396                 ccb->ccb_h.status = CAM_REQ_CMP;
  397                 break;
  398         }
  399         case XPT_RESET_BUS:
  400         case XPT_RESET_DEV:
  401                 ccb->ccb_h.status = CAM_REQ_CMP;
  402                 break;
  403         case XPT_CALC_GEOMETRY:
  404                 cam_calc_geometry(&ccb->ccg, 1);
  405                 break;
  406         case XPT_PATH_INQ:
  407         {
  408                 struct ccb_pathinq *cpi = &ccb->cpi;
  409 
  410                 cpi->version_num = 1;
  411                 cpi->hba_inquiry = 0;
  412                 cpi->target_sprt = 0;
  413                 cpi->hba_inquiry = PI_SDTR_ABLE;
  414                 cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN | PIM_NO_6_BYTE;
  415                 cpi->hba_eng_cnt = 0;
  416                 bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags));
  417                 cpi->max_target = 0;
  418                 cpi->max_lun = 0;
  419                 cpi->initiator_id = 7;
  420                 cpi->bus_id = cam_sim_bus(sim);
  421                 cpi->unit_number = cam_sim_unit(sim);
  422                 cpi->base_transfer_speed = 150000;
  423                 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
  424                 strlcpy(cpi->hba_vid, "Sony", HBA_IDLEN);
  425                 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
  426                 cpi->transport = XPORT_SPI;
  427                 cpi->transport_version = 2;
  428                 cpi->protocol = PROTO_SCSI;
  429                 cpi->protocol_version = SCSI_REV_2;
  430                 cpi->maxio = PAGE_SIZE;
  431                 cpi->ccb_h.status = CAM_REQ_CMP;
  432                 break;
  433         }
  434         default:
  435                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  436                     ("unsupported function code 0x%02x\n",
  437                     ccb->ccb_h.func_code));
  438                 ccb->ccb_h.status = CAM_REQ_INVALID;
  439                 break;
  440         }
  441 
  442         xpt_done(ccb);
  443 }
  444 
  445 static void
  446 ps3cdrom_poll(struct cam_sim *sim)
  447 {
  448         ps3cdrom_intr(cam_sim_softc(sim));
  449 }
  450 
  451 static void
  452 ps3cdrom_async(void *callback_arg, u_int32_t code,
  453         struct cam_path* path, void *arg)
  454 {
  455         switch (code) {
  456         case AC_LOST_DEVICE:
  457                 xpt_print_path(path);
  458                 break;
  459         default:
  460                 break;
  461         }
  462 }
  463 
  464 static void
  465 ps3cdrom_intr(void *arg)
  466 {
  467         struct ps3cdrom_softc *sc = (struct ps3cdrom_softc *) arg;
  468         device_t dev = sc->sc_dev;
  469         uint64_t devid = ps3bus_get_device(dev);
  470         struct ps3cdrom_xfer *xp;
  471         union ccb *ccb;
  472         u_int8_t *cdb, sense_key, asc, ascq;
  473         uint64_t tag, status;
  474 
  475         if (lv1_storage_get_async_status(devid, &tag, &status) != 0)
  476                 return;
  477 
  478         PS3CDROM_LOCK(sc);
  479 
  480         /* Find transfer with the returned tag */
  481 
  482         TAILQ_FOREACH(xp, &sc->sc_active_xferq, x_queue) {
  483                 if (xp->x_tag == tag)
  484                         break;
  485         }
  486 
  487         if (xp) {
  488                 ccb = xp->x_ccb;
  489                 cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
  490                             ccb->csio.cdb_io.cdb_ptr :
  491                             ccb->csio.cdb_io.cdb_bytes;
  492 
  493                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  494                    ("ATAPI command 0x%02x tag 0x%016lx completed (0x%016lx)\n",
  495                     cdb[0], tag, status));
  496 
  497                 if (!status) {
  498                         ccb->csio.scsi_status = SCSI_STATUS_OK;
  499                         ccb->csio.resid = 0;
  500                         ccb->ccb_h.status = CAM_REQ_CMP;
  501                 } else {
  502                         ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
  503                         ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  504 
  505                         if (!ps3cdrom_decode_lv1_status(status, &sense_key,
  506                             &asc, &ascq)) {
  507 
  508                                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  509                                    ("sense key 0x%02x asc 0x%02x ascq 0x%02x\n",
  510                                     sense_key, asc, ascq));
  511 
  512                                 scsi_set_sense_data(&ccb->csio.sense_data,
  513                                     /*sense_format*/ SSD_TYPE_NONE,
  514                                     /*current_error*/ 1,
  515                                     sense_key,
  516                                     asc,
  517                                     ascq,
  518                                     SSD_ELEM_NONE);
  519                                 ccb->csio.sense_len = SSD_FULL_SIZE;
  520                                 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR |
  521                                     CAM_AUTOSNS_VALID;
  522                         }
  523 
  524                         if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE)
  525                                 ccb->csio.resid = ccb->csio.dxfer_len;
  526                 }
  527 
  528                 if (ccb->ccb_h.flags & CAM_DIR_IN)
  529                         bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
  530                             BUS_DMASYNC_POSTREAD);
  531 
  532                 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
  533 
  534                 xp->x_ccb = NULL;
  535                 TAILQ_REMOVE(&sc->sc_active_xferq, xp, x_queue);
  536                 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
  537 
  538                 xpt_done(ccb);
  539         } else {
  540                 device_printf(dev,
  541                     "Could not find transfer with tag 0x%016lx\n",  tag);
  542         }
  543 
  544         PS3CDROM_UNLOCK(sc);
  545 }
  546 
  547 static void
  548 ps3cdrom_transfer(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
  549 {
  550         struct ps3cdrom_xfer *xp = (struct ps3cdrom_xfer *) arg;
  551         struct ps3cdrom_softc *sc = xp->x_sc;
  552         device_t dev = sc->sc_dev;
  553         uint64_t devid = ps3bus_get_device(dev);
  554         union ccb *ccb = xp->x_ccb;
  555         u_int8_t *cdb;
  556         uint64_t start_sector, block_count;
  557         int err;
  558 
  559         KASSERT(nsegs == 1 || nsegs == 0,
  560             ("ps3cdrom_transfer: invalid number of DMA segments %d", nsegs));
  561         KASSERT(error == 0, ("ps3cdrom_transfer: DMA error %d", error));
  562 
  563         PS3CDROM_ASSERT_LOCKED(sc);
  564 
  565         if (error) {
  566                 device_printf(dev, "Could not load DMA map (%d)\n",  error);
  567 
  568                 xp->x_ccb = NULL;
  569                 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
  570                 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR;
  571                 xpt_done(ccb);
  572                 return;
  573         }
  574 
  575         cdb = (ccb->ccb_h.flags & CAM_CDB_POINTER) ?
  576                     ccb->csio.cdb_io.cdb_ptr :
  577                     ccb->csio.cdb_io.cdb_bytes;
  578 
  579         CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  580            ("ATAPI command 0x%02x cdb_len %d dxfer_len %d\n ", cdb[0],
  581             ccb->csio.cdb_len, ccb->csio.dxfer_len));
  582 
  583         switch (cdb[0]) {
  584         case READ_10:
  585                 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to read"));
  586                 start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
  587                     (cdb[4] << 8) | cdb[5];
  588                 block_count = (cdb[7] << 8) | cdb[8];
  589 
  590                 err = lv1_storage_read(devid, 0 /* region id */,
  591                     start_sector, block_count, 0 /* flags */, segs[0].ds_addr,
  592                     &xp->x_tag);
  593                 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
  594                     BUS_DMASYNC_POSTREAD);
  595                 break;
  596         case WRITE_10:
  597                 KASSERT(nsegs == 1, ("ps3cdrom_transfer: no data to write"));
  598                 start_sector = (cdb[2] << 24) | (cdb[3] << 16) |
  599                     (cdb[4] << 8) | cdb[5];
  600                 block_count = (cdb[7] << 8) | cdb[8];
  601 
  602                 bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
  603                     BUS_DMASYNC_PREWRITE);
  604                 err = lv1_storage_write(devid, 0 /* region id */,
  605                     start_sector, block_count, 0 /* flags */,
  606                     segs[0].ds_addr, &xp->x_tag);
  607                 break;
  608         default:
  609                 {
  610                 struct lv1_atapi_cmd atapi_cmd;
  611 
  612                 bzero(&atapi_cmd, sizeof(atapi_cmd));
  613                 atapi_cmd.pktlen = 12;
  614                 bcopy(cdb, atapi_cmd.pkt, ccb->csio.cdb_len);
  615 
  616                 if (ccb->ccb_h.flags & CAM_DIR_IN) {
  617                         atapi_cmd.in_out = DIR_READ;
  618                         atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
  619                             DMA_PROTO : PIO_DATA_IN_PROTO;
  620                 } else if (ccb->ccb_h.flags & CAM_DIR_OUT) {
  621                         atapi_cmd.in_out = DIR_WRITE;
  622                         atapi_cmd.proto = (ccb->csio.dxfer_len >= 2048) ?
  623                             DMA_PROTO : PIO_DATA_OUT_PROTO;
  624                 } else {
  625                         atapi_cmd.proto = NON_DATA_PROTO;
  626                 }
  627 
  628                 atapi_cmd.nblocks = atapi_cmd.arglen =
  629                     (nsegs == 0) ? 0 : segs[0].ds_len;
  630                 atapi_cmd.blksize = 1;
  631                 atapi_cmd.buf = (nsegs == 0) ? 0 : segs[0].ds_addr;
  632 
  633                 if (ccb->ccb_h.flags & CAM_DIR_OUT)
  634                         bus_dmamap_sync(sc->sc_dmatag, xp->x_dmamap,
  635                             BUS_DMASYNC_PREWRITE);
  636 
  637                 err = lv1_storage_send_device_command(devid,
  638                     LV1_STORAGE_SEND_ATAPI_COMMAND, vtophys(&atapi_cmd),
  639                     sizeof(atapi_cmd), atapi_cmd.buf, atapi_cmd.arglen,
  640                     &xp->x_tag);
  641         
  642                 break;
  643                 }
  644         }
  645 
  646         if (err) {
  647                 device_printf(dev, "ATAPI command 0x%02x failed (%d)\n",
  648                     cdb[0], err);
  649 
  650                 bus_dmamap_unload(sc->sc_dmatag, xp->x_dmamap);
  651 
  652                 xp->x_ccb = NULL;
  653                 TAILQ_INSERT_TAIL(&sc->sc_free_xferq, xp, x_queue);
  654 
  655                 bzero(&ccb->csio.sense_data, sizeof(ccb->csio.sense_data));
  656                 /* Invalid field in parameter list */
  657                 scsi_set_sense_data(&ccb->csio.sense_data,
  658                                     /*sense_format*/ SSD_TYPE_NONE,
  659                                     /*current_error*/ 1,
  660                                     /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST,
  661                                     /*asc*/ 0x26,
  662                                     /*ascq*/ 0x00,
  663                                     SSD_ELEM_NONE);
  664 
  665                 ccb->csio.sense_len = SSD_FULL_SIZE;
  666                 ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND;
  667                 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
  668                 xpt_done(ccb);
  669         } else {
  670                 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE,
  671                    ("ATAPI command 0x%02x tag 0x%016lx submitted\n ", cdb[0],
  672                    xp->x_tag));
  673 
  674                 TAILQ_INSERT_TAIL(&sc->sc_active_xferq, xp, x_queue);
  675                 ccb->ccb_h.status |= CAM_SIM_QUEUED;
  676         }
  677 }
  678 
  679 static int
  680 ps3cdrom_decode_lv1_status(uint64_t status, u_int8_t *sense_key, u_int8_t *asc,
  681     u_int8_t *ascq)
  682 {
  683         if (((status >> 24) & 0xff) != SCSI_STATUS_CHECK_COND)
  684                 return -1;
  685 
  686         *sense_key = (status >> 16) & 0xff;
  687         *asc = (status >> 8) & 0xff;
  688         *ascq = status & 0xff;
  689 
  690         return (0);
  691 }
  692 
  693 static device_method_t ps3cdrom_methods[] = {
  694         DEVMETHOD(device_probe,         ps3cdrom_probe),
  695         DEVMETHOD(device_attach,        ps3cdrom_attach),
  696         DEVMETHOD(device_detach,        ps3cdrom_detach),
  697         {0, 0},
  698 };
  699 
  700 static driver_t ps3cdrom_driver = {
  701         "ps3cdrom",
  702         ps3cdrom_methods,
  703         sizeof(struct ps3cdrom_softc),
  704 };
  705 
  706 static devclass_t ps3cdrom_devclass;
  707 
  708 DRIVER_MODULE(ps3cdrom, ps3bus, ps3cdrom_driver, ps3cdrom_devclass, 0, 0);
  709 MODULE_DEPEND(ps3cdrom, cam, 1, 1, 1);

Cache object: 1e3c5ddfb9f9a4627892641a96fd135f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.