1 1.91 andvar /* $NetBSD: ss.c,v 1.91 2022/02/23 21:54:41 andvar 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.91 andvar __KERNEL_RCSID(0, "$NetBSD: ss.c,v 1.91 2022/02/23 21:54:41 andvar 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.85 dholland .d_open = ssopen, 93 1.85 dholland .d_close = ssclose, 94 1.85 dholland .d_read = ssread, 95 1.85 dholland .d_write = nowrite, 96 1.85 dholland .d_ioctl = ssioctl, 97 1.85 dholland .d_stop = nostop, 98 1.85 dholland .d_tty = notty, 99 1.85 dholland .d_poll = nopoll, 100 1.85 dholland .d_mmap = nommap, 101 1.85 dholland .d_kqfilter = nokqfilter, 102 1.86 dholland .d_discard = nodiscard, 103 1.88 mlelstv .d_flag = D_OTHER | D_MPSAFE 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.88 mlelstv struct scsipi_periph *periph = ss->sc_periph; 203 1.88 mlelstv struct scsipi_channel *chan = periph->periph_channel; 204 1.88 mlelstv int cmaj, mn; 205 1.32 augustss 206 1.32 augustss /* locate the major number */ 207 1.40 gehenna cmaj = cdevsw_lookup_major(&ss_cdevsw); 208 1.32 augustss 209 1.53 bouyer /* kill any pending restart */ 210 1.89 mlelstv callout_halt(&ss->sc_callout, NULL); 211 1.53 bouyer 212 1.88 mlelstv mutex_enter(chan_mtx(chan)); 213 1.32 augustss 214 1.32 augustss /* Kill off any queued buffers. */ 215 1.62 yamt bufq_drain(ss->buf_queue); 216 1.32 augustss 217 1.32 augustss /* Kill off any pending commands. */ 218 1.88 mlelstv scsipi_kill_pending(periph); 219 1.32 augustss 220 1.88 mlelstv mutex_exit(chan_mtx(chan)); 221 1.32 augustss 222 1.87 pgoyette bufq_free(ss->buf_queue); 223 1.87 pgoyette 224 1.32 augustss /* Nuke the vnodes for any open instances */ 225 1.65 thorpej mn = SSUNIT(device_unit(self)); 226 1.33 augustss vdevgone(cmaj, mn, mn+SSNMINOR-1, VCHR); 227 1.32 augustss 228 1.81 mbalmer return 0; 229 1.32 augustss } 230 1.32 augustss 231 1.84 mbalmer /* open the device. */ 232 1.52 thorpej static int 233 1.69 christos ssopen(dev_t dev, int flag, int mode, struct lwp *l) 234 1.1 mycroft { 235 1.1 mycroft int unit; 236 1.59 reinoud u_int ssmode; 237 1.23 thorpej int error; 238 1.1 mycroft struct ss_softc *ss; 239 1.34 bouyer struct scsipi_periph *periph; 240 1.34 bouyer struct scsipi_adapter *adapt; 241 1.1 mycroft 242 1.1 mycroft unit = SSUNIT(dev); 243 1.74 tsutsui ss = device_lookup_private(&ss_cd, unit); 244 1.74 tsutsui if (ss == NULL) 245 1.81 mbalmer return ENXIO; 246 1.1 mycroft 247 1.81 mbalmer if (!device_is_active(ss->sc_dev)) 248 1.81 mbalmer return ENODEV; 249 1.32 augustss 250 1.5 mycroft ssmode = SSMODE(dev); 251 1.1 mycroft 252 1.34 bouyer periph = ss->sc_periph; 253 1.34 bouyer adapt = periph->periph_channel->chan_adapter; 254 1.34 bouyer 255 1.81 mbalmer SC_DEBUG(periph, SCSIPI_DB1, 256 1.81 mbalmer ("open: dev=0x%"PRIx64" (unit %d (of %d))\n", dev, unit, 257 1.81 mbalmer ss_cd.cd_ndevs)); 258 1.1 mycroft 259 1.34 bouyer if (periph->periph_flags & PERIPH_OPEN) { 260 1.81 mbalmer aprint_error_dev(ss->sc_dev, "already open\n"); 261 1.81 mbalmer return EBUSY; 262 1.1 mycroft } 263 1.1 mycroft 264 1.34 bouyer if ((error = scsipi_adapter_addref(adapt)) != 0) 265 1.81 mbalmer return error; 266 1.23 thorpej 267 1.1 mycroft /* 268 1.1 mycroft * Catch any unit attention errors. 269 1.1 mycroft * 270 1.26 thorpej * XS_CTL_IGNORE_MEDIA_CHANGE: when you have an ADF, some scanners 271 1.1 mycroft * consider paper to be a changeable media 272 1.1 mycroft * 273 1.1 mycroft */ 274 1.34 bouyer error = scsipi_test_unit_ready(periph, 275 1.26 thorpej XS_CTL_IGNORE_MEDIA_CHANGE | XS_CTL_IGNORE_ILLEGAL_REQUEST | 276 1.26 thorpej (ssmode == MODE_CONTROL ? XS_CTL_IGNORE_NOT_READY : 0)); 277 1.1 mycroft if (error) 278 1.1 mycroft goto bad; 279 1.1 mycroft 280 1.34 bouyer periph->periph_flags |= PERIPH_OPEN; /* unit attn now errors */ 281 1.1 mycroft 282 1.1 mycroft /* 283 1.1 mycroft * If the mode is 3 (e.g. minor = 3,7,11,15) 284 1.1 mycroft * then the device has been opened to set defaults 285 1.1 mycroft * This mode does NOT ALLOW I/O, only ioctls 286 1.1 mycroft */ 287 1.5 mycroft if (ssmode == MODE_CONTROL) 288 1.81 mbalmer return 0; 289 1.1 mycroft 290 1.34 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n")); 291 1.81 mbalmer return 0; 292 1.1 mycroft 293 1.1 mycroft bad: 294 1.34 bouyer scsipi_adapter_delref(adapt); 295 1.34 bouyer periph->periph_flags &= ~PERIPH_OPEN; 296 1.81 mbalmer return error; 297 1.1 mycroft } 298 1.1 mycroft 299 1.1 mycroft /* 300 1.1 mycroft * close the device.. only called if we are the LAST 301 1.90 msaitoh * occurrence of an open device 302 1.1 mycroft */ 303 1.52 thorpej static int 304 1.69 christos ssclose(dev_t dev, int flag, int mode, struct lwp *l) 305 1.1 mycroft { 306 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev)); 307 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph; 308 1.34 bouyer struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter; 309 1.1 mycroft int error; 310 1.1 mycroft 311 1.34 bouyer SC_DEBUG(ss->sc_periph, SCSIPI_DB1, ("closing\n")); 312 1.1 mycroft 313 1.1 mycroft if (SSMODE(dev) == MODE_REWIND) { 314 1.21 explorer if (ss->special && ss->special->rewind_scanner) { 315 1.1 mycroft /* call special handler to rewind/abort scan */ 316 1.1 mycroft error = (ss->special->rewind_scanner)(ss); 317 1.1 mycroft if (error) 318 1.81 mbalmer return error; 319 1.82 mbalmer } else { 320 1.1 mycroft /* XXX add code to restart a SCSI2 scanner, if any */ 321 1.1 mycroft } 322 1.4 mycroft ss->sio.scan_window_size = 0; 323 1.1 mycroft ss->flags &= ~SSF_TRIGGERED; 324 1.1 mycroft } 325 1.24 thorpej 326 1.34 bouyer scsipi_wait_drain(periph); 327 1.23 thorpej 328 1.34 bouyer scsipi_adapter_delref(adapt); 329 1.34 bouyer periph->periph_flags &= ~PERIPH_OPEN; 330 1.1 mycroft 331 1.81 mbalmer return 0; 332 1.1 mycroft } 333 1.1 mycroft 334 1.1 mycroft /* 335 1.84 mbalmer * trim the size of the transfer if needed, called by physio 336 1.84 mbalmer * basically the smaller of our min and the scsi driver's minphys 337 1.1 mycroft */ 338 1.52 thorpej static void 339 1.32 augustss ssminphys(struct buf *bp) 340 1.1 mycroft { 341 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev)); 342 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph; 343 1.1 mycroft 344 1.51 thorpej scsipi_adapter_minphys(periph->periph_channel, bp); 345 1.1 mycroft 346 1.1 mycroft /* 347 1.1 mycroft * trim the transfer further for special devices this is 348 1.1 mycroft * because some scanners only read multiples of a line at a 349 1.1 mycroft * time, also some cannot disconnect, so the read must be 350 1.1 mycroft * short enough to happen quickly 351 1.1 mycroft */ 352 1.21 explorer if (ss->special && ss->special->minphys) 353 1.1 mycroft (ss->special->minphys)(ss, bp); 354 1.1 mycroft } 355 1.1 mycroft 356 1.1 mycroft /* 357 1.1 mycroft * Do a read on a device for a user process. 358 1.1 mycroft * Prime scanner at start of read, check uio values, call ssstrategy 359 1.1 mycroft * via physio for the actual transfer. 360 1.1 mycroft */ 361 1.52 thorpej static int 362 1.69 christos ssread(dev_t dev, struct uio *uio, int flag) 363 1.1 mycroft { 364 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev)); 365 1.1 mycroft int error; 366 1.1 mycroft 367 1.81 mbalmer if (!device_is_active(ss->sc_dev)) 368 1.81 mbalmer return ENODEV; 369 1.32 augustss 370 1.1 mycroft /* if the scanner has not yet been started, do it now */ 371 1.1 mycroft if (!(ss->flags & SSF_TRIGGERED)) { 372 1.21 explorer if (ss->special && ss->special->trigger_scanner) { 373 1.1 mycroft error = (ss->special->trigger_scanner)(ss); 374 1.1 mycroft if (error) 375 1.1 mycroft return (error); 376 1.1 mycroft } 377 1.1 mycroft ss->flags |= SSF_TRIGGERED; 378 1.1 mycroft } 379 1.1 mycroft 380 1.81 mbalmer return physio(ssstrategy, NULL, dev, B_READ, ssminphys, uio); 381 1.1 mycroft } 382 1.1 mycroft 383 1.1 mycroft /* 384 1.1 mycroft * Actually translate the requested transfer into one the physical 385 1.1 mycroft * driver can understand The transfer is described by a buf and will 386 1.1 mycroft * include only one physical transfer. 387 1.1 mycroft */ 388 1.52 thorpej static void 389 1.52 thorpej ssstrategy(struct buf *bp) 390 1.1 mycroft { 391 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(bp->b_dev)); 392 1.34 bouyer struct scsipi_periph *periph = ss->sc_periph; 393 1.88 mlelstv struct scsipi_channel *chan = periph->periph_channel; 394 1.1 mycroft 395 1.34 bouyer SC_DEBUG(ss->sc_periph, SCSIPI_DB1, 396 1.81 mbalmer ("ssstrategy %d bytes @ blk %" PRId64 "\n", bp->b_bcount, 397 1.81 mbalmer bp->b_blkno)); 398 1.25 bouyer 399 1.81 mbalmer /* If the device has been made invalid, error out */ 400 1.81 mbalmer if (!device_is_active(ss->sc_dev)) { 401 1.34 bouyer if (periph->periph_flags & PERIPH_OPEN) 402 1.32 augustss bp->b_error = EIO; 403 1.32 augustss else 404 1.32 augustss bp->b_error = ENODEV; 405 1.32 augustss goto done; 406 1.32 augustss } 407 1.32 augustss 408 1.25 bouyer /* If negative offset, error */ 409 1.25 bouyer if (bp->b_blkno < 0) { 410 1.25 bouyer bp->b_error = EINVAL; 411 1.25 bouyer goto done; 412 1.25 bouyer } 413 1.6 mycroft 414 1.6 mycroft if (bp->b_bcount > ss->sio.scan_window_size) 415 1.6 mycroft bp->b_bcount = ss->sio.scan_window_size; 416 1.1 mycroft 417 1.91 andvar /* If it's a null transfer, return immediately */ 418 1.1 mycroft if (bp->b_bcount == 0) 419 1.1 mycroft goto done; 420 1.1 mycroft 421 1.88 mlelstv mutex_enter(chan_mtx(chan)); 422 1.1 mycroft 423 1.1 mycroft /* 424 1.1 mycroft * Place it in the queue of activities for this scanner 425 1.1 mycroft * at the end (a bit silly because we only have on user.. 426 1.1 mycroft * (but it could fork())) 427 1.1 mycroft */ 428 1.76 yamt bufq_put(ss->buf_queue, bp); 429 1.1 mycroft 430 1.1 mycroft /* 431 1.1 mycroft * Tell the device to get going on the transfer if it's 432 1.1 mycroft * not doing anything, otherwise just wait for completion 433 1.1 mycroft * (All a bit silly if we're only allowing 1 open but..) 434 1.1 mycroft */ 435 1.88 mlelstv ssstart(periph); 436 1.1 mycroft 437 1.88 mlelstv mutex_exit(chan_mtx(chan)); 438 1.1 mycroft return; 439 1.1 mycroft done: 440 1.81 mbalmer /* Correctly set the buf to indicate a completed xfer */ 441 1.1 mycroft bp->b_resid = bp->b_bcount; 442 1.1 mycroft biodone(bp); 443 1.1 mycroft } 444 1.1 mycroft 445 1.1 mycroft /* 446 1.1 mycroft * ssstart looks to see if there is a buf waiting for the device 447 1.1 mycroft * and that the device is not already busy. If both are true, 448 1.1 mycroft * It dequeues the buf and creates a scsi command to perform the 449 1.16 bouyer * transfer required. The transfer request will call scsipi_done 450 1.1 mycroft * on completion, which will in turn call this routine again 451 1.1 mycroft * so that the next queued transfer is performed. 452 1.1 mycroft * The bufs are queued by the strategy routine (ssstrategy) 453 1.1 mycroft * 454 1.1 mycroft * This routine is also called after other non-queued requests 455 1.1 mycroft * have been made of the scsi driver, to ensure that the queue 456 1.1 mycroft * continues to be drained. 457 1.88 mlelstv * ssstart() is called with channel lock held. 458 1.1 mycroft */ 459 1.52 thorpej static void 460 1.52 thorpej ssstart(struct scsipi_periph *periph) 461 1.1 mycroft { 462 1.81 mbalmer struct ss_softc *ss = device_private(periph->periph_dev); 463 1.30 augustss struct buf *bp; 464 1.1 mycroft 465 1.34 bouyer SC_DEBUG(periph, SCSIPI_DB2, ("ssstart ")); 466 1.84 mbalmer 467 1.84 mbalmer /* See if there is a buf to do and we are not already doing one */ 468 1.34 bouyer while (periph->periph_active < periph->periph_openings) { 469 1.1 mycroft /* if a special awaits, let it proceed first */ 470 1.34 bouyer if (periph->periph_flags & PERIPH_WAITING) { 471 1.34 bouyer periph->periph_flags &= ~PERIPH_WAITING; 472 1.88 mlelstv cv_broadcast(periph_cv_periph(periph)); 473 1.1 mycroft return; 474 1.1 mycroft } 475 1.1 mycroft 476 1.84 mbalmer /* See if there is a buf with work for us to do.. */ 477 1.76 yamt if ((bp = bufq_peek(ss->buf_queue)) == NULL) 478 1.1 mycroft return; 479 1.1 mycroft 480 1.81 mbalmer if (ss->special && ss->special->read) 481 1.1 mycroft (ss->special->read)(ss, bp); 482 1.83 mbalmer else { 483 1.1 mycroft /* generic scsi2 scanner read */ 484 1.1 mycroft /* XXX add code for SCSI2 scanner read */ 485 1.1 mycroft } 486 1.1 mycroft } 487 1.1 mycroft } 488 1.1 mycroft 489 1.55 mycroft void 490 1.53 bouyer ssrestart(void *v) 491 1.53 bouyer { 492 1.88 mlelstv struct scsipi_periph *periph = v; 493 1.88 mlelstv struct scsipi_channel *chan = periph->periph_channel; 494 1.88 mlelstv 495 1.88 mlelstv mutex_enter(chan_mtx(chan)); 496 1.88 mlelstv ssstart(periph); 497 1.88 mlelstv mutex_exit(chan_mtx(chan)); 498 1.53 bouyer } 499 1.54 mycroft 500 1.54 mycroft static void 501 1.54 mycroft ssdone(struct scsipi_xfer *xs, int error) 502 1.54 mycroft { 503 1.54 mycroft struct buf *bp = xs->bp; 504 1.54 mycroft 505 1.54 mycroft if (bp) { 506 1.54 mycroft bp->b_error = error; 507 1.54 mycroft bp->b_resid = xs->resid; 508 1.54 mycroft biodone(bp); 509 1.54 mycroft } 510 1.54 mycroft } 511 1.53 bouyer 512 1.53 bouyer 513 1.1 mycroft /* 514 1.1 mycroft * Perform special action on behalf of the user; 515 1.1 mycroft * knows about the internals of this device 516 1.1 mycroft */ 517 1.1 mycroft int 518 1.70 christos ssioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l) 519 1.1 mycroft { 520 1.74 tsutsui struct ss_softc *ss = device_lookup_private(&ss_cd, SSUNIT(dev)); 521 1.1 mycroft int error = 0; 522 1.1 mycroft struct scan_io *sio; 523 1.32 augustss 524 1.81 mbalmer if (!device_is_active(ss->sc_dev)) 525 1.81 mbalmer return ENODEV; 526 1.1 mycroft 527 1.1 mycroft switch (cmd) { 528 1.1 mycroft case SCIOCGET: 529 1.21 explorer if (ss->special && ss->special->get_params) { 530 1.1 mycroft /* call special handler */ 531 1.3 mycroft error = (ss->special->get_params)(ss); 532 1.3 mycroft if (error) 533 1.81 mbalmer return error; 534 1.81 mbalmer } else 535 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */ 536 1.81 mbalmer return EOPNOTSUPP; 537 1.36 thorpej memcpy(addr, &ss->sio, sizeof(struct scan_io)); 538 1.1 mycroft break; 539 1.1 mycroft case SCIOCSET: 540 1.1 mycroft sio = (struct scan_io *)addr; 541 1.1 mycroft 542 1.21 explorer if (ss->special && ss->special->set_params) { 543 1.1 mycroft /* call special handler */ 544 1.3 mycroft error = (ss->special->set_params)(ss, sio); 545 1.3 mycroft if (error) 546 1.81 mbalmer return error; 547 1.81 mbalmer } else 548 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */ 549 1.81 mbalmer return EOPNOTSUPP; 550 1.1 mycroft break; 551 1.1 mycroft case SCIOCRESTART: 552 1.21 explorer if (ss->special && ss->special->rewind_scanner ) { 553 1.1 mycroft /* call special handler */ 554 1.3 mycroft error = (ss->special->rewind_scanner)(ss); 555 1.3 mycroft if (error) 556 1.81 mbalmer return error; 557 1.1 mycroft } else 558 1.1 mycroft /* XXX add code for SCSI2 scanner, if any */ 559 1.81 mbalmer return EOPNOTSUPP; 560 1.1 mycroft ss->flags &= ~SSF_TRIGGERED; 561 1.1 mycroft break; 562 1.1 mycroft #ifdef NOTYET 563 1.1 mycroft case SCAN_USE_ADF: 564 1.1 mycroft break; 565 1.1 mycroft #endif 566 1.1 mycroft default: 567 1.81 mbalmer return scsipi_do_ioctl(ss->sc_periph, dev, cmd, addr, flag, l); 568 1.1 mycroft } 569 1.81 mbalmer return error; 570 1.1 mycroft } 571