Annotation of sys/arch/mvme68k/dev/zs.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: zs.c,v 1.25 2006/06/11 20:46:50 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2000 Steve Murphree, Jr.
5: * Copyright (c) 1995 Theo de Raadt
6: * Copyright (c) 1993 Paul Mackerras.
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28: */
29: /*
30: * Serial I/O via an SCC,
31: */
32: #include <sys/param.h>
33: #include <sys/ioctl.h>
34: #include <sys/proc.h>
35: #include <sys/user.h>
36: #include <sys/tty.h>
37: #include <sys/uio.h>
38: #include <sys/systm.h>
39: #include <sys/kernel.h>
40: #include <sys/syslog.h>
41: #include <sys/fcntl.h>
42: #include <sys/device.h>
43:
44: #include <machine/autoconf.h>
45: #include <machine/conf.h>
46: #include <machine/cpu.h>
47:
48: #ifdef DDB
49: #include <ddb/db_var.h>
50: #endif
51:
52: #include <dev/cons.h>
53:
54: #include <mvme68k/dev/scc.h>
55:
56: #include "pcc.h"
57: #include "mc.h"
58:
59: #if NPCC > 0
60: #include <mvme68k/dev/pccreg.h>
61: #endif
62: #if NMC > 0
63: #include <mvme68k/dev/mcreg.h>
64: #endif
65:
66: #include "zs.h"
67:
68: #define NZSLINE (NZS*2)
69:
70: #define RECV_BUF 512
71: #define ERROR_DET 0xed
72:
73: #define TS_DRAIN TS_FLUSH /* waiting for output to drain */
74:
75: #define splzs() _splraise(PSL_S | PSL_IPL4)
76:
77: struct zs {
78: short flags; /* see below */
79: char rr0; /* holds previous CTS, DCD state */
80: u_char imask; /* mask for input chars */
81: int nzs_open; /* # opens as /dev/zsn */
82: struct tty *tty; /* link to tty structure */
83: struct sccregs scc; /* SCC shadow registers */
84: u_char *rcv_get;
85: u_char *rcv_put;
86: u_char *rcv_end;
87: volatile int rcv_count;
88: int rcv_len;
89: char *send_ptr;
90: int send_count;
91: int sent_count;
92: volatile char modem_state;
93: volatile char modem_change;
94: volatile short hflags;
95: char rcv_buf[RECV_BUF];
96: };
97:
98: /* Bits in flags */
99: #define ZS_SIDEA 1
100: #define ZS_INITED 2
101: #define ZS_INTEN 4
102: #define ZS_RESET 8
103: #define ZS_CONSOLE 0x20
104:
105: /* Bits in hflags */
106: #define ZH_OBLOCK 1 /* output blocked by CTS */
107: #define ZH_SIRQ 2 /* soft interrupt request */
108: #define ZH_TXING 4 /* transmitter active */
109: #define ZH_RXOVF 8 /* receiver buffer overflow */
110:
111: struct zssoftc {
112: struct device sc_dev;
113: struct zs sc_zs[2];
114: struct intrhand sc_ih;
115: int sc_flags;
116: };
117: #define ZSSF_85230 1
118:
119: struct tty *zs_tty[NZSLINE];
120:
121: struct termios zs_cons_termios;
122: int zs_cons_unit = 0;
123: int zs_is_console = 0;
124: struct sccregs *zs_cons_scc;
125:
126: void zsstart(struct tty *);
127: int zsparam(struct tty *, struct termios *);
128: int zsirq(void *);
129: int zsregs(vaddr_t, int, volatile u_char **, volatile u_char **);
130: int zspclk(void);
131:
132: u_int8_t sir_zs;
133: void zs_softint(void *);
134:
135: #define zsunit(dev) (minor(dev) >> 1)
136: #define zsside(dev) (minor(dev) & 1)
137:
138: /*
139: * Autoconfiguration stuff.
140: */
141: void zsattach(struct device *, struct device *, void *);
142: int zsmatch(struct device *, void *, void *);
143:
144: struct cfattach zs_ca = {
145: sizeof(struct zssoftc), zsmatch, zsattach
146: };
147:
148: struct cfdriver zs_cd = {
149: NULL, "zs", DV_TTY
150: };
151:
152: void zs_ttydef(struct zs *);
153: struct tty *zstty(dev_t);
154: void zs_init(struct zs *);
155: void zscc_init(struct zs *, struct termios *);
156: int zscc_params(struct sccregs *, struct termios *);
157: int zscc_mget(struct sccregs *);
158: void zscc_mset(struct sccregs *, int);
159: void zscc_mclr(struct sccregs *, int);
160: void zs_drain(struct zs *);
161: void zs_unblock(struct tty *);
162: void zs_txint(struct zs *);
163: void zs_rxint(struct zs *);
164: void zs_extint(struct zs *);
165: cons_decl(zs);
166:
167: int
168: zsmatch(parent, vcf, args)
169: struct device *parent;
170: void *vcf, *args;
171: {
172: struct confargs *ca = args;
173: unsigned char *zstest = (unsigned char *)ca->ca_vaddr;
174: /*
175: * If zs1 is in the config, we must test to see if it really exists.
176: * Some 162s only have one scc device, but the memory location for
177: * the second scc still checks valid and every byte contains 0xFF. So
178: * this is what we test with for now. XXX - smurph
179: */
180: if (!badvaddr((vaddr_t)ca->ca_vaddr, 1))
181: if (*zstest == 0xFF)
182: return (0);
183: else
184: return (1);
185: else
186: return (0);
187: }
188:
189: void
190: zsattach(parent, self, args)
191: struct device *parent, *self;
192: void *args;
193: {
194: struct zssoftc *sc;
195: struct zs *zp, *zc;
196: u_char ir;
197: volatile struct scc *scc;
198: volatile u_char *scc_cr, *scc_dr;
199: struct confargs *ca = args;
200: int zs_level = ca->ca_ipl;
201: int size;
202: static int initirq = 0;
203:
204: sc = (struct zssoftc *) self;
205:
206: /* connect the interrupt */
207: sc->sc_ih.ih_fn = zsirq;
208: sc->sc_ih.ih_arg = (void *)self->dv_unit;
209: sc->sc_ih.ih_ipl = zs_level;
210: sc->sc_ih.ih_wantframe = 0;
211:
212: switch (ca->ca_bustype) {
213: #if NPCC > 0
214: case BUS_PCC:
215: pccintr_establish(PCCV_ZS, &sc->sc_ih, self->dv_xname);
216: break;
217: #endif
218: #if NMC > 0
219: case BUS_MC:
220: if (sys_mc->mc_chiprev == 0x01)
221: /*
222: * MC rev 0x01 has a bug and can not access scc regs directly.
223: * Macros will do the right thing based on the value of
224: * mc_rev1_bug - XXX smurph
225: */
226: mc_rev1_bug = 1; /* defined in scc.h */
227: mcintr_establish(MCV_ZS, &sc->sc_ih, self->dv_xname);
228: break;
229: #endif
230: }
231:
232: zp = &sc->sc_zs[0];
233: scc = (volatile struct scc *)ca->ca_vaddr;
234:
235: /*
236: * the locations of the control and data register move around
237: * on different MVME models, so we generate independent pointers
238: * to them.
239: */
240: size = zsregs(ca->ca_vaddr, 0, &scc_cr, &scc_dr);
241:
242: if (zs_is_console && self->dv_unit == zs_cons_unit) {
243: /* SCC is the console - it's already reset */
244: zc = zp + zsside(zs_cons_unit);
245: zc->scc = *zs_cons_scc;
246: zs_cons_scc = &zc->scc;
247: zc->flags |= ZS_CONSOLE;
248: } else {
249: /* reset the SCC */
250: *(scc_cr + size) = 0;
251: *(scc_cr + size) = 9;
252: *(scc_cr + size) = 0xC0; /* hardware reset of SCC, both sides */
253: }
254:
255: /* side A */
256: zp->scc.s_cr = scc_cr + size;
257: zp->scc.s_dr = scc_dr + size;
258: zp->flags |= ZS_SIDEA | ZS_RESET;
259:
260: /* side B */
261: ++zp;
262: zp->scc.s_cr = scc_cr;
263: zp->scc.s_dr = scc_dr;
264: zp->flags |= ZS_RESET;
265:
266: if (sir_zs == 0)
267: sir_zs = allocate_sir(zs_softint, 0);
268:
269: printf("\n");
270:
271: /*
272: * XXX we end up doing this twice... once for
273: * each ZS chip. We should really not turn interrupts on until
274: * we have initialized the last of the two chips. But then we
275: * will need to search the config system to see if we will be
276: * called for the 2nd chip... otherwise, a config without a zs1
277: * would never enable interrupts!
278: */
279: switch (ca->ca_bustype) {
280: #if NPCC > 0
281: case BUS_PCC:
282: ir = sys_pcc->pcc_zsirq;
283: if ((ir & PCC_IRQ_IPL) != 0 && (ir & PCC_IRQ_IPL) != zs_level)
284: panic("zs configured at different IPLs");
285: if (initirq)
286: break;
287: sys_pcc->pcc_zsirq = zs_level | PCC_IRQ_IEN | PCC_ZS_PCCVEC;
288: break;
289: #endif
290: #if NMC > 0
291: case BUS_MC:
292: ir = sys_mc->mc_zsirq;
293: if ((ir & MC_IRQ_IPL) != 0 && (ir & MC_IRQ_IPL) != zs_level)
294: panic("zs configured at different IPLs");
295: if (initirq)
296: break;
297: sys_mc->mc_zsirq = zs_level | MC_IRQ_IEN;
298: break;
299: #endif
300: }
301: initirq = 1;
302: }
303:
304: void
305: zs_ttydef(zp)
306: struct zs *zp;
307: {
308: struct tty *tp = zp->tty;
309:
310: if ((zp->flags & ZS_CONSOLE) == 0) {
311: tp->t_iflag = TTYDEF_IFLAG;
312: tp->t_oflag = TTYDEF_OFLAG;
313: tp->t_cflag = TTYDEF_CFLAG;
314: tp->t_lflag = TTYDEF_LFLAG;
315: tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
316: } else
317: tp->t_termios = zs_cons_termios;
318: ttychars(tp);
319: ttsetwater(tp);
320: tp->t_oproc = zsstart;
321: tp->t_param = zsparam;
322:
323: zp->rcv_get = zp->rcv_buf;
324: zp->rcv_put = zp->rcv_buf;
325: zp->rcv_end = zp->rcv_buf + sizeof(zp->rcv_buf);
326: zp->rcv_len = sizeof(zp->rcv_buf) / 2;
327: }
328:
329: struct tty *
330: zstty(dev)
331: dev_t dev;
332: {
333: if (minor(dev) < NZSLINE)
334: return (zs_tty[minor(dev)]);
335: return (NULL);
336: }
337:
338: /* ARGSUSED */
339: int
340: zsopen(dev, flag, mode, p)
341: dev_t dev;
342: int flag, mode;
343: struct proc *p;
344: {
345: register struct tty *tp;
346: int error;
347: struct zs *zp;
348: struct zssoftc *sc;
349:
350: if (zsunit(dev) >= zs_cd.cd_ndevs ||
351: (sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
352: return (ENODEV);
353:
354: zp = &sc->sc_zs[zsside(dev)];
355: if (zp->tty == NULL) {
356: zp->tty = ttymalloc();
357: zs_ttydef(zp);
358: if (minor(dev) < NZSLINE)
359: zs_tty[minor(dev)] = zp->tty;
360: }
361: tp = zp->tty;
362: tp->t_dev = dev;
363:
364: if ((tp->t_state & TS_ISOPEN) == 0) {
365: tp->t_state |= TS_WOPEN;
366: zs_init(zp);
367: if ((zp->modem_state & SCC_DCD) != 0)
368: tp->t_state |= TS_CARR_ON;
369: } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
370: return (EBUSY);
371:
372: error = ((*linesw[tp->t_line].l_open) (dev, tp));
373:
374: if (error == 0)
375: ++zp->nzs_open;
376: return (error);
377: }
378:
379: int
380: zsclose(dev, flag, mode, p)
381: dev_t dev;
382: int flag, mode;
383: struct proc *p;
384: {
385: struct zs *zp;
386: struct tty *tp;
387: struct zssoftc *sc;
388: int s;
389:
390: if (zsunit(dev) >= zs_cd.cd_ndevs ||
391: (sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
392: return (ENODEV);
393: zp = &sc->sc_zs[zsside(dev)];
394: tp = zp->tty;
395:
396: (*linesw[tp->t_line].l_close) (tp, flag);
397: s = splzs();
398: if ((zp->flags & ZS_CONSOLE) == 0 && (tp->t_cflag & HUPCL) != 0)
399: ZBIC(&zp->scc, 5, 0x82); /* drop DTR, RTS */
400: ZBIC(&zp->scc, 3, 1); /* disable receiver */
401: splx(s);
402: ttyclose(tp);
403: zp->nzs_open = 0;
404: return (0);
405: }
406:
407: /*ARGSUSED*/
408: int
409: zsread(dev, uio, flag)
410: dev_t dev;
411: struct uio *uio;
412: int flag;
413: {
414: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
415: struct zs *zp = &sc->sc_zs[zsside(dev)];
416: struct tty *tp = zp->tty;
417:
418: return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
419: }
420:
421: /*ARGSUSED*/
422: int
423: zswrite(dev, uio, flag)
424: dev_t dev;
425: struct uio *uio;
426: int flag;
427: {
428: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
429: struct zs *zp = &sc->sc_zs[zsside(dev)];
430: struct tty *tp = zp->tty;
431:
432: return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
433: }
434:
435: int
436: zsioctl(dev, cmd, data, flag, p)
437: dev_t dev;
438: u_long cmd;
439: caddr_t data;
440: int flag;
441: struct proc *p;
442: {
443: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
444: struct zs *zp = &sc->sc_zs[zsside(dev)];
445: struct tty *tp = zp->tty;
446: register struct sccregs *scc = &zp->scc;
447: register int error, s;
448:
449: error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
450: if (error >= 0)
451: return (error);
452: error = ttioctl(tp, cmd, data, flag, p);
453: if (error >= 0)
454: return (error);
455: error = 0;
456: s = splzs();
457: switch (cmd) {
458: case TIOCSDTR:
459: ZBIS(scc, 5, 0x80);
460: break;
461: case TIOCCDTR:
462: ZBIC(scc, 5, 0x80);
463: break;
464: case TIOCSBRK:
465: splx(s);
466: zs_drain(zp);
467: s = splzs();
468: ZBIS(scc, 5, 0x10);
469: spltty();
470: zs_unblock(tp);
471: break;
472: case TIOCCBRK:
473: ZBIC(scc, 5, 0x10);
474: break;
475: case TIOCMGET:
476: *(int *) data = zscc_mget(scc);
477: break;
478: case TIOCMSET:
479: zscc_mset(scc, *(int *) data);
480: zscc_mclr(scc, ~*(int *) data);
481: break;
482: case TIOCMBIS:
483: zscc_mset(scc, *(int *) data);
484: break;
485: case TIOCMBIC:
486: zscc_mclr(scc, *(int *) data);
487: break;
488: default:
489: error = ENOTTY;
490: }
491: splx(s);
492: return (error);
493: }
494:
495: int
496: zsparam(tp, t)
497: struct tty *tp;
498: struct termios *t;
499: {
500: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
501: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
502: register int s;
503:
504: zs_drain(zp);
505: s = splzs();
506: zp->imask = zscc_params(&zp->scc, t);
507: tp->t_ispeed = t->c_ispeed;
508: tp->t_ospeed = t->c_ospeed;
509: tp->t_cflag = t->c_cflag;
510: if ((tp->t_cflag & CCTS_OFLOW) == 0)
511: zp->hflags &= ~ZH_OBLOCK;
512: else if ((zp->modem_state & 0x20) == 0)
513: zp->hflags |= ZH_OBLOCK;
514: spltty();
515: zs_unblock(tp);
516: splx(s);
517: return (0);
518: }
519:
520: void
521: zsstart(tp)
522: struct tty *tp;
523: {
524: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
525: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
526: register int s, n;
527:
528: s = spltty();
529: if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_DRAIN)) == 0) {
530: n = ndqb(&tp->t_outq, 0);
531: if (n > 0) {
532: tp->t_state |= TS_BUSY;
533: splzs();
534: zp->hflags |= ZH_TXING;
535: zp->send_ptr = tp->t_outq.c_cf;
536: zp->send_count = n;
537: zp->sent_count = 0;
538: zs_txint(zp);
539: spltty();
540: }
541: }
542: splx(s);
543: }
544:
545: int
546: zsstop(tp, flag)
547: struct tty *tp;
548: int flag;
549: {
550: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
551: struct zs *zp = &sc->sc_zs[zsside(tp->t_dev)];
552: int s, n;
553:
554: s = splzs();
555: zp->send_count = 0;
556: n = zp->sent_count;
557: zp->sent_count = 0;
558: if ((tp->t_state & TS_BUSY) != 0 && (flag & FWRITE) == 0) {
559: tp->t_state &= ~TS_BUSY;
560: spltty();
561: ndflush(&tp->t_outq, n);
562: if (tp->t_outq.c_cc <= tp->t_lowat) {
563: if (tp->t_state & TS_ASLEEP) {
564: tp->t_state &= ~TS_ASLEEP;
565: wakeup((caddr_t) & tp->t_outq);
566: }
567: selwakeup(&tp->t_wsel);
568: }
569: }
570: splx(s);
571: return (0);
572: }
573:
574: void
575: zs_init(zp)
576: struct zs *zp;
577: {
578: register int s;
579:
580: s = splzs();
581: zscc_init(zp, &zp->tty->t_termios);
582: zp->rr0 = zp->modem_state = ZREAD0(&zp->scc);
583: ZBIS(&zp->scc, 1, 0x13);/* ints on tx, rx and ext/status */
584: ZBIS(&zp->scc, 9, 8); /* enable ints */
585: zp->flags |= ZS_INTEN;
586: splx(s);
587: }
588:
589: void
590: zscc_init(zp, par)
591: struct zs *zp;
592: struct termios *par;
593: {
594: struct sccregs *scc;
595:
596: scc = &zp->scc;
597: #if defined(MVME162) || defined(MVME172)
598: if (cputyp == CPU_162 || cputyp == CPU_172)
599: ZWRITE(scc, 2, MC_VECBASE+MCV_ZS);
600: #endif
601: ZWRITE(scc, 10, 0);
602: ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
603: ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
604: zp->imask = zscc_params(scc, par);
605: ZBIS(scc, 5, 0x82); /* set DTR and RTS */
606: zp->flags |= ZS_INITED;
607: }
608:
609: int
610: zscc_params(scc, par)
611: struct sccregs *scc;
612: struct termios *par;
613: {
614: unsigned divisor, speed;
615: int spd, imask, ints;
616:
617: speed = par->c_ospeed;
618: if (speed == 0) {
619: /* disconnect - drop DTR & RTS, disable receiver */
620: ZBIC(scc, 5, 0x82);
621: ZBIC(scc, 3, 1);
622: return (0xFF);
623: }
624: if ((par->c_cflag & CREAD) == 0)
625: ZBIC(scc, 3, 1);/* disable receiver */
626: divisor = (zspclk() / 32 + (speed >> 1)) / speed - 2;
627: ZWRITE(scc, 12, divisor);
628: ZWRITE(scc, 13, divisor >> 8);
629: switch (par->c_cflag & CSIZE) {
630: case CS5:
631: spd = 0;
632: imask = 0x1F;
633: break;
634: case CS6:
635: spd = 0x40;
636: imask = 0x3F;
637: break;
638: case CS7:
639: spd = 0x20;
640: imask = 0x7F;
641: break;
642: default:
643: spd = 0x60;
644: imask = 0xFF;
645: }
646: ZWRITE(scc, 5, (scc->s_val[5] & ~0x60) | spd);
647: ZWRITE(scc, 3, (scc->s_val[3] & ~0xC0) | (spd << 1));
648: spd = par->c_cflag & CSTOPB ? 8 : 0;
649: spd |= par->c_cflag & PARENB ? par->c_cflag & PARODD ? 1 : 3 : 0;
650: ZWRITE(scc, 4, 0x44 | spd);
651: ZBIS(scc, 5, 8); /* enable transmitter */
652: if ((par->c_cflag & CREAD) != 0)
653: ZBIS(scc, 3, 1);/* enable receiver */
654: ints = 0;
655: if ((par->c_cflag & CLOCAL) == 0)
656: ints |= SCC_DCD;
657: if ((par->c_cflag & CCTS_OFLOW) != 0)
658: ints |= SCC_CTS;
659: #if 0
660: if (cputyp == CPU_162 || cputyp == CPU_172) {
661: ZWRITE(scc, 15, ints | 1);
662: /*
663: * now.. register 7 has become register 7': disable all
664: * 82530-only features for now
665: */
666: ZWRITE(scc, 7, 0x20);
667: }
668: #endif
669: ZWRITE(scc, 15, ints);
670: return (imask);
671: }
672:
673: int
674: zscc_mget(scc)
675: register struct sccregs *scc;
676: {
677: int bits = 0, rr0;
678:
679: if ((scc->s_val[3] & SCC_RCVEN) != 0)
680: bits |= TIOCM_LE;
681: if ((scc->s_val[5] & SCC_DTR) != 0)
682: bits |= TIOCM_DTR;
683: if ((scc->s_val[5] & SCC_RTS) != 0)
684: bits |= TIOCM_RTS;
685: rr0 = ZREAD0(scc);
686: if ((rr0 & SCC_CTS) != 0)
687: bits |= TIOCM_CTS;
688: if ((rr0 & SCC_DCD) != 0)
689: bits |= TIOCM_CAR;
690: return (bits);
691: }
692:
693: void
694: zscc_mset(scc, bits)
695: register struct sccregs *scc;
696: int bits;
697: {
698: if ((bits & TIOCM_LE) != 0)
699: ZBIS(scc, 3, SCC_RCVEN);
700: if ((bits & TIOCM_DTR) != 0)
701: ZBIS(scc, 5, SCC_DTR);
702: if ((bits & TIOCM_RTS) != 0)
703: ZBIS(scc, 5, SCC_RTS);
704: }
705:
706: void
707: zscc_mclr(scc, bits)
708: register struct sccregs *scc;
709: int bits;
710: {
711: if ((bits & TIOCM_LE) != 0)
712: ZBIC(scc, 3, SCC_RCVEN);
713: if ((bits & TIOCM_DTR) != 0)
714: ZBIC(scc, 5, TIOCM_DTR);
715: if ((bits & TIOCM_RTS) != 0)
716: ZBIC(scc, 5, SCC_RTS);
717: }
718:
719: void
720: zs_drain(zp)
721: register struct zs *zp;
722: {
723: register int s;
724:
725: zp->tty->t_state |= TS_DRAIN;
726: /* wait for Tx buffer empty and All sent bits to be set */
727: s = splzs();
728: while ((ZREAD0(&zp->scc) & SCC_TXRDY) == 0 ||
729: (ZREAD(&zp->scc, 1) & 1) == 0) {
730: splx(s);
731: DELAY(100);
732: s = splzs();
733: }
734: splx(s);
735: }
736:
737: void
738: zs_unblock(tp)
739: register struct tty *tp;
740: {
741: tp->t_state &= ~TS_DRAIN;
742: if (tp->t_outq.c_cc != 0)
743: zsstart(tp);
744: }
745:
746: /*
747: * Hardware interrupt from an SCC.
748: */
749: int
750: zsirq(arg)
751: void *arg;
752: {
753: int unit = (int)arg;
754: struct zssoftc *sc = (struct zssoftc *) zs_cd.cd_devs[unit];
755: struct zs *zp = &sc->sc_zs[0];
756: int ipend;
757:
758: ipend = ZREAD(&zp->scc, 3); /* read int pending from A side */
759: if (ipend == 0)
760: return (0);
761: if ((ipend & 0x20) != 0)
762: zs_rxint(zp);
763: if ((ipend & 0x10) != 0)
764: zs_txint(zp);
765: if ((ipend & 0x8) != 0)
766: zs_extint(zp);
767: ++zp; /* now look for B side ints */
768: if ((ipend & 0x4) != 0)
769: zs_rxint(zp);
770: if ((ipend & 0x2) != 0)
771: zs_txint(zp);
772: if ((ipend & 0x1) != 0)
773: zs_extint(zp);
774: ZWRITE0(&zp->scc, 0x38); /* reset highest IUS */
775:
776: return (1);
777: }
778:
779: void
780: zs_txint(zp)
781: register struct zs *zp;
782: {
783: struct sccregs *scc;
784: int c;
785: u_char *get;
786:
787: scc = &zp->scc;
788: ZWRITE0(scc, 0x28); /* reset Tx interrupt */
789: if ((zp->hflags & ZH_OBLOCK) == 0) {
790: get = zp->send_ptr;
791: while ((ZREAD0(scc) & SCC_TXRDY) != 0 && zp->send_count > 0) {
792: c = *get++;
793: ZWRITED(scc, c);
794: --zp->send_count;
795: ++zp->sent_count;
796: }
797: zp->send_ptr = get;
798: if (zp->send_count == 0 && (zp->hflags & ZH_TXING) != 0) {
799: zp->hflags &= ~ZH_TXING;
800: zp->hflags |= ZH_SIRQ;
801: setsoftint(sir_zs);
802: }
803: }
804: }
805:
806: void
807: zs_rxint(zp)
808: register struct zs *zp;
809: {
810: register int stat, c, n, extra;
811: u_char *put;
812:
813: put = zp->rcv_put;
814: n = zp->rcv_count;
815: for (;;) {
816: if ((ZREAD0(&zp->scc) & SCC_RXFULL) == 0) /* check Rx full */
817: break;
818: stat = ZREAD(&zp->scc, 1) & 0x70;
819: c = ZREADD(&zp->scc) & zp->imask;
820: /* stat encodes parity, overrun, framing errors */
821: if (stat != 0)
822: ZWRITE0(&zp->scc, 0x30); /* reset error */
823: if ((zp->hflags & ZH_RXOVF) != 0) {
824: zp->hflags &= ~ZH_RXOVF;
825: stat |= 0x20;
826: }
827: extra = (stat != 0 || c == ERROR_DET) ? 2 : 0;
828: if (n + extra + 1 < zp->rcv_len) {
829: if (extra != 0) {
830: *put++ = ERROR_DET;
831: if (put >= zp->rcv_end)
832: put = zp->rcv_buf;
833: *put++ = stat;
834: if (put >= zp->rcv_end)
835: put = zp->rcv_buf;
836: n += 2;
837: }
838: *put++ = c;
839: if (put >= zp->rcv_end)
840: put = zp->rcv_buf;
841: ++n;
842: } else
843: zp->hflags |= ZH_RXOVF;
844: }
845: if (n > zp->rcv_count) {
846: zp->rcv_put = put;
847: zp->rcv_count = n;
848: zp->hflags |= ZH_SIRQ;
849: setsoftint(sir_zs);
850: }
851: }
852:
853: /* Ext/status interrupt */
854: void
855: zs_extint(zp)
856: register struct zs *zp;
857: {
858: int rr0;
859: struct tty *tp = zp->tty;
860:
861: rr0 = ZREAD0(&zp->scc);
862: ZWRITE0(&zp->scc, 0x10);/* reset ext/status int */
863:
864: /* Handle break */
865: if (rr0 & 0x80) {
866: #ifdef DDB
867: if (ISSET(zp->flags, ZS_CONSOLE) && db_console != 0)
868: Debugger();
869: #endif
870: }
871:
872: if ((tp->t_cflag & CCTS_OFLOW) != 0) {
873: if ((rr0 & 0x20) == 0)
874: zp->hflags |= ZH_OBLOCK;
875: else {
876: zp->hflags &= ~ZH_OBLOCK;
877: if ((rr0 & SCC_TXRDY) != 0)
878: zs_txint(zp);
879: }
880: }
881: zp->modem_change |= rr0 ^ zp->modem_state;
882: zp->modem_state = rr0;
883: zp->hflags |= ZH_SIRQ;
884: setsoftint(sir_zs);
885: }
886:
887: /* ARGSUSED */
888: void
889: zs_softint(arg)
890: void *arg;
891: {
892: int s, c, stat, rr0;
893: struct zs *zp;
894: struct tty *tp;
895: u_char *get;
896: int unit, side;
897:
898: s = splzs();
899: for (unit = 0; unit < zs_cd.cd_ndevs; ++unit) {
900: if (zs_cd.cd_devs[unit] == NULL)
901: continue;
902: zp = &((struct zssoftc *) zs_cd.cd_devs[unit])->sc_zs[0];
903: for (side = 0; side < 2; ++side, ++zp) {
904: if ((zp->hflags & ZH_SIRQ) == 0)
905: continue;
906: zp->hflags &= ~ZH_SIRQ;
907: tp = zp->tty;
908:
909: /* check for tx done */
910: spltty();
911: if (tp != NULL && zp->send_count == 0
912: && (tp->t_state & TS_BUSY) != 0) {
913: tp->t_state &= ~(TS_BUSY | TS_FLUSH);
914: ndflush(&tp->t_outq, zp->sent_count);
915: if (tp->t_outq.c_cc <= tp->t_lowat) {
916: if (tp->t_state & TS_ASLEEP) {
917: tp->t_state &= ~TS_ASLEEP;
918: wakeup((caddr_t) & tp->t_outq);
919: }
920: selwakeup(&tp->t_wsel);
921: }
922: if (tp->t_line != 0)
923: (*linesw[tp->t_line].l_start) (tp);
924: else
925: zsstart(tp);
926: }
927: splzs();
928:
929: /* check for received characters */
930: get = zp->rcv_get;
931: while (zp->rcv_count > 0) {
932: c = *get++;
933: if (get >= zp->rcv_end)
934: get = zp->rcv_buf;
935: if (c == ERROR_DET) {
936: stat = *get++;
937: if (get >= zp->rcv_end)
938: get = zp->rcv_buf;
939: c = *get++;
940: if (get >= zp->rcv_end)
941: get = zp->rcv_buf;
942: zp->rcv_count -= 3;
943: } else {
944: stat = 0;
945: --zp->rcv_count;
946: }
947: spltty();
948: if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
949: continue;
950: if (zp->nzs_open == 0) {
951:
952: } else {
953: if ((stat & 0x10) != 0)
954: c |= TTY_PE;
955: if ((stat & 0x20) != 0) {
956: log(LOG_WARNING, "zs: fifo overflow\n");
957: c |= TTY_FE; /* need some error for
958: * slip stuff */
959: }
960: if ((stat & 0x40) != 0)
961: c |= TTY_FE;
962: (*linesw[tp->t_line].l_rint) (c, tp);
963: }
964: splzs();
965: }
966: zp->rcv_get = get;
967:
968: /* check for modem lines changing */
969: while (zp->modem_change != 0 || zp->modem_state != zp->rr0) {
970: rr0 = zp->rr0 ^ zp->modem_change;
971: zp->modem_change = rr0 ^ zp->modem_state;
972:
973: /* Check if DCD (carrier detect) has changed */
974: if (tp != NULL && (rr0 & 8) != (zp->rr0 & 8)) {
975: spltty();
976: ttymodem(tp, rr0 & 8);
977: /* XXX possibly should disable line if
978: * return value is 0 */
979: splzs();
980: }
981: zp->rr0 = rr0;
982: }
983: }
984: }
985: splx(s);
986: }
987:
988: /*
989: * Routines for using side A of the first SCC as a console.
990: */
991:
992: /* probe for the SCC; should check hardware */
993: void
994: zscnprobe(cp)
995: struct consdev *cp;
996: {
997: int maj;
998:
999: switch (cputyp) {
1000: case CPU_147:
1001: case CPU_162:
1002: case CPU_172:
1003: break;
1004: default:
1005: return;
1006: }
1007:
1008: /* locate the major number */
1009: for (maj = 0; maj < nchrdev; maj++)
1010: if (cdevsw[maj].d_open == zsopen)
1011: break;
1012:
1013: cp->cn_dev = makedev(maj, 0);
1014: cp->cn_pri = CN_NORMAL;
1015: }
1016:
1017: /* initialize the keyboard for use as the console */
1018: struct termios zscn_termios = {
1019: TTYDEF_IFLAG,
1020: TTYDEF_OFLAG,
1021: (CREAD | CS8 | HUPCL),
1022: TTYDEF_LFLAG,
1023: {0},
1024: TTYDEF_SPEED,
1025: TTYDEF_SPEED
1026: };
1027:
1028: struct sccregs zs_cons_sccregs;
1029: int zs_cons_imask;
1030:
1031: /* Polling routine for console input from a serial port. */
1032: int
1033: zscngetc(dev)
1034: dev_t dev;
1035: {
1036: register struct sccregs *scc = zs_cons_scc;
1037: int c, s, stat;
1038:
1039: s = splhigh(); /* XXX was splzs() */
1040: for (;;) {
1041: while ((ZREAD0(scc) & SCC_RXFULL) == 0) /* wait for Rx full */
1042: ;
1043: stat = ZREAD(scc, 1) & 0x70;
1044: c = ZREADD(scc) & zs_cons_imask;
1045: /* stat encodes parity, overrun, framing errors */
1046: if (stat == 0)
1047: break;
1048: ZWRITE0(scc, 0x30); /* reset error */
1049: }
1050: splx(s);
1051: return (c);
1052: }
1053:
1054: void
1055: zscnputc(dev, c)
1056: dev_t dev;
1057: int c;
1058: {
1059: register struct sccregs *scc = zs_cons_scc;
1060: int s;
1061:
1062: s = splhigh(); /* XXX was splzs() */
1063: while ((ZREAD0(scc) & SCC_TXRDY) == 0)
1064: ;
1065: ZWRITED(scc, c);
1066: splx(s);
1067: }
1068:
1069: void
1070: zscninit(cp)
1071: struct consdev *cp;
1072: {
1073: int unit = 0;
1074: struct termios *tiop = &zscn_termios;
1075: volatile u_char *scc_cr, *scc_dr;
1076: struct sccregs *scc;
1077: int size;
1078:
1079: zs_cons_unit = unit;
1080: zs_is_console = 1;
1081: zs_cons_scc = scc = &zs_cons_sccregs;
1082:
1083: /*
1084: * the locations of the control and data register move around
1085: * on different MVME models, so we generate independent pointers
1086: * to them.
1087: */
1088: size = zsregs(0, unit, &scc_cr, &scc_dr);
1089:
1090: *(scc_cr + size) = 0;
1091: *(scc_cr + size) = 9;
1092: *(scc_cr + size) = 0xC0; /* hardware reset of SCC, both sides */
1093: if (!zsside(unit)) {
1094: scc_cr += size;
1095: scc_dr += size;
1096: }
1097:
1098: scc->s_cr = scc_cr;
1099: scc->s_dr = scc_dr;
1100: #if defined(MVME162) || defined(MVME172)
1101: if (cputyp == CPU_162 || cputyp == CPU_172)
1102: ZWRITE(scc, 2, MC_VECBASE+MCV_ZS);
1103: #endif
1104: ZWRITE(scc, 10, 0);
1105: ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
1106: ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
1107: zs_cons_imask = zscc_params(scc, tiop);
1108: ZBIS(scc, 5, 0x82); /* set DTR and RTS */
1109:
1110: zs_cons_termios = *tiop;/* save for later */
1111: }
1112:
1113: #ifdef MVME147
1114: u_long zs_cons_addrs_147[] = { ZS0_PHYS_147, ZS1_PHYS_147};
1115: #endif
1116: #if defined(MVME162) || defined(MVME172)
1117: u_long zs_cons_addrs_162[] = { ZS0_PHYS_162, ZS1_PHYS_162};
1118: #endif
1119:
1120: /*
1121: * fills in pointers to the registers and returns how far apart
1122: * the two halves of the chip are.
1123: *
1124: * it vaddr == NULL, it tries to determine the hardware address in
1125: * an intelligent fashion from the unit number.
1126: */
1127: int
1128: zsregs(va, unit, crp, drp)
1129: vaddr_t va;
1130: int unit;
1131: volatile u_char **crp, **drp;
1132: {
1133: #ifdef MVME147
1134: volatile struct scc_147 *scc_adr_147;
1135: #endif
1136: #if defined(MVME162) || defined(MVME172)
1137: volatile struct scc_162 *scc_adr_162;
1138: #endif
1139: volatile u_char *scc_cr, *scc_dr;
1140: int size;
1141:
1142: switch (cputyp) {
1143: #ifdef MVME147
1144: case CPU_147:
1145: if (va == 0)
1146: va = IIOV(zs_cons_addrs_147[unit]);
1147: scc_adr_147 = (volatile struct scc_147 *)va;
1148: scc_cr = &scc_adr_147->cr;
1149: scc_dr = &scc_adr_147->dr;
1150: size = sizeof(struct scc_147);
1151: break;
1152: #endif
1153: #if defined(MVME162) || defined(MVME172)
1154: case CPU_162:
1155: case CPU_172:
1156: if (va == 0)
1157: va = IIOV(zs_cons_addrs_162[unit]);
1158: scc_adr_162 = (volatile struct scc_162 *)va;
1159: scc_cr = &scc_adr_162->cr;
1160: scc_dr = &scc_adr_162->dr;
1161: size = sizeof(struct scc_162);
1162: break;
1163: #endif
1164: }
1165:
1166: *crp = scc_cr;
1167: *drp = scc_dr;
1168: return (size);
1169: }
1170:
1171: int
1172: zspclk()
1173: {
1174: switch (cputyp) {
1175: #ifdef MVME147
1176: case CPU_147:
1177: return (PCLK_FREQ_147);
1178: #endif
1179: #if defined(MVME162) || defined(MVME172)
1180: case CPU_162:
1181: case CPU_172:
1182: return (PCLK_FREQ_162);
1183: #endif
1184: default:
1185: return 0;
1186: }
1187: }
CVSweb