1 /* $NetBSD: lpt_mvme.c,v 1.15 2009/03/14 15:36:19 dsl Exp $ */
4 * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Steve C. Woodford.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1993, 1994 Charles M. Hannum.
34 * Copyright (c) 1990 William F. Jolitz, TeleMuse
35 * All rights reserved.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. All advertising materials mentioning features or use of this software
46 * must display the following acknowledgement:
47 * This software is a component of "386BSD" developed by
48 * William F. Jolitz, TeleMuse.
49 * 4. Neither the name of the developer nor the name "386BSD"
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
53 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
54 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
55 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
56 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
57 * NOT MAKE USE OF THIS WORK.
59 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
60 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
61 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
62 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
63 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
64 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
65 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
66 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
68 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
69 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
70 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
71 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
72 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
73 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
74 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
75 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
76 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
77 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
82 * Device Driver for an MVME68K/MVME88K board's parallel printer port
83 * This driver attaches above the board-specific back-end.
86 #include <sys/cdefs.h>
87 __KERNEL_RCSID(0, "$NetBSD: lpt_mvme.c,v 1.15 2009/03/14 15:36:19 dsl Exp $");
89 #include <sys/param.h>
90 #include <sys/systm.h>
93 #include <sys/kernel.h>
94 #include <sys/ioctl.h>
96 #include <sys/device.h>
98 #include <sys/syslog.h>
103 #include <dev/mvme/lptvar.h>
106 #define TIMEOUT hz*16 /* wait up to 16 seconds for a ready */
109 #define LPTPRI (PZERO+8)
110 #define LPT_BSIZE 1024
112 #if !defined(DEBUG) || !defined(notdef)
115 #define LPRINTF if (lptdebug) aprint_verbose_dev a
119 #define LPTUNIT(s) (minor(s) & 0x0f)
120 #define LPTFLAGS(s) (minor(s) & 0xf0)
122 static void lpt_wakeup(void *arg
);
123 static int pushbytes(struct lpt_softc
*);
125 extern struct cfdriver lpt_cd
;
127 dev_type_open(lptopen
);
128 dev_type_close(lptclose
);
129 dev_type_write(lptwrite
);
130 dev_type_ioctl(lptioctl
);
132 const struct cdevsw lpt_cdevsw
= {
133 lptopen
, lptclose
, noread
, lptwrite
, lptioctl
,
134 nostop
, notty
, nopoll
, nommap
, nokqfilter
,
138 lpt_attach_subr(struct lpt_softc
*sc
)
142 callout_init(&sc
->sc_wakeup_ch
, 0);
146 * Reset the printer, then wait until it's selected and not busy.
149 lptopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
152 struct lpt_softc
*sc
;
156 flags
= LPTFLAGS(dev
);
158 sc
= device_lookup_private(&lpt_cd
, LPTUNIT(dev
));
164 aprint_verbose_dev(sc
->sc_dev
, "stat=0x%x not zero\n",
171 sc
->sc_state
= LPT_INIT
;
172 sc
->sc_flags
= flags
;
173 LPRINTF((sc
->sc_dev
, "open: flags=0x%x\n", flags
));
175 if ((flags
& LPT_NOPRIME
) == 0) {
176 /* assert Input Prime for 100 usec to start up printer */
177 (sc
->sc_funcs
->lf_iprime
) (sc
);
180 /* select fast or slow strobe depending on minor device number */
181 if (flags
& LPT_FAST_STROBE
)
182 (sc
->sc_funcs
->lf_speed
) (sc
, LPT_STROBE_FAST
);
184 (sc
->sc_funcs
->lf_speed
) (sc
, LPT_STROBE_SLOW
);
186 /* wait till ready (printer running diagnostics) */
187 for (spin
= 0; (sc
->sc_funcs
->lf_notrdy
) (sc
, 1); spin
+= STEP
) {
188 if (spin
>= TIMEOUT
) {
192 /* wait 1/4 second, give up if we get a signal */
193 error
= tsleep((void *) sc
, LPTPRI
| PCATCH
, "lptopen", STEP
);
194 if (error
!= EWOULDBLOCK
) {
200 sc
->sc_inbuf
= geteblk(LPT_BSIZE
);
202 sc
->sc_state
= LPT_OPEN
;
204 if ((sc
->sc_flags
& LPT_NOINTR
) == 0)
207 (sc
->sc_funcs
->lf_open
) (sc
, sc
->sc_flags
& LPT_NOINTR
);
209 LPRINTF((sc
->sc_dev
, "opened\n"));
214 lpt_wakeup(void *arg
)
216 struct lpt_softc
*sc
;
225 callout_reset(&sc
->sc_wakeup_ch
, STEP
, lpt_wakeup
, sc
);
229 * Close the device, and free the local line buffer.
232 lptclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
234 struct lpt_softc
*sc
;
236 sc
= device_lookup_private(&lpt_cd
, LPTUNIT(dev
));
239 (void) pushbytes(sc
);
241 if ((sc
->sc_flags
& LPT_NOINTR
) == 0)
242 callout_stop(&sc
->sc_wakeup_ch
);
244 (sc
->sc_funcs
->lf_close
) (sc
);
247 brelse(sc
->sc_inbuf
, 0);
249 LPRINTF((sc
->sc_dev
, "%s: closed\n"));
254 pushbytes(struct lpt_softc
*sc
)
256 int s
, error
, spin
, tic
;
258 if (sc
->sc_flags
& LPT_NOINTR
) {
259 while (sc
->sc_count
> 0) {
261 while ((sc
->sc_funcs
->lf_notrdy
) (sc
, 0)) {
262 if (++spin
< sc
->sc_spinmax
)
265 /* adapt busy-wait algorithm */
267 while ((sc
->sc_funcs
->lf_notrdy
) (sc
, 1)) {
268 /* exponential backoff */
272 error
= tsleep((void *) sc
,
273 LPTPRI
| PCATCH
, "lptpsh", tic
);
274 if (error
!= EWOULDBLOCK
)
280 (sc
->sc_funcs
->lf_wrdata
) (sc
, *sc
->sc_cp
++);
283 /* adapt busy-wait algorithm */
284 if (spin
* 2 + 16 < sc
->sc_spinmax
)
288 while (sc
->sc_count
> 0) {
289 /* if the printer is ready for a char, give it one */
290 if ((sc
->sc_state
& LPT_OBUSY
) == 0) {
291 LPRINTF((sc
->sc_dev
, "write %d\n",
297 error
= tsleep((void *) sc
, LPTPRI
| PCATCH
,
307 * Copy a line from user space to a local buffer, then call putc to get the
308 * chars moved to the output queue.
311 lptwrite(dev_t dev
, struct uio
*uio
, int flags
)
313 struct lpt_softc
*sc
;
317 sc
= device_lookup_private(&lpt_cd
, LPTUNIT(dev
));
320 while ((n
= min(LPT_BSIZE
, uio
->uio_resid
)) != 0) {
321 uiomove(sc
->sc_cp
= sc
->sc_inbuf
->b_data
, n
, uio
);
323 error
= pushbytes(sc
);
326 * Return accurate residual if interrupted or timed
329 uio
->uio_resid
+= sc
->sc_count
;
338 * Handle printer interrupts which occur when the printer is ready to accept
342 lpt_intr(struct lpt_softc
*sc
)
347 (sc
->sc_funcs
->lf_wrdata
) (sc
, *sc
->sc_cp
++);
349 sc
->sc_state
|= LPT_OBUSY
;
351 sc
->sc_state
&= ~LPT_OBUSY
;
353 if (sc
->sc_count
== 0) {
354 /* none, wake up the top half to get more */
363 lptioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)