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