Annotation of sys/arch/vax/qbus/dl.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: dl.c,v 1.5 2003/10/03 16:44:50 miod Exp $ */
2: /* $NetBSD: dl.c,v 1.11 2000/01/24 02:40:29 matt Exp $ */
3:
4: /*-
5: * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
6: * All rights reserved.
7: *
8: * This code is derived from software contributed to The NetBSD Foundation
9: * by Jason R. Thorpe.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: * 3. All advertising materials mentioning features or use of this software
20: * must display the following acknowledgement:
21: * This product includes software developed by the NetBSD
22: * Foundation, Inc. and its contributors.
23: * 4. Neither the name of The NetBSD Foundation nor the names of its
24: * contributors may be used to endorse or promote products derived
25: * from this software without specific prior written permission.
26: *
27: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37: * POSSIBILITY OF SUCH DAMAGE.
38: */
39:
40: /*
41: * Copyright (c) 1997 Ben Harris. All rights reserved.
42: * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
43: * Copyright (c) 1982, 1986, 1990, 1992, 1993
44: * The Regents of the University of California. All rights reserved.
45: *
46: * This code is derived from software contributed to Berkeley by
47: * Ralph Campbell and Rick Macklem.
48: *
49: * Redistribution and use in source and binary forms, with or without
50: * modification, are permitted provided that the following conditions
51: * are met:
52: * 1. Redistributions of source code must retain the above copyright
53: * notice, this list of conditions and the following disclaimer.
54: * 2. Redistributions in binary form must reproduce the above copyright
55: * notice, this list of conditions and the following disclaimer in the
56: * documentation and/or other materials provided with the distribution.
57: * 3. Neither the name of the University nor the names of its contributors
58: * may be used to endorse or promote products derived from this software
59: * without specific prior written permission.
60: *
61: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71: * SUCH DAMAGE.
72: */
73:
74: /*
75: * dl.c -- Device driver for the DL11 and DLV11 serial cards.
76: *
77: * OS-interface code derived from the dz and dca (hp300) drivers.
78: */
79:
80: #include <sys/param.h>
81: #include <sys/systm.h>
82: #include <sys/ioctl.h>
83: #include <sys/tty.h>
84: #include <sys/proc.h>
85: #include <sys/buf.h>
86: #include <sys/conf.h>
87: #include <sys/file.h>
88: #include <sys/uio.h>
89: #include <sys/kernel.h>
90: #include <sys/syslog.h>
91: #include <sys/device.h>
92:
93: #include <machine/bus.h>
94: #include <machine/scb.h>
95:
96: #include <arch/vax/qbus/ubavar.h>
97: #include <arch/vax/qbus/dlreg.h>
98:
99: struct dl_softc {
100: struct device sc_dev;
101: bus_space_tag_t sc_iot;
102: bus_space_handle_t sc_ioh;
103: struct tty *sc_tty;
104: };
105:
106: static int dl_match(struct device *, struct cfdata *, void *);
107: static void dl_attach(struct device *, struct device *, void *);
108: static void dlrint(void *);
109: static void dlxint(void *);
110: static void dlstart(struct tty *);
111: static int dlparam(struct tty *, struct termios *);
112: static void dlbrk(struct dl_softc *, int);
113: struct tty * dltty(dev_t);
114: int dlopen(dev_t, int, int, struct proc *);
115: int dlclose(dev_t, int, int, struct proc *);
116: int dlread(dev_t, struct uio *, int);
117: int dlwrite(dev_t, struct uio *, int);
118: int dlioctl(dev_t, int, caddr_t, int, struct proc *);
119: void dlstop(struct tty *, int);
120:
121: struct cfattach dl_ca = {
122: sizeof(struct dl_softc), (cfmatch_t)dl_match, dl_attach
123: };
124:
125: struct cfdriver dl_cd = {
126: NULL, "dl", DV_TTY
127: };
128:
129: #define DL_READ_WORD(reg) \
130: bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
131: #define DL_WRITE_WORD(reg, val) \
132: bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
133: #define DL_WRITE_BYTE(reg, val) \
134: bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
135:
136: /* Autoconfig handles: setup the controller to interrupt, */
137: /* then complete the housecleaning for full operation */
138:
139: static int
140: dl_match (parent, cf, aux)
141: struct device * parent;
142: struct cfdata *cf;
143: void *aux;
144: {
145: struct uba_attach_args *ua = aux;
146:
147: #ifdef DL_DEBUG
148: printf("Probing for dl at %lo ... ", (long)ua->ua_iaddr);
149: #endif
150:
151: bus_space_write_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR, DL_XCSR_TXIE);
152: if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
153: (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
154: #ifdef DL_DEBUG
155: printf("failed (step 1; XCSR = %.4b)\n",
156: bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
157: DL_XCSR_BITS);
158: #endif
159: return 0;
160: }
161:
162: /*
163: * We have to force an interrupt so the uba driver can work
164: * out where we are. Unfortunately, the only way to make a
165: * DL11 interrupt is to get it to send or receive a
166: * character. We'll send a NUL and hope it doesn't hurt
167: * anything.
168: */
169:
170: bus_space_write_1(ua->ua_iot, ua->ua_ioh, DL_UBA_XBUFL, '\0');
171: #if 0 /* This test seems to fail 2/3 of the time :-( */
172: if (dladdr->dl_xcsr != (DL_XCSR_TXIE)) {
173: #ifdef DL_DEBUG
174: printf("failed (step 2; XCSR = %.4b)\n", dladdr->dl_xcsr,
175: DL_XCSR_BITS);
176: #endif
177: return 0;
178: }
179: #endif
180: DELAY(100000); /* delay 1/10 s for character to transmit */
181: if (bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR) !=
182: (DL_XCSR_TXIE | DL_XCSR_TX_READY)) {
183: #ifdef DL_DEBUG
184: printf("failed (step 3; XCSR = %.4b)\n",
185: bus_space_read_2(ua->ua_iot, ua->ua_ioh, DL_UBA_XCSR),
186: DL_XCSR_BITS);
187: #endif
188: return 0;
189: }
190:
191:
192: /* What else do I need to do? */
193:
194: return 1;
195:
196: }
197:
198: static void
199: dl_attach (parent, self, aux)
200: struct device *parent, *self;
201: void *aux;
202: {
203: struct dl_softc *sc = (void *)self;
204: register struct uba_attach_args *ua = aux;
205:
206: sc->sc_iot = ua->ua_iot;
207: sc->sc_ioh = ua->ua_ioh;
208:
209: /* Tidy up the device */
210:
211: DL_WRITE_WORD(DL_UBA_RCSR, DL_RCSR_RXIE);
212: DL_WRITE_WORD(DL_UBA_XCSR, DL_XCSR_TXIE);
213:
214: /* Initialize our softc structure. Should be done in open? */
215:
216: sc->sc_tty = ttymalloc();
217:
218: /* Now register the TX & RX interrupt handlers */
219: uba_intr_establish(ua->ua_icookie, ua->ua_cvec , dlxint, sc);
220: uba_intr_establish(ua->ua_icookie, ua->ua_cvec - 4, dlrint, sc);
221:
222: printf("\n");
223: }
224:
225: /* Receiver Interrupt Handler */
226:
227: static void
228: dlrint(arg)
229: void *arg;
230: {
231: struct dl_softc *sc = arg;
232: register struct tty *tp;
233: register int cc;
234: register unsigned c;
235:
236: if (DL_READ_WORD(DL_UBA_RCSR) & DL_RCSR_RX_DONE) {
237: c = DL_READ_WORD(DL_UBA_RBUF);
238: cc = c & 0xFF;
239: tp = sc->sc_tty;
240:
241: if (!(tp->t_state & TS_ISOPEN)) {
242: wakeup((caddr_t)&tp->t_rawq);
243: return;
244: }
245:
246: if (c & DL_RBUF_OVERRUN_ERR)
247: /*
248: * XXX: This should really be logged somwhere
249: * else where we can afford the time.
250: */
251: log(LOG_WARNING, "%s: rx overrun\n",
252: sc->sc_dev.dv_xname);
253: if (c & DL_RBUF_FRAMING_ERR)
254: cc |= TTY_FE;
255: if (c & DL_RBUF_PARITY_ERR)
256: cc |= TTY_PE;
257:
258: (*linesw[tp->t_line].l_rint)(cc, tp);
259: } else
260: log(LOG_WARNING, "%s: stray rx interrupt\n",
261: sc->sc_dev.dv_xname);
262: return;
263: }
264:
265: /* Transmitter Interrupt Handler */
266:
267: static void
268: dlxint(arg)
269: void *arg;
270: {
271: struct dl_softc *sc = arg;
272: register struct tty *tp;
273:
274: tp = sc->sc_tty;
275: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
276: if (tp->t_line)
277: (*linesw[tp->t_line].l_start)(tp);
278: else
279: dlstart(tp);
280:
281: return;
282: }
283:
284: int
285: dlopen(dev, flag, mode, p)
286: dev_t dev;
287: int flag, mode;
288: struct proc *p;
289: {
290: register struct tty *tp;
291: register int unit;
292: struct dl_softc *sc;
293:
294: unit = minor(dev);
295:
296: if (unit >= dl_cd.cd_ndevs || dl_cd.cd_devs[unit] == NULL)
297: return ENXIO;
298: sc = dl_cd.cd_devs[unit];
299:
300: tp = sc->sc_tty;
301: if (tp == NULL)
302: return ENODEV;
303: tp->t_oproc = dlstart;
304: tp->t_param = dlparam;
305: tp->t_dev = dev;
306:
307: if (!(tp->t_state & TS_ISOPEN)) {
308: ttychars(tp);
309: tp->t_iflag = TTYDEF_IFLAG;
310: tp->t_oflag = TTYDEF_OFLAG;
311: /* No modem control, so set CLOCAL. */
312: tp->t_cflag = TTYDEF_CFLAG | CLOCAL;
313: tp->t_lflag = TTYDEF_LFLAG;
314: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
315:
316: dlparam(tp, &tp->t_termios);
317: ttsetwater(tp);
318:
319: } else if ((tp->t_state & TS_XCLUDE) && p->p_ucred->cr_uid != 0)
320: return EBUSY;
321:
322: return ((*linesw[tp->t_line].l_open)(dev, tp));
323: }
324:
325: /*ARGSUSED*/
326: int
327: dlclose(dev, flag, mode, p)
328: dev_t dev;
329: int flag, mode;
330: struct proc *p;
331: {
332: struct dl_softc *sc;
333: register struct tty *tp;
334: register int unit;
335:
336: unit = minor(dev);
337: sc = dl_cd.cd_devs[unit];
338: tp = sc->sc_tty;
339:
340: (*linesw[tp->t_line].l_close)(tp, flag);
341:
342: /* Make sure a BREAK state is not left enabled. */
343: dlbrk(sc, 0);
344:
345: return (ttyclose(tp));
346: }
347:
348: int
349: dlread(dev, uio, flag)
350: dev_t dev;
351: struct uio *uio;
352: int flag;
353: {
354: register struct tty *tp;
355: struct dl_softc *sc;
356: register int unit;
357:
358: unit = minor(dev);
359: sc = dl_cd.cd_devs[unit];
360: tp = sc->sc_tty;
361: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
362: }
363:
364: int
365: dlwrite(dev, uio, flag)
366: dev_t dev;
367: struct uio *uio;
368: int flag;
369: {
370: register struct tty *tp;
371: struct dl_softc *sc;
372: register int unit;
373:
374: unit = minor(dev);
375: sc = dl_cd.cd_devs[unit];
376: tp = sc->sc_tty;
377: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
378: }
379:
380: int
381: dlioctl(dev, cmd, data, flag, p)
382: dev_t dev;
383: int cmd;
384: caddr_t data;
385: int flag;
386: struct proc *p;
387: {
388: struct dl_softc *sc;
389: register struct tty *tp;
390: register int unit;
391: int error;
392:
393: unit = minor(dev);
394: sc = dl_cd.cd_devs[unit];
395: tp = sc->sc_tty;
396:
397: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
398: if (error >= 0)
399: return (error);
400: error = ttioctl(tp, cmd, data, flag, p);
401: if (error >= 0)
402: return (error);
403:
404: switch (cmd) {
405:
406: case TIOCSBRK:
407: dlbrk(sc, 1);
408: break;
409:
410: case TIOCCBRK:
411: dlbrk(sc, 0);
412: break;
413:
414: case TIOCMGET:
415: /* No modem control, assume they're all low. */
416: *(int *)data = 0;
417: break;
418:
419: default:
420: return (ENOTTY);
421: }
422: return (0);
423: }
424:
425: struct tty *
426: dltty(dev)
427: dev_t dev;
428: {
429: register struct dl_softc* sc;
430:
431: sc = dl_cd.cd_devs[minor(dev)];
432: return sc->sc_tty;
433: }
434:
435: void
436: dlstop(tp, flag)
437: register struct tty *tp;
438: int flag;
439: {
440: register struct dl_softc *sc;
441: int unit, s;
442:
443: unit = minor(tp->t_dev);
444: sc = dl_cd.cd_devs[unit];
445:
446: s = spltty();
447:
448: if (tp->t_state & TS_BUSY)
449: if (!(tp->t_state & TS_TTSTOP))
450: tp->t_state |= TS_FLUSH;
451: splx(s);
452: }
453:
454: static void
455: dlstart(tp)
456: register struct tty *tp;
457: {
458: register struct dl_softc *sc;
459: register int unit;
460: int s;
461:
462: unit = minor(tp->t_dev);
463: sc = dl_cd.cd_devs[unit];
464:
465: s = spltty();
466: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
467: goto out;
468: if (tp->t_outq.c_cc <= tp->t_lowat) {
469: if (tp->t_state & TS_ASLEEP) {
470: tp->t_state &= ~TS_ASLEEP;
471: wakeup((caddr_t)&tp->t_outq);
472: }
473: selwakeup(&tp->t_wsel);
474: }
475: if (tp->t_outq.c_cc == 0)
476: goto out;
477:
478:
479: if (DL_READ_WORD(DL_UBA_XCSR) & DL_XCSR_TX_READY) {
480: tp->t_state |= TS_BUSY;
481: DL_WRITE_BYTE(DL_UBA_XBUFL, getc(&tp->t_outq));
482: }
483: out:
484: splx(s);
485: return;
486: }
487:
488: /*ARGSUSED*/
489: static int
490: dlparam(tp, t)
491: register struct tty *tp;
492: register struct termios *t;
493: {
494: /*
495: * All this kind of stuff (speed, character format, whatever)
496: * is set by jumpers on the card. Changing it is thus rather
497: * tricky for a mere device driver.
498: */
499: return 0;
500: }
501:
502: static void
503: dlbrk(sc, state)
504: register struct dl_softc *sc;
505: int state;
506: {
507: int s = spltty();
508:
509: if (state) {
510: DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) |
511: DL_XCSR_TX_BREAK);
512: } else {
513: DL_WRITE_WORD(DL_UBA_XCSR, DL_READ_WORD(DL_UBA_XCSR) &
514: ~DL_XCSR_TX_BREAK);
515: }
516: splx(s);
517: }
CVSweb