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/scsi/sctarg.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  * sctarg: Target mode user interface
    3  *
    4  * Copyright (C) 1995, HD Associates, Inc.
    5  * PO Box 276
    6  * Pepperell, MA 01463
    7  * 508 433 5266
    8  * dufault@hda.com
    9  *
   10  * This code is contributed to the University of California at Berkeley:
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the University of
   23  *      California, Berkeley and its contributors.
   24  * 4. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  * $FreeBSD: src/sys/scsi/sctarg.c,v 1.17.2.2 1999/09/05 08:21:48 peter Exp $
   41  */
   42 
   43 #include "opt_bounce.h"
   44 #include "opt_scsi.h"
   45 
   46 #include <sys/param.h>
   47 #include <sys/systm.h>
   48 #include <sys/buf.h>
   49 #include <sys/proc.h>
   50 #include <sys/conf.h>
   51 #include <sys/kernel.h>
   52 #ifdef DEVFS
   53 #include <sys/devfsext.h>
   54 #endif /*DEVFS*/
   55 #include <scsi/scsi_all.h>
   56 #include <scsi/scsiconf.h>
   57 
   58 
   59 #define OPEN 0x01
   60 
   61 struct scsi_data {
   62         struct buf_queue_head buf_queue;
   63         int flags;                                      /* Already open */
   64 };
   65 
   66 static  d_open_t        sctargopen;
   67 static  d_close_t       sctargclose;
   68 static  d_ioctl_t       sctargioctl;
   69 static  d_strategy_t    sctargstrategy;
   70 
   71 #define CDEV_MAJOR 65
   72 static struct cdevsw sctarg_cdevsw = 
   73         { sctargopen,   sctargclose,    rawread,        rawwrite,       /*65*/
   74           sctargioctl,  nostop,         nullreset,      nodevtotty,/* sctarg */
   75           seltrue,      nommap,         sctargstrategy, "sctarg", NULL, -1 };
   76 
   77 SCSI_DEVICE_ENTRIES(sctarg)
   78 
   79 static errval sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
   80                           struct scsi_link *sc_link);
   81 static void sctargstart(u_int32_t unit, u_int32_t unused_flags);
   82 static void sctarg_strategy(struct buf *bp, struct scsi_link *sc_link);
   83 
   84 static struct scsi_device sctarg_switch =
   85 {
   86         NULL,
   87         sctargstart,    /* we have a queue, and this is how we service it */
   88         NULL,
   89         NULL,
   90         "sctarg",
   91         0,
   92         {0, 0},
   93         SDEV_ONCE_ONLY,
   94         sctargattach,
   95         "Processor Target",
   96         sctargopen,
   97         sizeof(struct scsi_data),
   98         T_TARGET,
   99         0,
  100         0,
  101         sctarg_open,
  102         0,
  103         0,
  104         sctarg_strategy,
  105 };
  106 
  107 static errval
  108 sctargattach(struct scsi_link *sc_link)
  109 {
  110         struct scsi_data *sctarg;
  111 
  112         sctarg = sc_link->sd;
  113         bufq_init(&sctarg->buf_queue);
  114         sctarg->flags = 0;
  115         return 0;
  116 }
  117 
  118 static errval
  119 sctarg_open(dev_t dev, int flags, int fmt, struct proc *p,
  120             struct scsi_link *sc_link)
  121 {
  122         int ret = 0;
  123 
  124         /* Does this host adapter support target mode operation?
  125          */
  126         if ((sc_link->flags & SDEV_TARGET_OPS) == 0)
  127                 return ENODEV;  /* Operation not supported */
  128 
  129         if (SCSI_FIXED(dev)) {
  130                 sc_link->scsibus = SCSI_BUS(dev);
  131                 scsi_set_bus(sc_link->scsibus, sc_link);
  132 
  133                 sc_link->target = SCSI_ID(dev);
  134                 sc_link->lun = SCSI_LUN(dev);
  135         }
  136 
  137         if (sc_link->scsibus == SCCONF_UNSPEC ||
  138                 sc_link->target == SCCONF_UNSPEC ||
  139                 sc_link->lun == SCCONF_UNSPEC)
  140                         return ENXIO;
  141 
  142         /* XXX: You can have more than one target device on a single
  143          * host adapter.  We need a reference count.
  144          */
  145         if ((sc_link->sd->flags & OPEN) == 0)   /* Enable target mode */
  146         {
  147                 ret = scsi_target_mode(sc_link, 1);
  148                 sc_link->sd->flags |= OPEN;
  149         }
  150 
  151         return ret;
  152 }
  153 
  154 /*
  155  * sctargstart looks to see if there is a buf waiting for the device
  156  * and that the device is not already busy. If both are true,
  157  * It dequeues the buf and creates a scsi command to perform the
  158  * transfer required. The transfer request will call scsi_done
  159  * on completion, which will in turn call this routine again
  160  * so that the next queued transfer is performed.
  161  * The bufs are queued by the strategy routine (sctargstrategy)
  162  *
  163  * This routine is also called after other non-queued requests
  164  * have been made of the scsi driver, to ensure that the queue
  165  * continues to be drained.
  166  * sctargstart() is called at splbio
  167  */
  168 static void
  169 sctargstart(unit, unused_flags)
  170         u_int32_t       unit;
  171         u_int32_t       unused_flags;
  172 {
  173         struct scsi_link *sc_link = SCSI_LINK(&sctarg_switch, unit);
  174         struct scsi_data *sctarg = sc_link->sd;
  175         register struct buf *bp = 0;
  176         struct
  177         {
  178 #define PROCESSOR_SEND 0x0A
  179 #define PROCESSOR_RECEIVE 0x08
  180                 u_char  op_code;
  181                 u_char  byte2;
  182                 u_char  len[3];
  183                 u_char  control;
  184         } cmd;
  185 
  186         u_int32_t flags;
  187 
  188         SC_DEBUG(sc_link, SDEV_DB2, ("sctargstart "));
  189         /*
  190          * See if there is a buf to do and we are not already
  191          * doing one
  192          */
  193         while (sc_link->opennings != 0) {
  194 
  195                 /* if a special awaits, let it proceed first */
  196                 if (sc_link->flags & SDEV_WAITING) {
  197                         sc_link->flags &= ~SDEV_WAITING;
  198                         wakeup((caddr_t)sc_link);
  199                         return;
  200                 }
  201 
  202                 bp = bufq_first(&sctarg->buf_queue);
  203                 if (bp == NULL)
  204                         return;
  205                 bufq_remove(&sctarg->buf_queue, bp);
  206 
  207                 /*
  208                  *  Fill out the scsi command
  209                  */
  210                 bzero(&cmd, sizeof(cmd));
  211                 flags = SCSI_TARGET;
  212                 if ((bp->b_flags & B_READ) == B_WRITE) {
  213                         cmd.op_code = PROCESSOR_SEND;
  214                         flags |= SCSI_DATA_OUT;
  215                 } else {
  216                         cmd.op_code = PROCESSOR_RECEIVE;
  217                         flags |= SCSI_DATA_IN;
  218                 }
  219 
  220                 scsi_uto3b(bp->b_bcount, cmd.len);
  221                 /*
  222                  * go ask the adapter to do all this for us
  223                  */
  224                 if (scsi_scsi_cmd(sc_link,
  225                         (struct scsi_generic *) &cmd,
  226                         sizeof(cmd),
  227                         (u_char *) bp->b_un.b_addr,
  228                         bp->b_bcount,
  229                         0,
  230                         100000,
  231                         bp,
  232                         flags | SCSI_NOSLEEP) == SUCCESSFULLY_QUEUED) {
  233                 } else {
  234                         printf("sctarg%ld: oops not queued\n", unit);
  235                         bp->b_flags |= B_ERROR;
  236                         bp->b_error = EIO;
  237                         biodone(bp);
  238                 }
  239         } /* go back and see if we can cram more work in.. */
  240 }
  241 
  242 static void
  243 sctarg_strategy(struct buf *bp, struct scsi_link *sc_link)
  244 {
  245         unsigned char unit;
  246         u_int32_t opri;
  247         struct scsi_data *sctarg;
  248 
  249         unit = minor((bp->b_dev));
  250         sctarg = sc_link->sd;
  251 
  252         opri = splbio();
  253 
  254         /*
  255          * Use a bounce buffer if necessary
  256          */
  257 #ifdef BOUNCE_BUFFERS
  258         if (sc_link->flags & SDEV_BOUNCE)
  259                 vm_bounce_alloc(bp);
  260 #endif
  261 
  262         /*
  263          * Place it at the end of the queue of activities for this device.
  264          */
  265         bufq_insert_tail(&sctarg->buf_queue, bp);
  266 
  267         /*
  268          * Tell the device to get going on the transfer if it's
  269          * not doing anything, otherwise just wait for completion
  270          * (All a bit silly if we're only allowing 1 open but..)
  271          */
  272         sctargstart(unit, 0);
  273 
  274         splx(opri);
  275         return;
  276 }
  277 
  278 static sctarg_devsw_installed = 0;
  279 #ifdef DEVFS
  280 static void *sctarg_devfs_token;
  281 #endif
  282 
  283 static void     sctarg_drvinit(void *unused)
  284 {
  285         dev_t dev;
  286 
  287         if( ! sctarg_devsw_installed ) {
  288                 dev = makedev(CDEV_MAJOR, 0);
  289                 cdevsw_add(&dev,&sctarg_cdevsw, NULL);
  290                 sctarg_devsw_installed = 1;
  291 #ifdef DEVFS
  292                 /* XXX should be in ADAPTER code */
  293                 sctarg_devfs_token =
  294                         devfs_add_devswf(&sctarg_cdevsw, 0, DV_CHR, 0,  0, 
  295                                         0600, "sctarg");
  296 #endif
  297         }
  298 }
  299 
  300 SYSINIT(sctargdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,sctarg_drvinit,NULL)
  301 
  302 

Cache object: 445c8f4d40df7cd2f8adc071448f2a7b


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