ss.c revision 1.8
1/*	$NetBSD: ss.c,v 1.8 1996/03/17 00:59:52 thorpej Exp $	*/
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 */
32
33#include <sys/types.h>
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>		/* for cdevsw */
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
66int ssmatch __P((struct device *, void *, void *));
67void ssattach __P((struct device *, struct device *, void *));
68
69struct cfattach ss_ca = {
70	sizeof(struct ss_softc), ssmatch, ssattach
71};
72
73struct cfdriver ss_cd = {
74	NULL, "ss", DV_DULL
75};
76
77void    ssstrategy __P((struct buf *));
78void    ssstart __P((void *));
79
80struct scsi_device ss_switch = {
81	NULL,
82	ssstart,
83	NULL,
84	NULL,
85};
86
87struct scsi_inquiry_pattern ss_patterns[] = {
88	{T_SCANNER, T_FIXED,
89	 "",         "",                 ""},
90	{T_SCANNER, T_REMOV,
91	 "",         "",                 ""},
92	{T_PROCESSOR, T_FIXED,
93	 "HP      ", "C1750A          ", ""},
94	{T_PROCESSOR, T_FIXED,
95	 "HP      ", "C2500A          ", ""},
96};
97
98int
99ssmatch(parent, match, aux)
100	struct device *parent;
101	void *match, *aux;
102{
103	struct scsibus_attach_args *sa = aux;
104	int priority;
105
106	(void)scsi_inqmatch(sa->sa_inqbuf,
107	    (caddr_t)ss_patterns, sizeof(ss_patterns)/sizeof(ss_patterns[0]),
108	    sizeof(ss_patterns[0]), &priority);
109	return (priority);
110}
111
112/*
113 * The routine called by the low level scsi routine when it discovers
114 * A device suitable for this driver
115 * If it is a know special, call special attach routine to install
116 * special handlers into the ss_softc structure
117 */
118void
119ssattach(parent, self, aux)
120	struct device *parent, *self;
121	void *aux;
122{
123	struct ss_softc *ss = (void *)self;
124	struct scsibus_attach_args *sa = aux;
125	struct scsi_link *sc_link = sa->sa_sc_link;
126
127	SC_DEBUG(sc_link, SDEV_DB2, ("ssattach: "));
128
129	/*
130	 * Store information needed to contact our base driver
131	 */
132	ss->sc_link = sc_link;
133	sc_link->device = &ss_switch;
134	sc_link->device_softc = ss;
135	sc_link->openings = 1;
136
137	/*
138	 * look for non-standard scanners with help of the quirk table
139	 * and install functions for special handling
140	 */
141	SC_DEBUG(sc_link, SDEV_DB2, ("ssattach:\n"));
142	if (!bcmp(sa->sa_inqbuf->vendor, "MUSTEK  ", 8))
143		mustek_attach(ss, sa);
144	if (!bcmp(sa->sa_inqbuf->vendor, "HP      ", 8))
145		scanjet_attach(ss, sa);
146	if (ss->special == NULL) {
147		/* XXX add code to restart a SCSI2 scanner, if any */
148	}
149
150	/*
151	 * Set up the buf queue for this device
152	 */
153	ss->buf_queue.b_active = 0;
154	ss->buf_queue.b_actf = 0;
155	ss->buf_queue.b_actb = &ss->buf_queue.b_actf;
156
157	printf("\n");
158}
159
160/*
161 * open the device.
162 */
163int
164ssopen(dev, flag, mode, p)
165	dev_t dev;
166	int flag;
167	int mode;
168	struct proc *p;
169{
170	int unit;
171	u_int ssmode;
172	int error = 0;
173	struct ss_softc *ss;
174	struct scsi_link *sc_link;
175
176	unit = SSUNIT(dev);
177	if (unit >= ss_cd.cd_ndevs)
178		return (ENXIO);
179	ss = ss_cd.cd_devs[unit];
180	if (!ss)
181		return (ENXIO);
182
183	ssmode = SSMODE(dev);
184	sc_link = ss->sc_link;
185
186	SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
187	    unit, ss_cd.cd_ndevs));
188
189	if (sc_link->flags & SDEV_OPEN) {
190		printf("%s: already open\n", ss->sc_dev.dv_xname);
191		return (EBUSY);
192	}
193
194	/*
195	 * Catch any unit attention errors.
196	 *
197	 * SCSI_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
198	 * consider paper to be a changeable media
199	 *
200	 */
201	error = scsi_test_unit_ready(sc_link,
202	    SCSI_IGNORE_MEDIA_CHANGE | SCSI_IGNORE_ILLEGAL_REQUEST |
203	    (ssmode == MODE_CONTROL ? SCSI_IGNORE_NOT_READY : 0));
204	if (error)
205		goto bad;
206
207	sc_link->flags |= SDEV_OPEN;	/* unit attn are now errors */
208
209	/*
210	 * If the mode is 3 (e.g. minor = 3,7,11,15)
211	 * then the device has been opened to set defaults
212	 * This mode does NOT ALLOW I/O, only ioctls
213	 */
214	if (ssmode == MODE_CONTROL)
215		return (0);
216
217	SC_DEBUG(sc_link, SDEV_DB2, ("open complete\n"));
218	return (0);
219
220bad:
221	sc_link->flags &= ~SDEV_OPEN;
222	return (error);
223}
224
225/*
226 * close the device.. only called if we are the LAST
227 * occurence of an open device
228 */
229int
230ssclose(dev)
231	dev_t dev;
232{
233	struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
234	int error;
235
236	SC_DEBUG(ss->sc_link, SDEV_DB1, ("closing\n"));
237
238	if (SSMODE(dev) == MODE_REWIND) {
239		if (ss->special->rewind_scanner) {
240			/* call special handler to rewind/abort scan */
241			error = (ss->special->rewind_scanner)(ss);
242			if (error)
243				return (error);
244		} else {
245			/* XXX add code to restart a SCSI2 scanner, if any */
246		}
247		ss->sio.scan_window_size = 0;
248		ss->flags &= ~SSF_TRIGGERED;
249	}
250	ss->sc_link->flags &= ~SDEV_OPEN;
251
252	return (0);
253}
254
255/*
256 * trim the size of the transfer if needed,
257 * called by physio
258 * basically the smaller of our min and the scsi driver's
259 * minphys
260 */
261void
262ssminphys(bp)
263	struct buf *bp;
264{
265	register struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
266
267	(ss->sc_link->adapter->scsi_minphys)(bp);
268
269	/*
270	 * trim the transfer further for special devices this is
271	 * because some scanners only read multiples of a line at a
272	 * time, also some cannot disconnect, so the read must be
273	 * short enough to happen quickly
274	 */
275	if (ss->special->minphys)
276		(ss->special->minphys)(ss, bp);
277}
278
279/*
280 * Do a read on a device for a user process.
281 * Prime scanner at start of read, check uio values, call ssstrategy
282 * via physio for the actual transfer.
283 */
284int
285ssread(dev, uio, flag)
286	dev_t dev;
287	struct uio *uio;
288	int flag;
289{
290	struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
291	int error;
292
293	/* if the scanner has not yet been started, do it now */
294	if (!(ss->flags & SSF_TRIGGERED)) {
295		if (ss->special->trigger_scanner) {
296			error = (ss->special->trigger_scanner)(ss);
297			if (error)
298				return (error);
299		}
300		ss->flags |= SSF_TRIGGERED;
301	}
302
303	return (physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio));
304}
305
306/*
307 * Actually translate the requested transfer into one the physical
308 * driver can understand The transfer is described by a buf and will
309 * include only one physical transfer.
310 */
311void
312ssstrategy(bp)
313	struct buf *bp;
314{
315	struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(bp->b_dev)];
316	struct buf *dp;
317	int s;
318
319	SC_DEBUG(ss->sc_link, SDEV_DB1,
320	    ("ssstrategy %d bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
321
322	if (bp->b_bcount > ss->sio.scan_window_size)
323		bp->b_bcount = ss->sio.scan_window_size;
324
325	/*
326	 * If it's a null transfer, return immediatly
327	 */
328	if (bp->b_bcount == 0)
329		goto done;
330
331	s = splbio();
332
333	/*
334	 * Place it in the queue of activities for this scanner
335	 * at the end (a bit silly because we only have on user..
336	 * (but it could fork()))
337	 */
338	dp = &ss->buf_queue;
339	bp->b_actf = NULL;
340	bp->b_actb = dp->b_actb;
341	*dp->b_actb = bp;
342	dp->b_actb = &bp->b_actf;
343
344	/*
345	 * Tell the device to get going on the transfer if it's
346	 * not doing anything, otherwise just wait for completion
347	 * (All a bit silly if we're only allowing 1 open but..)
348	 */
349	ssstart(ss);
350
351	splx(s);
352	return;
353bad:
354	bp->b_flags |= B_ERROR;
355done:
356	/*
357	 * Correctly set the buf to indicate a completed xfer
358	 */
359	bp->b_resid = bp->b_bcount;
360	biodone(bp);
361}
362
363/*
364 * ssstart looks to see if there is a buf waiting for the device
365 * and that the device is not already busy. If both are true,
366 * It dequeues the buf and creates a scsi command to perform the
367 * transfer required. The transfer request will call scsi_done
368 * on completion, which will in turn call this routine again
369 * so that the next queued transfer is performed.
370 * The bufs are queued by the strategy routine (ssstrategy)
371 *
372 * This routine is also called after other non-queued requests
373 * have been made of the scsi driver, to ensure that the queue
374 * continues to be drained.
375 * ssstart() is called at splbio
376 */
377void
378ssstart(v)
379	void *v;
380{
381	struct ss_softc *ss = v;
382	struct scsi_link *sc_link = ss->sc_link;
383	register struct buf *bp, *dp;
384
385	SC_DEBUG(sc_link, SDEV_DB2, ("ssstart "));
386	/*
387	 * See if there is a buf to do and we are not already
388	 * doing one
389	 */
390	while (sc_link->openings > 0) {
391		/* if a special awaits, let it proceed first */
392		if (sc_link->flags & SDEV_WAITING) {
393			sc_link->flags &= ~SDEV_WAITING;
394			wakeup((caddr_t)sc_link);
395			return;
396		}
397
398		/*
399		 * See if there is a buf with work for us to do..
400		 */
401		dp = &ss->buf_queue;
402		if ((bp = dp->b_actf) == NULL)
403			return;
404		if ((dp = bp->b_actf) != NULL)
405			dp->b_actb = bp->b_actb;
406		else
407			ss->buf_queue.b_actb = bp->b_actb;
408		*bp->b_actb = dp;
409
410		if (ss->special->read) {
411			(ss->special->read)(ss, bp);
412		} else {
413			/* generic scsi2 scanner read */
414			/* XXX add code for SCSI2 scanner read */
415		}
416	}
417}
418
419/*
420 * Perform special action on behalf of the user;
421 * knows about the internals of this device
422 */
423int
424ssioctl(dev, cmd, addr, flag, p)
425	dev_t dev;
426	u_long cmd;
427	caddr_t addr;
428	int flag;
429	struct proc *p;
430{
431	struct ss_softc *ss = ss_cd.cd_devs[SSUNIT(dev)];
432	int error = 0;
433	int unit;
434	struct scan_io *sio;
435
436	switch (cmd) {
437	case SCIOCGET:
438		if (ss->special->get_params) {
439			/* call special handler */
440			error = (ss->special->get_params)(ss);
441			if (error)
442				return (error);
443		} else {
444			/* XXX add code for SCSI2 scanner, if any */
445			return (EOPNOTSUPP);
446		}
447		bcopy(&ss->sio, addr, sizeof(struct scan_io));
448		break;
449	case SCIOCSET:
450		sio = (struct scan_io *)addr;
451
452		if (ss->special->set_params) {
453			/* call special handler */
454			error = (ss->special->set_params)(ss, sio);
455			if (error)
456				return (error);
457		} else {
458			/* XXX add code for SCSI2 scanner, if any */
459			return (EOPNOTSUPP);
460		}
461		break;
462	case SCIOCRESTART:
463		if (ss->special->rewind_scanner ) {
464			/* call special handler */
465			error = (ss->special->rewind_scanner)(ss);
466			if (error)
467				return (error);
468		} else
469			/* XXX add code for SCSI2 scanner, if any */
470			return (EOPNOTSUPP);
471		ss->flags &= ~SSF_TRIGGERED;
472		break;
473#ifdef NOTYET
474	case SCAN_USE_ADF:
475		break;
476#endif
477	default:
478		if (SSMODE(dev) != MODE_CONTROL)
479			return (ENOTTY);
480		return (scsi_do_ioctl(ss->sc_link, dev, cmd, addr, flag, p));
481	}
482	return (error);
483}
484