[BACK]Return to ss.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / scsipi

Annotation of src/sys/dev/scsipi/ss.c, Revision 1.70.2.2

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

CVSweb <webmaster@jp.NetBSD.org>