lpt_pcc.c revision 1.12 1 1.12 martin /* $NetBSD: lpt_pcc.c,v 1.12 2008/04/28 20:23:29 martin Exp $ */
2 1.2 scw
3 1.2 scw /*-
4 1.2 scw * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 1.2 scw * All rights reserved.
6 1.2 scw *
7 1.2 scw * This code is derived from software contributed to The NetBSD Foundation
8 1.2 scw * by Steve C. Woodford.
9 1.2 scw *
10 1.2 scw * Redistribution and use in source and binary forms, with or without
11 1.2 scw * modification, are permitted provided that the following conditions
12 1.2 scw * are met:
13 1.2 scw * 1. Redistributions of source code must retain the above copyright
14 1.2 scw * notice, this list of conditions and the following disclaimer.
15 1.2 scw * 2. Redistributions in binary form must reproduce the above copyright
16 1.2 scw * notice, this list of conditions and the following disclaimer in the
17 1.2 scw * documentation and/or other materials provided with the distribution.
18 1.2 scw *
19 1.2 scw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.2 scw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.2 scw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.2 scw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.2 scw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.2 scw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.2 scw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.2 scw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.2 scw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.2 scw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.2 scw * POSSIBILITY OF SUCH DAMAGE.
30 1.2 scw */
31 1.2 scw
32 1.2 scw /*
33 1.2 scw * Device Driver back-end for the MVME147's parallel printer port
34 1.2 scw */
35 1.8 lukem
36 1.8 lukem #include <sys/cdefs.h>
37 1.12 martin __KERNEL_RCSID(0, "$NetBSD: lpt_pcc.c,v 1.12 2008/04/28 20:23:29 martin Exp $");
38 1.2 scw
39 1.2 scw #include <sys/param.h>
40 1.2 scw #include <sys/systm.h>
41 1.2 scw #include <sys/kernel.h>
42 1.2 scw #include <sys/device.h>
43 1.2 scw #include <sys/syslog.h>
44 1.2 scw
45 1.3 scw #include <machine/bus.h>
46 1.2 scw
47 1.5 scw #include <dev/mvme/lptvar.h>
48 1.5 scw
49 1.2 scw #include <mvme68k/dev/lpt_pccreg.h>
50 1.2 scw #include <mvme68k/dev/pccreg.h>
51 1.2 scw #include <mvme68k/dev/pccvar.h>
52 1.2 scw
53 1.10 tsutsui #include "ioconf.h"
54 1.2 scw
55 1.2 scw
56 1.10 tsutsui static int lpt_pcc_intr(void *);
57 1.10 tsutsui static void lpt_pcc_open(struct lpt_softc *, int);
58 1.10 tsutsui static void lpt_pcc_close(struct lpt_softc *);
59 1.10 tsutsui static void lpt_pcc_iprime(struct lpt_softc *);
60 1.10 tsutsui static void lpt_pcc_speed(struct lpt_softc *, int);
61 1.10 tsutsui static int lpt_pcc_notrdy(struct lpt_softc *, int);
62 1.10 tsutsui static void lpt_pcc_wr_data(struct lpt_softc *, u_char);
63 1.2 scw
64 1.2 scw struct lpt_funcs lpt_pcc_funcs = {
65 1.2 scw lpt_pcc_open,
66 1.2 scw lpt_pcc_close,
67 1.2 scw lpt_pcc_iprime,
68 1.2 scw lpt_pcc_speed,
69 1.2 scw lpt_pcc_notrdy,
70 1.2 scw lpt_pcc_wr_data
71 1.2 scw };
72 1.2 scw
73 1.2 scw /*
74 1.2 scw * Autoconfig stuff
75 1.2 scw */
76 1.11 cube static int lpt_pcc_match(device_t, cfdata_t , void *);
77 1.11 cube static void lpt_pcc_attach(device_t, device_t, void *);
78 1.2 scw
79 1.11 cube CFATTACH_DECL_NEW(lpt_pcc, sizeof(struct lpt_softc),
80 1.7 thorpej lpt_pcc_match, lpt_pcc_attach, NULL, NULL);
81 1.2 scw
82 1.2 scw
83 1.2 scw /*ARGSUSED*/
84 1.3 scw static int
85 1.11 cube lpt_pcc_match(device_t parent, cfdata_t cf, void *args)
86 1.2 scw {
87 1.3 scw struct pcc_attach_args *pa;
88 1.3 scw
89 1.3 scw pa = args;
90 1.2 scw
91 1.2 scw if (strcmp(pa->pa_name, lpt_cd.cd_name))
92 1.10 tsutsui return 0;
93 1.2 scw
94 1.2 scw pa->pa_ipl = cf->pcccf_ipl;
95 1.10 tsutsui return 1;
96 1.2 scw }
97 1.2 scw
98 1.2 scw /*ARGSUSED*/
99 1.2 scw static void
100 1.11 cube lpt_pcc_attach(device_t parent, device_t self, void *args)
101 1.2 scw {
102 1.3 scw struct lpt_softc *sc;
103 1.3 scw struct pcc_attach_args *pa;
104 1.3 scw
105 1.11 cube sc = device_private(self);
106 1.11 cube sc->sc_dev = self;
107 1.3 scw pa = args;
108 1.3 scw
109 1.3 scw sc->sc_bust = pa->pa_bust;
110 1.3 scw bus_space_map(pa->pa_bust, pa->pa_offset, LPREG_SIZE, 0, &sc->sc_bush);
111 1.2 scw
112 1.2 scw sc->sc_ipl = pa->pa_ipl & PCC_IMASK;
113 1.3 scw sc->sc_funcs = &lpt_pcc_funcs;
114 1.2 scw sc->sc_laststatus = 0;
115 1.2 scw
116 1.11 cube aprint_normal(": PCC Parallel Printer\n");
117 1.2 scw
118 1.2 scw /*
119 1.2 scw * Disable interrupts until device is opened
120 1.2 scw */
121 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL, 0);
122 1.2 scw
123 1.2 scw /*
124 1.2 scw * Main attachment code
125 1.2 scw */
126 1.2 scw lpt_attach_subr(sc);
127 1.2 scw
128 1.4 scw /* Register the event counter */
129 1.4 scw evcnt_attach_dynamic(&sc->sc_evcnt, EVCNT_TYPE_INTR,
130 1.11 cube pccintr_evcnt(sc->sc_ipl), "printer", device_xname(sc->sc_dev));
131 1.4 scw
132 1.2 scw /*
133 1.2 scw * Hook into the printer interrupt
134 1.2 scw */
135 1.4 scw pccintr_establish(PCCV_PRINTER, lpt_pcc_intr, sc->sc_ipl, sc,
136 1.4 scw &sc->sc_evcnt);
137 1.2 scw }
138 1.2 scw
139 1.2 scw /*
140 1.2 scw * Handle printer interrupts which occur when the printer is ready to accept
141 1.2 scw * another char.
142 1.2 scw */
143 1.2 scw int
144 1.10 tsutsui lpt_pcc_intr(void *arg)
145 1.2 scw {
146 1.3 scw struct lpt_softc *sc;
147 1.2 scw int i;
148 1.2 scw
149 1.3 scw sc = arg;
150 1.3 scw
151 1.2 scw /* is printer online and ready for output */
152 1.2 scw if (lpt_pcc_notrdy(sc, 0) && lpt_pcc_notrdy(sc, 1))
153 1.2 scw return 0;
154 1.2 scw
155 1.2 scw i = lpt_intr(sc);
156 1.2 scw
157 1.3 scw if (pcc_reg_read(sys_pcc, PCCREG_PRNT_INTR_CTRL) & LPI_ACKINT) {
158 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL,
159 1.3 scw sc->sc_icr | LPI_ACKINT);
160 1.3 scw }
161 1.2 scw
162 1.10 tsutsui return i;
163 1.2 scw }
164 1.2 scw
165 1.2 scw
166 1.2 scw static void
167 1.10 tsutsui lpt_pcc_open(struct lpt_softc *sc, int int_ena)
168 1.2 scw {
169 1.2 scw int sps;
170 1.2 scw
171 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL,
172 1.3 scw LPI_ACKINT | LPI_FAULTINT);
173 1.2 scw
174 1.3 scw if (int_ena == 0) {
175 1.2 scw sps = splhigh();
176 1.2 scw sc->sc_icr = sc->sc_ipl | LPI_ENABLE;
177 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL, sc->sc_icr);
178 1.2 scw splx(sps);
179 1.2 scw }
180 1.2 scw }
181 1.2 scw
182 1.2 scw static void
183 1.10 tsutsui lpt_pcc_close(struct lpt_softc *sc)
184 1.2 scw {
185 1.3 scw
186 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL, 0);
187 1.2 scw sc->sc_icr = sc->sc_ipl;
188 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL, sc->sc_icr);
189 1.2 scw }
190 1.2 scw
191 1.3 scw /* ARGSUSED */
192 1.2 scw static void
193 1.10 tsutsui lpt_pcc_iprime(struct lpt_softc *sc)
194 1.2 scw {
195 1.3 scw
196 1.3 scw lpt_control_write(LPC_INPUT_PRIME);
197 1.2 scw delay(100);
198 1.2 scw }
199 1.2 scw
200 1.3 scw /* ARGSUSED */
201 1.2 scw static void
202 1.10 tsutsui lpt_pcc_speed(struct lpt_softc *sc, int speed)
203 1.2 scw {
204 1.3 scw
205 1.3 scw if (speed == LPT_STROBE_FAST)
206 1.3 scw lpt_control_write(LPC_FAST_STROBE);
207 1.2 scw else
208 1.3 scw lpt_control_write(0);
209 1.2 scw }
210 1.2 scw
211 1.2 scw static int
212 1.10 tsutsui lpt_pcc_notrdy(struct lpt_softc *sc, int err)
213 1.2 scw {
214 1.2 scw u_char status;
215 1.2 scw u_char new;
216 1.2 scw
217 1.2 scw #define LPS_INVERT (LPS_SELECT)
218 1.2 scw #define LPS_MASK (LPS_SELECT|LPS_FAULT|LPS_BUSY|LPS_PAPER_EMPTY)
219 1.2 scw
220 1.3 scw status = (lpt_status_read(sc) ^ LPS_INVERT) & LPS_MASK;
221 1.2 scw
222 1.3 scw if (err) {
223 1.2 scw new = status & ~sc->sc_laststatus;
224 1.2 scw sc->sc_laststatus = status;
225 1.2 scw
226 1.2 scw if (new & LPS_SELECT)
227 1.2 scw log(LOG_NOTICE, "%s: offline\n",
228 1.11 cube device_xname(sc->sc_dev));
229 1.2 scw else if (new & LPS_PAPER_EMPTY)
230 1.2 scw log(LOG_NOTICE, "%s: out of paper\n",
231 1.11 cube device_xname(sc->sc_dev));
232 1.2 scw else if (new & LPS_FAULT)
233 1.2 scw log(LOG_NOTICE, "%s: output error\n",
234 1.11 cube device_xname(sc->sc_dev));
235 1.2 scw }
236 1.2 scw
237 1.3 scw pcc_reg_write(sys_pcc, PCCREG_PRNT_INTR_CTRL,
238 1.3 scw sc->sc_icr | LPI_FAULTINT);
239 1.2 scw
240 1.10 tsutsui return status;
241 1.2 scw }
242 1.2 scw
243 1.2 scw static void
244 1.10 tsutsui lpt_pcc_wr_data(struct lpt_softc *sc, u_char data)
245 1.2 scw {
246 1.2 scw
247 1.3 scw lpt_data_write(sc, data);
248 1.2 scw }
249