[BACK]Return to ss.c CVS log [TXT][DIR] Up to [local] / sys / scsi

Annotation of sys/scsi/ss.c, Revision 1.1.1.1

1.1       nbrk        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

CVSweb