ss.c revision 1.84.2.1 1 1.84.2.1 tls /* $NetBSD: ss.c,v 1.84.2.1 2012/09/12 06:15:33 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.1 tls __KERNEL_RCSID(0, "$NetBSD: ss.c,v 1.84.2.1 2012/09/12 06:15:33 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.40 gehenna ssopen, ssclose, ssread, nowrite, ssioctl,
93 1.67 christos nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
94 1.40 gehenna };
95 1.40 gehenna
96 1.52 thorpej static void ssstrategy(struct buf *);
97 1.52 thorpej static void ssstart(struct scsipi_periph *);
98 1.54 mycroft static void ssdone(struct scsipi_xfer *, int);
99 1.52 thorpej static void ssminphys(struct buf *);
100 1.1 mycroft
101 1.52 thorpej static const struct scsipi_periphsw ss_switch = {
102 1.1 mycroft NULL,
103 1.1 mycroft ssstart,
104 1.1 mycroft NULL,
105 1.54 mycroft ssdone,
106 1.1 mycroft };
107 1.1 mycroft
108 1.52 thorpej static const struct scsipi_inquiry_pattern ss_patterns[] = {
109 1.1 mycroft {T_SCANNER, T_FIXED,
110 1.1 mycroft "", "", ""},
111 1.1 mycroft {T_SCANNER, T_REMOV,
112 1.1 mycroft "", "", ""},
113 1.1 mycroft {T_PROCESSOR, T_FIXED,
114 1.41 chs "HP ", "C1130A ", ""},
115 1.41 chs {T_PROCESSOR, T_FIXED,
116 1.1 mycroft "HP ", "C1750A ", ""},
117 1.1 mycroft {T_PROCESSOR, T_FIXED,
118 1.1 mycroft "HP ", "C2500A ", ""},
119 1.14 thorpej {T_PROCESSOR, T_FIXED,
120 1.41 chs "HP ", "C2520A ", ""},
121 1.18 augustss {T_PROCESSOR, T_FIXED,
122 1.18 augustss "HP ", "C5110A ", ""},
123 1.31 phil {T_PROCESSOR, T_FIXED,
124 1.31 phil "HP ", "C7670A ", ""},
125 1.41 chs {T_PROCESSOR, T_FIXED,
126 1.41 chs "HP ", "", ""},
127 1.1 mycroft };
128 1.1 mycroft
129 1.52 thorpej static int
130 1.81 mbalmer ssmatch(device_t parent, cfdata_t match, void *aux)
131 1.1 mycroft {
132 1.16 bouyer struct scsipibus_attach_args *sa = aux;
133 1.1 mycroft int priority;
134 1.1 mycroft
135 1.16 bouyer (void)scsipi_inqmatch(&sa->sa_inqbuf,
136 1.61 christos ss_patterns, sizeof(ss_patterns) / sizeof(ss_patterns[0]),
137 1.1 mycroft sizeof(ss_patterns[0]), &priority);
138 1.81 mbalmer return priority;
139 1.1 mycroft }
140 1.1 mycroft
141 1.1 mycroft /*
142 1.1 mycroft * The routine called by the low level scsi routine when it discovers
143 1.1 mycroft * A device suitable for this driver
144 1.1 mycroft * If it is a know special, call special attach routine to install
145 1.1 mycroft * special handlers into the ss_softc structure
146 1.1 mycroft */
147 1.52 thorpej static void
148 1.78 cegger ssattach(device_t parent, device_t self, void *aux)
149 1.1 mycroft {
150 1.66 thorpej struct ss_softc *ss = device_private(self);
151 1.16 bouyer struct scsipibus_attach_args *sa = aux;
152 1.34 bouyer struct scsipi_periph *periph = sa->sa_periph;
153 1.1 mycroft
154 1.34 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("ssattach: "));
155 1.81 mbalmer ss->sc_dev = self;
156 1.1 mycroft
157 1.20 pk ss->flags |= SSF_AUTOCONF;
158 1.20 pk
159 1.81 mbalmer /* Store information needed to contact our base driver */
160 1.34 bouyer ss->sc_periph = periph;
161 1.81 mbalmer periph->periph_dev = ss->sc_dev;
162 1.34 bouyer periph->periph_switch = &ss_switch;
163 1.28 abs
164 1.28 abs printf("\n");
165 1.1 mycroft
166 1.81 mbalmer /* Set up the buf queue for this device */
167 1.62 yamt bufq_alloc(&ss->buf_queue, "fcfs", 0);
168 1.39 hannken
169 1.71 ad callout_init(&ss->sc_callout, 0);
170 1.53 bouyer
171 1.39 hannken /*
172 1.1 mycroft * look for non-standard scanners with help of the quirk table
173 1.1 mycroft * and install functions for special handling
174 1.1 mycroft */
175 1.35 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("ssattach:\n"));
176 1.32 augustss if (memcmp(sa->sa_inqbuf.vendor, "MUSTEK", 6) == 0)
177 1.1 mycroft mustek_attach(ss, sa);
178 1.32 augustss if (memcmp(sa->sa_inqbuf.vendor, "HP ", 8) == 0 &&
179 1.32 augustss memcmp(sa->sa_inqbuf.product, "ScanJet 5300C", 13) != 0)
180 1.1 mycroft scanjet_attach(ss, sa);
181 1.82 mbalmer
182 1.1 mycroft if (ss->special == NULL) {
183 1.1 mycroft /* XXX add code to restart a SCSI2 scanner, if any */
184 1.1 mycroft }
185 1.20 pk ss->flags &= ~SSF_AUTOCONF;
186 1.1 mycroft }
187 1.1 mycroft
188 1.52 thorpej static int
189 1.78 cegger ssdetach(device_t self, int flags)
190 1.32 augustss {
191 1.66 thorpej struct ss_softc *ss = device_private(self);
192 1.32 augustss int s, cmaj, mn;
193 1.32 augustss
194 1.32 augustss /* locate the major number */
195 1.40 gehenna cmaj = cdevsw_lookup_major(&ss_cdevsw);
196 1.32 augustss
197 1.53 bouyer /* kill any pending restart */
198 1.53 bouyer callout_stop(&ss->sc_callout);
199 1.53 bouyer
200 1.32 augustss s = splbio();
201 1.32 augustss
202 1.32 augustss /* Kill off any queued buffers. */
203 1.62 yamt bufq_drain(ss->buf_queue);
204 1.32 augustss
205 1.62 yamt bufq_free(ss->buf_queue);
206 1.39 hannken
207 1.32 augustss /* Kill off any pending commands. */
208 1.34 bouyer scsipi_kill_pending(ss->sc_periph);
209 1.32 augustss
210 1.32 augustss splx(s);
211 1.32 augustss
212 1.32 augustss /* Nuke the vnodes for any open instances */
213 1.65 thorpej mn = SSUNIT(device_unit(self));
214 1.33 augustss vdevgone(cmaj, mn, mn+SSNMINOR-1, VCHR);
215 1.32 augustss
216 1.81 mbalmer return 0;
217 1.32 augustss }
218 1.32 augustss
219 1.84 mbalmer /* open the device. */
220 1.52 thorpej static int
221 1.69 christos ssopen(dev_t dev, int flag, int mode, struct lwp *l)
222 1.1 mycroft {
223 1.1 mycroft int unit;
224 1.59 reinoud u_int ssmode;
225 1.23 thorpej int error;
226 1.1 mycroft struct ss_softc *ss;
227 1.34 bouyer struct scsipi_periph *periph;
228 1.34 bouyer struct scsipi_adapter *adapt;
229 1.1 mycroft
230 1.1 mycroft unit = SSUNIT(dev);
231 1.74 tsutsui ss = device_lookup_private(&ss_cd, unit);
232 1.74 tsutsui if (ss == NULL)
233 1.81 mbalmer return ENXIO;
234 1.1 mycroft
235 1.81 mbalmer if (!device_is_active(ss->sc_dev))
236 1.81 mbalmer return ENODEV;
237 1.32 augustss
238 1.5 mycroft ssmode = SSMODE(dev);
239 1.1 mycroft
240 1.34 bouyer periph = ss->sc_periph;
241 1.34 bouyer adapt = periph->periph_channel->chan_adapter;
242 1.34 bouyer
243 1.81 mbalmer SC_DEBUG(periph, SCSIPI_DB1,
244 1.81 mbalmer ("open: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit,
245 1.81 mbalmer ss_cd.cd_ndevs));
246 1.1 mycroft
247 1.34 bouyer if (periph->periph_flags & PERIPH_OPEN) {
248 1.81 mbalmer aprint_error_dev(ss->sc_dev, "already open\n");
249 1.81 mbalmer return EBUSY;
250 1.1 mycroft }
251 1.1 mycroft
252 1.34 bouyer if ((error = scsipi_adapter_addref(adapt)) != 0)
253 1.81 mbalmer return error;
254 1.23 thorpej
255 1.1 mycroft /*
256 1.1 mycroft * Catch any unit attention errors.
257 1.1 mycroft *
258 1.26 thorpej * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners
259 1.1 mycroft * consider paper to be a changeable media
260 1.1 mycroft *
261 1.1 mycroft */
262 1.34 bouyer error = scsipi_test_unit_ready(periph,
263 1.26 thorpej XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST |
264 1.26 thorpej (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0));
265 1.1 mycroft if (error)
266 1.1 mycroft goto bad;
267 1.1 mycroft
268 1.34 bouyer periph->periph_flags |= PERIPH_OPEN; /* unit attn now errors */
269 1.1 mycroft
270 1.1 mycroft /*
271 1.1 mycroft * If the mode is 3 (e.g. minor = 3,7,11,15)
272 1.1 mycroft * then the device has been opened to set defaults
273 1.1 mycroft * This mode does NOT ALLOW I/O, only ioctls
274 1.1 mycroft */
275 1.5 mycroft if (ssmode == MODE_CONTROL)
276 1.81 mbalmer return 0;
277 1.1 mycroft
278 1.34 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
279 1.81 mbalmer return 0;
280 1.1 mycroft
281 1.1 mycroft bad:
282 1.34 bouyer scsipi_adapter_delref(adapt);
283 1.34 bouyer periph->periph_flags &= ~PERIPH_OPEN;
284 1.81 mbalmer return error;
285 1.1 mycroft }
286 1.1 mycroft
287 1.1 mycroft /*
288 1.1 mycroft * close the device.. only called if we are the LAST
289 1.1 mycroft * occurence of an open device
290 1.1 mycroft */
291 1.52 thorpej static int
292 1.69 christos ssclose(dev_t dev, int flag, int mode, struct lwp *l)
293 1.1 mycroft {
294 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
295 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph;
296 1.34 bouyer struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
297 1.1 mycroft int error;
298 1.1 mycroft
299 1.34 bouyer SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n"));
300 1.1 mycroft
301 1.1 mycroft if (SSMODE(dev) == MODE_REWIND) {
302 1.21 explorer if (ss->special && ss->special->rewind_scanner) {
303 1.1 mycroft /* call special handler to rewind/abort scan */
304 1.1 mycroft error = (ss->special->rewind_scanner)(ss);
305 1.1 mycroft if (error)
306 1.81 mbalmer return error;
307 1.82 mbalmer } else {
308 1.1 mycroft /* XXX add code to restart a SCSI2 scanner, if any */
309 1.1 mycroft }
310 1.4 mycroft ss->sio.scan_window_size = 0;
311 1.1 mycroft ss->flags &= ~SSF_TRIGGERED;
312 1.1 mycroft }
313 1.24 thorpej
314 1.34 bouyer scsipi_wait_drain(periph);
315 1.23 thorpej
316 1.34 bouyer scsipi_adapter_delref(adapt);
317 1.34 bouyer periph->periph_flags &= ~PERIPH_OPEN;
318 1.1 mycroft
319 1.81 mbalmer return 0;
320 1.1 mycroft }
321 1.1 mycroft
322 1.1 mycroft /*
323 1.84 mbalmer * trim the size of the transfer if needed, called by physio
324 1.84 mbalmer * basically the smaller of our min and the scsi driver's minphys
325 1.1 mycroft */
326 1.52 thorpej static void
327 1.32 augustss ssminphys(struct buf *bp)
328 1.1 mycroft {
329 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
330 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph;
331 1.84.2.1 tls long xmax;
332 1.1 mycroft
333 1.84.2.1 tls /* Impose any restrictions inherited down the device tree */
334 1.84.2.1 tls xmax = ss->sc_dev->dv_maxphys;
335 1.84.2.1 tls if (bp->b_bcount > xmax)
336 1.84.2.1 tls bp->b_bcount = xmax;
337 1.84.2.1 tls
338 1.84.2.1 tls /* Adapters could enforce their own limits on the
339 1.84.2.1 tls attached scsibuses via the device tree, but existing
340 1.84.2.1 tls drivers mostly do it in their own minphys routines. */
341 1.51 thorpej scsipi_adapter_minphys(periph->periph_channel, bp);
342 1.1 mycroft
343 1.1 mycroft /*
344 1.1 mycroft * trim the transfer further for special devices this is
345 1.1 mycroft * because some scanners only read multiples of a line at a
346 1.1 mycroft * time, also some cannot disconnect, so the read must be
347 1.1 mycroft * short enough to happen quickly
348 1.1 mycroft */
349 1.21 explorer if (ss->special && ss->special->minphys)
350 1.1 mycroft (ss->special->minphys)(ss, bp);
351 1.1 mycroft }
352 1.1 mycroft
353 1.1 mycroft /*
354 1.1 mycroft * Do a read on a device for a user process.
355 1.1 mycroft * Prime scanner at start of read, check uio values, call ssstrategy
356 1.1 mycroft * via physio for the actual transfer.
357 1.1 mycroft */
358 1.52 thorpej static int
359 1.69 christos ssread(dev_t dev, struct uio *uio, int flag)
360 1.1 mycroft {
361 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
362 1.1 mycroft int error;
363 1.1 mycroft
364 1.81 mbalmer if (!device_is_active(ss->sc_dev))
365 1.81 mbalmer return ENODEV;
366 1.32 augustss
367 1.1 mycroft /* if the scanner has not yet been started, do it now */
368 1.1 mycroft if (!(ss->flags & SSF_TRIGGERED)) {
369 1.21 explorer if (ss->special && ss->special->trigger_scanner) {
370 1.1 mycroft error = (ss->special->trigger_scanner)(ss);
371 1.1 mycroft if (error)
372 1.1 mycroft return (error);
373 1.1 mycroft }
374 1.1 mycroft ss->flags |= SSF_TRIGGERED;
375 1.1 mycroft }
376 1.1 mycroft
377 1.81 mbalmer return physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio);
378 1.1 mycroft }
379 1.1 mycroft
380 1.1 mycroft /*
381 1.1 mycroft * Actually translate the requested transfer into one the physical
382 1.1 mycroft * driver can understand The transfer is described by a buf and will
383 1.1 mycroft * include only one physical transfer.
384 1.1 mycroft */
385 1.52 thorpej static void
386 1.52 thorpej ssstrategy(struct buf *bp)
387 1.1 mycroft {
388 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev));
389 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph;
390 1.1 mycroft int s;
391 1.1 mycroft
392 1.34 bouyer SC_DEBUG(ss->sc_periph, SCSIPI_DB1,
393 1.81 mbalmer ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount,
394 1.81 mbalmer bp->b_blkno));
395 1.25 bouyer
396 1.81 mbalmer /* If the device has been made invalid, error out */
397 1.81 mbalmer if (!device_is_active(ss->sc_dev)) {
398 1.34 bouyer if (periph->periph_flags & PERIPH_OPEN)
399 1.32 augustss bp->b_error = EIO;
400 1.32 augustss else
401 1.32 augustss bp->b_error = ENODEV;
402 1.32 augustss goto done;
403 1.32 augustss }
404 1.32 augustss
405 1.25 bouyer /* If negative offset, error */
406 1.25 bouyer if (bp->b_blkno < 0) {
407 1.25 bouyer bp->b_error = EINVAL;
408 1.25 bouyer goto done;
409 1.25 bouyer }
410 1.6 mycroft
411 1.6 mycroft if (bp->b_bcount > ss->sio.scan_window_size)
412 1.6 mycroft bp->b_bcount = ss->sio.scan_window_size;
413 1.1 mycroft
414 1.81 mbalmer /* If it's a null transfer, return immediatly */
415 1.1 mycroft if (bp->b_bcount == 0)
416 1.1 mycroft goto done;
417 1.1 mycroft
418 1.1 mycroft s = splbio();
419 1.1 mycroft
420 1.1 mycroft /*
421 1.1 mycroft * Place it in the queue of activities for this scanner
422 1.1 mycroft * at the end (a bit silly because we only have on user..
423 1.1 mycroft * (but it could fork()))
424 1.1 mycroft */
425 1.76 yamt bufq_put(ss->buf_queue, bp);
426 1.1 mycroft
427 1.1 mycroft /*
428 1.1 mycroft * Tell the device to get going on the transfer if it's
429 1.1 mycroft * not doing anything, otherwise just wait for completion
430 1.1 mycroft * (All a bit silly if we're only allowing 1 open but..)
431 1.1 mycroft */
432 1.34 bouyer ssstart(ss->sc_periph);
433 1.1 mycroft
434 1.1 mycroft splx(s);
435 1.1 mycroft return;
436 1.1 mycroft done:
437 1.81 mbalmer /* Correctly set the buf to indicate a completed xfer */
438 1.1 mycroft bp->b_resid = bp->b_bcount;
439 1.1 mycroft biodone(bp);
440 1.1 mycroft }
441 1.1 mycroft
442 1.1 mycroft /*
443 1.1 mycroft * ssstart looks to see if there is a buf waiting for the device
444 1.1 mycroft * and that the device is not already busy. If both are true,
445 1.1 mycroft * It dequeues the buf and creates a scsi command to perform the
446 1.16 bouyer * transfer required. The transfer request will call scsipi_done
447 1.1 mycroft * on completion, which will in turn call this routine again
448 1.1 mycroft * so that the next queued transfer is performed.
449 1.1 mycroft * The bufs are queued by the strategy routine (ssstrategy)
450 1.1 mycroft *
451 1.1 mycroft * This routine is also called after other non-queued requests
452 1.1 mycroft * have been made of the scsi driver, to ensure that the queue
453 1.1 mycroft * continues to be drained.
454 1.1 mycroft * ssstart() is called at splbio
455 1.1 mycroft */
456 1.52 thorpej static void
457 1.52 thorpej ssstart(struct scsipi_periph *periph)
458 1.1 mycroft {
459 1.81 mbalmer struct ss_softc *ss = device_private(periph->periph_dev);
460 1.30 augustss struct buf *bp;
461 1.1 mycroft
462 1.34 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("ssstart "));
463 1.84 mbalmer
464 1.84 mbalmer /* See if there is a buf to do and we are not already doing one */
465 1.34 bouyer while (periph->periph_active < periph->periph_openings) {
466 1.1 mycroft /* if a special awaits, let it proceed first */
467 1.34 bouyer if (periph->periph_flags & PERIPH_WAITING) {
468 1.34 bouyer periph->periph_flags &= ~PERIPH_WAITING;
469 1.70 christos wakeup((void *)periph);
470 1.1 mycroft return;
471 1.1 mycroft }
472 1.1 mycroft
473 1.84 mbalmer /* See if there is a buf with work for us to do.. */
474 1.76 yamt if ((bp = bufq_peek(ss->buf_queue)) == NULL)
475 1.1 mycroft return;
476 1.1 mycroft
477 1.81 mbalmer if (ss->special && ss->special->read)
478 1.1 mycroft (ss->special->read)(ss, bp);
479 1.83 mbalmer else {
480 1.1 mycroft /* generic scsi2 scanner read */
481 1.1 mycroft /* XXX add code for SCSI2 scanner read */
482 1.1 mycroft }
483 1.1 mycroft }
484 1.1 mycroft }
485 1.1 mycroft
486 1.55 mycroft void
487 1.53 bouyer ssrestart(void *v)
488 1.53 bouyer {
489 1.53 bouyer int s = splbio();
490 1.53 bouyer ssstart((struct scsipi_periph *)v);
491 1.53 bouyer splx(s);
492 1.53 bouyer }
493 1.54 mycroft
494 1.54 mycroft static void
495 1.54 mycroft ssdone(struct scsipi_xfer *xs, int error)
496 1.54 mycroft {
497 1.54 mycroft struct buf *bp = xs->bp;
498 1.54 mycroft
499 1.54 mycroft if (bp) {
500 1.54 mycroft bp->b_error = error;
501 1.54 mycroft bp->b_resid = xs->resid;
502 1.54 mycroft biodone(bp);
503 1.54 mycroft }
504 1.54 mycroft }
505 1.53 bouyer
506 1.53 bouyer
507 1.1 mycroft /*
508 1.1 mycroft * Perform special action on behalf of the user;
509 1.1 mycroft * knows about the internals of this device
510 1.1 mycroft */
511 1.1 mycroft int
512 1.70 christos ssioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
513 1.1 mycroft {
514 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev));
515 1.1 mycroft int error = 0;
516 1.1 mycroft struct scan_io *sio;
517 1.32 augustss
518 1.81 mbalmer if (!device_is_active(ss->sc_dev))
519 1.81 mbalmer return ENODEV;
520 1.1 mycroft
521 1.1 mycroft switch (cmd) {
522 1.1 mycroft case SCIOCGET:
523 1.21 explorer if (ss->special && ss->special->get_params) {
524 1.1 mycroft /* call special handler */
525 1.3 mycroft error = (ss->special->get_params)(ss);
526 1.3 mycroft if (error)
527 1.81 mbalmer return error;
528 1.81 mbalmer } else
529 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */
530 1.81 mbalmer return EOPNOTSUPP;
531 1.36 thorpej memcpy(addr, &ss->sio, sizeof(struct scan_io));
532 1.1 mycroft break;
533 1.1 mycroft case SCIOCSET:
534 1.1 mycroft sio = (struct scan_io *)addr;
535 1.1 mycroft
536 1.21 explorer if (ss->special && ss->special->set_params) {
537 1.1 mycroft /* call special handler */
538 1.3 mycroft error = (ss->special->set_params)(ss, sio);
539 1.3 mycroft if (error)
540 1.81 mbalmer return error;
541 1.81 mbalmer } else
542 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */
543 1.81 mbalmer return EOPNOTSUPP;
544 1.1 mycroft break;
545 1.1 mycroft case SCIOCRESTART:
546 1.21 explorer if (ss->special && ss->special->rewind_scanner ) {
547 1.1 mycroft /* call special handler */
548 1.3 mycroft error = (ss->special->rewind_scanner)(ss);
549 1.3 mycroft if (error)
550 1.81 mbalmer return error;
551 1.1 mycroft } else
552 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */
553 1.81 mbalmer return EOPNOTSUPP;
554 1.1 mycroft ss->flags &= ~SSF_TRIGGERED;
555 1.1 mycroft break;
556 1.1 mycroft #ifdef NOTYET
557 1.1 mycroft case SCAN_USE_ADF:
558 1.1 mycroft break;
559 1.1 mycroft #endif
560 1.1 mycroft default:
561 1.81 mbalmer return scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr, flag, l);
562 1.1 mycroft }
563 1.81 mbalmer return error;
564 1.1 mycroft }
565