This source file includes following definitions.
- lpt_port_test
- lpt_attach_common
- lptopen
- lpt_not_ready
- lptwakeup
- lptclose
- lptpushbytes
- lptwrite
- lptintr
- lptioctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/proc.h>
60 #include <sys/user.h>
61 #include <sys/buf.h>
62 #include <sys/kernel.h>
63 #include <sys/ioctl.h>
64 #include <sys/uio.h>
65 #include <sys/device.h>
66 #include <sys/conf.h>
67 #include <sys/syslog.h>
68
69 #include <machine/bus.h>
70 #include <machine/intr.h>
71
72 #include <dev/ic/lptreg.h>
73 #include <dev/ic/lptvar.h>
74
75 #include "lpt.h"
76
77 #define TIMEOUT hz*16
78 #define STEP hz/4
79
80 #define LPTPRI (PZERO+8)
81 #define LPT_BSIZE 1024
82
83 #if !defined(DEBUG) || !defined(notdef)
84 #define LPRINTF(a)
85 #else
86 #define LPRINTF(a) if (lptdebug) printf a
87 int lptdebug = 1;
88 #endif
89
90
91 cdev_decl(lpt);
92
93 struct cfdriver lpt_cd = {
94 NULL, "lpt", DV_TTY
95 };
96
97 #define LPTUNIT(s) (minor(s) & 0x1f)
98 #define LPTFLAGS(s) (minor(s) & 0xe0)
99
100 #define LPS_INVERT (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK)
101 #define LPS_MASK (LPS_SELECT|LPS_NERR|LPS_NBSY|LPS_NACK|LPS_NOPAPER)
102 #define NOT_READY() \
103 ((bus_space_read_1(iot, ioh, lpt_status) ^ LPS_INVERT) & LPS_MASK)
104 #define NOT_READY_ERR() \
105 lpt_not_ready(bus_space_read_1(iot, ioh, lpt_status), sc)
106
107 int lpt_not_ready(u_int8_t, struct lpt_softc *);
108 void lptwakeup(void *arg);
109 int lptpushbytes(struct lpt_softc *);
110
111
112
113
114 int
115 lpt_port_test(iot, ioh, base, off, data, mask)
116 bus_space_tag_t iot;
117 bus_space_handle_t ioh;
118 bus_addr_t base;
119 bus_size_t off;
120 u_int8_t data, mask;
121 {
122 int timeout;
123 u_int8_t temp;
124
125 data &= mask;
126 bus_space_write_1(iot, ioh, off, data);
127 timeout = 1000;
128 do {
129 delay(10);
130 temp = bus_space_read_1(iot, ioh, off) & mask;
131 } while (temp != data && --timeout);
132 LPRINTF(("lpt: port=0x%x out=0x%x in=0x%x timeout=%d\n", base + off,
133 data, temp, timeout));
134 return (temp == data);
135 }
136
137 void
138 lpt_attach_common(sc)
139 struct lpt_softc *sc;
140 {
141 printf("\n");
142
143 bus_space_write_1(sc->sc_iot, sc->sc_ioh, lpt_control, LPC_NINIT);
144
145 timeout_set(&sc->sc_wakeup_tmo, lptwakeup, sc);
146 }
147
148
149
150
151 int
152 lptopen(dev, flag, mode, p)
153 dev_t dev;
154 int flag;
155 int mode;
156 struct proc *p;
157 {
158 int unit = LPTUNIT(dev);
159 u_int8_t flags = LPTFLAGS(dev);
160 struct lpt_softc *sc;
161 bus_space_tag_t iot;
162 bus_space_handle_t ioh;
163 u_int8_t control;
164 int error;
165 int spin;
166
167 if (unit >= lpt_cd.cd_ndevs)
168 return ENXIO;
169 sc = lpt_cd.cd_devs[unit];
170 if (!sc)
171 return ENXIO;
172
173 sc->sc_flags = (sc->sc_flags & LPT_POLLED) | flags;
174 if ((sc->sc_flags & (LPT_POLLED|LPT_NOINTR)) == LPT_POLLED)
175 return ENXIO;
176
177 #ifdef DIAGNOSTIC
178 if (sc->sc_state)
179 printf("%s: stat=0x%x not zero\n", sc->sc_dev.dv_xname,
180 sc->sc_state);
181 #endif
182
183 if (sc->sc_state)
184 return EBUSY;
185
186 sc->sc_state = LPT_INIT;
187 LPRINTF(("%s: open: flags=0x%x\n", sc->sc_dev.dv_xname, flags));
188 iot = sc->sc_iot;
189 ioh = sc->sc_ioh;
190
191 if ((flags & LPT_NOPRIME) == 0) {
192
193 bus_space_write_1(iot, ioh, lpt_control, LPC_SELECT);
194 delay(100);
195 }
196
197 control = LPC_SELECT | LPC_NINIT;
198 bus_space_write_1(iot, ioh, lpt_control, control);
199
200
201 for (spin = 0; NOT_READY_ERR(); spin += STEP) {
202 if (spin >= TIMEOUT) {
203 sc->sc_state = 0;
204 return EBUSY;
205 }
206
207
208 error = tsleep((caddr_t)sc, LPTPRI | PCATCH, "lptopen", STEP);
209 if (error != EWOULDBLOCK) {
210 sc->sc_state = 0;
211 return error;
212 }
213 }
214
215 if ((flags & LPT_NOINTR) == 0)
216 control |= LPC_IENABLE;
217 if (flags & LPT_AUTOLF)
218 control |= LPC_AUTOLF;
219 sc->sc_control = control;
220 bus_space_write_1(iot, ioh, lpt_control, control);
221
222 sc->sc_inbuf = geteblk(LPT_BSIZE);
223 sc->sc_count = 0;
224 sc->sc_state = LPT_OPEN;
225
226 if ((sc->sc_flags & LPT_NOINTR) == 0)
227 lptwakeup(sc);
228
229 LPRINTF(("%s: opened\n", sc->sc_dev.dv_xname));
230 return 0;
231 }
232
233 int
234 lpt_not_ready(status, sc)
235 u_int8_t status;
236 struct lpt_softc *sc;
237 {
238 u_int8_t new;
239
240 status = (status ^ LPS_INVERT) & LPS_MASK;
241 new = status & ~sc->sc_laststatus;
242 sc->sc_laststatus = status;
243
244 if (new & LPS_SELECT)
245 log(LOG_NOTICE, "%s: offline\n", sc->sc_dev.dv_xname);
246 else if (new & LPS_NOPAPER)
247 log(LOG_NOTICE, "%s: out of paper\n", sc->sc_dev.dv_xname);
248 else if (new & LPS_NERR)
249 log(LOG_NOTICE, "%s: output error\n", sc->sc_dev.dv_xname);
250
251 return status;
252 }
253
254 void
255 lptwakeup(arg)
256 void *arg;
257 {
258 struct lpt_softc *sc = arg;
259 int s;
260
261 s = spltty();
262 lptintr(sc);
263 splx(s);
264
265 timeout_add(&sc->sc_wakeup_tmo, STEP);
266 }
267
268
269
270
271 int
272 lptclose(dev, flag, mode, p)
273 dev_t dev;
274 int flag;
275 int mode;
276 struct proc *p;
277 {
278 int unit = LPTUNIT(dev);
279 struct lpt_softc *sc = lpt_cd.cd_devs[unit];
280 bus_space_tag_t iot = sc->sc_iot;
281 bus_space_handle_t ioh = sc->sc_ioh;
282
283 if (sc->sc_count)
284 (void) lptpushbytes(sc);
285
286 if ((sc->sc_flags & LPT_NOINTR) == 0)
287 timeout_del(&sc->sc_wakeup_tmo);
288
289 bus_space_write_1(iot, ioh, lpt_control, LPC_NINIT);
290 sc->sc_state = 0;
291 bus_space_write_1(iot, ioh, lpt_control, LPC_NINIT);
292 brelse(sc->sc_inbuf);
293
294 LPRINTF(("%s: closed\n", sc->sc_dev.dv_xname));
295 return 0;
296 }
297
298 int
299 lptpushbytes(sc)
300 struct lpt_softc *sc;
301 {
302 bus_space_tag_t iot = sc->sc_iot;
303 bus_space_handle_t ioh = sc->sc_ioh;
304 int error;
305
306 if (sc->sc_flags & LPT_NOINTR) {
307 int spin, tic;
308 u_int8_t control = sc->sc_control;
309
310 while (sc->sc_count > 0) {
311 spin = 0;
312 while (NOT_READY()) {
313 if (++spin < sc->sc_spinmax)
314 continue;
315 tic = 0;
316
317 sc->sc_spinmax++;
318 while (NOT_READY_ERR()) {
319
320 tic = tic + tic + 1;
321 if (tic > TIMEOUT)
322 tic = TIMEOUT;
323 error = tsleep((caddr_t)sc,
324 LPTPRI | PCATCH, "lptpsh", tic);
325 if (error != EWOULDBLOCK)
326 return error;
327 }
328 break;
329 }
330
331 bus_space_write_1(iot, ioh, lpt_data, *sc->sc_cp++);
332 bus_space_write_1(iot, ioh, lpt_control,
333 control | LPC_STROBE);
334 sc->sc_count--;
335 bus_space_write_1(iot, ioh, lpt_control, control);
336
337
338 if (spin*2 + 16 < sc->sc_spinmax)
339 sc->sc_spinmax--;
340 }
341 } else {
342 int s;
343
344 while (sc->sc_count > 0) {
345
346 if ((sc->sc_state & LPT_OBUSY) == 0) {
347 LPRINTF(("%s: write %d\n", sc->sc_dev.dv_xname,
348 sc->sc_count));
349 s = spltty();
350 (void) lptintr(sc);
351 splx(s);
352 }
353 error = tsleep((caddr_t)sc, LPTPRI | PCATCH,
354 "lptwrite2", 0);
355 if (error)
356 return error;
357 }
358 }
359 return 0;
360 }
361
362
363
364
365
366 int
367 lptwrite(dev, uio, flags)
368 dev_t dev;
369 struct uio *uio;
370 int flags;
371 {
372 struct lpt_softc *sc = lpt_cd.cd_devs[LPTUNIT(dev)];
373 size_t n;
374 int error = 0;
375
376 while ((n = min(LPT_BSIZE, uio->uio_resid)) != 0) {
377 uiomove(sc->sc_cp = sc->sc_inbuf->b_data, n, uio);
378 sc->sc_count = n;
379 error = lptpushbytes(sc);
380 if (error) {
381
382
383
384
385 uio->uio_resid += sc->sc_count;
386 sc->sc_count = 0;
387 return error;
388 }
389 }
390 return 0;
391 }
392
393
394
395
396
397 int
398 lptintr(arg)
399 void *arg;
400 {
401 struct lpt_softc *sc = arg;
402 bus_space_tag_t iot = sc->sc_iot;
403 bus_space_handle_t ioh = sc->sc_ioh;
404
405 if (((sc->sc_state & LPT_OPEN) == 0 && sc->sc_count == 0) ||
406 (sc->sc_flags & LPT_NOINTR))
407 return 0;
408
409
410 if (NOT_READY() && NOT_READY_ERR())
411 return -1;
412
413 if (sc->sc_count) {
414 u_int8_t control = sc->sc_control;
415
416 bus_space_write_1(iot, ioh, lpt_data, *sc->sc_cp++);
417 delay (50);
418 bus_space_write_1(iot, ioh, lpt_control, control | LPC_STROBE);
419 sc->sc_count--;
420 bus_space_write_1(iot, ioh, lpt_control, control);
421 sc->sc_state |= LPT_OBUSY;
422 } else
423 sc->sc_state &= ~LPT_OBUSY;
424
425 if (sc->sc_count == 0) {
426
427 wakeup((caddr_t)sc);
428 }
429
430 return 1;
431 }
432
433 int
434 lptioctl(dev, cmd, data, flag, p)
435 dev_t dev;
436 u_long cmd;
437 caddr_t data;
438 int flag;
439 struct proc *p;
440 {
441 int error = 0;
442
443 switch (cmd) {
444 default:
445 error = ENODEV;
446 }
447
448 return error;
449 }