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.0/sys/cam/scsi/scsi_pt.c 257049 2013-10-24 10:33:31Z mav $");
   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_release_locked(periph);
  152                 cam_periph_unlock(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_release_locked(periph);
  186         cam_periph_unlock(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, CAM_PRIORITY_NORMAL);
  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         struct ccb_pathinq cpi;
  256 
  257         cgd = (struct ccb_getdev *)arg;
  258         if (cgd == NULL) {
  259                 printf("ptregister: no getdev CCB, can't register device\n");
  260                 return(CAM_REQ_CMP_ERR);
  261         }
  262 
  263         softc = (struct pt_softc *)malloc(sizeof(*softc),M_DEVBUF,M_NOWAIT);
  264 
  265         if (softc == NULL) {
  266                 printf("daregister: Unable to probe new device. "
  267                        "Unable to allocate softc\n");                           
  268                 return(CAM_REQ_CMP_ERR);
  269         }
  270 
  271         bzero(softc, sizeof(*softc));
  272         LIST_INIT(&softc->pending_ccbs);
  273         softc->state = PT_STATE_NORMAL;
  274         bioq_init(&softc->bio_queue);
  275 
  276         softc->io_timeout = SCSI_PT_DEFAULT_TIMEOUT * 1000;
  277 
  278         periph->softc = softc;
  279 
  280         bzero(&cpi, sizeof(cpi));
  281         xpt_setup_ccb(&cpi.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
  282         cpi.ccb_h.func_code = XPT_PATH_INQ;
  283         xpt_action((union ccb *)&cpi);
  284 
  285         cam_periph_unlock(periph);
  286         softc->device_stats = devstat_new_entry("pt",
  287                           periph->unit_number, 0,
  288                           DEVSTAT_NO_BLOCKSIZE,
  289                           SID_TYPE(&cgd->inq_data) |
  290                           XPORT_DEVSTAT_TYPE(cpi.transport),
  291                           DEVSTAT_PRIORITY_OTHER);
  292 
  293         softc->dev = make_dev(&pt_cdevsw, periph->unit_number, UID_ROOT,
  294                               GID_OPERATOR, 0600, "%s%d", periph->periph_name,
  295                               periph->unit_number);
  296         cam_periph_lock(periph);
  297         softc->dev->si_drv1 = periph;
  298 
  299         /*
  300          * Add async callbacks for bus reset and
  301          * bus device reset calls.  I don't bother
  302          * checking if this fails as, in most cases,
  303          * the system will function just fine without
  304          * them and the only alternative would be to
  305          * not attach the device on failure.
  306          */
  307         xpt_register_async(AC_SENT_BDR | AC_BUS_RESET | AC_LOST_DEVICE,
  308                            ptasync, periph, periph->path);
  309 
  310         /* Tell the user we've attached to the device */
  311         xpt_announce_periph(periph, NULL);
  312 
  313         return(CAM_REQ_CMP);
  314 }
  315 
  316 static void
  317 ptoninvalidate(struct cam_periph *periph)
  318 {
  319         struct pt_softc *softc;
  320 
  321         softc = (struct pt_softc *)periph->softc;
  322 
  323         /*
  324          * De-register any async callbacks.
  325          */
  326         xpt_register_async(0, ptasync, periph, periph->path);
  327 
  328         softc->flags |= PT_FLAG_DEVICE_INVALID;
  329 
  330         /*
  331          * Return all queued I/O with ENXIO.
  332          * XXX Handle any transactions queued to the card
  333          *     with XPT_ABORT_CCB.
  334          */
  335         bioq_flush(&softc->bio_queue, NULL, ENXIO);
  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         cam_periph_unlock(periph);
  347         destroy_dev(softc->dev);
  348         cam_periph_lock(periph);
  349         free(softc, M_DEVBUF);
  350 }
  351 
  352 static void
  353 ptasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
  354 {
  355         struct cam_periph *periph;
  356 
  357         periph = (struct cam_periph *)callback_arg;
  358         switch (code) {
  359         case AC_FOUND_DEVICE:
  360         {
  361                 struct ccb_getdev *cgd;
  362                 cam_status status;
  363  
  364                 cgd = (struct ccb_getdev *)arg;
  365                 if (cgd == NULL)
  366                         break;
  367 
  368                 if (cgd->protocol != PROTO_SCSI)
  369                         break;
  370 
  371                 if (SID_TYPE(&cgd->inq_data) != T_PROCESSOR)
  372                         break;
  373 
  374                 /*
  375                  * Allocate a peripheral instance for
  376                  * this device and start the probe
  377                  * process.
  378                  */
  379                 status = cam_periph_alloc(ptctor, ptoninvalidate, ptdtor,
  380                                           ptstart, "pt", CAM_PERIPH_BIO,
  381                                           cgd->ccb_h.path, ptasync,
  382                                           AC_FOUND_DEVICE, cgd);
  383 
  384                 if (status != CAM_REQ_CMP
  385                  && status != CAM_REQ_INPROG)
  386                         printf("ptasync: Unable to attach to new device "
  387                                 "due to status 0x%x\n", status);
  388                 break;
  389         }
  390         case AC_SENT_BDR:
  391         case AC_BUS_RESET:
  392         {
  393                 struct pt_softc *softc;
  394                 struct ccb_hdr *ccbh;
  395 
  396                 softc = (struct pt_softc *)periph->softc;
  397                 /*
  398                  * Don't fail on the expected unit attention
  399                  * that will occur.
  400                  */
  401                 softc->flags |= PT_FLAG_RETRY_UA;
  402                 LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
  403                         ccbh->ccb_state |= PT_CCB_RETRY_UA;
  404         }
  405         /* FALLTHROUGH */
  406         default:
  407                 cam_periph_async(periph, code, path, arg);
  408                 break;
  409         }
  410 }
  411 
  412 static void
  413 ptstart(struct cam_periph *periph, union ccb *start_ccb)
  414 {
  415         struct pt_softc *softc;
  416         struct bio *bp;
  417 
  418         softc = (struct pt_softc *)periph->softc;
  419 
  420         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptstart\n"));
  421 
  422         /*
  423          * See if there is a buf with work for us to do..
  424          */
  425         bp = bioq_first(&softc->bio_queue);
  426         if (periph->immediate_priority <= periph->pinfo.priority) {
  427                 CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE,
  428                                 ("queuing for immediate ccb\n"));
  429                 start_ccb->ccb_h.ccb_state = PT_CCB_WAITING;
  430                 SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
  431                                   periph_links.sle);
  432                 periph->immediate_priority = CAM_PRIORITY_NONE;
  433                 wakeup(&periph->ccb_list);
  434         } else if (bp == NULL) {
  435                 xpt_release_ccb(start_ccb);
  436         } else {
  437                 bioq_remove(&softc->bio_queue, bp);
  438 
  439                 devstat_start_transaction_bio(softc->device_stats, bp);
  440 
  441                 scsi_send_receive(&start_ccb->csio,
  442                                   /*retries*/4,
  443                                   ptdone,
  444                                   MSG_SIMPLE_Q_TAG,
  445                                   bp->bio_cmd == BIO_READ,
  446                                   /*byte2*/0,
  447                                   bp->bio_bcount,
  448                                   bp->bio_data,
  449                                   /*sense_len*/SSD_FULL_SIZE,
  450                                   /*timeout*/softc->io_timeout);
  451 
  452                 start_ccb->ccb_h.ccb_state = PT_CCB_BUFFER_IO_UA;
  453 
  454                 /*
  455                  * Block out any asynchronous callbacks
  456                  * while we touch the pending ccb list.
  457                  */
  458                 LIST_INSERT_HEAD(&softc->pending_ccbs, &start_ccb->ccb_h,
  459                                  periph_links.le);
  460 
  461                 start_ccb->ccb_h.ccb_bp = bp;
  462                 bp = bioq_first(&softc->bio_queue);
  463 
  464                 xpt_action(start_ccb);
  465                 
  466                 if (bp != NULL) {
  467                         /* Have more work to do, so ensure we stay scheduled */
  468                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
  469                 }
  470         }
  471 }
  472 
  473 static void
  474 ptdone(struct cam_periph *periph, union ccb *done_ccb)
  475 {
  476         struct pt_softc *softc;
  477         struct ccb_scsiio *csio;
  478 
  479         softc = (struct pt_softc *)periph->softc;
  480 
  481         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("ptdone\n"));
  482 
  483         csio = &done_ccb->csio;
  484         switch (csio->ccb_h.ccb_state) {
  485         case PT_CCB_BUFFER_IO:
  486         case PT_CCB_BUFFER_IO_UA:
  487         {
  488                 struct bio *bp;
  489 
  490                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
  491                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
  492                         int error;
  493                         int sf;
  494                         
  495                         if ((csio->ccb_h.ccb_state & PT_CCB_RETRY_UA) != 0)
  496                                 sf = SF_RETRY_UA;
  497                         else
  498                                 sf = 0;
  499 
  500                         error = pterror(done_ccb, CAM_RETRY_SELTO, sf);
  501                         if (error == ERESTART) {
  502                                 /*
  503                                  * A retry was scheuled, so
  504                                  * just return.
  505                                  */
  506                                 return;
  507                         }
  508                         if (error != 0) {
  509                                 if (error == ENXIO) {
  510                                         /*
  511                                          * Catastrophic error.  Mark our device
  512                                          * as invalid.
  513                                          */
  514                                         xpt_print(periph->path,
  515                                             "Invalidating device\n");
  516                                         softc->flags |= PT_FLAG_DEVICE_INVALID;
  517                                 }
  518 
  519                                 /*
  520                                  * return all queued I/O with EIO, so that
  521                                  * the client can retry these I/Os in the
  522                                  * proper order should it attempt to recover.
  523                                  */
  524                                 bioq_flush(&softc->bio_queue, NULL, EIO);
  525                                 bp->bio_error = error;
  526                                 bp->bio_resid = bp->bio_bcount;
  527                                 bp->bio_flags |= BIO_ERROR;
  528                         } else {
  529                                 bp->bio_resid = csio->resid;
  530                                 bp->bio_error = 0;
  531                                 if (bp->bio_resid != 0) {
  532                                         /* Short transfer ??? */
  533                                         bp->bio_flags |= BIO_ERROR;
  534                                 }
  535                         }
  536                         if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
  537                                 cam_release_devq(done_ccb->ccb_h.path,
  538                                                  /*relsim_flags*/0,
  539                                                  /*reduction*/0,
  540                                                  /*timeout*/0,
  541                                                  /*getcount_only*/0);
  542                 } else {
  543                         bp->bio_resid = csio->resid;
  544                         if (bp->bio_resid != 0)
  545                                 bp->bio_flags |= BIO_ERROR;
  546                 }
  547 
  548                 /*
  549                  * Block out any asynchronous callbacks
  550                  * while we touch the pending ccb list.
  551                  */
  552                 LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
  553 
  554                 biofinish(bp, softc->device_stats, 0);
  555                 break;
  556         }
  557         case PT_CCB_WAITING:
  558                 /* Caller will release the CCB */
  559                 wakeup(&done_ccb->ccb_h.cbfcnp);
  560                 return;
  561         }
  562         xpt_release_ccb(done_ccb);
  563 }
  564 
  565 static int
  566 pterror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
  567 {
  568         struct pt_softc   *softc;
  569         struct cam_periph *periph;
  570 
  571         periph = xpt_path_periph(ccb->ccb_h.path);
  572         softc = (struct pt_softc *)periph->softc;
  573 
  574         return(cam_periph_error(ccb, cam_flags, sense_flags,
  575                                 &softc->saved_ccb));
  576 }
  577 
  578 static int
  579 ptioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
  580 {
  581         struct cam_periph *periph;
  582         struct pt_softc *softc;
  583         int error = 0;
  584 
  585         periph = (struct cam_periph *)dev->si_drv1;
  586         if (periph == NULL)
  587                 return(ENXIO);
  588 
  589         softc = (struct pt_softc *)periph->softc;
  590 
  591         cam_periph_lock(periph);
  592 
  593         switch(cmd) {
  594         case PTIOCGETTIMEOUT:
  595                 if (softc->io_timeout >= 1000)
  596                         *(int *)addr = softc->io_timeout / 1000;
  597                 else
  598                         *(int *)addr = 0;
  599                 break;
  600         case PTIOCSETTIMEOUT:
  601                 if (*(int *)addr < 1) {
  602                         error = EINVAL;
  603                         break;
  604                 }
  605 
  606                 softc->io_timeout = *(int *)addr * 1000;
  607 
  608                 break;
  609         default:
  610                 error = cam_periph_ioctl(periph, cmd, addr, pterror);
  611                 break;
  612         }
  613 
  614         cam_periph_unlock(periph);
  615 
  616         return(error);
  617 }
  618 
  619 void
  620 scsi_send_receive(struct ccb_scsiio *csio, u_int32_t retries,
  621                   void (*cbfcnp)(struct cam_periph *, union ccb *),
  622                   u_int tag_action, int readop, u_int byte2,
  623                   u_int32_t xfer_len, u_int8_t *data_ptr, u_int8_t sense_len,
  624                   u_int32_t timeout)
  625 {
  626         struct scsi_send_receive *scsi_cmd;
  627 
  628         scsi_cmd = (struct scsi_send_receive *)&csio->cdb_io.cdb_bytes;
  629         scsi_cmd->opcode = readop ? RECEIVE : SEND;
  630         scsi_cmd->byte2 = byte2;
  631         scsi_ulto3b(xfer_len, scsi_cmd->xfer_len);
  632         scsi_cmd->control = 0;
  633 
  634         cam_fill_csio(csio,
  635                       retries,
  636                       cbfcnp,
  637                       /*flags*/readop ? CAM_DIR_IN : CAM_DIR_OUT,
  638                       tag_action,
  639                       data_ptr,
  640                       xfer_len,
  641                       sense_len,
  642                       sizeof(*scsi_cmd),
  643                       timeout);
  644 }

Cache object: 6e4889f400c609598ab81d490d80671d


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