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>