1 /* $NetBSD: arcpp.c,v 1.10 2009/01/07 23:05:46 bjh21 Exp $ */
4 * Copyright (c) 2001 Ben Harris
5 * Copyright (c) 1993, 1994 Charles M. Hannum.
6 * Copyright (c) 1990 William F. Jolitz, TeleMuse
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This software is a component of "386BSD" developed by
20 * William F. Jolitz, TeleMuse.
21 * 4. Neither the name of the developer nor the name "386BSD"
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
26 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
27 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
28 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
29 * NOT MAKE USE OF THIS WORK.
31 * FOR USERS WHO WISH TO UNDERSTAND THE 386BSD SYSTEM DEVELOPED
32 * BY WILLIAM F. JOLITZ, WE RECOMMEND THE USER STUDY WRITTEN
33 * REFERENCES SUCH AS THE "PORTING UNIX TO THE 386" SERIES
34 * (BEGINNING JANUARY 1991 "DR. DOBBS JOURNAL", USA AND BEGINNING
35 * JUNE 1991 "UNIX MAGAZIN", GERMANY) BY WILLIAM F. JOLITZ AND
36 * LYNNE GREER JOLITZ, AS WELL AS OTHER BOOKS ON UNIX AND THE
37 * ON-LINE 386BSD USER MANUAL BEFORE USE. A BOOK DISCUSSING THE INTERNALS
38 * OF 386BSD ENTITLED "386BSD FROM THE INSIDE OUT" WILL BE AVAILABLE LATE 1992.
40 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE DEVELOPER BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 #include <sys/param.h>
55 __KERNEL_RCSID(0, "$NetBSD: arcpp.c,v 1.10 2009/01/07 23:05:46 bjh21 Exp $");
58 #include <sys/device.h>
59 #include <sys/kernel.h>
60 #include <sys/malloc.h>
62 #include <sys/systm.h>
64 #include <machine/bus.h>
65 #include <machine/intr.h>
66 #include <machine/irq.h>
68 #include <arch/acorn26/iobus/iocvar.h>
69 #include <arch/acorn26/ioc/arcppreg.h>
70 #include <arch/acorn26/ioc/latchreg.h>
71 #include <arch/acorn26/ioc/latchvar.h>
72 #include <arch/acorn26/ioc/ioebvar.h>
78 void *sc_aih
; /* ACK interrupt handler */
79 struct evcnt sc_aintrcnt
; /* ... and count */
80 void *sc_bih
; /* BUSY interrupt handler */
81 struct evcnt sc_bintrcnt
; /* ... and count */
86 bus_space_tag_t sc_iot
;
87 bus_space_handle_t sc_ioh
;
89 #define ARCPP_OPEN 0x01 /* device is open */
90 #define ARCPP_OBUSY 0x02 /* printer is busy doing output */
91 #define ARCPP_INIT 0x04 /* waiting to initialize for open */
93 /*#define ARCPP_AUTOLF 0x20 * automatic LF on CR */
94 /*#define ARCPP_NOPRIME 0x40 * don't prime on open */
95 /*#define ARCPP_NOINTR 0x80 * do not use interrupt */
99 #define TIMEOUT (hz*16) /* wait up to 16 seconds for a ready */
102 #define ARCPPPRI (PZERO+8)
103 #define ARCPP_BSIZE 1024
105 extern struct cfdriver arcpp_cd
;
107 dev_type_open(arcppopen
);
108 dev_type_close(arcppclose
);
109 dev_type_write(arcppwrite
);
111 const struct cdevsw arcpp_cdevsw
= {
112 arcppopen
, arcppclose
, noread
, arcppwrite
, noioctl
,
113 nostop
, notty
, nopoll
, nommap
, nokqfilter
,
116 #define ARCPPUNIT(s) (minor(s) & 0x1f)
117 #define ARCPPFLAGS(s) (minor(s) & 0xe0)
119 static int arcpp_match(device_t
, cfdata_t
, void *);
120 static void arcpp_attach(device_t
, device_t
, void *);
122 static int arcppintr(void *);
123 static int arcpppushbytes(struct arcpp_softc
*);
125 CFATTACH_DECL_NEW(arcpp
, sizeof(struct arcpp_softc
),
126 arcpp_match
, arcpp_attach
, NULL
, NULL
);
129 arcpp_match(device_t parent
, cfdata_t cf
, void *aux
)
133 * The parallel port is write-only, so we can't probe for it.
134 * Happily, the set of machines it exists on is precisely the
135 * set that doesn't have IOEBs, so...
138 if (the_ioeb
!= NULL
)
145 arcpp_attach(device_t parent
, device_t self
, void *aux
)
147 struct arcpp_softc
*sc
= device_private(self
);
148 struct ioc_attach_args
*ioc
= aux
;
150 bus_space_handle_t ioh
;
154 iot
= sc
->sc_iot
= ioc
->ioc_fast_t
;
155 ioh
= sc
->sc_ioh
= ioc
->ioc_fast_h
;
157 evcnt_attach_dynamic(&sc
->sc_aintrcnt
, EVCNT_TYPE_INTR
, NULL
,
158 device_xname(self
), "ack intr");
159 evcnt_attach_dynamic(&sc
->sc_bintrcnt
, EVCNT_TYPE_INTR
, NULL
,
160 device_xname(self
), "busy intr");
161 sc
->sc_aih
= irq_establish(IRQ_PACK
, IPL_VM
, arcppintr
, sc
,
163 sc
->sc_bih
= irq_establish(IRQ_PBSY
, IPL_VM
, arcppintr
, sc
,
166 /* We're not interested in interrupts while the device is closed. */
167 irq_disable(sc
->sc_aih
);
168 irq_disable(sc
->sc_bih
);
174 * Wait until the printer's selected and not busy.
177 arcppopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
179 u_char flags
= ARCPPFLAGS(dev
);
180 struct arcpp_softc
*sc
;
182 bus_space_handle_t ioh
;
185 sc
= device_lookup_private(&arcpp_cd
, ARCPPUNIT(dev
));
191 printf("%s: stat=0x%x not zero\n", device_xname(sc
->sc_dev
),
198 sc
->sc_state
= ARCPP_INIT
;
199 sc
->sc_flags
= flags
;
204 /* wait till ready (printer running diagnostics) */
205 irq_enable(sc
->sc_bih
);
206 /* XXX Is it really appropriate to time out? */
207 error
= tsleep((void *)sc
, ARCPPPRI
| PCATCH
, "arcppopen", TIMEOUT
);
208 if (error
== EWOULDBLOCK
) {
217 sc
->sc_inbuf
= malloc(ARCPP_BSIZE
, M_DEVBUF
, M_WAITOK
);
220 sc
->sc_state
= ARCPP_OPEN
;
229 * Close the device, and free the local line buffer.
232 arcppclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
234 struct arcpp_softc
*sc
= device_lookup_private(&arcpp_cd
, ARCPPUNIT(dev
));
237 (void) arcpppushbytes(sc
);
239 irq_disable(sc
->sc_aih
);
240 irq_disable(sc
->sc_bih
);
242 free(sc
->sc_inbuf
, M_DEVBUF
);
248 arcpppushbytes(struct arcpp_softc
*sc
)
253 while (sc
->sc_count
> 0) {
254 /* if the printer is ready for a char, give it one */
255 if ((sc
->sc_state
& ARCPP_OBUSY
) == 0) {
260 error
= tsleep((void *)sc
, ARCPPPRI
| PCATCH
, "arcppwr", 0);
268 arcppwrite(dev_t dev
, struct uio
*uio
, int flags
)
270 struct arcpp_softc
*sc
= device_lookup_private(&arcpp_cd
, ARCPPUNIT(dev
));
274 while ((n
= min(ARCPP_BSIZE
, uio
->uio_resid
)) != 0) {
275 uiomove(sc
->sc_cp
= sc
->sc_inbuf
, n
, uio
);
277 error
= arcpppushbytes(sc
);
280 * Return accurate residual if interrupted or timed
283 uio
->uio_resid
+= sc
->sc_count
;
292 * Handle printer interrupts which occur when the printer is ready to accept
298 struct arcpp_softc
*sc
= arg
;
299 bus_space_tag_t iot
= sc
->sc_iot
;
300 bus_space_handle_t ioh
= sc
->sc_ioh
;
302 /* is printer online and ready for output */
303 if (!ioc_irq_status(IRQ_PBSY
)) {
309 bus_space_write_1(iot
, ioh
, ARCPP_DATA
, *sc
->sc_cp
++);
311 latchb_update(LATCHB_NPSTB
, 0);
314 latchb_update(LATCHB_NPSTB
, LATCHB_NPSTB
);
316 sc
->sc_state
|= ARCPP_OBUSY
;
318 sc
->sc_state
&= ~ARCPP_OBUSY
;
320 if (sc
->sc_count
== 0)
321 /* none, wake up the top half to get more */