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