lpt_pioc.c revision 1.1.4.5 1 /* $NetBSD: lpt_pioc.c,v 1.1.4.5 2002/10/18 02:33:39 nathanw Exp $ */
2
3 /*
4 * Copyright (c) 1997 Mark Brinicombe
5 * Copyright (c) 1997 Causality Limited
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the company nor the name of the author may be used to
17 * endorse or promote products derived from this software without specific
18 * prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTERS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /*
34 * Device Driver for AT parallel printer port
35 */
36
37 #include <sys/param.h>
38
39 __KERNEL_RCSID(0, "$NetBSD: lpt_pioc.c,v 1.1.4.5 2002/10/18 02:33:39 nathanw Exp $");
40
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <machine/bus.h>
45 #include <machine/intr.h>
46 #include <acorn32/mainbus/piocvar.h>
47 #include <dev/ic/lptreg.h>
48 #include <dev/ic/lptvar.h>
49
50 #include "locators.h"
51
52 /* Prototypes for functions */
53
54 static int lpt_port_test __P((bus_space_tag_t, bus_space_handle_t, bus_addr_t,
55 bus_size_t, u_char, u_char));
56 static int lptprobe __P((bus_space_tag_t, u_int));
57 static int lpt_pioc_probe __P((struct device *, struct cfdata *, void *));
58 static void lpt_pioc_attach __P((struct device *, struct device *, void *));
59
60 /* device attach structure */
61
62 CFATTACH_DECL(lpt_pioc, sizeof(struct lpt_softc),
63 lpt_pioc_probe, lpt_pioc_attach, NULL, NULL);
64
65 /*
66 * Internal routine to lptprobe to do port tests of one byte value.
67 */
68 static int
69 lpt_port_test(iot, ioh, base, off, data, mask)
70 bus_space_tag_t iot;
71 bus_space_handle_t ioh;
72 bus_addr_t base;
73 bus_size_t off;
74 u_char data, mask;
75 {
76 int timeout;
77 u_char temp;
78
79 data &= mask;
80 bus_space_write_1(iot, ioh, off, data);
81 timeout = 1000;
82 do {
83 delay(10);
84 temp = bus_space_read_1(iot, ioh, off) & mask;
85 } while (temp != data && --timeout);
86 return (temp == data);
87 }
88
89 /*
90 * Logic:
91 * 1) You should be able to write to and read back the same value
92 * to the data port. Do an alternating zeros, alternating ones,
93 * walking zero, and walking one test to check for stuck bits.
94 *
95 * 2) You should be able to write to and read back the same value
96 * to the control port lower 5 bits, the upper 3 bits are reserved
97 * per the IBM PC technical reference manauls and different boards
98 * do different things with them. Do an alternating zeros, alternating
99 * ones, walking zero, and walking one test to check for stuck bits.
100 *
101 * Some printers drag the strobe line down when the are powered off
102 * so this bit has been masked out of the control port test.
103 *
104 * XXX Some printers may not like a fast pulse on init or strobe, I
105 * don't know at this point, if that becomes a problem these bits
106 * should be turned off in the mask byte for the control port test.
107 *
108 * 3) Set the data and control ports to a value of 0
109 */
110 static int
111 lptprobe(iot, iobase)
112 bus_space_tag_t iot;
113 u_int iobase;
114 {
115 bus_space_handle_t ioh;
116 u_char mask, data;
117 int i, rv;
118 #ifdef DEBUG
119 #define ABORT do {printf("lptprobe: mask %x data %x failed\n", mask, data); \
120 goto out;} while (0)
121 #else
122 #define ABORT goto out
123 #endif
124
125 if (bus_space_map(iot, iobase, LPT_NPORTS, 0, &ioh))
126 return 0;
127 rv = 0;
128 mask = 0xff;
129
130 data = 0x55; /* Alternating zeros */
131 if (!lpt_port_test(iot, ioh, iobase, lpt_data, data, mask))
132 ABORT;
133
134 data = 0xaa; /* Alternating ones */
135 if (!lpt_port_test(iot, ioh, iobase, lpt_data, data, mask))
136 ABORT;
137
138 for (i = 0; i < CHAR_BIT; i++) { /* Walking zero */
139 data = ~(1 << i);
140 if (!lpt_port_test(iot, ioh, iobase, lpt_data, data, mask))
141 ABORT;
142 }
143
144 for (i = 0; i < CHAR_BIT; i++) { /* Walking one */
145 data = (1 << i);
146 if (!lpt_port_test(iot, ioh, iobase, lpt_data, data, mask))
147 ABORT;
148 }
149
150 bus_space_write_1(iot, ioh, lpt_data, 0);
151 bus_space_write_1(iot, ioh, lpt_control, 0);
152
153 rv = LPT_NPORTS;
154
155 out:
156 bus_space_unmap(iot, ioh, LPT_NPORTS);
157 return rv;
158 }
159
160 /*
161 * int lpt_pioc_probe(struct device *parent, struct cfdata *cf, void *aux)
162 *
163 * Make sure we are trying to attach a lpt device and then
164 * probe for one.
165 */
166
167 static int
168 lpt_pioc_probe(parent, match, aux)
169 struct device *parent;
170 struct cfdata *match;
171 void *aux;
172 {
173 struct pioc_attach_args *pa = aux;
174 int rv;
175
176 if (pa->pa_name && strcmp(pa->pa_name, "lpt") != 0)
177 return(0);
178
179 /* We need an offset */
180 if (pa->pa_offset == PIOCCF_OFFSET_DEFAULT)
181 return(0);
182
183 rv = lptprobe(pa->pa_iot, pa->pa_iobase + pa->pa_offset);
184
185 if (rv) {
186 pa->pa_iosize = rv;
187 return(1);
188 }
189 return(0);
190 }
191
192 /*
193 * void lpt_pioc_attach(struct device *parent, struct device *self, void *aux)
194 *
195 * attach the lpt device
196 */
197
198 static void
199 lpt_pioc_attach(parent, self, aux)
200 struct device *parent, *self;
201 void *aux;
202 {
203 struct lpt_softc *sc = (void *)self;
204 struct pioc_attach_args *pa = aux;
205 bus_space_tag_t iot;
206 bus_space_handle_t ioh;
207 u_int iobase;
208
209 if (pa->pa_irq != MAINBUSCF_IRQ_DEFAULT)
210 printf("\n");
211 else
212 printf(": polled\n");
213
214 iobase = pa->pa_iobase + pa->pa_offset;
215
216 iot = sc->sc_iot = pa->pa_iot;
217 if (bus_space_map(iot, iobase, LPT_NPORTS, 0, &ioh))
218 panic("lptattach: couldn't map I/O ports");
219 sc->sc_ioh = ioh;
220
221 lpt_attach_subr(sc);
222
223 if (pa->pa_irq != MAINBUSCF_IRQ_DEFAULT)
224 sc->sc_ih = intr_claim(pa->pa_irq, IPL_TTY, "lpt",
225 lptintr, sc);
226 }
227
228 /* End of lpt_pioc.c */
229