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.74 2008/06/08 18:18:34 tsutsui 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.74 2008/06/08 18:18:34 tsutsui 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, 0);
  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         ss = device_lookup_private(&ss_cd, unit);
  253         if (ss == NULL)
  254                 return (ENXIO);
  255 
  256         if (!device_is_active(&ss->sc_dev))
  257                 return (ENODEV);
  258 
  259         ssmode = SSMODE(dev);
  260 
  261         periph = ss->sc_periph;
  262         adapt = periph->periph_channel->chan_adapter;
  263 
  264         SC_DEBUG(periph, SCSIPI_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
  265             unit, ss_cd.cd_ndevs));
  266 
  267         if (periph->periph_flags & PERIPH_OPEN) {
  268                 aprint_error_dev(&ss->sc_dev, "already open\n");
  269                 return (EBUSY);
  270         }
  271 
  272         if ((error = scsipi_adapter_addref(adapt)) != 0)
  273                 return (error);
  274 
  275         /*
  276          * Catch any unit attention errors.
  277          *
  278          * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
  279          * consider paper to be a changeable media
  280          *
  281          */
  282         error = scsipi_test_unit_ready(periph,
  283             XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST |
  284             (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0));
  285         if (error)
  286                 goto bad;
  287 
  288         periph->periph_flags |= PERIPH_OPEN;    /* unit attn now errors */
  289 
  290         /*
  291          * If the mode is 3 (e.g. minor = 3,7,11,15)
  292          * then the device has been opened to set defaults
  293          * This mode does NOT ALLOW I/O, only ioctls
  294          */
  295         if (ssmode == MODE_CONTROL)
  296                 return (0);
  297 
  298         SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
  299         return (0);
  300 
  301 bad:
  302         scsipi_adapter_delref(adapt);
  303         periph->periph_flags &= ~PERIPH_OPEN;
  304         return (error);
  305 }
  306 
  307 /*
  308  * close the device.. only called if we are the LAST
  309  * occurence of an open device
  310  */
  311 static int
  312 ssclose(dev_t dev, int flag, int mode, struct lwp *l)
  313 {
  314         struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
  315         struct scsipi_periph *periph = ss->sc_periph;
  316         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  317         int error;
  318 
  319         SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n"));
  320 
  321         if (SSMODE(dev) == MODE_REWIND) {
  322                 if (ss->special && ss->special->rewind_scanner) {
  323                         /* call special handler to rewind/abort scan */
  324                         error = (ss->special->rewind_scanner)(ss);
  325                         if (error)
  326                                 return (error);
  327                 } else {
  328                         /* XXX add code to restart a SCSI2 scanner, if any */
  329                 }
  330                 ss->sio.scan_window_size = 0;
  331                 ss->flags &= ~SSF_TRIGGERED;
  332         }
  333 
  334         scsipi_wait_drain(periph);
  335 
  336         scsipi_adapter_delref(adapt);
  337         periph->periph_flags &= ~PERIPH_OPEN;
  338 
  339         return (0);
  340 }
  341 
  342 /*
  343  * trim the size of the transfer if needed,
  344  * called by physio
  345  * basically the smaller of our min and the scsi driver's
  346  * minphys
  347  */
  348 static void
  349 ssminphys(struct buf *bp)
  350 {
  351         struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
  352         struct scsipi_periph *periph = ss->sc_periph;
  353 
  354         scsipi_adapter_minphys(periph->periph_channel, bp);
  355 
  356         /*
  357          * trim the transfer further for special devices this is
  358          * because some scanners only read multiples of a line at a
  359          * time, also some cannot disconnect, so the read must be
  360          * short enough to happen quickly
  361          */
  362         if (ss->special && ss->special->minphys)
  363                 (ss->special->minphys)(ss, bp);
  364 }
  365 
  366 /*
  367  * Do a read on a device for a user process.
  368  * Prime scanner at start of read, check uio values, call ssstrategy
  369  * via physio for the actual transfer.
  370  */
  371 static int
  372 ssread(dev_t dev, struct uio *uio, int flag)
  373 {
  374         struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
  375         int error;
  376 
  377         if (!device_is_active(&ss->sc_dev))
  378                 return (ENODEV);
  379 
  380         /* if the scanner has not yet been started, do it now */
  381         if (!(ss->flags & SSF_TRIGGERED)) {
  382                 if (ss->special && ss->special->trigger_scanner) {
  383                         error = (ss->special->trigger_scanner)(ss);
  384                         if (error)
  385                                 return (error);
  386                 }
  387                 ss->flags |= SSF_TRIGGERED;
  388         }
  389 
  390         return (physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio));
  391 }
  392 
  393 /*
  394  * Actually translate the requested transfer into one the physical
  395  * driver can understand The transfer is described by a buf and will
  396  * include only one physical transfer.
  397  */
  398 static void
  399 ssstrategy(struct buf *bp)
  400 {
  401         struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
  402         struct scsipi_periph *periph = ss->sc_periph;
  403         int s;
  404 
  405         SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
  406             ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
  407 
  408         /*
  409          * If the device has been made invalid, error out
  410          */
  411         if (!device_is_active(&ss->sc_dev)) {
  412                 if (periph->periph_flags & PERIPH_OPEN)
  413                         bp->b_error = EIO;
  414                 else
  415                         bp->b_error = ENODEV;
  416                 goto done;
  417         }
  418 
  419         /* If negative offset, error */
  420         if (bp->b_blkno < 0) {
  421                 bp->b_error = EINVAL;
  422                 goto done;
  423         }
  424 
  425         if (bp->b_bcount > ss->sio.scan_window_size)
  426                 bp->b_bcount = ss->sio.scan_window_size;
  427 
  428         /*
  429          * If it's a null transfer, return immediatly
  430          */
  431         if (bp->b_bcount == 0)
  432                 goto done;
  433 
  434         s = splbio();
  435 
  436         /*
  437          * Place it in the queue of activities for this scanner
  438          * at the end (a bit silly because we only have on user..
  439          * (but it could fork()))
  440          */
  441         BUFQ_PUT(ss->buf_queue, bp);
  442 
  443         /*
  444          * Tell the device to get going on the transfer if it's
  445          * not doing anything, otherwise just wait for completion
  446          * (All a bit silly if we're only allowing 1 open but..)
  447          */
  448         ssstart(ss->sc_periph);
  449 
  450         splx(s);
  451         return;
  452 done:
  453         /*
  454          * Correctly set the buf to indicate a completed xfer
  455          */
  456         bp->b_resid = bp->b_bcount;
  457         biodone(bp);
  458 }
  459 
  460 /*
  461  * ssstart looks to see if there is a buf waiting for the device
  462  * and that the device is not already busy. If both are true,
  463  * It dequeues the buf and creates a scsi command to perform the
  464  * transfer required. The transfer request will call scsipi_done
  465  * on completion, which will in turn call this routine again
  466  * so that the next queued transfer is performed.
  467  * The bufs are queued by the strategy routine (ssstrategy)
  468  *
  469  * This routine is also called after other non-queued requests
  470  * have been made of the scsi driver, to ensure that the queue
  471  * continues to be drained.
  472  * ssstart() is called at splbio
  473  */
  474 static void
  475 ssstart(struct scsipi_periph *periph)
  476 {
  477         struct ss_softc *ss = (void *)periph->periph_dev;
  478         struct buf *bp;
  479 
  480         SC_DEBUG(periph, SCSIPI_DB2, ("ssstart "));
  481         /*
  482          * See if there is a buf to do and we are not already
  483          * doing one
  484          */
  485         while (periph->periph_active < periph->periph_openings) {
  486                 /* if a special awaits, let it proceed first */
  487                 if (periph->periph_flags & PERIPH_WAITING) {
  488                         periph->periph_flags &= ~PERIPH_WAITING;
  489                         wakeup((void *)periph);
  490                         return;
  491                 }
  492 
  493                 /*
  494                  * See if there is a buf with work for us to do..
  495                  */
  496                 if ((bp = BUFQ_PEEK(ss->buf_queue)) == NULL)
  497                         return;
  498 
  499                 if (ss->special && ss->special->read) {
  500                         (ss->special->read)(ss, bp);
  501                 } else {
  502                         /* generic scsi2 scanner read */
  503                         /* XXX add code for SCSI2 scanner read */
  504                 }
  505         }
  506 }
  507 
  508 void
  509 ssrestart(void *v)
  510 {
  511         int s = splbio();
  512         ssstart((struct scsipi_periph *)v);
  513         splx(s);
  514 }
  515 
  516 static void
  517 ssdone(struct scsipi_xfer *xs, int error)
  518 {
  519         struct buf *bp = xs->bp;
  520 
  521         if (bp) {
  522                 bp->b_error = error;
  523                 bp->b_resid = xs->resid;
  524                 biodone(bp);
  525         }
  526 }
  527 
  528 
  529 /*
  530  * Perform special action on behalf of the user;
  531  * knows about the internals of this device
  532  */
  533 int
  534 ssioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
  535 {
  536         struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
  537         int error = 0;
  538         struct scan_io *sio;
  539 
  540         if (!device_is_active(&ss->sc_dev))
  541                 return (ENODEV);
  542 
  543         switch (cmd) {
  544         case SCIOCGET:
  545                 if (ss->special && ss->special->get_params) {
  546                         /* call special handler */
  547                         error = (ss->special->get_params)(ss);
  548                         if (error)
  549                                 return (error);
  550                 } else {
  551                         /* XXX add code for SCSI2 scanner, if any */
  552                         return (EOPNOTSUPP);
  553                 }
  554                 memcpy(addr, &ss->sio, sizeof(struct scan_io));
  555                 break;
  556         case SCIOCSET:
  557                 sio = (struct scan_io *)addr;
  558 
  559                 if (ss->special && ss->special->set_params) {
  560                         /* call special handler */
  561                         error = (ss->special->set_params)(ss, sio);
  562                         if (error)
  563                                 return (error);
  564                 } else {
  565                         /* XXX add code for SCSI2 scanner, if any */
  566                         return (EOPNOTSUPP);
  567                 }
  568                 break;
  569         case SCIOCRESTART:
  570                 if (ss->special && ss->special->rewind_scanner ) {
  571                         /* call special handler */
  572                         error = (ss->special->rewind_scanner)(ss);
  573                         if (error)
  574                                 return (error);
  575                 } else
  576                         /* XXX add code for SCSI2 scanner, if any */
  577                         return (EOPNOTSUPP);
  578                 ss->flags &= ~SSF_TRIGGERED;
  579                 break;
  580 #ifdef NOTYET
  581         case SCAN_USE_ADF:
  582                 break;
  583 #endif
  584         default:
  585                 return (scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr,
  586                     flag, l));
  587         }
  588         return (error);
  589 }

Cache object: a4a8e63516f6d2c469018d4491b8da2b


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