root/scsi/ss.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssmatch
  2. ssattach
  3. ss_identify_scanner
  4. ssopen
  5. ssclose
  6. ssminphys
  7. ssread
  8. ssstrategy
  9. ssstart
  10. ssioctl
  11. ss_set_window
  12. ricoh_is410_sw
  13. umax_uc630_sw
  14. fujitsu_m3096g_sw
  15. get_buffer_status
  16. umax_compute_sizes
  17. calc_umax_row_len

    1 /*      $OpenBSD: ss.c,v 1.58 2006/12/21 02:05:46 krw Exp $     */
    2 /*      $NetBSD: ss.c,v 1.10 1996/05/05 19:52:55 christos Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1995, 1997 Kenneth Stailey.  All rights reserved.
    6  *   modified for configurable scanner support by Joachim Koenig
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by Kenneth Stailey.
   19  * 4. The name of the author may not be used to endorse or promote products
   20  *    derived from this software without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/fcntl.h>
   37 #include <sys/errno.h>
   38 #include <sys/ioctl.h>
   39 #include <sys/malloc.h>
   40 #include <sys/buf.h>
   41 #include <sys/proc.h>
   42 #include <sys/user.h>
   43 #include <sys/device.h>
   44 #include <sys/conf.h>
   45 #include <sys/scanio.h>
   46 
   47 #include <scsi/scsi_all.h>
   48 #include <scsi/scsi_scanner.h>
   49 #include <scsi/scsiconf.h>
   50 #include <scsi/ssvar.h>
   51 
   52 #include <scsi/ss_mustek.h>
   53 
   54 #define SSMODE(z)       ( minor(z)       & 0x03)
   55 #define SSUNIT(z)       ((minor(z) >> 4)       )
   56 
   57 /*
   58  * If the mode is 3 (e.g. minor = 3,7,11,15)
   59  * then the device has been openned to set defaults
   60  * This mode does NOT ALLOW I/O, only ioctls
   61  */
   62 #define MODE_REWIND     0
   63 #define MODE_NONREWIND  1
   64 #define MODE_CONTROL    3
   65 
   66 struct quirkdata {
   67         char *name;
   68         u_int quirks;
   69 #define SS_Q_WINDOW_DESC_LEN    0x0001 /* needs special WDL */
   70 #define SS_Q_BRIGHTNESS         0x0002 /* needs special value for brightness */
   71 #define SS_Q_REV_BRIGHTNESS     0x0004 /* reverse brightness control in s/w */
   72 #define SS_Q_THRESHOLD          0x0008 /* needs special value for threshold */
   73 #define SS_Q_MONO_THRESHOLD     0x0010 /* same as SS_Q_THRESHOLD but only
   74                                         * for monochrome image data */
   75 #define SS_Q_CONTRAST           0x0020 /* needs special value for contrast */
   76 #define SS_Q_REV_CONTRAST       0x0040 /* reverse contrast control in s/w */
   77 #define SS_Q_HALFTONE           0x0080 /* uses non-zero halftone */
   78 #define SS_Q_SET_RIF            0x0100 /* set RIF bit */
   79 #define SS_Q_PADDING_TYPE       0x0200 /* does not truncate to byte boundary */
   80 #define SS_Q_BIT_ORDERING       0x0400 /* needs non-zero bit ordering */
   81         long window_descriptor_length;
   82         u_int8_t brightness;
   83         u_int8_t threshold;
   84         u_int8_t contrast;
   85         u_int8_t halftone_pattern[2];
   86         int pad_type;
   87         long bit_ordering;
   88         u_int8_t scanner_type;
   89         /*
   90          * To enable additional scanner options, point vendor_unique_sw
   91          * at a function that adds more stuff to the SET_WINDOW parameters.
   92          */
   93         int     (*vendor_unique_sw)(struct ss_softc *, struct scan_io *,
   94                                         struct scsi_set_window *, void *);
   95         /*
   96          * If the scanner requires use of GET_BUFFER_STATUS before READ
   97          * it can be called from ss_minphys().
   98          */
   99         void    (*special_minphys)(struct ss_softc *, struct buf *);
  100 
  101         /*
  102          *
  103          */
  104         int     (*compute_sizes)(void);
  105 };
  106 
  107 struct ss_quirk_inquiry_pattern {
  108         struct scsi_inquiry_pattern pattern;
  109         struct quirkdata quirkdata;
  110 };
  111 
  112 struct  quirkdata ss_gen_quirks = {
  113         "generic", 0, 0, 0, 0, 0,
  114         {0, 0}, 0, 0, GENERIC_SCSI2,
  115         NULL, NULL, NULL
  116 };
  117 
  118 void    ssstrategy(struct buf *);
  119 void    ssstart(void *);
  120 void    ssminphys(struct buf *);
  121 
  122 void    ss_identify_scanner(struct ss_softc *, struct scsi_inquiry_data*);
  123 int     ss_set_window(struct ss_softc *, struct scan_io *);
  124 
  125 int     ricoh_is410_sw(struct ss_softc *, struct scan_io *,
  126                             struct scsi_set_window *, void *);
  127 int     umax_uc630_sw(struct ss_softc *, struct scan_io *,
  128                            struct scsi_set_window *, void *);
  129 #ifdef NOTYET   /* for ADF support  */
  130 int     fujitsu_m3096g_sw(struct ss_softc *, struct scan_io *,
  131                                struct scsi_set_window *, void *);
  132 #endif
  133 
  134 void    get_buffer_status(struct ss_softc *, struct buf *);
  135 
  136 /*
  137  * WDL:
  138  *
  139  *  Ricoh IS-50 & IS-410 insist on 320 (even it transfer len is less.)
  140  *  Ricoh FS-1 accepts 256 (I haven't tested other values.)
  141  *  UMAX UC-630 accepts 46 (I haven't tested other values.)
  142  *  Fujitsu M3096G wants 40 <= x <= 248 (tested OK at 40 & 64.)
  143  */
  144 
  145 const struct ss_quirk_inquiry_pattern ss_quirk_patterns[] = {
  146         {{T_SCANNER, T_FIXED,
  147          "ULTIMA  ", "AT3     1.60    ", "    "}, {
  148                  "Ultima AT3",
  149                  SS_Q_HALFTONE |
  150                  SS_Q_PADDING_TYPE,
  151                  0, 0, 0, 0, { 3, 0 }, 0, 0,
  152                  ULTIMA_AT3,
  153                  NULL, NULL, NULL
  154          }},
  155         {{T_SCANNER, T_FIXED,
  156          "ULTIMA  ", "A6000C PLUS     ", "    "}, {
  157                  "Ultima A6000C",
  158                  SS_Q_HALFTONE |
  159                  SS_Q_PADDING_TYPE,
  160                  0, 0, 0, 0, { 3, 0 }, 0, 0,
  161                  ULTIMA_AC6000C,
  162                  NULL, NULL, NULL
  163          }},
  164         {{T_SCANNER, T_FIXED,
  165          "RICOH   ", "IS50            ", "    "}, {
  166                  "Ricoh IS-50",
  167                  SS_Q_WINDOW_DESC_LEN |
  168                  SS_Q_REV_BRIGHTNESS |
  169                  SS_Q_THRESHOLD |
  170                  SS_Q_REV_CONTRAST |
  171                  SS_Q_HALFTONE |
  172                  SS_Q_BIT_ORDERING,
  173                  320, 0, 0, 0, { 2, 0x0a }, 0, 7,
  174                  RICOH_IS50,
  175                  ricoh_is410_sw, get_buffer_status, NULL
  176          }},
  177         {{T_SCANNER, T_FIXED,
  178          "RICOH   ", "IS410           ", "    "}, {
  179                  "Ricoh IS-410",
  180                  SS_Q_WINDOW_DESC_LEN |
  181                  SS_Q_THRESHOLD |
  182                  SS_Q_HALFTONE |
  183                  SS_Q_BIT_ORDERING,
  184                  320, 0, 0, 0, { 2, 0x0a }, 0, 7,
  185                  RICOH_IS410,
  186                  ricoh_is410_sw, get_buffer_status, NULL
  187          }},
  188         {{T_SCANNER, T_FIXED,          /* Ricoh IS-410 OEMed by IBM */
  189          "IBM     ", "2456-001        ", "    "}, {
  190                  "IBM 2456",
  191                  SS_Q_WINDOW_DESC_LEN |
  192                  SS_Q_THRESHOLD |
  193                  SS_Q_HALFTONE |
  194                  SS_Q_BIT_ORDERING,
  195                  320, 0, 0, 0, { 2, 0x0a }, 0, 7,
  196                  RICOH_IS410,
  197                  ricoh_is410_sw, get_buffer_status, NULL
  198          }},
  199         {{T_SCANNER, T_FIXED,
  200          "UMAX    ", "UC630           ", "    "}, {
  201                  "UMAX UC-630",
  202                  SS_Q_WINDOW_DESC_LEN |
  203                  SS_Q_HALFTONE,
  204                  0x2e, 0, 0, 0, { 0, 1 }, 0, 0,
  205                  UMAX_UC630,
  206                  umax_uc630_sw, NULL, NULL
  207          }},
  208         {{T_SCANNER, T_FIXED,
  209          "UMAX    ", "UG630           ", "    "}, {
  210                  "UMAX UG-630",
  211                  SS_Q_WINDOW_DESC_LEN |
  212                  SS_Q_HALFTONE,
  213                  0x2e, 0, 0, 0, { 0, 1 }, 0, 0,
  214                  UMAX_UG630,
  215                  umax_uc630_sw, NULL, NULL
  216          }},
  217 #ifdef NOTYET                   /* ADF version */
  218         {{T_SCANNER, T_FIXED,
  219          "FUJITSU ", "M3096Gm         ", "    "}, {
  220                  "Fujitsu M3096G",
  221                  SS_Q_WINDOW_DESC_LEN |
  222                  SS_Q_BRIGHTNESS |
  223                  SS_Q_MONO_THRESHOLD |
  224                  SS_Q_HALFTONE |
  225                  SS_Q_SET_RIF |
  226                  SS_Q_PADDING_TYPE,
  227                  64, 0, 0, 0, { 0, 1 }, 0, 0,
  228                  FUJITSU_M3096G,
  229                  fujistsu_m3096g_sw, NULL, NULL
  230          }},
  231 #else                           /* flatbed-only version */
  232         {{T_SCANNER, T_FIXED,
  233          "FUJITSU ", "M3096Gm         ", "    "}, {
  234                  "Fujitsu M3096G",
  235                  SS_Q_BRIGHTNESS |
  236                  SS_Q_MONO_THRESHOLD |
  237                  SS_Q_CONTRAST |
  238                  SS_Q_HALFTONE |
  239                  SS_Q_PADDING_TYPE,
  240                  0, 0, 0, 0, { 0, 1 }, 0, 0,
  241                  FUJITSU_M3096G,
  242                  NULL, NULL, NULL
  243          }},
  244 #endif
  245 };
  246 
  247 
  248 int ssmatch(struct device *, void *, void *);
  249 void ssattach(struct device *, struct device *, void *);
  250 
  251 struct cfattach ss_ca = {
  252         sizeof(struct ss_softc), ssmatch, ssattach
  253 };
  254 
  255 struct cfdriver ss_cd = {
  256         NULL, "ss", DV_DULL
  257 };
  258 
  259 struct scsi_device ss_switch = {
  260         NULL,
  261         ssstart,
  262         NULL,
  263         NULL,
  264 };
  265 
  266 const struct scsi_inquiry_pattern ss_patterns[] = {
  267         {T_SCANNER, T_FIXED,
  268          "",         "",                 ""},
  269         {T_SCANNER, T_REMOV,
  270          "",         "",                 ""},
  271         {T_PROCESSOR, T_FIXED,
  272          "HP      ", "C1750A          ", ""},
  273         {T_PROCESSOR, T_FIXED,
  274          "HP      ", "C1790A          ", ""},
  275         {T_PROCESSOR, T_FIXED,
  276          "HP      ", "C2500A          ", ""},
  277         {T_PROCESSOR, T_FIXED,
  278          "HP      ", "C2570A          ", ""},
  279         {T_PROCESSOR, T_FIXED,
  280          "HP      ", "C2520A          ", ""},
  281         {T_PROCESSOR, T_FIXED,
  282          "HP      ", "C1130A          ", ""},
  283         {T_PROCESSOR, T_FIXED,
  284          "HP      ", "C5110A          ", ""},
  285         {T_PROCESSOR, T_FIXED,
  286          "HP      ", "C6290A          ", ""},
  287         {T_PROCESSOR, T_FIXED,
  288          "HP      ", "C5190A          ", ""},
  289         {T_PROCESSOR, T_FIXED,
  290          "HP      ", "C7190A          ", ""},
  291         {T_PROCESSOR, T_FIXED,
  292          "HP      ", "C6270A          ", ""},
  293         {T_PROCESSOR, T_FIXED,
  294          "HP      ", "C7670A          ", ""},
  295 };
  296 
  297 int
  298 ssmatch(parent, match, aux)
  299         struct device *parent;
  300         void *match, *aux;
  301 {
  302         struct scsi_attach_args *sa = aux;
  303         int priority;
  304 
  305         (void)scsi_inqmatch(sa->sa_inqbuf,
  306             ss_patterns, sizeof(ss_patterns)/sizeof(ss_patterns[0]),
  307             sizeof(ss_patterns[0]), &priority);
  308         return (priority);
  309 }
  310 
  311 /*
  312  * The routine called by the low level scsi routine when it discovers
  313  * A device suitable for this driver
  314  * If it is a know special, call special attach routine to install
  315  * special handlers into the ss_softc structure
  316  */
  317 void
  318 ssattach(parent, self, aux)
  319         struct device *parent, *self;
  320         void *aux;
  321 {
  322         struct ss_softc *ss = (void *)self;
  323         struct scsi_attach_args *sa = aux;
  324         struct scsi_link *sc_link = sa->sa_sc_link;
  325 
  326         SC_DEBUG(sc_link, SDEV_DB2, ("ssattach:\n"));
  327 
  328         /*
  329          * Store information needed to contact our base driver
  330          */
  331         ss->sc_link = sc_link;
  332         sc_link->device = &ss_switch;
  333         sc_link->device_softc = ss;
  334         sc_link->openings = 1;
  335 
  336         if (!bcmp(sa->sa_inqbuf->vendor, "MUSTEK", 6))
  337                 mustek_attach(ss, sa);
  338         else if (!bcmp(sa->sa_inqbuf->vendor, "HP      ", 8))
  339                 scanjet_attach(ss, sa);
  340         else
  341                 ss_identify_scanner(ss, sa->sa_inqbuf);
  342 
  343         /*
  344          * populate the scanio struct with legal values
  345          */
  346         ss->sio.scan_width              = 1200;
  347         ss->sio.scan_height             = 1200;
  348         ss->sio.scan_x_resolution       = 100;
  349         ss->sio.scan_y_resolution       = 100;
  350         ss->sio.scan_x_origin           = 0;
  351         ss->sio.scan_y_origin           = 0;
  352         ss->sio.scan_brightness         = 128;
  353         ss->sio.scan_contrast           = 128;
  354         ss->sio.scan_quality            = 100;
  355         ss->sio.scan_image_mode         = SIM_GRAYSCALE;
  356 
  357         /* XXX fill in the rest of the scan_io struct by calling the
  358            compute_sizes routine */
  359 
  360         /*
  361          * Set up the buf queue for this device
  362          */
  363         ss->buf_queue.b_active = 0;
  364         ss->buf_queue.b_actf = 0;
  365         ss->buf_queue.b_actb = &ss->buf_queue.b_actf;
  366 }
  367 
  368 void
  369 ss_identify_scanner(ss, inqbuf)
  370         struct ss_softc *ss;
  371         struct scsi_inquiry_data *inqbuf;
  372 {
  373         const struct ss_quirk_inquiry_pattern *finger;
  374         int priority;
  375         /*
  376          * look for non-standard scanners with help of the quirk table
  377          * and install functions for special handling
  378          */
  379         finger = (const struct ss_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf,
  380             ss_quirk_patterns,
  381             sizeof(ss_quirk_patterns)/sizeof(ss_quirk_patterns[0]),
  382             sizeof(ss_quirk_patterns[0]), &priority);
  383         if (priority != 0) {
  384                 ss->quirkdata = &finger->quirkdata;
  385                 if (ss->quirkdata->special_minphys != NULL) {
  386                         ss->special.minphys = ss->quirkdata->special_minphys;
  387                 }
  388                 ss->sio.scan_scanner_type = ss->quirkdata->scanner_type;
  389                 printf("\n%s: %s\n", ss->sc_dev.dv_xname, ss->quirkdata->name);
  390         } else {
  391                 printf("\n%s: generic scanner\n", ss->sc_dev.dv_xname);
  392                 bzero(&ss_gen_quirks, sizeof(ss_gen_quirks));
  393                 ss->quirkdata = &ss_gen_quirks;
  394                 ss->sio.scan_scanner_type = GENERIC_SCSI2;
  395         }
  396 }
  397 
  398 /*
  399  * open the device.
  400  */
  401 int
  402 ssopen(dev, flag, mode, p)
  403         dev_t dev;
  404         int flag;
  405         int mode;
  406         struct proc *p;
  407 {
  408         int unit;
  409         u_int ssmode;
  410         int error = 0;
  411         struct ss_softc *ss;
  412         struct scsi_link *sc_link;
  413 
  414         unit = SSUNIT(dev);
  415         if (unit >= ss_cd.cd_ndevs)
  416                 return (ENXIO);
  417         ss = ss_cd.cd_devs[unit];
  418         if (!ss)
  419                 return (ENXIO);
  420 
  421         ssmode = SSMODE(dev);
  422         sc_link = ss->sc_link;
  423 
  424         SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
  425             unit, ss_cd.cd_ndevs));
  426 
  427         if (sc_link->flags & SDEV_OPEN) {
  428                 printf("%s: already open\n", ss->sc_dev.dv_xname);
  429                 return (EBUSY);
  430         }
  431 
  432         /*
  433          * Catch any unit attention errors.
  434          *
  435          * SCSI_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
  436          * consider paper to be a changeable media
  437          *
  438          */
  439         error = scsi_test_unit_ready(sc_link, TEST_READY_RETRIES,
  440             SCSI_IGNORE_MEDIA_CHANGE | SCSI_IGNORE_ILLEGAL_REQUEST |
  441             (ssmode == MODE_CONTROL ? SCSI_IGNORE_NOT_READY : 0));
  442         if (error)
  443                 goto bad;
  444 
  445         sc_link->flags |= SDEV_OPEN;    /* unit attn are now errors */
  446 
  447         /*
  448          * If the mode is 3 (e.g. minor = 3,7,11,15)
  449          * then the device has been opened to set defaults
  450          * This mode does NOT ALLOW I/O, only ioctls
  451          */
  452         if (ssmode == MODE_CONTROL)
  453                 return (0);
  454 
  455         SC_DEBUG(sc_link, SDEV_DB2, ("open complete\n"));
  456         return (0);
  457 
  458 bad:
  459         sc_link->flags &= ~SDEV_OPEN;
  460         return (error);
  461 }
  462 
  463 /*
  464  * close the device.. only called if we are the LAST
  465  * occurence of an open device
  466  */
  467 int
  468 ssclose(dev, flag, mode, p)
  469         dev_t dev;
  470         int flag;
  471         int mode;
  472         struct proc *p;
  473 {
  474         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  475         int error;
  476 
  477         SC_DEBUG(ss->sc_link, SDEV_DB1, ("closing\n"));
  478 
  479         if (SSMODE(dev) == MODE_REWIND) {
  480                 if (ss->special.rewind_scanner) {
  481                         /* call special handler to rewind/abort scan */
  482                         error = (ss->special.rewind_scanner)(ss);
  483                         if (error)
  484                                 return (error);
  485                 } else {
  486                         /* XXX add code to restart a SCSI2 scanner, if any */
  487                 }
  488                 ss->sio.scan_window_size = 0;
  489                 ss->flags &= ~SSF_TRIGGERED;
  490         }
  491         ss->sc_link->flags &= ~SDEV_OPEN;
  492 
  493         return (0);
  494 }
  495 
  496 /*
  497  * trim the size of the transfer if needed,
  498  * called by physio
  499  * basically the smaller of our min and the scsi driver's
  500  * minphys
  501  */
  502 void
  503 ssminphys(bp)
  504         struct buf *bp;
  505 {
  506         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  507 
  508         (ss->sc_link->adapter->scsi_minphys)(bp);
  509 
  510         /*
  511          * trim the transfer further for special devices this is
  512          * because some scanners only read multiples of a line at a
  513          * time, also some cannot disconnect, so the read must be
  514          * short enough to happen quickly
  515          */
  516         if (ss->special.minphys)
  517                 (ss->special.minphys)(ss, bp);
  518 }
  519 
  520 /*
  521  * Do a read on a device for a user process.
  522  * Prime scanner at start of read, check uio values, call ssstrategy
  523  * via physio for the actual transfer.
  524  */
  525 int
  526 ssread(dev, uio, flag)
  527         dev_t dev;
  528         struct uio *uio;
  529         int flag;
  530 {
  531         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  532         int error;
  533 
  534         /* if the scanner has not yet been started, do it now */
  535         if (!(ss->flags & SSF_TRIGGERED)) {
  536                 if (ss->special.trigger_scanner) {
  537                         error = (ss->special.trigger_scanner)(ss);
  538                         if (error)
  539                                 return (error);
  540                 } else {
  541                         struct scsi_start_stop trigger_cmd;
  542                         bzero(&trigger_cmd, sizeof(trigger_cmd));
  543                         trigger_cmd.opcode = START_STOP;
  544                         trigger_cmd.how = SSS_START;
  545                         scsi_scsi_cmd(ss->sc_link,
  546                                 (struct scsi_generic *)&trigger_cmd,
  547                                 sizeof(trigger_cmd), 0, 0, 4, 5000, NULL, 0);
  548                 }
  549                 ss->flags |= SSF_TRIGGERED;
  550         }
  551 
  552         return (physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio));
  553 }
  554 
  555 /*
  556  * Actually translate the requested transfer into one the physical
  557  * driver can understand The transfer is described by a buf and will
  558  * include only one physical transfer.
  559  */
  560 void
  561 ssstrategy(bp)
  562         struct buf *bp;
  563 {
  564         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
  565         struct buf *dp;
  566         int s;
  567 
  568         SC_DEBUG(ss->sc_link, SDEV_DB2, ("ssstrategy: %ld bytes @ blk %d\n",
  569             bp->b_bcount, bp->b_blkno));
  570 
  571         if (bp->b_bcount > ss->sio.scan_window_size)
  572                 bp->b_bcount = ss->sio.scan_window_size;
  573 
  574         /*
  575          * If it's a null transfer, return immediately
  576          */
  577         if (bp->b_bcount == 0)
  578                 goto done;
  579 
  580         s = splbio();
  581 
  582         /*
  583          * Place it in the queue of activities for this scanner
  584          * at the end (a bit silly because we only have on user..)
  585          * (but it could fork() or dup())
  586          */
  587         dp = &ss->buf_queue;
  588         bp->b_actf = NULL;
  589         bp->b_actb = dp->b_actb;
  590         *dp->b_actb = bp;
  591         dp->b_actb = &bp->b_actf;
  592 
  593         /*
  594          * Tell the device to get going on the transfer if it's
  595          * not doing anything, otherwise just wait for completion
  596          * (All a bit silly if we're only allowing 1 open but..)
  597          */
  598         ssstart(ss);
  599 
  600         splx(s);
  601         return;
  602 
  603 done:
  604         /*
  605          * Correctly set the buf to indicate a completed xfer
  606          */
  607         bp->b_resid = bp->b_bcount;
  608         s = splbio();
  609         biodone(bp);
  610         splx(s);
  611 }
  612 
  613 /*
  614  * ssstart looks to see if there is a buf waiting for the device
  615  * and that the device is not already busy. If both are true,
  616  * It dequeues the buf and creates a scsi command to perform the
  617  * transfer required. The transfer request will call scsi_done
  618  * on completion, which will in turn call this routine again
  619  * so that the next queued transfer is performed.
  620  * The bufs are queued by the strategy routine (ssstrategy)
  621  *
  622  * This routine is also called after other non-queued requests
  623  * have been made of the scsi driver, to ensure that the queue
  624  * continues to be drained.
  625  * ssstart() is called at splbio
  626  */
  627 void
  628 ssstart(v)
  629         void *v;
  630 {
  631         struct ss_softc *ss = v;
  632         struct scsi_link *sc_link = ss->sc_link;
  633         struct buf *bp, *dp;
  634         struct scsi_r_scanner read_cmd;
  635         int flags;
  636 
  637         SC_DEBUG(sc_link, SDEV_DB2, ("ssstart\n"));
  638         /*
  639          * See if there is a buf to do and we are not already
  640          * doing one
  641          */
  642         while (sc_link->openings > 0) {
  643                 /* if a special awaits, let it proceed first */
  644                 if (sc_link->flags & SDEV_WAITING) {
  645                         sc_link->flags &= ~SDEV_WAITING;
  646                         wakeup((caddr_t)sc_link);
  647                         return;
  648                 }
  649 
  650                 /*
  651                  * See if there is a buf with work for us to do..
  652                  */
  653                 dp = &ss->buf_queue;
  654                 if ((bp = dp->b_actf) == NULL)
  655                         return;
  656                 if ((dp = bp->b_actf) != NULL)
  657                         dp->b_actb = bp->b_actb;
  658                 else
  659                         ss->buf_queue.b_actb = bp->b_actb;
  660                 *bp->b_actb = dp;
  661 
  662                 if (ss->special.read) {
  663                         (ss->special.read)(ss, bp);
  664                 } else {
  665                         /* generic scsi2 scanner read */
  666                         bzero(&read_cmd, sizeof(read_cmd));
  667                         read_cmd.opcode = READ_BIG;
  668                         _lto3b(bp->b_bcount, read_cmd.len);
  669                         flags = SCSI_DATA_IN;
  670                         /*
  671                          * go ask the adapter to do all this for us
  672                          */
  673                         if (scsi_scsi_cmd(sc_link, (struct scsi_generic *)
  674                             &read_cmd, sizeof(read_cmd), (u_char *) bp->b_data,
  675                             bp->b_bcount, 0, 100000, bp, flags | SCSI_NOSLEEP))
  676                                 printf("%s: not queued\n", ss->sc_dev.dv_xname);
  677                 }
  678         }
  679 }
  680 
  681 /*
  682  * Perform special action on behalf of the user;
  683  * knows about the internals of this device
  684  */
  685 int
  686 ssioctl(dev, cmd, addr, flag, p)
  687         dev_t dev;
  688         u_long cmd;
  689         caddr_t addr;
  690         int flag;
  691         struct proc *p;
  692 {
  693         struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
  694         int error = 0;
  695         struct scan_io *sio;
  696 
  697         switch (cmd) {
  698         case SCIOCGET:
  699                 /* call special handler, if any */
  700                 if (ss->special.get_params) {
  701                         error = (ss->special.get_params)(ss);
  702                         if (error)
  703                                 return (error);
  704                 }
  705                 bcopy(&ss->sio, addr, sizeof(struct scan_io));
  706                 break;
  707         case SCIOCSET:
  708                 sio = (struct scan_io *)addr;
  709 
  710                 /* call special handler, if any */
  711                 if (ss->special.set_params) {
  712                         error = (ss->special.set_params)(ss, sio);
  713                         if (error)
  714                                 return (error);
  715                 } else {
  716                         /* XXX add routine to validate parameters */
  717                         ss_set_window(ss, sio);
  718                 }
  719                 break;
  720         case SCIOCRESTART:
  721                 /* call special handler, if any */
  722                 if (ss->special.rewind_scanner ) {
  723                         error = (ss->special.rewind_scanner)(ss);
  724                         if (error)
  725                                 return (error);
  726                 } else
  727                         /* XXX add code for SCSI2 scanner, if any */
  728                         return (EOPNOTSUPP);
  729                 ss->flags &= ~SSF_TRIGGERED;
  730                 break;
  731         case SCIOC_USE_ADF:
  732                 /* XXX add Automatic Document Feeder Support */
  733                 return (EOPNOTSUPP);
  734         default:
  735                 if (SSMODE(dev) != MODE_CONTROL)
  736                         return (ENOTTY);
  737                 return (scsi_do_ioctl(ss->sc_link, dev, cmd, addr,
  738                     flag, p));
  739         }
  740         return (error);
  741 }
  742 
  743 int
  744 ss_set_window(ss, sio)
  745         struct ss_softc *ss;
  746         struct scan_io *sio;
  747 {
  748         struct scsi_set_window  window_cmd;
  749         struct {
  750                 struct scsi_window_data window_data;
  751                 /* vendor_unique must provide enough space for worst case
  752                  * (currently Ricoh IS-410.)  40 + 280 = 320 which is the size
  753                  * of its window descriptor length
  754                  */
  755                 u_int8_t vendor_unique[280];
  756         } wd;
  757 #define window_data   wd.window_data
  758 #define vendor_unique wd.vendor_unique
  759         struct scsi_link        *sc_link = ss->sc_link;
  760 
  761         /*
  762          * The CDB for SET WINDOW goes in here.
  763          * The two structures that follow are sent via data out.
  764          */
  765         bzero(&window_cmd, sizeof(window_cmd));
  766         window_cmd.opcode = SET_WINDOW;
  767         _lto3l(sizeof(window_data), window_cmd.len);
  768 
  769         bzero(&window_data, sizeof(window_data));
  770         if (ss->quirkdata->quirks & SS_Q_WINDOW_DESC_LEN)
  771                 _lto2l(ss->quirkdata->window_descriptor_length,
  772                     window_data.window_desc_len);
  773         else
  774                 _lto2l(40L, window_data.window_desc_len);
  775 
  776         /* start of SET_WINDOW parameter block */
  777 
  778         /* leave window id at zero */
  779         /* leave auto bit at zero */
  780         _lto2l(sio->scan_x_resolution, window_data.x_res);
  781         _lto2l(sio->scan_y_resolution, window_data.y_res);
  782         _lto4l(sio->scan_x_origin, window_data.x_org);
  783         _lto4l(sio->scan_y_origin, window_data.y_org);
  784         _lto4l(sio->scan_width,  window_data.width);
  785         _lto4l(sio->scan_height, window_data.length);
  786 
  787         if (ss->quirkdata->quirks & SS_Q_REV_BRIGHTNESS)
  788                 window_data.brightness = 256 - sio->scan_brightness;
  789         else if (ss->quirkdata->quirks & SS_Q_BRIGHTNESS)
  790                 window_data.brightness = ss->quirkdata->brightness;
  791         else
  792                 window_data.brightness = sio->scan_brightness;
  793 
  794         /*
  795          * threshold: Default is to follow brightness.
  796          * If SS_Q_MONO_THRESHOLD is set then the quirkdata contains a special
  797          * value to be used instead of default when image data is monochrome.
  798          * Otherwise if SS_Q_THRESHOLD is set then the quirkdata contains
  799          * the threshold to always use.
  800          * Both SS_Q_MONO_THRESHOLD and SS_Q_THRESHOLD should not be set at
  801          * the same time.
  802          */
  803         if (ss->quirkdata->quirks & SS_Q_MONO_THRESHOLD) {
  804                 if (sio->scan_image_mode == SIM_BINARY_MONOCHROME ||
  805                     sio->scan_image_mode == SIM_DITHERED_MONOCHROME)
  806                         window_data.threshold = ss->quirkdata->threshold;
  807                 else
  808                         window_data.threshold = sio->scan_brightness;
  809         } else if (ss->quirkdata->quirks & SS_Q_THRESHOLD)
  810                 window_data.threshold = ss->quirkdata->threshold;
  811         else
  812                 window_data.threshold = sio->scan_brightness;
  813 
  814         if (ss->quirkdata->quirks & SS_Q_REV_CONTRAST)
  815                 window_data.contrast = 256 - sio->scan_contrast;
  816         else if (ss->quirkdata->quirks & SS_Q_CONTRAST)
  817                 window_data.contrast = ss->quirkdata->contrast;
  818         else
  819                 window_data.contrast = sio->scan_contrast;
  820 
  821         switch (sio->scan_image_mode) {
  822         case SIM_RED:
  823         case SIM_GREEN:
  824         case SIM_BLUE:
  825                 window_data.image_comp = SIM_GRAYSCALE;
  826                 break;
  827         default:
  828                 window_data.image_comp = sio->scan_image_mode;
  829         }
  830 
  831         window_data.bits_per_pixel = sio->scan_bits_per_pixel;
  832 
  833         if (ss->quirkdata->quirks & SS_Q_HALFTONE) {
  834                 window_data.halftone_pattern[0] =
  835                         ss->quirkdata->halftone_pattern[0];
  836                 window_data.halftone_pattern[1] = 
  837                         ss->quirkdata->halftone_pattern[1];
  838         } /* else leave halftone set to zero. */
  839 
  840         if (ss->quirkdata->quirks & SS_Q_SET_RIF)
  841                 window_data.rif = 1;
  842 
  843         if (ss->quirkdata->quirks & SS_Q_PADDING_TYPE)
  844                 window_data.pad_type = ss->quirkdata->pad_type;
  845         else
  846                 window_data.pad_type = 3; /* 3 = truncate to byte boundary */
  847 
  848         if (ss->quirkdata->quirks & SS_Q_BIT_ORDERING)
  849                 _lto2l(ss->quirkdata->bit_ordering, window_data.bit_ordering);
  850         /* else leave bit_ordering set to zero. */
  851 
  852         /* leave compression type & argument set to zero. */
  853 
  854 #undef window_data
  855 
  856         if (ss->quirkdata->vendor_unique_sw != NULL)
  857                 return ((*ss->quirkdata->vendor_unique_sw)(ss, sio,
  858                     &window_cmd, (void *)&wd));
  859         else
  860                 /* send the command to the scanner */
  861                 return (scsi_scsi_cmd(sc_link,
  862                     (struct scsi_generic *)&window_cmd,
  863                     sizeof(window_cmd), (u_char *) &wd.window_data,
  864                     (ss->quirkdata->quirks & SS_Q_WINDOW_DESC_LEN) ?
  865                     ss->quirkdata->window_descriptor_length : 40,
  866                     4, 5000, NULL, SCSI_DATA_OUT));
  867 }
  868 
  869 int
  870 ricoh_is410_sw(ss, sio, wcmd, vwd)
  871         struct ss_softc *ss;
  872         struct scan_io *sio;
  873         struct scsi_set_window *wcmd;
  874         void *vwd;
  875 {
  876         struct ricoh_is410_window_data {
  877                 struct scsi_window_data window_data;
  878                 u_int8_t res1;
  879                 u_int8_t res2;
  880                 u_int    mrif:1; /* reverse image format (grayscale negative) */
  881                 u_int    filtering:3;
  882                 u_int    gamma_id:4;
  883         } *rwd = (struct ricoh_is410_window_data*)vwd;
  884         struct scsi_link *sc_link = ss->sc_link;
  885 
  886         rwd->mrif = 1;          /* force grayscale to match PGM */
  887 
  888         /* send the command to the scanner */
  889         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)wcmd,
  890             sizeof(struct scsi_set_window), (u_char *)rwd,
  891             sizeof(struct ricoh_is410_window_data), 4, 5000, NULL,
  892             SCSI_DATA_OUT));
  893 }
  894 
  895 int
  896 umax_uc630_sw(ss, sio, wcmd, vwd)
  897         struct ss_softc *ss;
  898         struct scan_io *sio;
  899         struct scsi_set_window *wcmd;
  900         void *vwd;
  901 {
  902         struct umax_uc630_window_data {
  903                 struct scsi_window_data window_data;
  904                 u_int8_t speed;
  905                 u_int8_t select_color;
  906                 u_int8_t highlight;
  907                 u_int8_t shadow;
  908                 u_int8_t paper_length[2];
  909         } *uwd = (struct umax_uc630_window_data*)vwd;
  910         struct scsi_link *sc_link = ss->sc_link;
  911 
  912         uwd->speed = 1;         /* speed: fastest speed that doesn't smear */
  913         switch (sio->scan_image_mode) { /* UMAX has three-pass color. */
  914         case SIM_RED:                   /* This selects which filter to use. */
  915                 uwd->select_color = 0x80;
  916                 break;
  917         case SIM_GREEN:
  918                 uwd->select_color = 0x40;
  919                 break;
  920         case SIM_BLUE:
  921                 uwd->select_color = 0x20;
  922                 break;
  923         }
  924         uwd->highlight = 50;            /* 50 = highest; 0 = lowest */
  925         /* leave shadow set to zero. */
  926         /* XXX paper length is for ADF */
  927 
  928         /* send the command to the scanner */
  929         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)wcmd,
  930             sizeof(struct scsi_set_window), (u_char *)uwd,
  931             sizeof(struct umax_uc630_window_data), 4, 5000, NULL,
  932             SCSI_DATA_OUT));
  933 }
  934 
  935 #ifdef NOTYET /* for ADF support */
  936 int
  937 fujitsu_m3096g_sw(ss, sio, wcmd, vwd)
  938         struct ss_softc *ss;
  939         struct scan_io *sio;
  940         struct scsi_set_window *wcmd;
  941         void *vwd;
  942 {
  943         struct fujitsu_m3096g_window_data {
  944                 struct scsi_window_data window_data;
  945                 u_int8_t id;
  946                 u_int8_t res1;
  947                 u_int8_t outline;
  948                 u_int8_t emphasis;
  949                 u_int8_t mixed;
  950                 u_int8_t mirroring;
  951                 u_int8_t res2[5];
  952                 u_int8_t subwindow_list[2];
  953                 u_int    paper_size_std:2;
  954                 u_int    res3:1;
  955                 u_int    paper_orientaton:1;
  956                 u_int    paper_size_type:4;
  957 /* defines for Paper Size Type: */
  958 #define FUJITSU_PST_A3                  0x03
  959 #define FUJITSU_PST_A4                  0x04
  960 #define FUJITSU_PST_A5                  0x05
  961 #define FUJITSU_PST_DOUBLE_LETTER       0x06
  962 #define FUJITSU_PST_LETTER              0x07
  963 #define FUJITSU_PST_B4                  0x0C
  964 #define FUJITSU_PST_B5                  0x0D
  965 #define FUJITSU_PST_LEGAL               0x0F
  966                 u_int8_t paper_width_x[4];
  967                 u_int8_t paper_width_y[4];
  968                 u_int8_t res4[2];
  969         } *fwd = (struct fujitsu_m3096g_window_data*)vwd;
  970         struct scsi_link *sc_link = ss->sc_link;
  971 
  972         /* send the command to the scanner */
  973         return (scsi_scsi_cmd(sc_link, (struct scsi_generic *)wcmd,
  974             sizeof(struct scsi_set_window), (u_char *)fwd,
  975             sizeof(struct fujitsu_m3096g_window_data), 4, 5000, NULL,
  976             SCSI_DATA_OUT));
  977 }
  978 #endif
  979 
  980 void
  981 get_buffer_status(ss, bp)
  982         struct ss_softc *ss;
  983         struct buf *bp;
  984 {
  985         struct scsi_get_buffer_status gbs_cmd;
  986         struct scsi_link *sc_link = ss->sc_link;
  987         struct {
  988                 u_int8_t stat_len[3];
  989                 u_int8_t res1;
  990                 u_int8_t window_id;
  991                 u_int8_t res2;
  992                 u_int8_t tgt_accept_buf_len[3];
  993                 u_int8_t tgt_send_buf_len[3];
  994         } buf_sz_retn;
  995         int flags;
  996 
  997         bzero(&gbs_cmd, sizeof(gbs_cmd));
  998         gbs_cmd.opcode = GET_BUFFER_STATUS;
  999         _lto2b(12, gbs_cmd.len);
 1000         flags = SCSI_DATA_IN;
 1001 
 1002         if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &gbs_cmd,
 1003             sizeof(gbs_cmd), (u_char *) &buf_sz_retn, sizeof(buf_sz_retn),
 1004             0, 100000, bp, flags | SCSI_NOSLEEP)) {
 1005                 printf("%s: not queued\n", ss->sc_dev.dv_xname);
 1006         }
 1007         bp->b_bcount = MIN(_3btol(buf_sz_retn.tgt_send_buf_len), bp->b_bcount);
 1008 }
 1009 
 1010 #ifdef NOTYET
 1011 int
 1012 umax_compute_sizes(ss)
 1013         struct ss_softc *ss;
 1014 {
 1015         ss->sio.scan_lines = ;
 1016         ss->sio.scan_window_size = ;
 1017 }
 1018 
 1019 int
 1020 calc_umax_row_len(dpi, ww)
 1021         int dpi;
 1022         int ww;
 1023 {
 1024         int st[301];
 1025         int i;
 1026         int rowB = 0;
 1027 
 1028         for (i = 1; i <= 300; i++)
 1029                 st[i] = 1;
 1030 
 1031         for (i = 1; i <= 300 - dpi; i++)
 1032                 st[i * 300 / (300 - dpi)] = 0;
 1033 
 1034         for (i = 1; i <= (ww % 1200) / 4; i++) {
 1035                 if (st[i])
 1036                         rowB++;
 1037         }
 1038 
 1039         return ((ww / 1200) * dpi + rowB);
 1040 }
 1041 #endif

/* [<][>][^][v][top][bottom][index][help] */