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.59.4.1 2005/04/06 11:56:31 tron 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.59.4.1 2005/04/06 11:56:31 tron 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,
   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, void *aux)
  127 {
  128         struct scsipibus_attach_args *sa = aux;
  129         int priority;
  130 
  131         (void)scsipi_inqmatch(&sa->sa_inqbuf,
  132             (caddr_t)ss_patterns, sizeof(ss_patterns) / sizeof(ss_patterns[0]),
  133             sizeof(ss_patterns[0]), &priority);
  134         return (priority);
  135 }
  136 
  137 /*
  138  * The routine called by the low level scsi routine when it discovers
  139  * A device suitable for this driver
  140  * If it is a know special, call special attach routine to install
  141  * special handlers into the ss_softc structure
  142  */
  143 static void
  144 ssattach(struct device *parent, struct device *self, void *aux)
  145 {
  146         struct ss_softc *ss = (void *)self;
  147         struct scsipibus_attach_args *sa = aux;
  148         struct scsipi_periph *periph = sa->sa_periph;
  149 
  150         SC_DEBUG(periph, SCSIPI_DB2, ("ssattach: "));
  151 
  152         ss->flags |= SSF_AUTOCONF;
  153 
  154         /*
  155          * Store information needed to contact our base driver
  156          */
  157         ss->sc_periph = periph;
  158         periph->periph_dev = &ss->sc_dev;
  159         periph->periph_switch = &ss_switch;
  160 
  161         printf("\n");
  162 
  163         /*
  164          * Set up the buf queue for this device
  165          */
  166         bufq_alloc(&ss->buf_queue, BUFQ_FCFS);
  167 
  168         callout_init(&ss->sc_callout);
  169 
  170         /*
  171          * look for non-standard scanners with help of the quirk table
  172          * and install functions for special handling
  173          */
  174         SC_DEBUG(periph, SCSIPI_DB2, ("ssattach:\n"));
  175         if (memcmp(sa->sa_inqbuf.vendor, "MUSTEK", 6) == 0)
  176                 mustek_attach(ss, sa);
  177         if (memcmp(sa->sa_inqbuf.vendor, "HP      ", 8) == 0 &&
  178             memcmp(sa->sa_inqbuf.product, "ScanJet 5300C", 13) != 0)
  179                 scanjet_attach(ss, sa);
  180         if (ss->special == NULL) {
  181                 /* XXX add code to restart a SCSI2 scanner, if any */
  182         }
  183 
  184         ss->flags &= ~SSF_AUTOCONF;
  185 }
  186 
  187 static int
  188 ssdetach(struct device *self, int flags)
  189 {
  190         struct ss_softc *ss = (struct ss_softc *) self;
  191         int s, cmaj, mn;
  192 
  193         /* locate the major number */
  194         cmaj = cdevsw_lookup_major(&ss_cdevsw);
  195 
  196         /* kill any pending restart */
  197         callout_stop(&ss->sc_callout);
  198 
  199         s = splbio();
  200 
  201         /* Kill off any queued buffers. */
  202         bufq_drain(&ss->buf_queue);
  203 
  204         bufq_free(&ss->buf_queue);
  205 
  206         /* Kill off any pending commands. */
  207         scsipi_kill_pending(ss->sc_periph);
  208 
  209         splx(s);
  210 
  211         /* Nuke the vnodes for any open instances */
  212         mn = SSUNIT(self->dv_unit);
  213         vdevgone(cmaj, mn, mn+SSNMINOR-1, VCHR);
  214 
  215         return (0);
  216 }
  217 
  218 static int
  219 ssactivate(struct device *self, enum devact act)
  220 {
  221         int rv = 0;
  222 
  223         switch (act) {
  224         case DVACT_ACTIVATE:
  225                 rv = EOPNOTSUPP;
  226                 break;
  227 
  228         case DVACT_DEACTIVATE:
  229                 /*
  230                  * Nothing to do; we key off the device's DVF_ACTIVE.
  231                  */
  232                 break;
  233         }
  234         return (rv);
  235 }
  236 
  237 /*
  238  * open the device.
  239  */
  240 static int
  241 ssopen(dev_t dev, int flag, int mode, struct proc *p)
  242 {
  243         int unit;
  244         u_int ssmode;
  245         int error;
  246         struct ss_softc *ss;
  247         struct scsipi_periph *periph;
  248         struct scsipi_adapter *adapt;
  249 
  250         unit = SSUNIT(dev);
  251         if (unit >= ss_cd.cd_ndevs)
  252                 return (ENXIO);
  253         ss = ss_cd.cd_devs[unit];
  254         if (!ss)
  255                 return (ENXIO);
  256 
  257         if ((ss->sc_dev.dv_flags & DVF_ACTIVE) == 0)
  258                 return (ENODEV);
  259 
  260         ssmode = SSMODE(dev);
  261 
  262         periph = ss->sc_periph;
  263         adapt = periph->periph_channel->chan_adapter;
  264 
  265         SC_DEBUG(periph, SCSIPI_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
  266             unit, ss_cd.cd_ndevs));
  267 
  268         if (periph->periph_flags & PERIPH_OPEN) {
  269                 printf("%s: already open\n", ss->sc_dev.dv_xname);
  270                 return (EBUSY);
  271         }
  272 
  273         if ((error = scsipi_adapter_addref(adapt)) != 0)
  274                 return (error);
  275 
  276         /*
  277          * Catch any unit attention errors.
  278          *
  279          * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
  280          * consider paper to be a changeable media
  281          *
  282          */
  283         error = scsipi_test_unit_ready(periph,
  284             XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST |
  285             (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0));
  286         if (error)
  287                 goto bad;
  288 
  289         periph->periph_flags |= PERIPH_OPEN;    /* unit attn now errors */
  290 
  291         /*
  292          * If the mode is 3 (e.g. minor = 3,7,11,15)
  293          * then the device has been opened to set defaults
  294          * This mode does NOT ALLOW I/O, only ioctls
  295          */
  296         if (ssmode == MODE_CONTROL)
  297                 return (0);
  298 
  299         SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
  300         return (0);
  301 
  302 bad:
  303         scsipi_adapter_delref(adapt);
  304         periph->periph_flags &= ~PERIPH_OPEN;
  305         return (error);
  306 }
  307 
  308 /*
  309  * close the device.. only called if we are the LAST
  310  * occurence of an open device
  311  */
  312 static int
  313 ssclose(dev_t dev, int flag, int mode, struct proc *p)
  314 {
  315         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  316         struct scsipi_periph *periph = ss->sc_periph;
  317         struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
  318         int error;
  319 
  320         SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n"));
  321 
  322         if (SSMODE(dev) == MODE_REWIND) {
  323                 if (ss->special && ss->special->rewind_scanner) {
  324                         /* call special handler to rewind/abort scan */
  325                         error = (ss->special->rewind_scanner)(ss);
  326                         if (error)
  327                                 return (error);
  328                 } else {
  329                         /* XXX add code to restart a SCSI2 scanner, if any */
  330                 }
  331                 ss->sio.scan_window_size = 0;
  332                 ss->flags &= ~SSF_TRIGGERED;
  333         }
  334 
  335         scsipi_wait_drain(periph);
  336 
  337         scsipi_adapter_delref(adapt);
  338         periph->periph_flags &= ~PERIPH_OPEN;
  339 
  340         return (0);
  341 }
  342 
  343 /*
  344  * trim the size of the transfer if needed,
  345  * called by physio
  346  * basically the smaller of our min and the scsi driver's
  347  * minphys
  348  */
  349 static void
  350 ssminphys(struct buf *bp)
  351 {
  352         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  353         struct scsipi_periph *periph = ss->sc_periph;
  354 
  355         scsipi_adapter_minphys(periph->periph_channel, bp);
  356 
  357         /*
  358          * trim the transfer further for special devices this is
  359          * because some scanners only read multiples of a line at a
  360          * time, also some cannot disconnect, so the read must be
  361          * short enough to happen quickly
  362          */
  363         if (ss->special && ss->special->minphys)
  364                 (ss->special->minphys)(ss, bp);
  365 }
  366 
  367 /*
  368  * Do a read on a device for a user process.
  369  * Prime scanner at start of read, check uio values, call ssstrategy
  370  * via physio for the actual transfer.
  371  */
  372 static int
  373 ssread(dev_t dev, struct uio *uio, int flag)
  374 {
  375         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  376         int error;
  377 
  378         if ((ss->sc_dev.dv_flags & DVF_ACTIVE) == 0)
  379                 return (ENODEV);
  380 
  381         /* if the scanner has not yet been started, do it now */
  382         if (!(ss->flags & SSF_TRIGGERED)) {
  383                 if (ss->special && ss->special->trigger_scanner) {
  384                         error = (ss->special->trigger_scanner)(ss);
  385                         if (error)
  386                                 return (error);
  387                 }
  388                 ss->flags |= SSF_TRIGGERED;
  389         }
  390 
  391         return (physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio));
  392 }
  393 
  394 /*
  395  * Actually translate the requested transfer into one the physical
  396  * driver can understand The transfer is described by a buf and will
  397  * include only one physical transfer.
  398  */
  399 static void
  400 ssstrategy(struct buf *bp)
  401 {
  402         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  403         struct scsipi_periph *periph = ss->sc_periph;
  404         int s;
  405 
  406         SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
  407             ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, bp->b_blkno));
  408 
  409         /*
  410          * If the device has been made invalid, error out
  411          */
  412         if ((ss->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
  413                 bp->b_flags |= B_ERROR;
  414                 if (periph->periph_flags & PERIPH_OPEN)
  415                         bp->b_error = EIO;
  416                 else
  417                         bp->b_error = ENODEV;
  418                 goto done;
  419         }
  420 
  421         /* If negative offset, error */
  422         if (bp->b_blkno < 0) {
  423                 bp->b_flags |= B_ERROR;
  424                 bp->b_error = EINVAL;
  425                 goto done;
  426         }
  427 
  428         if (bp->b_bcount > ss->sio.scan_window_size)
  429                 bp->b_bcount = ss->sio.scan_window_size;
  430 
  431         /*
  432          * If it's a null transfer, return immediatly
  433          */
  434         if (bp->b_bcount == 0)
  435                 goto done;
  436 
  437         s = splbio();
  438 
  439         /*
  440          * Place it in the queue of activities for this scanner
  441          * at the end (a bit silly because we only have on user..
  442          * (but it could fork()))
  443          */
  444         BUFQ_PUT(&ss->buf_queue, bp);
  445 
  446         /*
  447          * Tell the device to get going on the transfer if it's
  448          * not doing anything, otherwise just wait for completion
  449          * (All a bit silly if we're only allowing 1 open but..)
  450          */
  451         ssstart(ss->sc_periph);
  452 
  453         splx(s);
  454         return;
  455 done:
  456         /*
  457          * Correctly set the buf to indicate a completed xfer
  458          */
  459         bp->b_resid = bp->b_bcount;
  460         biodone(bp);
  461 }
  462 
  463 /*
  464  * ssstart looks to see if there is a buf waiting for the device
  465  * and that the device is not already busy. If both are true,
  466  * It dequeues the buf and creates a scsi command to perform the
  467  * transfer required. The transfer request will call scsipi_done
  468  * on completion, which will in turn call this routine again
  469  * so that the next queued transfer is performed.
  470  * The bufs are queued by the strategy routine (ssstrategy)
  471  *
  472  * This routine is also called after other non-queued requests
  473  * have been made of the scsi driver, to ensure that the queue
  474  * continues to be drained.
  475  * ssstart() is called at splbio
  476  */
  477 static void
  478 ssstart(struct scsipi_periph *periph)
  479 {
  480         struct ss_softc *ss = (void *)periph->periph_dev;
  481         struct buf *bp;
  482 
  483         SC_DEBUG(periph, SCSIPI_DB2, ("ssstart "));
  484         /*
  485          * See if there is a buf to do and we are not already
  486          * doing one
  487          */
  488         while (periph->periph_active < periph->periph_openings) {
  489                 /* if a special awaits, let it proceed first */
  490                 if (periph->periph_flags & PERIPH_WAITING) {
  491                         periph->periph_flags &= ~PERIPH_WAITING;
  492                         wakeup((caddr_t)periph);
  493                         return;
  494                 }
  495 
  496                 /*
  497                  * See if there is a buf with work for us to do..
  498                  */
  499                 if ((bp = BUFQ_PEEK(&ss->buf_queue)) == NULL)
  500                         return;
  501 
  502                 if (ss->special && ss->special->read) {
  503                         (ss->special->read)(ss, bp);
  504                 } else {
  505                         /* generic scsi2 scanner read */
  506                         /* XXX add code for SCSI2 scanner read */
  507                 }
  508         }
  509 }
  510 
  511 void
  512 ssrestart(void *v)
  513 {
  514         int s = splbio();
  515         ssstart((struct scsipi_periph *)v);
  516         splx(s);
  517 }
  518 
  519 static void
  520 ssdone(struct scsipi_xfer *xs, int error)
  521 {
  522         struct buf *bp = xs->bp;
  523 
  524         if (bp) {
  525                 bp->b_error = error;
  526                 bp->b_resid = xs->resid;
  527                 if (error)
  528                         bp->b_flags |= B_ERROR;
  529                 biodone(bp);
  530         }
  531 }
  532 
  533 
  534 /*
  535  * Perform special action on behalf of the user;
  536  * knows about the internals of this device
  537  */
  538 int
  539 ssioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  540 {
  541         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  542         int error = 0;
  543         struct scan_io *sio;
  544 
  545         if ((ss->sc_dev.dv_flags & DVF_ACTIVE) == 0)
  546                 return (ENODEV);
  547 
  548         switch (cmd) {
  549         case SCIOCGET:
  550                 if (ss->special && ss->special->get_params) {
  551                         /* call special handler */
  552                         error = (ss->special->get_params)(ss);
  553                         if (error)
  554                                 return (error);
  555                 } else {
  556                         /* XXX add code for SCSI2 scanner, if any */
  557                         return (EOPNOTSUPP);
  558                 }
  559                 memcpy(addr, &ss->sio, sizeof(struct scan_io));
  560                 break;
  561         case SCIOCSET:
  562                 sio = (struct scan_io *)addr;
  563 
  564                 if (ss->special && ss->special->set_params) {
  565                         /* call special handler */
  566                         error = (ss->special->set_params)(ss, sio);
  567                         if (error)
  568                                 return (error);
  569                 } else {
  570                         /* XXX add code for SCSI2 scanner, if any */
  571                         return (EOPNOTSUPP);
  572                 }
  573                 break;
  574         case SCIOCRESTART:
  575                 if (ss->special && ss->special->rewind_scanner ) {
  576                         /* call special handler */
  577                         error = (ss->special->rewind_scanner)(ss);
  578                         if (error)
  579                                 return (error);
  580                 } else
  581                         /* XXX add code for SCSI2 scanner, if any */
  582                         return (EOPNOTSUPP);
  583                 ss->flags &= ~SSF_TRIGGERED;
  584                 break;
  585 #ifdef NOTYET
  586         case SCAN_USE_ADF:
  587                 break;
  588 #endif
  589         default:
  590                 return (scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr,
  591                     flag, p));
  592         }
  593         return (error);
  594 }

Cache object: fa995254981f486f7c93ed41fb9a0eb6


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