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$");
   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_WAITING          = 0x02,
   70         PT_CCB_RETRY_UA         = 0x04,
   71         PT_CCB_BUFFER_IO_UA     = PT_CCB_BUFFER_IO|PT_CCB_RETRY_UA
   72 } pt_ccb_state;
   73 
   74 /* Offsets into our private area for storing information */
   75 #define ccb_state       ppriv_field0
   76 #define ccb_bp          ppriv_ptr1
   77 
   78 struct pt_softc {
   79         struct   bio_queue_head bio_queue;
   80         struct   devstat *device_stats;
   81         LIST_HEAD(, ccb_hdr) pending_ccbs;
   82         pt_state state;
   83         pt_flags flags; 
   84         union    ccb saved_ccb;
   85         int      io_timeout;
   86         struct cdev *dev;
   87 };
   88 
   89 static  d_open_t        ptopen;
   90 static  d_close_t       ptclose;
   91 static  d_strategy_t    ptstrategy;
   92 static  periph_init_t   ptinit;
   93 static  void            ptasync(void *callback_arg, u_int32_t code,
   94                                 struct cam_path *path, void *arg);
   95 static  periph_ctor_t   ptctor;
   96 static  periph_oninv_t  ptoninvalidate;
   97 static  periph_dtor_t   ptdtor;
   98 static  periph_start_t  ptstart;
   99 static  void            ptdone(struct cam_periph *periph,
  100                                union ccb *done_ccb);
  101 static  d_ioctl_t       ptioctl;
  102 static  int             pterror(union ccb *ccb, u_int32_t cam_flags,
  103                                 u_int32_t sense_flags);
  104 
  105 void    scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
  106                           void (*cbfcnp)(struct cam_periph *, union ccb *),
  107                           u_int tag_action, int readop, u_int byte2,
  108                           u_int32_t xfer_len, u_int8_t *data_ptr,
  109                           u_int8_t sense_len, u_int32_t timeout);
  110 
  111 static struct periph_driver ptdriver =
  112 {
  113         ptinit, "pt",
  114         TAILQ_HEAD_INITIALIZER(ptdriver.units), /* generation */ 0
  115 };
  116 
  117 PERIPHDRIVER_DECLARE(pt, ptdriver);
  118 
  119 
  120 static struct cdevsw pt_cdevsw = {
  121         .d_version =    D_VERSION,
  122         .d_flags =      0,
  123         .d_open =       ptopen,
  124         .d_close =      ptclose,
  125         .d_read =       physread,
  126         .d_write =      physwrite,
  127         .d_ioctl =      ptioctl,
  128         .d_strategy =   ptstrategy,
  129         .d_name =       "pt",
  130 };
  131 
  132 #ifndef SCSI_PT_DEFAULT_TIMEOUT
  133 #define SCSI_PT_DEFAULT_TIMEOUT         60
  134 #endif
  135 
  136 static int
  137 ptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
  138 {
  139         struct cam_periph *periph;
  140         struct pt_softc *softc;
  141         int error = 0;
  142 
  143         periph = (struct cam_periph *)dev->si_drv1;
  144         if (cam_periph_acquire(periph) != CAM_REQ_CMP)
  145                 return (ENXIO); 
  146 
  147         softc = (struct pt_softc *)periph->softc;
  148 
  149         cam_periph_lock(periph);
  150         if (softc->flags & PT_FLAG_DEVICE_INVALID) {
  151                 cam_periph_unlock(periph);
  152                 cam_periph_release(periph);
  153                 return(ENXIO);
  154         }
  155 
  156         if ((softc->flags & PT_FLAG_OPEN) == 0)
  157                 softc->flags |= PT_FLAG_OPEN;
  158         else {
  159                 error = EBUSY;
  160                 cam_periph_release(periph);
  161         }
  162 
  163         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
  164             ("ptopen: dev=%s\n", devtoname(dev)));
  165 
  166         cam_periph_unlock(periph);
  167         return (error);
  168 }
  169 
  170 static int
  171 ptclose(struct cdev *dev, int flag, int fmt, struct thread *td)
  172 {
  173         struct  cam_periph *periph;
  174         struct  pt_softc *softc;
  175 
  176         periph = (struct cam_periph *)dev->si_drv1;
  177         if (periph == NULL)
  178                 return (ENXIO); 
  179 
  180         softc = (struct pt_softc *)periph->softc;
  181 
  182         cam_periph_lock(periph);
  183 
  184         softc->flags &= ~PT_FLAG_OPEN;
  185         cam_periph_unlock(periph);
  186         cam_periph_release(periph);
  187         return (0);
  188 }
  189 
  190 /*
  191  * Actually translate the requested transfer into one the physical driver
  192  * can understand.  The transfer is described by a buf and will include
  193  * only one physical transfer.
  194  */
  195 static void
  196 ptstrategy(struct bio *bp)
  197 {
  198         struct cam_periph *periph;
  199         struct pt_softc *softc;
  200         
  201         periph = (struct cam_periph *)bp->bio_dev->si_drv1;
  202         bp->bio_resid = bp->bio_bcount;
  203         if (periph == NULL) {
  204                 biofinish(bp, NULL, ENXIO);
  205                 return;
  206         }
  207         cam_periph_lock(periph);
  208         softc = (struct pt_softc *)periph->softc;
  209 
  210         /*
  211          * If the device has been made invalid, error out
  212          */
  213         if ((softc->flags & PT_FLAG_DEVICE_INVALID)) {
  214                 cam_periph_unlock(periph);
  215                 biofinish(bp, NULL, ENXIO);
  216                 return;
  217         }
  218         
  219         /*
  220          * Place it in the queue of disk activities for this disk
  221          */
  222         bioq_insert_tail(&softc->bio_queue, bp);
  223 
  224         /*
  225          * Schedule ourselves for performing the work.
  226          */
  227         xpt_schedule(periph, /* XXX priority */1);
  228         cam_periph_unlock(periph);
  229 
  230         return;
  231 }
  232 
  233 static void
  234 ptinit(void)
  235 {
  236         cam_status status;
  237 
  238         /*
  239          * Install a global async callback.  This callback will
  240          * receive async callbacks like "new device found".
  241          */
  242         status = xpt_register_async(AC_FOUND_DEVICE, ptasync, NULL, NULL);
  243 
  244         if (status != CAM_REQ_CMP) {
  245                 printf("pt: Failed to attach master async callback "
  246                        "due to status 0x%x!\n", status);
  247         }
  248 }
  249 
  250 static cam_status
  251 ptctor(struct cam_periph *periph, void *arg)
  252 {
  253         struct pt_softc *softc;
  254         struct ccb_getdev *cgd;
  255 
  256         cgd = (struct ccb_getdev *)arg;
  257         if (periph == NULL) {
  258                 printf("ptregister: periph was NULL!!\n");
  259                 return(CAM_REQ_CMP_ERR);
  260         }
  261 
  262         if (cgd == NULL) {
  263                 printf("ptregister: no getdev CCB, can't register device\n");
  264                 return(CAM_REQ_CMP_ERR);
  265         }
  266 
  267         softc = (struct pt_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT);
  268 
  269         if (softc == NULL) {
  270                 printf("daregister: Unable to probe new device. "
  271                        "Unable to allocate softc\n");                           
  272                 return(CAM_REQ_CMP_ERR);
  273         }
  274 
  275         bzero(softc, sizeof(*softc));
  276         LIST_INIT(&softc->pending_ccbs);
  277         softc->state = PT_STATE_NORMAL;
  278         bioq_init(&softc->bio_queue);
  279 
  280         softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;
  281 
  282         periph->softc = softc;
  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) | DEVSTAT_TYPE_IF_SCSI,
  289                           DEVSTAT_PRIORITY_OTHER);
  290 
  291         softc->dev = make_dev(&pt_cdevsw, periph->unit_number, UID_ROOT,
  292                               GID_OPERATOR, 0600, "%s%d", periph->periph_name,
  293                               periph->unit_number);
  294         cam_periph_lock(periph);
  295         softc->dev->si_drv1 = periph;
  296 
  297         /*
  298          * Add async callbacks for bus reset and
  299          * bus device reset calls.  I don't bother
  300          * checking if this fails as, in most cases,
  301          * the system will function just fine without
  302          * them and the only alternative would be to
  303          * not attach the device on failure.
  304          */
  305         xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
  306                            ptasync, periph, periph->path);
  307 
  308         /* Tell the user we've attached to the device */
  309         xpt_announce_periph(periph, NULL);
  310 
  311         return(CAM_REQ_CMP);
  312 }
  313 
  314 static void
  315 ptoninvalidate(struct cam_periph *periph)
  316 {
  317         struct pt_softc *softc;
  318 
  319         softc = (struct pt_softc *)periph->softc;
  320 
  321         /*
  322          * De-register any async callbacks.
  323          */
  324         xpt_register_async(0, ptasync, periph, periph->path);
  325 
  326         softc->flags |= PT_FLAG_DEVICE_INVALID;
  327 
  328         /*
  329          * Return all queued I/O with ENXIO.
  330          * XXX Handle any transactions queued to the card
  331          *     with XPT_ABORT_CCB.
  332          */
  333         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  334 
  335         xpt_print(periph->path, "lost device\n");
  336 }
  337 
  338 static void
  339 ptdtor(struct cam_periph *periph)
  340 {
  341         struct pt_softc *softc;
  342 
  343         softc = (struct pt_softc *)periph->softc;
  344 
  345         devstat_remove_entry(softc->device_stats);
  346 
  347         destroy_dev(softc->dev);
  348 
  349         xpt_print(periph->path, "removing device entry\n");
  350         free(softc, M_DEVBUF);
  351 }
  352 
  353 static void
  354 ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
  355 {
  356         struct cam_periph *periph;
  357 
  358         periph = (struct cam_periph *)callback_arg;
  359         switch (code) {
  360         case AC_FOUND_DEVICE:
  361         {
  362                 struct ccb_getdev *cgd;
  363                 cam_status status;
  364  
  365                 cgd = (struct ccb_getdev *)arg;
  366                 if (cgd == NULL)
  367                         break;
  368 
  369                 if (SID_TYPE(&cgd->inq_data) != T_PROCESSOR)
  370                         break;
  371 
  372                 /*
  373                  * Allocate a peripheral instance for
  374                  * this device and start the probe
  375                  * process.
  376                  */
  377                 status = cam_periph_alloc(ptctor, ptoninvalidate, ptdtor,
  378                                           ptstart, "pt", CAM_PERIPH_BIO,
  379                                           cgd->ccb_h.path, ptasync,
  380                                           AC_FOUND_DEVICE, cgd);
  381 
  382                 if (status != CAM_REQ_CMP
  383                  && status != CAM_REQ_INPROG)
  384                         printf("ptasync: Unable to attach to new device "
  385                                 "due to status 0x%x\n", status);
  386                 break;
  387         }
  388         case AC_SENT_BDR:
  389         case AC_BUS_RESET:
  390         {
  391                 struct pt_softc *softc;
  392                 struct ccb_hdr *ccbh;
  393 
  394                 softc = (struct pt_softc *)periph->softc;
  395                 /*
  396                  * Don't fail on the expected unit attention
  397                  * that will occur.
  398                  */
  399                 softc->flags |= PT_FLAG_RETRY_UA;
  400                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
  401                         ccbh->ccb_state |= PT_CCB_RETRY_UA;
  402         }
  403         /* FALLTHROUGH */
  404         default:
  405                 cam_periph_async(periph, code, path, arg);
  406                 break;
  407         }
  408 }
  409 
  410 static void
  411 ptstart(struct cam_periph *periph, union ccb *start_ccb)
  412 {
  413         struct pt_softc *softc;
  414         struct bio *bp;
  415 
  416         softc = (struct pt_softc *)periph->softc;
  417 
  418         /*
  419          * See if there is a buf with work for us to do..
  420          */
  421         bp = bioq_first(&softc->bio_queue);
  422         if (periph->immediate_priority <= periph->pinfo.priority) {
  423                 CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
  424                                 ("queuing for immediate ccb\n"));
  425                 start_ccb->ccb_h.ccb_state = PT_CCB_WAITING;
  426                 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
  427                                   periph_links.sle);
  428                 periph->immediate_priority = CAM_PRIORITY_NONE;
  429                 wakeup(&periph->ccb_list);
  430         } else if (bp == NULL) {
  431                 xpt_release_ccb(start_ccb);
  432         } else {
  433                 bioq_remove(&softc->bio_queue, bp);
  434 
  435                 devstat_start_transaction_bio(softc->device_stats, bp);
  436 
  437                 scsi_send_receive(&start_ccb->csio,
  438                                   /*retries*/4,
  439                                   ptdone,
  440                                   MSG_SIMPLE_Q_TAG,
  441                                   bp->bio_cmd == BIO_READ,
  442                                   /*byte2*/0,
  443                                   bp->bio_bcount,
  444                                   bp->bio_data,
  445                                   /*sense_len*/SSD_FULL_SIZE,
  446                                   /*timeout*/softc->io_timeout);
  447 
  448                 start_ccb->ccb_h.ccb_state = PT_CCB_BUFFER_IO_UA;
  449 
  450                 /*
  451                  * Block out any asyncronous callbacks
  452                  * while we touch the pending ccb list.
  453                  */
  454                 LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h,
  455                                  periph_links.le);
  456 
  457                 start_ccb->ccb_h.ccb_bp = bp;
  458                 bp = bioq_first(&softc->bio_queue);
  459 
  460                 xpt_action(start_ccb);
  461                 
  462                 if (bp != NULL) {
  463                         /* Have more work to do, so ensure we stay scheduled */
  464                         xpt_schedule(periph, /* XXX priority */1);
  465                 }
  466         }
  467 }
  468 
  469 static void
  470 ptdone(struct cam_periph *periph, union ccb *done_ccb)
  471 {
  472         struct pt_softc *softc;
  473         struct ccb_scsiio *csio;
  474 
  475         softc = (struct pt_softc *)periph->softc;
  476         csio = &done_ccb->csio;
  477         switch (csio->ccb_h.ccb_state) {
  478         case PT_CCB_BUFFER_IO:
  479         case PT_CCB_BUFFER_IO_UA:
  480         {
  481                 struct bio *bp;
  482 
  483                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
  484                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  485                         int error;
  486                         int sf;
  487                         
  488                         if ((csio->ccb_h.ccb_state & PT_CCB_RETRY_UA) != 0)
  489                                 sf = SF_RETRY_UA;
  490                         else
  491                                 sf = 0;
  492 
  493                         error = pterror(done_ccb, CAM_RETRY_SELTO, sf);
  494                         if (error == ERESTART) {
  495                                 /*
  496                                  * A retry was scheuled, so
  497                                  * just return.
  498                                  */
  499                                 return;
  500                         }
  501                         if (error != 0) {
  502                                 if (error == ENXIO) {
  503                                         /*
  504                                          * Catastrophic error.  Mark our device
  505                                          * as invalid.
  506                                          */
  507                                         xpt_print(periph->path,
  508                                             "Invalidating device\n");
  509                                         softc->flags |= PT_FLAG_DEVICE_INVALID;
  510                                 }
  511 
  512                                 /*
  513                                  * return all queued I/O with EIO, so that
  514                                  * the client can retry these I/Os in the
  515                                  * proper order should it attempt to recover.
  516                                  */
  517                                 bioq_flush(&softc->bio_queue, NULL, EIO);
  518                                 bp->bio_error = error;
  519                                 bp->bio_resid = bp->bio_bcount;
  520                                 bp->bio_flags |= BIO_ERROR;
  521                         } else {
  522                                 bp->bio_resid = csio->resid;
  523                                 bp->bio_error = 0;
  524                                 if (bp->bio_resid != 0) {
  525                                         /* Short transfer ??? */
  526                                         bp->bio_flags |= BIO_ERROR;
  527                                 }
  528                         }
  529                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  530                                 cam_release_devq(done_ccb->ccb_h.path,
  531                                                  /*relsim_flags*/0,
  532                                                  /*reduction*/0,
  533                                                  /*timeout*/0,
  534                                                  /*getcount_only*/0);
  535                 } else {
  536                         bp->bio_resid = csio->resid;
  537                         if (bp->bio_resid != 0)
  538                                 bp->bio_flags |= BIO_ERROR;
  539                 }
  540 
  541                 /*
  542                  * Block out any asyncronous callbacks
  543                  * while we touch the pending ccb list.
  544                  */
  545                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
  546 
  547                 biofinish(bp, softc->device_stats, 0);
  548                 break;
  549         }
  550         case PT_CCB_WAITING:
  551                 /* Caller will release the CCB */
  552                 wakeup(&done_ccb->ccb_h.cbfcnp);
  553                 return;
  554         }
  555         xpt_release_ccb(done_ccb);
  556 }
  557 
  558 static int
  559 pterror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
  560 {
  561         struct pt_softc   *softc;
  562         struct cam_periph *periph;
  563 
  564         periph = xpt_path_periph(ccb->ccb_h.path);
  565         softc = (struct pt_softc *)periph->softc;
  566 
  567         return(cam_periph_error(ccb, cam_flags, sense_flags,
  568                                 &softc->saved_ccb));
  569 }
  570 
  571 static int
  572 ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
  573 {
  574         struct cam_periph *periph;
  575         struct pt_softc *softc;
  576         int error = 0;
  577 
  578         periph = (struct cam_periph *)dev->si_drv1;
  579         if (periph == NULL)
  580                 return(ENXIO);
  581 
  582         softc = (struct pt_softc *)periph->softc;
  583 
  584         cam_periph_lock(periph);
  585 
  586         switch(cmd) {
  587         case PTIOCGETTIMEOUT:
  588                 if (softc->io_timeout >= 1000)
  589                         *(int *)addr = softc->io_timeout / 1000;
  590                 else
  591                         *(int *)addr = 0;
  592                 break;
  593         case PTIOCSETTIMEOUT:
  594                 if (*(int *)addr < 1) {
  595                         error = EINVAL;
  596                         break;
  597                 }
  598 
  599                 softc->io_timeout = *(int *)addr * 1000;
  600 
  601                 break;
  602         default:
  603                 error = cam_periph_ioctl(periph, cmd, addr, pterror);
  604                 break;
  605         }
  606 
  607         cam_periph_unlock(periph);
  608 
  609         return(error);
  610 }
  611 
  612 void
  613 scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
  614                   void (*cbfcnp)(struct cam_periph *, union ccb *),
  615                   u_int tag_action, int readop, u_int byte2,
  616                   u_int32_t xfer_len, u_int8_t *data_ptr, u_int8_t sense_len,
  617                   u_int32_t timeout)
  618 {
  619         struct scsi_send_receive *scsi_cmd;
  620 
  621         scsi_cmd = (struct scsi_send_receive *)&csio->cdb_io.cdb_bytes;
  622         scsi_cmd->opcode = readop ? RECEIVE : SEND;
  623         scsi_cmd->byte2 = byte2;
  624         scsi_ulto3b(xfer_len, scsi_cmd->xfer_len);
  625         scsi_cmd->control = 0;
  626 
  627         cam_fill_csio(csio,
  628                       retries,
  629                       cbfcnp,
  630                       /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
  631                       tag_action,
  632                       data_ptr,
  633                       xfer_len,
  634                       sense_len,
  635                       sizeof(*scsi_cmd),
  636                       timeout);
  637 }

Cache object: a5e1bd9be2cc4259e7b9e3b840660fd2


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