xref: /netbsd-src/sys/dev/mvme/lpt_pcctwo.c (revision 23c8222edbfb0f0932d88a8351d3a0cf817dfb9e)
1 /*	$NetBSD: lpt_pcctwo.c,v 1.5 2003/07/14 15:47:19 lukem Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Steve C. Woodford.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
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.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 /*
40  * Device Driver back-end for the PCCChip2's parallel printer port
41  */
42 
43 #include <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: lpt_pcctwo.c,v 1.5 2003/07/14 15:47:19 lukem Exp $");
45 
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/systm.h>
49 #include <sys/device.h>
50 #include <sys/syslog.h>
51 
52 #include <machine/cpu.h>
53 #include <machine/bus.h>
54 
55 #include <dev/mvme/lptvar.h>
56 #include <dev/mvme/pcctworeg.h>
57 #include <dev/mvme/pcctwovar.h>
58 
59 /*
60  * Autoconfig stuff
61  */
62 int lpt_pcctwo_match __P((struct device *, struct cfdata *, void *));
63 void lpt_pcctwo_attach __P((struct device *, struct device *, void *));
64 
65 CFATTACH_DECL(lpt_pcctwo, sizeof(struct lpt_softc),
66     lpt_pcctwo_match, lpt_pcctwo_attach, NULL, NULL);
67 
68 extern struct cfdriver lpt_cd;
69 
70 
71 int lpt_pcctwo_intr __P((void *));
72 void lpt_pcctwo_open __P((struct lpt_softc *, int));
73 void lpt_pcctwo_close __P((struct lpt_softc *));
74 void lpt_pcctwo_iprime __P((struct lpt_softc *));
75 void lpt_pcctwo_speed __P((struct lpt_softc *, int));
76 int lpt_pcctwo_notrdy __P((struct lpt_softc *, int));
77 void lpt_pcctwo_wr_data __P((struct lpt_softc *, u_char));
78 
79 struct lpt_funcs lpt_pcctwo_funcs = {
80 	lpt_pcctwo_open,
81 	lpt_pcctwo_close,
82 	lpt_pcctwo_iprime,
83 	lpt_pcctwo_speed,
84 	lpt_pcctwo_notrdy,
85 	lpt_pcctwo_wr_data
86 };
87 
88 /* ARGSUSED */
89 int
90 lpt_pcctwo_match(parent, cf, args)
91 	struct device *parent;
92 	struct cfdata *cf;
93 	void *args;
94 {
95 	struct pcctwo_attach_args *pa;
96 
97 	pa = args;
98 
99 	if (strcmp(pa->pa_name, lpt_cd.cd_name))
100 		return (0);
101 
102 #ifdef MVME68K
103 	if (machineid != MVME_167 && machineid != MVME_177)
104 		return (0);
105 #endif
106 
107 #ifdef MVME88K
108 	if (machineid != MVME_187)
109 		return (0);
110 #endif
111 
112 	pa->pa_ipl = cf->pcctwocf_ipl;
113 
114 	return (1);
115 }
116 
117 /* ARGSUSED */
118 void
119 lpt_pcctwo_attach(parent, self, args)
120 	struct device *parent;
121 	struct device *self;
122 	void *args;
123 {
124 	struct pcctwo_attach_args *pa;
125 	struct lpt_softc *sc;
126 
127 	pa = (struct pcctwo_attach_args *) args;
128 	sc = (struct lpt_softc *) self;
129 
130 	/* The printer registers are part of the PCCChip2's own registers. */
131 	sc->sc_bust = pa->pa_bust;
132 	bus_space_map(pa->pa_bust, pa->pa_offset, PCC2REG_SIZE, 0,
133 	    &sc->sc_bush);
134 
135 	sc->sc_ipl = pa->pa_ipl & PCCTWO_ICR_LEVEL_MASK;
136 	sc->sc_laststatus = 0;
137 	sc->sc_funcs = &lpt_pcctwo_funcs;
138 
139 	printf(": PCCchip2 Parallel Printer\n");
140 
141 	/*
142 	 * Disable interrupts until device is opened
143 	 */
144 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, 0);
145 	pcc2_reg_write(sc, PCC2REG_PRT_FAULT_ICSR, 0);
146 	pcc2_reg_write(sc, PCC2REG_PRT_SEL_ICSR, 0);
147 	pcc2_reg_write(sc, PCC2REG_PRT_PE_ICSR, 0);
148 	pcc2_reg_write(sc, PCC2REG_PRT_BUSY_ICSR, 0);
149 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
150 
151 	/*
152 	 * Main attachment code
153 	 */
154 	lpt_attach_subr(sc);
155 
156 	/* Register the event counter */
157 	evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
158 	    pcctwointr_evcnt(sc->sc_ipl), "printer", sc->sc_dev.dv_xname);
159 
160 	/*
161 	 * Hook into the printer interrupt
162 	 */
163 	pcctwointr_establish(PCCTWOV_PRT_ACK, lpt_pcctwo_intr, sc->sc_ipl, sc,
164 	    &sc->sc_evcnt);
165 }
166 
167 /*
168  * Handle printer interrupts
169  */
170 int
171 lpt_pcctwo_intr(arg)
172 	void *arg;
173 {
174 	struct lpt_softc *sc;
175 	int i;
176 
177 	sc = (struct lpt_softc *) arg;
178 
179 	/* is printer online and ready for output */
180 	if (lpt_pcctwo_notrdy(sc, 0) || lpt_pcctwo_notrdy(sc, 1))
181 		return (0);
182 
183 	i = lpt_intr(sc);
184 
185 	if (pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) & PCCTWO_PRT_IN_SR_PINT)
186 		pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
187 		    sc->sc_icr | PCCTWO_ICR_ICLR);
188 
189 	return (i);
190 }
191 
192 void
193 lpt_pcctwo_open(sc, int_ena)
194 	struct lpt_softc *sc;
195 	int int_ena;
196 {
197 	int sps;
198 
199 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
200 	    PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
201 
202 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
203 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_DOEN);
204 
205 	if (int_ena == 0) {
206 		sps = splhigh();
207 		sc->sc_icr = sc->sc_ipl | PCCTWO_ICR_EDGE;
208 		pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR, sc->sc_icr);
209 		splx(sps);
210 	}
211 }
212 
213 void
214 lpt_pcctwo_close(sc)
215 	struct lpt_softc *sc;
216 {
217 
218 	pcc2_reg_write(sc, PCC2REG_PRT_ACK_ICSR,
219 	    PCCTWO_ICR_ICLR | PCCTWO_ICR_EDGE);
220 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, 0);
221 }
222 
223 void
224 lpt_pcctwo_iprime(sc)
225 	struct lpt_softc *sc;
226 {
227 
228 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
229 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) | PCCTWO_PRT_CTRL_INP);
230 
231 	delay(100);
232 
233 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL,
234 	    pcc2_reg_read(sc, PCC2REG_PRT_CONTROL) & ~PCCTWO_PRT_CTRL_INP);
235 
236 	delay(100);
237 }
238 
239 void
240 lpt_pcctwo_speed(sc, speed)
241 	struct lpt_softc *sc;
242 	int speed;
243 {
244 	u_int8_t reg;
245 
246 	reg = pcc2_reg_read(sc, PCC2REG_PRT_CONTROL);
247 
248 	if (speed == LPT_STROBE_FAST)
249 		reg |= PCCTWO_PRT_CTRL_FAST;
250 	else
251 		reg &= ~PCCTWO_PRT_CTRL_FAST;
252 
253 	pcc2_reg_write(sc, PCC2REG_PRT_CONTROL, reg);
254 }
255 
256 int
257 lpt_pcctwo_notrdy(sc, err)
258 	struct lpt_softc *sc;
259 	int err;
260 {
261 	u_int8_t status;
262 	u_int8_t new;
263 
264 #define	LPS_INVERT	(PCCTWO_PRT_IN_SR_SEL)
265 #define	LPS_MASK	(PCCTWO_PRT_IN_SR_SEL | PCCTWO_PRT_IN_SR_FLT | \
266 			 PCCTWO_PRT_IN_SR_BSY | PCCTWO_PRT_IN_SR_PE)
267 
268 	status = pcc2_reg_read(sc, PCC2REG_PRT_INPUT_STATUS) ^ LPS_INVERT;
269 	status &= LPS_MASK;
270 
271 	if (err) {
272 		new = status & ~sc->sc_laststatus;
273 		sc->sc_laststatus = status;
274 
275 		if (new & PCCTWO_PRT_IN_SR_SEL)
276 			log(LOG_NOTICE, "%s: offline\n",
277 			    sc->sc_dev.dv_xname);
278 		else if (new & PCCTWO_PRT_IN_SR_PE)
279 			log(LOG_NOTICE, "%s: out of paper\n",
280 			    sc->sc_dev.dv_xname);
281 		else if (new & PCCTWO_PRT_IN_SR_FLT)
282 			log(LOG_NOTICE, "%s: output error\n",
283 			    sc->sc_dev.dv_xname);
284 	}
285 
286 	return (status);
287 }
288 
289 void
290 lpt_pcctwo_wr_data(sc, data)
291 	struct lpt_softc *sc;
292 	u_char data;
293 {
294 
295 	pcc2_reg_write16(sc, PCC2REG_PRT_DATA, (u_int16_t) data);
296 }
297