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

Cache object: 3668e40608893e912a52b2f5747a9dbe


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