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/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  * pt: Processor Type driver.
    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/pt.c,v 1.18.2.3 1999/09/05 08:21:36 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 struct scsi_data {
   59         struct buf_queue_head buf_queue;
   60 };
   61 
   62 static  d_open_t        ptopen;
   63 static  d_close_t       ptclose;
   64 static  d_ioctl_t       ptioctl;
   65 static  d_strategy_t    ptstrategy;
   66 
   67 #define CDEV_MAJOR 61
   68 static struct cdevsw pt_cdevsw = 
   69         { ptopen,       ptclose,        rawread,        rawwrite,       /*61*/
   70           ptioctl,      nostop,         nullreset,      nodevtotty,/* pt */
   71           seltrue,      nommap,         ptstrategy,     "pt",   NULL,   -1 };
   72 
   73 SCSI_DEVICE_ENTRIES(pt)
   74 
   75 static void     ptstart(u_int32_t unit, u_int32_t flags);
   76 static void     pt_strategy(struct buf *bp, struct scsi_link *sc_link);
   77 static int      pt_sense(struct scsi_xfer *scsi_xfer);
   78 
   79 static struct scsi_device pt_switch =
   80 {
   81     pt_sense,
   82     ptstart,                    /* we have a queue, and this is how we service it */
   83     NULL,
   84     NULL,
   85     "pt",
   86     0,
   87         {0, 0},
   88         SDEV_ONCE_ONLY, /* Only one open allowed */
   89         ptattach,
   90         "Processor",
   91         ptopen,
   92     sizeof(struct scsi_data),
   93         T_PROCESSOR,
   94         0,
   95         0,
   96         0,
   97         0,
   98         0,
   99         pt_strategy,
  100 };
  101 
  102 static errval
  103 ptattach(struct scsi_link *sc_link)
  104 {
  105         struct scsi_data *pt = sc_link->sd;
  106 
  107         bufq_init(&pt->buf_queue);
  108         return 0;
  109 }
  110 
  111 /*
  112  * ptstart looks to see if there is a buf waiting for the device
  113  * and that the device is not already busy. If both are true,
  114  * It dequeues the buf and creates a scsi command to perform the
  115  * transfer required. The transfer request will call scsi_done
  116  * on completion, which will in turn call this routine again
  117  * so that the next queued transfer is performed.
  118  * The bufs are queued by the strategy routine (ptstrategy)
  119  *
  120  * This routine is also called after other non-queued requests
  121  * have been made of the scsi driver, to ensure that the queue
  122  * continues to be drained.
  123  * ptstart() is called at splbio
  124  */
  125 static void
  126 ptstart(unit, flags)
  127         u_int32_t       unit;
  128         u_int32_t flags;
  129 {
  130         struct scsi_link *sc_link = SCSI_LINK(&pt_switch, unit);
  131         struct scsi_data *pt = sc_link->sd;
  132         register struct buf *bp = 0;
  133         struct
  134         {
  135 #define PROCESSOR_SEND 0x0A
  136 #define PROCESSOR_RECEIVE 0x08
  137                 u_char  op_code;
  138                 u_char  byte2;
  139                 u_char  len[3];
  140                 u_char  control;
  141         } cmd;
  142 
  143 
  144         SC_DEBUG(sc_link, SDEV_DB2, ("ptstart "));
  145         /*
  146          * See if there is a buf to do and we are not already
  147          * doing one
  148          */
  149         while (sc_link->opennings != 0) {
  150 
  151                 /* if a special awaits, let it proceed first */
  152                 if (sc_link->flags & SDEV_WAITING) {
  153                         sc_link->flags &= ~SDEV_WAITING;
  154                         wakeup((caddr_t)sc_link);
  155                         return;
  156                 }
  157 
  158                 bp = bufq_first(&pt->buf_queue);
  159                 if (bp == NULL) {       /* yes, an assign */
  160                         return;
  161                 }
  162                 bufq_remove(&pt->buf_queue, bp);
  163 
  164                 /*
  165                  *  Fill out the scsi command
  166                  */
  167                 bzero(&cmd, sizeof(cmd));
  168                 if ((bp->b_flags & B_READ) == B_WRITE) {
  169                         cmd.op_code = PROCESSOR_SEND;
  170                         flags |= SCSI_DATA_OUT;
  171                 } else {
  172                         cmd.op_code = PROCESSOR_RECEIVE;
  173                         flags |= SCSI_DATA_IN;
  174                 }
  175 
  176                 scsi_uto3b(bp->b_bcount, cmd.len);
  177                 /*
  178                  * go ask the adapter to do all this for us
  179                  */
  180                 if (scsi_scsi_cmd(sc_link,
  181                         (struct scsi_generic *) &cmd,
  182                         sizeof(cmd),
  183                         (u_char *) bp->b_un.b_addr,
  184                         bp->b_bcount,
  185                         0,
  186                         10000,
  187                         bp,
  188                         flags) == SUCCESSFULLY_QUEUED) {
  189                 } else {
  190                         printf("pt%ld: oops not queued\n", unit);
  191                         bp->b_flags |= B_ERROR;
  192                         bp->b_error = EIO;
  193                         biodone(bp);
  194                 }
  195         } /* go back and see if we can cram more work in.. */
  196 }
  197 
  198 static void
  199 pt_strategy(struct buf *bp, struct scsi_link *sc_link)
  200 {
  201         unsigned char unit;
  202         u_int32_t opri;
  203         struct scsi_data *pt;
  204 
  205         unit = minor((bp->b_dev));
  206         pt = sc_link->sd;
  207 
  208         opri = splbio();
  209 
  210         /*
  211          * Use a bounce buffer if necessary
  212          */
  213 #ifdef BOUNCE_BUFFERS
  214         if (sc_link->flags & SDEV_BOUNCE)
  215                 vm_bounce_alloc(bp);
  216 #endif
  217 
  218         /*
  219          * Place it in the queue of activities for this tape
  220          * at the end (a bit silly because we only have one user..
  221          * (but it could fork() ))
  222          */
  223         bufq_insert_tail(&pt->buf_queue, bp);
  224 
  225         /*
  226          * Tell the device to get going on the transfer if it's
  227          * not doing anything, otherwise just wait for completion
  228          * (All a bit silly if we're only allowing 1 open but..)
  229          */
  230         ptstart(unit, 0);
  231 
  232         splx(opri);
  233         return;
  234 }
  235 
  236 /*
  237  * sense handler: Called to determine what to do when the
  238  * device returns a CHECK CONDITION.
  239  *
  240  * For the processor type devices we try to handle the "info" field.
  241  */
  242 
  243 static int
  244 pt_sense(struct scsi_xfer *xs)
  245 {
  246         struct scsi_sense_data *sense = &(xs->sense);
  247         struct buf *bp;
  248 
  249         long resid;
  250 
  251         if ((sense->error_code & SSD_ERRCODE_VALID) == 0 ||
  252         (sense->ext.extended.flags & SSD_ILI) == 0) {
  253                 return SCSIRET_CONTINUE;        /* let the default handler handle it */
  254         }
  255 
  256         resid = ntohl(*((int32_t *) sense->ext.extended.info));
  257 
  258         bp = xs->bp;
  259 
  260         if (resid < 0) {
  261                 /* It synthesized data in order to fill our request.
  262                  * Move resid back to cover this.
  263                  */
  264                 xs->resid = -resid;
  265                 xs->flags |= SCSI_RESID_VALID;
  266                 return 0;
  267         }
  268         else {
  269                 /* It wanted to send more data.  We can't really do anything
  270                  * about this.
  271                  */
  272                 return SCSIRET_CONTINUE;
  273         }
  274 }
  275 
  276 static pt_devsw_installed = 0;
  277 
  278 static void     pt_drvinit(void *unused)
  279 {
  280         dev_t dev;
  281 #ifdef DEVFS
  282         int unit;
  283 #endif
  284 
  285         if( ! pt_devsw_installed ) {
  286                 dev = makedev(CDEV_MAJOR, 0);
  287                 cdevsw_add(&dev,&pt_cdevsw, NULL);
  288                 pt_devsw_installed = 1;
  289 #ifdef DEVFS
  290                 /* XXX only 1 unit. */
  291                 for (unit = 0; unit < 1; unit++) {
  292                         /* XXX not saving tokens yet. */
  293                         devfs_add_devswf(&pt_cdevsw, unit, DV_CHR,
  294                                          UID_ROOT, GID_WHEEL, 0600,
  295                                          "pt%d", unit);
  296                         devfs_add_devswf(&pt_cdevsw, unit | SCSI_CONTROL_MASK,
  297                                          DV_CHR,
  298                                          UID_ROOT, GID_WHEEL, 0600,
  299                                          "pt%d.ctl", unit);
  300                 }
  301 #endif
  302         }
  303 }
  304 
  305 SYSINIT(ptdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,pt_drvinit,NULL)
  306 
  307 

Cache object: 288e9c9fa76959875987ed8b8d0d1718


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