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/cam/scsi/scsi_pt.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  * Implementation of SCSI Processor Target Peripheral driver for CAM.
    3  *
    4  * Copyright (c) 1998 Justin T. Gibbs.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions, and the following disclaimer,
   12  *    without modification, immediately at the beginning of the file.
   13  * 2. The name of the author may not be used to endorse or promote products
   14  *    derived from this software without specific prior written permission.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   20  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/10.1/sys/cam/scsi/scsi_pt.c 260387 2014-01-07 01:51:48Z scottl $");
   31 
   32 #include <sys/param.h>
   33 #include <sys/queue.h>
   34 #include <sys/systm.h>
   35 #include <sys/kernel.h>
   36 #include <sys/types.h>
   37 #include <sys/bio.h>
   38 #include <sys/devicestat.h>
   39 #include <sys/malloc.h>
   40 #include <sys/conf.h>
   41 #include <sys/ptio.h>
   42 
   43 #include <cam/cam.h>
   44 #include <cam/cam_ccb.h>
   45 #include <cam/cam_periph.h>
   46 #include <cam/cam_xpt_periph.h>
   47 #include <cam/cam_debug.h>
   48 
   49 #include <cam/scsi/scsi_all.h>
   50 #include <cam/scsi/scsi_message.h>
   51 #include <cam/scsi/scsi_pt.h>
   52 
   53 #include "opt_pt.h"
   54 
   55 typedef enum {
   56         PT_STATE_PROBE,
   57         PT_STATE_NORMAL
   58 } pt_state;
   59 
   60 typedef enum {
   61         PT_FLAG_NONE            = 0x00,
   62         PT_FLAG_OPEN            = 0x01,
   63         PT_FLAG_DEVICE_INVALID  = 0x02,
   64         PT_FLAG_RETRY_UA        = 0x04
   65 } pt_flags;
   66 
   67 typedef enum {
   68         PT_CCB_BUFFER_IO        = 0x01,
   69         PT_CCB_RETRY_UA         = 0x04,
   70         PT_CCB_BUFFER_IO_UA     = PT_CCB_BUFFER_IO|PT_CCB_RETRY_UA
   71 } pt_ccb_state;
   72 
   73 /* Offsets into our private area for storing information */
   74 #define ccb_state       ppriv_field0
   75 #define ccb_bp          ppriv_ptr1
   76 
   77 struct pt_softc {
   78         struct   bio_queue_head bio_queue;
   79         struct   devstat *device_stats;
   80         LIST_HEAD(, ccb_hdr) pending_ccbs;
   81         pt_state state;
   82         pt_flags flags; 
   83         union    ccb saved_ccb;
   84         int      io_timeout;
   85         struct cdev *dev;
   86 };
   87 
   88 static  d_open_t        ptopen;
   89 static  d_close_t       ptclose;
   90 static  d_strategy_t    ptstrategy;
   91 static  periph_init_t   ptinit;
   92 static  void            ptasync(void *callback_arg, u_int32_t code,
   93                                 struct cam_path *path, void *arg);
   94 static  periph_ctor_t   ptctor;
   95 static  periph_oninv_t  ptoninvalidate;
   96 static  periph_dtor_t   ptdtor;
   97 static  periph_start_t  ptstart;
   98 static  void            ptdone(struct cam_periph *periph,
   99                                union ccb *done_ccb);
  100 static  d_ioctl_t       ptioctl;
  101 static  int             pterror(union ccb *ccb, u_int32_t cam_flags,
  102                                 u_int32_t sense_flags);
  103 
  104 void    scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
  105                           void (*cbfcnp)(struct cam_periph *, union ccb *),
  106                           u_int tag_action, int readop, u_int byte2,
  107                           u_int32_t xfer_len, u_int8_t *data_ptr,
  108                           u_int8_t sense_len, u_int32_t timeout);
  109 
  110 static struct periph_driver ptdriver =
  111 {
  112         ptinit, "pt",
  113         TAILQ_HEAD_INITIALIZER(ptdriver.units), /* generation */ 0
  114 };
  115 
  116 PERIPHDRIVER_DECLARE(pt, ptdriver);
  117 
  118 
  119 static struct cdevsw pt_cdevsw = {
  120         .d_version =    D_VERSION,
  121         .d_flags =      0,
  122         .d_open =       ptopen,
  123         .d_close =      ptclose,
  124         .d_read =       physread,
  125         .d_write =      physwrite,
  126         .d_ioctl =      ptioctl,
  127         .d_strategy =   ptstrategy,
  128         .d_name =       "pt",
  129 };
  130 
  131 #ifndef SCSI_PT_DEFAULT_TIMEOUT
  132 #define SCSI_PT_DEFAULT_TIMEOUT         60
  133 #endif
  134 
  135 static int
  136 ptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
  137 {
  138         struct cam_periph *periph;
  139         struct pt_softc *softc;
  140         int error = 0;
  141 
  142         periph = (struct cam_periph *)dev->si_drv1;
  143         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
  144                 return (ENXIO); 
  145 
  146         softc = (struct pt_softc *)periph->softc;
  147 
  148         cam_periph_lock(periph);
  149         if (softc->flags & PT_FLAG_DEVICE_INVALID) {
  150                 cam_periph_release_locked(periph);
  151                 cam_periph_unlock(periph);
  152                 return(ENXIO);
  153         }
  154 
  155         if ((softc->flags & PT_FLAG_OPEN) == 0)
  156                 softc->flags |= PT_FLAG_OPEN;
  157         else {
  158                 error = EBUSY;
  159                 cam_periph_release(periph);
  160         }
  161 
  162         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  163             ("ptopen: dev=%s\n", devtoname(dev)));
  164 
  165         cam_periph_unlock(periph);
  166         return (error);
  167 }
  168 
  169 static int
  170 ptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
  171 {
  172         struct  cam_periph *periph;
  173         struct  pt_softc *softc;
  174 
  175         periph = (struct cam_periph *)dev->si_drv1;
  176         if (periph == NULL)
  177                 return (ENXIO); 
  178 
  179         softc = (struct pt_softc *)periph->softc;
  180 
  181         cam_periph_lock(periph);
  182 
  183         softc->flags &= ~PT_FLAG_OPEN;
  184         cam_periph_release_locked(periph);
  185         cam_periph_unlock(periph);
  186         return (0);
  187 }
  188 
  189 /*
  190  * Actually translate the requested transfer into one the physical driver
  191  * can understand.  The transfer is described by a buf and will include
  192  * only one physical transfer.
  193  */
  194 static void
  195 ptstrategy(struct bio *bp)
  196 {
  197         struct cam_periph *periph;
  198         struct pt_softc *softc;
  199         
  200         periph = (struct cam_periph *)bp->bio_dev->si_drv1;
  201         bp->bio_resid = bp->bio_bcount;
  202         if (periph == NULL) {
  203                 biofinish(bp, NULL, ENXIO);
  204                 return;
  205         }
  206         cam_periph_lock(periph);
  207         softc = (struct pt_softc *)periph->softc;
  208 
  209         /*
  210          * If the device has been made invalid, error out
  211          */
  212         if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
  213                 cam_periph_unlock(periph);
  214                 biofinish(bp, NULL, ENXIO);
  215                 return;
  216         }
  217         
  218         /*
  219          * Place it in the queue of disk activities for this disk
  220          */
  221         bioq_insert_tail(&softc->bio_queue, bp);
  222 
  223         /*
  224          * Schedule ourselves for performing the work.
  225          */
  226         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  227         cam_periph_unlock(periph);
  228 
  229         return;
  230 }
  231 
  232 static void
  233 ptinit(void)
  234 {
  235         cam_status status;
  236 
  237         /*
  238          * Install a global async callback.  This callback will
  239          * receive async callbacks like "new device found".
  240          */
  241         status = xpt_register_async(AC_FOUND_DEVICE, ptasync, NULL, NULL);
  242 
  243         if (status != CAM_REQ_CMP) {
  244                 printf("pt: Failed to attach master async callback "
  245                        "due to status 0x%x!\n", status);
  246         }
  247 }
  248 
  249 static cam_status
  250 ptctor(struct cam_periph *periph, void *arg)
  251 {
  252         struct pt_softc *softc;
  253         struct ccb_getdev *cgd;
  254         struct ccb_pathinq cpi;
  255 
  256         cgd = (struct ccb_getdev *)arg;
  257         if (cgd == NULL) {
  258                 printf("ptregister: no getdev CCB, can't register device\n");
  259                 return(CAM_REQ_CMP_ERR);
  260         }
  261 
  262         softc = (struct pt_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT);
  263 
  264         if (softc == NULL) {
  265                 printf("daregister: Unable to probe new device. "
  266                        "Unable to allocate softc\n");                           
  267                 return(CAM_REQ_CMP_ERR);
  268         }
  269 
  270         bzero(softc, sizeof(*softc));
  271         LIST_INIT(&softc->pending_ccbs);
  272         softc->state = PT_STATE_NORMAL;
  273         bioq_init(&softc->bio_queue);
  274 
  275         softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;
  276 
  277         periph->softc = softc;
  278 
  279         bzero(&cpi, sizeof(cpi));
  280         xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
  281         cpi.ccb_h.func_code = XPT_PATH_INQ;
  282         xpt_action((union ccb *)&cpi);
  283 
  284         cam_periph_unlock(periph);
  285         softc->device_stats = devstat_new_entry("pt",
  286                           periph->unit_number, 0,
  287                           DEVSTAT_NO_BLOCKSIZE,
  288                           SID_TYPE(&cgd->inq_data) |
  289                           XPORT_DEVSTAT_TYPE(cpi.transport),
  290                           DEVSTAT_PRIORITY_OTHER);
  291 
  292         softc->dev = make_dev(&pt_cdevsw, periph->unit_number, UID_ROOT,
  293                               GID_OPERATOR, 0600, "%s%d", periph->periph_name,
  294                               periph->unit_number);
  295         cam_periph_lock(periph);
  296         softc->dev->si_drv1 = periph;
  297 
  298         /*
  299          * Add async callbacks for bus reset and
  300          * bus device reset calls.  I don't bother
  301          * checking if this fails as, in most cases,
  302          * the system will function just fine without
  303          * them and the only alternative would be to
  304          * not attach the device on failure.
  305          */
  306         xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
  307                            ptasync, periph, periph->path);
  308 
  309         /* Tell the user we've attached to the device */
  310         xpt_announce_periph(periph, NULL);
  311 
  312         return(CAM_REQ_CMP);
  313 }
  314 
  315 static void
  316 ptoninvalidate(struct cam_periph *periph)
  317 {
  318         struct pt_softc *softc;
  319 
  320         softc = (struct pt_softc *)periph->softc;
  321 
  322         /*
  323          * De-register any async callbacks.
  324          */
  325         xpt_register_async(0, ptasync, periph, periph->path);
  326 
  327         softc->flags |= PT_FLAG_DEVICE_INVALID;
  328 
  329         /*
  330          * Return all queued I/O with ENXIO.
  331          * XXX Handle any transactions queued to the card
  332          *     with XPT_ABORT_CCB.
  333          */
  334         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  335 }
  336 
  337 static void
  338 ptdtor(struct cam_periph *periph)
  339 {
  340         struct pt_softc *softc;
  341 
  342         softc = (struct pt_softc *)periph->softc;
  343 
  344         devstat_remove_entry(softc->device_stats);
  345         cam_periph_unlock(periph);
  346         destroy_dev(softc->dev);
  347         cam_periph_lock(periph);
  348         free(softc, M_DEVBUF);
  349 }
  350 
  351 static void
  352 ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
  353 {
  354         struct cam_periph *periph;
  355 
  356         periph = (struct cam_periph *)callback_arg;
  357         switch (code) {
  358         case AC_FOUND_DEVICE:
  359         {
  360                 struct ccb_getdev *cgd;
  361                 cam_status status;
  362  
  363                 cgd = (struct ccb_getdev *)arg;
  364                 if (cgd == NULL)
  365                         break;
  366 
  367                 if (cgd->protocol != PROTO_SCSI)
  368                         break;
  369 
  370                 if (SID_TYPE(&cgd->inq_data) != T_PROCESSOR)
  371                         break;
  372 
  373                 /*
  374                  * Allocate a peripheral instance for
  375                  * this device and start the probe
  376                  * process.
  377                  */
  378                 status = cam_periph_alloc(ptctor, ptoninvalidate, ptdtor,
  379                                           ptstart, "pt", CAM_PERIPH_BIO,
  380                                           path, ptasync,
  381                                           AC_FOUND_DEVICE, cgd);
  382 
  383                 if (status != CAM_REQ_CMP
  384                  && status != CAM_REQ_INPROG)
  385                         printf("ptasync: Unable to attach to new device "
  386                                 "due to status 0x%x\n", status);
  387                 break;
  388         }
  389         case AC_SENT_BDR:
  390         case AC_BUS_RESET:
  391         {
  392                 struct pt_softc *softc;
  393                 struct ccb_hdr *ccbh;
  394 
  395                 softc = (struct pt_softc *)periph->softc;
  396                 /*
  397                  * Don't fail on the expected unit attention
  398                  * that will occur.
  399                  */
  400                 softc->flags |= PT_FLAG_RETRY_UA;
  401                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
  402                         ccbh->ccb_state |= PT_CCB_RETRY_UA;
  403         }
  404         /* FALLTHROUGH */
  405         default:
  406                 cam_periph_async(periph, code, path, arg);
  407                 break;
  408         }
  409 }
  410 
  411 static void
  412 ptstart(struct cam_periph *periph, union ccb *start_ccb)
  413 {
  414         struct pt_softc *softc;
  415         struct bio *bp;
  416 
  417         softc = (struct pt_softc *)periph->softc;
  418 
  419         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptstart\n"));
  420 
  421         /*
  422          * See if there is a buf with work for us to do..
  423          */
  424         bp = bioq_first(&softc->bio_queue);
  425         if (bp == NULL) {
  426                 xpt_release_ccb(start_ccb);
  427         } else {
  428                 bioq_remove(&softc->bio_queue, bp);
  429 
  430                 devstat_start_transaction_bio(softc->device_stats, bp);
  431 
  432                 scsi_send_receive(&start_ccb->csio,
  433                                   /*retries*/4,
  434                                   ptdone,
  435                                   MSG_SIMPLE_Q_TAG,
  436                                   bp->bio_cmd == BIO_READ,
  437                                   /*byte2*/0,
  438                                   bp->bio_bcount,
  439                                   bp->bio_data,
  440                                   /*sense_len*/SSD_FULL_SIZE,
  441                                   /*timeout*/softc->io_timeout);
  442 
  443                 start_ccb->ccb_h.ccb_state = PT_CCB_BUFFER_IO_UA;
  444 
  445                 /*
  446                  * Block out any asynchronous callbacks
  447                  * while we touch the pending ccb list.
  448                  */
  449                 LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h,
  450                                  periph_links.le);
  451 
  452                 start_ccb->ccb_h.ccb_bp = bp;
  453                 bp = bioq_first(&softc->bio_queue);
  454 
  455                 xpt_action(start_ccb);
  456                 
  457                 if (bp != NULL) {
  458                         /* Have more work to do, so ensure we stay scheduled */
  459                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  460                 }
  461         }
  462 }
  463 
  464 static void
  465 ptdone(struct cam_periph *periph, union ccb *done_ccb)
  466 {
  467         struct pt_softc *softc;
  468         struct ccb_scsiio *csio;
  469 
  470         softc = (struct pt_softc *)periph->softc;
  471 
  472         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptdone\n"));
  473 
  474         csio = &done_ccb->csio;
  475         switch (csio->ccb_h.ccb_state) {
  476         case PT_CCB_BUFFER_IO:
  477         case PT_CCB_BUFFER_IO_UA:
  478         {
  479                 struct bio *bp;
  480 
  481                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
  482                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  483                         int error;
  484                         int sf;
  485                         
  486                         if ((csio->ccb_h.ccb_state & PT_CCB_RETRY_UA) != 0)
  487                                 sf = SF_RETRY_UA;
  488                         else
  489                                 sf = 0;
  490 
  491                         error = pterror(done_ccb, CAM_RETRY_SELTO, sf);
  492                         if (error == ERESTART) {
  493                                 /*
  494                                  * A retry was scheuled, so
  495                                  * just return.
  496                                  */
  497                                 return;
  498                         }
  499                         if (error != 0) {
  500                                 if (error == ENXIO) {
  501                                         /*
  502                                          * Catastrophic error.  Mark our device
  503                                          * as invalid.
  504                                          */
  505                                         xpt_print(periph->path,
  506                                             "Invalidating device\n");
  507                                         softc->flags |= PT_FLAG_DEVICE_INVALID;
  508                                 }
  509 
  510                                 /*
  511                                  * return all queued I/O with EIO, so that
  512                                  * the client can retry these I/Os in the
  513                                  * proper order should it attempt to recover.
  514                                  */
  515                                 bioq_flush(&softc->bio_queue, NULL, EIO);
  516                                 bp->bio_error = error;
  517                                 bp->bio_resid = bp->bio_bcount;
  518                                 bp->bio_flags |= BIO_ERROR;
  519                         } else {
  520                                 bp->bio_resid = csio->resid;
  521                                 bp->bio_error = 0;
  522                                 if (bp->bio_resid != 0) {
  523                                         /* Short transfer ??? */
  524                                         bp->bio_flags |= BIO_ERROR;
  525                                 }
  526                         }
  527                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  528                                 cam_release_devq(done_ccb->ccb_h.path,
  529                                                  /*relsim_flags*/0,
  530                                                  /*reduction*/0,
  531                                                  /*timeout*/0,
  532                                                  /*getcount_only*/0);
  533                 } else {
  534                         bp->bio_resid = csio->resid;
  535                         if (bp->bio_resid != 0)
  536                                 bp->bio_flags |= BIO_ERROR;
  537                 }
  538 
  539                 /*
  540                  * Block out any asynchronous callbacks
  541                  * while we touch the pending ccb list.
  542                  */
  543                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
  544 
  545                 biofinish(bp, softc->device_stats, 0);
  546                 break;
  547         }
  548         }
  549         xpt_release_ccb(done_ccb);
  550 }
  551 
  552 static int
  553 pterror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
  554 {
  555         struct pt_softc   *softc;
  556         struct cam_periph *periph;
  557 
  558         periph = xpt_path_periph(ccb->ccb_h.path);
  559         softc = (struct pt_softc *)periph->softc;
  560 
  561         return(cam_periph_error(ccb, cam_flags, sense_flags,
  562                                 &softc->saved_ccb));
  563 }
  564 
  565 static int
  566 ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
  567 {
  568         struct cam_periph *periph;
  569         struct pt_softc *softc;
  570         int error = 0;
  571 
  572         periph = (struct cam_periph *)dev->si_drv1;
  573         if (periph == NULL)
  574                 return(ENXIO);
  575 
  576         softc = (struct pt_softc *)periph->softc;
  577 
  578         cam_periph_lock(periph);
  579 
  580         switch(cmd) {
  581         case PTIOCGETTIMEOUT:
  582                 if (softc->io_timeout >= 1000)
  583                         *(int *)addr = softc->io_timeout / 1000;
  584                 else
  585                         *(int *)addr = 0;
  586                 break;
  587         case PTIOCSETTIMEOUT:
  588                 if (*(int *)addr < 1) {
  589                         error = EINVAL;
  590                         break;
  591                 }
  592 
  593                 softc->io_timeout = *(int *)addr * 1000;
  594 
  595                 break;
  596         default:
  597                 error = cam_periph_ioctl(periph, cmd, addr, pterror);
  598                 break;
  599         }
  600 
  601         cam_periph_unlock(periph);
  602 
  603         return(error);
  604 }
  605 
  606 void
  607 scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
  608                   void (*cbfcnp)(struct cam_periph *, union ccb *),
  609                   u_int tag_action, int readop, u_int byte2,
  610                   u_int32_t xfer_len, u_int8_t *data_ptr, u_int8_t sense_len,
  611                   u_int32_t timeout)
  612 {
  613         struct scsi_send_receive *scsi_cmd;
  614 
  615         scsi_cmd = (struct scsi_send_receive *)&csio->cdb_io.cdb_bytes;
  616         scsi_cmd->opcode = readop ? RECEIVE : SEND;
  617         scsi_cmd->byte2 = byte2;
  618         scsi_ulto3b(xfer_len, scsi_cmd->xfer_len);
  619         scsi_cmd->control = 0;
  620 
  621         cam_fill_csio(csio,
  622                       retries,
  623                       cbfcnp,
  624                       /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
  625                       tag_action,
  626                       data_ptr,
  627                       xfer_len,
  628                       sense_len,
  629                       sizeof(*scsi_cmd),
  630                       timeout);
  631 }

Cache object: 23ecbaf26f3108f21497c6494915aff6


[ 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.