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