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/dev/scsipi/ss.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 /*      $NetBSD: ss.c,v 1.69 2006/11/16 01:33:26 christos Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1995 Kenneth Stailey.  All rights reserved.
    5  *   modified for configurable scanner support by Joachim Koenig
    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  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Kenneth Stailey.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: ss.c,v 1.69 2006/11/16 01:33:26 christos Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/fcntl.h>
   39 #include <sys/errno.h>
   40 #include <sys/ioctl.h>
   41 #include <sys/malloc.h>
   42 #include <sys/buf.h>
   43 #include <sys/bufq.h>
   44 #include <sys/proc.h>
   45 #include <sys/user.h>
   46 #include <sys/device.h>
   47 #include <sys/conf.h>
   48 #include <sys/vnode.h>
   49 #include <sys/scanio.h>
   50 
   51 #include <dev/scsipi/scsi_all.h>
   52 #include <dev/scsipi/scsipi_all.h>
   53 #include <dev/scsipi/scsi_scanner.h>
   54 #include <dev/scsipi/scsiconf.h>
   55 #include <dev/scsipi/ssvar.h>
   56 
   57 #include <dev/scsipi/ss_mustek.h>
   58 
   59 #define SSMODE(z)       ( minor(z)       & 0x03)
   60 #define SSUNIT(z)       ((minor(z) >> 4)       )
   61 #define SSNMINOR 16
   62 
   63 /*
   64  * If the mode is 3 (e.g. minor = 3,7,11,15)
   65  * then the device has been openned to set defaults
   66  * This mode does NOT ALLOW I/O, only ioctls
   67  */
   68 #define MODE_REWIND     0
   69 #define MODE_NONREWIND  1
   70 #define MODE_CONTROL    3
   71 
   72 static int      ssmatch(struct device *, struct cfdata *, void *);
   73 static void     ssattach(struct device *, struct device *, void *);
   74 static int      ssdetach(struct device *self, int flags);
   75 static int      ssactivate(struct device *self, enum devact act);
   76 
   77 CFATTACH_DECL(ss, sizeof(struct ss_softc),
   78     ssmatch, ssattach, ssdetach, ssactivate);
   79 
   80 extern struct cfdriver ss_cd;
   81 
   82 static dev_type_open(ssopen);
   83 static dev_type_close(ssclose);
   84 static dev_type_read(ssread);
   85 static dev_type_ioctl(ssioctl);
   86 
   87 const struct cdevsw ss_cdevsw = {
   88         ssopen, ssclose, ssread, nowrite, ssioctl,
   89         nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
   90 };
   91 
   92 static void     ssstrategy(struct buf *);
   93 static void     ssstart(struct scsipi_periph *);
   94 static void     ssdone(struct scsipi_xfer *, int);
   95 static void     ssminphys(struct buf *);
   96 
   97 static const struct scsipi_periphsw ss_switch = {
   98         NULL,
   99         ssstart,
  100         NULL,
  101         ssdone,
  102 };
  103 
  104 static const struct scsipi_inquiry_pattern ss_patterns[] = {
  105         {T_SCANNER, T_FIXED,
  106          "",         "",                 ""},
  107         {T_SCANNER, T_REMOV,
  108          "",         "",                 ""},
  109         {T_PROCESSOR, T_FIXED,
  110          "HP      ", "C1130A          ", ""},
  111         {T_PROCESSOR, T_FIXED,
  112          "HP      ", "C1750A          ", ""},
  113         {T_PROCESSOR, T_FIXED,
  114          "HP      ", "C2500A          ", ""},
  115         {T_PROCESSOR, T_FIXED,
  116          "HP      ", "C2520A          ", ""},
  117         {T_PROCESSOR, T_FIXED,
  118          "HP      ", "C5110A          ", ""},
  119         {T_PROCESSOR, T_FIXED,
  120          "HP      ", "C7670A          ", ""},
  121         {T_PROCESSOR, T_FIXED,
  122          "HP      ", "", ""},
  123 };
  124 
  125 static int
  126 ssmatch(struct device *parent, struct cfdata *match,
  127     void *aux)
  128 {
  129         struct scsipibus_attach_args *sa = aux;
  130         int priority;
  131 
  132         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  133             ss_patterns, sizeof(ss_patterns) / sizeof(ss_patterns[0]),
  134             sizeof(ss_patterns[0]), &priority);
  135         return (priority);
  136 }
  137 
  138 /*
  139  * The routine called by the low level scsi routine when it discovers
  140  * A device suitable for this driver
  141  * If it is a know special, call special attach routine to install
  142  * special handlers into the ss_softc structure
  143  */
  144 static void
  145 ssattach(struct device *parent, struct device *self, void *aux)
  146 {
  147         struct ss_softc *ss = device_private(self);
  148         struct scsipibus_attach_args *sa = aux;
  149         struct scsipi_periph *periph = sa->sa_periph;
  150 
  151         SC_DEBUG(periph, SCSIPI_DB2, ("ssattach: "));
  152 
  153         ss->flags |= SSF_AUTOCONF;
  154 
  155         /*
  156          * Store information needed to contact our base driver
  157          */
  158         ss->sc_periph = periph;
  159         periph->periph_dev = &ss->sc_dev;
  160         periph->periph_switch = &ss_switch;
  161 
  162         printf("\n");
  163 
  164         /*
  165          * Set up the buf queue for this device
  166          */
  167         bufq_alloc(&ss->buf_queue, "fcfs", 0);
  168 
  169         callout_init(&ss->sc_callout);
  170 
  171         /*
  172          * look for non-standard scanners with help of the quirk table
  173          * and install functions for special handling
  174          */
  175         SC_DEBUG(periph, SCSIPI_DB2, ("ssattach:\n"));
  176         if (memcmp(sa->sa_inqbuf.vendor, "MUSTEK", 6) == 0)
  177                 mustek_attach(ss, sa);
  178         if (memcmp(sa->sa_inqbuf.vendor, "HP      ", 8) == 0 &&
  179             memcmp(sa->sa_inqbuf.product, "ScanJet 5300C", 13) != 0)
  180                 scanjet_attach(ss, sa);
  181         if (ss->special == NULL) {
  182                 /* XXX add code to restart a SCSI2 scanner, if any */
  183         }
  184 
  185         ss->flags &= ~SSF_AUTOCONF;
  186 }
  187 
  188 static int
  189 ssdetach(struct device *self, int flags)
  190 {
  191         struct ss_softc *ss = device_private(self);
  192         int s, cmaj, mn;
  193 
  194         /* locate the major number */
  195         cmaj = cdevsw_lookup_major(&ss_cdevsw);
  196 
  197         /* kill any pending restart */
  198         callout_stop(&ss->sc_callout);
  199 
  200         s = splbio();
  201 
  202         /* Kill off any queued buffers. */
  203         bufq_drain(ss->buf_queue);
  204 
  205         bufq_free(ss->buf_queue);
  206 
  207         /* Kill off any pending commands. */
  208         scsipi_kill_pending(ss->sc_periph);
  209 
  210         splx(s);
  211 
  212         /* Nuke the vnodes for any open instances */
  213         mn = SSUNIT(device_unit(self));
  214         vdevgone(cmaj, mn, mn+SSNMINOR-1, VCHR);
  215 
  216         return (0);
  217 }
  218 
  219 static int
  220 ssactivate(struct device *self, enum devact act)
  221 {
  222         int rv = 0;
  223 
  224         switch (act) {
  225         case DVACT_ACTIVATE:
  226                 rv = EOPNOTSUPP;
  227                 break;
  228 
  229         case DVACT_DEACTIVATE:
  230                 /*
  231                  * Nothing to do; we key off the device's DVF_ACTIVE.
  232                  */
  233                 break;
  234         }
  235         return (rv);
  236 }
  237 
  238 /*
  239  * open the device.
  240  */
  241 static int
  242 ssopen(dev_t dev, int flag, int mode, struct lwp *l)
  243 {
  244         int unit;
  245         u_int ssmode;
  246         int error;
  247         struct ss_softc *ss;
  248         struct scsipi_periph *periph;
  249         struct scsipi_adapter *adapt;
  250 
  251         unit = SSUNIT(dev);
  252         if (unit >= ss_cd.cd_ndevs)
  253                 return (ENXIO);
  254         ss = ss_cd.cd_devs[unit];
  255         if (!ss)
  256                 return (ENXIO);
  257 
  258         if (!device_is_active(&ss->sc_dev))
  259                 return (ENODEV);
  260 
  261         ssmode = SSMODE(dev);
  262 
  263         periph = ss->sc_periph;
  264         adapt = periph->periph_channel->chan_adapter;
  265 
  266         SC_DEBUG(periph, SCSIPI_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
  267             unit, ss_cd.cd_ndevs));
  268 
  269         if (periph->periph_flags & PERIPH_OPEN) {
  270                 printf("%s: already open\n", ss->sc_dev.dv_xname);
  271                 return (EBUSY);
  272         }
  273 
  274         if ((error = scsipi_adapter_addref(adapt)) != 0)
  275                 return (error);
  276 
  277         /*
  278          * Catch any unit attention errors.
  279          *
  280          * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
  281          * consider paper to be a changeable media
  282          *
  283          */
  284         error = scsipi_test_unit_ready(periph,
  285             XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST |
  286             (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0));
  287         if (error)
  288                 goto bad;
  289 
  290         periph->periph_flags |= PERIPH_OPEN;    /* unit attn now errors */
  291 
  292         /*
  293          * If the mode is 3 (e.g. minor = 3,7,11,15)
  294          * then the device has been opened to set defaults
  295          * This mode does NOT ALLOW I/O, only ioctls
  296          */
  297         if (ssmode == MODE_CONTROL)
  298                 return (0);
  299 
  300         SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
  301         return (0);
  302 
  303 bad:
  304         scsipi_adapter_delref(adapt);
  305         periph->periph_flags &= ~PERIPH_OPEN;
  306         return (error);
  307 }
  308 
  309 /*
  310  * close the device.. only called if we are the LAST
  311  * occurence of an open device
  312  */
  313 static int
  314 ssclose(dev_t dev, int flag, int mode, struct lwp *l)
  315 {
  316         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  317         struct scsipi_periph *periph = ss->sc_periph;
  318         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  319         int error;
  320 
  321         SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n"));
  322 
  323         if (SSMODE(dev) == MODE_REWIND) {
  324                 if (ss->special && ss->special->rewind_scanner) {
  325                         /* call special handler to rewind/abort scan */
  326                         error = (ss->special->rewind_scanner)(ss);
  327                         if (error)
  328                                 return (error);
  329                 } else {
  330                         /* XXX add code to restart a SCSI2 scanner, if any */
  331                 }
  332                 ss->sio.scan_window_size = 0;
  333                 ss->flags &= ~SSF_TRIGGERED;
  334         }
  335 
  336         scsipi_wait_drain(periph);
  337 
  338         scsipi_adapter_delref(adapt);
  339         periph->periph_flags &= ~PERIPH_OPEN;
  340 
  341         return (0);
  342 }
  343 
  344 /*
  345  * trim the size of the transfer if needed,
  346  * called by physio
  347  * basically the smaller of our min and the scsi driver's
  348  * minphys
  349  */
  350 static void
  351 ssminphys(struct buf *bp)
  352 {
  353         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  354         struct scsipi_periph *periph = ss->sc_periph;
  355 
  356         scsipi_adapter_minphys(periph->periph_channel, bp);
  357 
  358         /*
  359          * trim the transfer further for special devices this is
  360          * because some scanners only read multiples of a line at a
  361          * time, also some cannot disconnect, so the read must be
  362          * short enough to happen quickly
  363          */
  364         if (ss->special && ss->special->minphys)
  365                 (ss->special->minphys)(ss, bp);
  366 }
  367 
  368 /*
  369  * Do a read on a device for a user process.
  370  * Prime scanner at start of read, check uio values, call ssstrategy
  371  * via physio for the actual transfer.
  372  */
  373 static int
  374 ssread(dev_t dev, struct uio *uio, int flag)
  375 {
  376         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  377         int error;
  378 
  379         if (!device_is_active(&ss->sc_dev))
  380                 return (ENODEV);
  381 
  382         /* if the scanner has not yet been started, do it now */
  383         if (!(ss->flags & SSF_TRIGGERED)) {
  384                 if (ss->special && ss->special->trigger_scanner) {
  385                         error = (ss->special->trigger_scanner)(ss);
  386                         if (error)
  387                                 return (error);
  388                 }
  389                 ss->flags |= SSF_TRIGGERED;
  390         }
  391 
  392         return (physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio));
  393 }
  394 
  395 /*
  396  * Actually translate the requested transfer into one the physical
  397  * driver can understand The transfer is described by a buf and will
  398  * include only one physical transfer.
  399  */
  400 static void
  401 ssstrategy(struct buf *bp)
  402 {
  403         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  404         struct scsipi_periph *periph = ss->sc_periph;
  405         int s;
  406 
  407         SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
  408             ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
  409 
  410         /*
  411          * If the device has been made invalid, error out
  412          */
  413         if (!device_is_active(&ss->sc_dev)) {
  414                 bp->b_flags |= B_ERROR;
  415                 if (periph->periph_flags & PERIPH_OPEN)
  416                         bp->b_error = EIO;
  417                 else
  418                         bp->b_error = ENODEV;
  419                 goto done;
  420         }
  421 
  422         /* If negative offset, error */
  423         if (bp->b_blkno < 0) {
  424                 bp->b_flags |= B_ERROR;
  425                 bp->b_error = EINVAL;
  426                 goto done;
  427         }
  428 
  429         if (bp->b_bcount > ss->sio.scan_window_size)
  430                 bp->b_bcount = ss->sio.scan_window_size;
  431 
  432         /*
  433          * If it's a null transfer, return immediatly
  434          */
  435         if (bp->b_bcount == 0)
  436                 goto done;
  437 
  438         s = splbio();
  439 
  440         /*
  441          * Place it in the queue of activities for this scanner
  442          * at the end (a bit silly because we only have on user..
  443          * (but it could fork()))
  444          */
  445         BUFQ_PUT(ss->buf_queue, bp);
  446 
  447         /*
  448          * Tell the device to get going on the transfer if it's
  449          * not doing anything, otherwise just wait for completion
  450          * (All a bit silly if we're only allowing 1 open but..)
  451          */
  452         ssstart(ss->sc_periph);
  453 
  454         splx(s);
  455         return;
  456 done:
  457         /*
  458          * Correctly set the buf to indicate a completed xfer
  459          */
  460         bp->b_resid = bp->b_bcount;
  461         biodone(bp);
  462 }
  463 
  464 /*
  465  * ssstart looks to see if there is a buf waiting for the device
  466  * and that the device is not already busy. If both are true,
  467  * It dequeues the buf and creates a scsi command to perform the
  468  * transfer required. The transfer request will call scsipi_done
  469  * on completion, which will in turn call this routine again
  470  * so that the next queued transfer is performed.
  471  * The bufs are queued by the strategy routine (ssstrategy)
  472  *
  473  * This routine is also called after other non-queued requests
  474  * have been made of the scsi driver, to ensure that the queue
  475  * continues to be drained.
  476  * ssstart() is called at splbio
  477  */
  478 static void
  479 ssstart(struct scsipi_periph *periph)
  480 {
  481         struct ss_softc *ss = (void *)periph->periph_dev;
  482         struct buf *bp;
  483 
  484         SC_DEBUG(periph, SCSIPI_DB2, ("ssstart "));
  485         /*
  486          * See if there is a buf to do and we are not already
  487          * doing one
  488          */
  489         while (periph->periph_active < periph->periph_openings) {
  490                 /* if a special awaits, let it proceed first */
  491                 if (periph->periph_flags & PERIPH_WAITING) {
  492                         periph->periph_flags &= ~PERIPH_WAITING;
  493                         wakeup((caddr_t)periph);
  494                         return;
  495                 }
  496 
  497                 /*
  498                  * See if there is a buf with work for us to do..
  499                  */
  500                 if ((bp = BUFQ_PEEK(ss->buf_queue)) == NULL)
  501                         return;
  502 
  503                 if (ss->special && ss->special->read) {
  504                         (ss->special->read)(ss, bp);
  505                 } else {
  506                         /* generic scsi2 scanner read */
  507                         /* XXX add code for SCSI2 scanner read */
  508                 }
  509         }
  510 }
  511 
  512 void
  513 ssrestart(void *v)
  514 {
  515         int s = splbio();
  516         ssstart((struct scsipi_periph *)v);
  517         splx(s);
  518 }
  519 
  520 static void
  521 ssdone(struct scsipi_xfer *xs, int error)
  522 {
  523         struct buf *bp = xs->bp;
  524 
  525         if (bp) {
  526                 bp->b_error = error;
  527                 bp->b_resid = xs->resid;
  528                 if (error)
  529                         bp->b_flags |= B_ERROR;
  530                 biodone(bp);
  531         }
  532 }
  533 
  534 
  535 /*
  536  * Perform special action on behalf of the user;
  537  * knows about the internals of this device
  538  */
  539 int
  540 ssioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct lwp *l)
  541 {
  542         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  543         int error = 0;
  544         struct scan_io *sio;
  545 
  546         if (!device_is_active(&ss->sc_dev))
  547                 return (ENODEV);
  548 
  549         switch (cmd) {
  550         case SCIOCGET:
  551                 if (ss->special && ss->special->get_params) {
  552                         /* call special handler */
  553                         error = (ss->special->get_params)(ss);
  554                         if (error)
  555                                 return (error);
  556                 } else {
  557                         /* XXX add code for SCSI2 scanner, if any */
  558                         return (EOPNOTSUPP);
  559                 }
  560                 memcpy(addr, &ss->sio, sizeof(struct scan_io));
  561                 break;
  562         case SCIOCSET:
  563                 sio = (struct scan_io *)addr;
  564 
  565                 if (ss->special && ss->special->set_params) {
  566                         /* call special handler */
  567                         error = (ss->special->set_params)(ss, sio);
  568                         if (error)
  569                                 return (error);
  570                 } else {
  571                         /* XXX add code for SCSI2 scanner, if any */
  572                         return (EOPNOTSUPP);
  573                 }
  574                 break;
  575         case SCIOCRESTART:
  576                 if (ss->special && ss->special->rewind_scanner ) {
  577                         /* call special handler */
  578                         error = (ss->special->rewind_scanner)(ss);
  579                         if (error)
  580                                 return (error);
  581                 } else
  582                         /* XXX add code for SCSI2 scanner, if any */
  583                         return (EOPNOTSUPP);
  584                 ss->flags &= ~SSF_TRIGGERED;
  585                 break;
  586 #ifdef NOTYET
  587         case SCAN_USE_ADF:
  588                 break;
  589 #endif
  590         default:
  591                 return (scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr,
  592                     flag, l));
  593         }
  594         return (error);
  595 }

Cache object: 5770506754fd730b9fc2963b46bd821e


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