1 /*        $NetBSD: dz.c,v 1.44 2024/02/02 15:44:43 tsutsui Exp $      */
2 /*
3  * Copyright (c) 1992, 1993
4  *        The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Ralph Campbell and Rick Macklem.
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  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
36  *
37  * This code is derived from software contributed to Berkeley by
38  * Ralph Campbell and Rick Macklem.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. All advertising materials mentioning features or use of this software
49  *    must display the following acknowledgement:
50  *        This product includes software developed by the University of
51  *        California, Berkeley and its contributors.
52  * 4. Neither the name of the University nor the names of its contributors
53  *    may be used to endorse or promote products derived from this software
54  *    without specific prior written permission.
55  *
56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66  * SUCH DAMAGE.
67  */
68 
69 #include <sys/cdefs.h>
70 __KERNEL_RCSID(0, "$NetBSD: dz.c,v 1.44 2024/02/02 15:44:43 tsutsui Exp $");
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/callout.h>
75 #include <sys/ioctl.h>
76 #include <sys/tty.h>
77 #include <sys/proc.h>
78 #include <sys/buf.h>
79 #include <sys/conf.h>
80 #include <sys/file.h>
81 #include <sys/uio.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84 #include <sys/device.h>
85 #include <sys/kauth.h>
86 
87 #include <sys/bus.h>
88 
89 #include <dev/dec/dzreg.h>
90 #include <dev/dec/dzvar.h>
91 
92 #include <dev/cons.h>
93 
94 #ifdef __mips__
95 #define   DZ_DELAY(x)         DELAY(x)
96 #define control               __noinline
97 #else     /* presumably vax */
98 #define   DZ_DELAY(x)         /* nothing */
99 #define   control             inline
100 #endif
101 
102 static control uint
dz_read1(struct dz_softc * sc,u_int off)103 dz_read1(struct dz_softc *sc, u_int off)
104 {
105           u_int rv;
106 
107           rv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off);
108           DZ_DELAY(1);
109           return rv;
110 }
111 
112 static control u_int
dz_read2(struct dz_softc * sc,u_int off)113 dz_read2(struct dz_softc *sc, u_int off)
114 {
115           u_int rv;
116 
117           rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
118           DZ_DELAY(1);
119           return rv;
120 }
121 
122 static control void
dz_write1(struct dz_softc * sc,u_int off,u_int val)123 dz_write1(struct dz_softc *sc, u_int off, u_int val)
124 {
125 
126           bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, val);
127           bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_dr.dr_firstreg,
128               sc->sc_dr.dr_winsize, BUS_SPACE_BARRIER_WRITE |
129               BUS_SPACE_BARRIER_READ);
130           DZ_DELAY(10);
131 }
132 
133 static control void
dz_write2(struct dz_softc * sc,u_int off,u_int val)134 dz_write2(struct dz_softc *sc, u_int off, u_int val)
135 {
136 
137           bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, val);
138           bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_dr.dr_firstreg,
139               sc->sc_dr.dr_winsize, BUS_SPACE_BARRIER_WRITE |
140               BUS_SPACE_BARRIER_READ);
141           DZ_DELAY(10);
142 }
143 
144 #include "ioconf.h"
145 
146 /* Flags used to monitor modem bits, make them understood outside driver */
147 
148 #define DML_DTR               TIOCM_DTR
149 #define DML_DCD               TIOCM_CD
150 #define DML_RI                TIOCM_RI
151 #define DML_BRK               0100000             /* no equivalent, we will mask */
152 
153 static const struct speedtab dzspeedtab[] =
154 {
155   {       0,        0                   },
156   {      50,        DZ_LPR_B50          },
157   {      75,        DZ_LPR_B75          },
158   {     110,        DZ_LPR_B110         },
159   {     134,        DZ_LPR_B134         },
160   {     150,        DZ_LPR_B150         },
161   {     300,        DZ_LPR_B300         },
162   {     600,        DZ_LPR_B600         },
163   {    1200,        DZ_LPR_B1200        },
164   {    1800,        DZ_LPR_B1800        },
165   {    2000,        DZ_LPR_B2000        },
166   {    2400,        DZ_LPR_B2400        },
167   {    3600,        DZ_LPR_B3600        },
168   {    4800,        DZ_LPR_B4800        },
169   {    7200,        DZ_LPR_B7200        },
170   {    9600,        DZ_LPR_B9600        },
171   {   19200,        DZ_LPR_B19200       },
172   {      -1,        -1                  }
173 };
174 
175 static void         dzstart(struct tty *);
176 static int          dzparam(struct tty *, struct termios *);
177 static unsigned     dzmctl(struct dz_softc *, int, int, int);
178 static void         dzscan(void *);
179 
180 static dev_type_open(dzopen);
181 static dev_type_close(dzclose);
182 static dev_type_read(dzread);
183 static dev_type_write(dzwrite);
184 static dev_type_ioctl(dzioctl);
185 static dev_type_stop(dzstop);
186 static dev_type_tty(dztty);
187 static dev_type_poll(dzpoll);
188 
189 const struct cdevsw dz_cdevsw = {
190           .d_open = dzopen,
191           .d_close = dzclose,
192           .d_read = dzread,
193           .d_write = dzwrite,
194           .d_ioctl = dzioctl,
195           .d_stop = dzstop,
196           .d_tty = dztty,
197           .d_poll = dzpoll,
198           .d_mmap = nommap,
199           .d_kqfilter = ttykqfilter,
200           .d_discard = nodiscard,
201           .d_flag = D_TTY
202 };
203 
204 /*
205  * The DZ series doesn't interrupt on carrier transitions,
206  * so we have to use a timer to watch it.
207  */
208 int       dz_timer; /* true if timer started */
209 struct callout dzscan_ch;
210 static struct cnm_state dz_cnm_state;
211 
212 void
dzattach(struct dz_softc * sc,struct evcnt * parent_evcnt,int consline)213 dzattach(struct dz_softc *sc, struct evcnt *parent_evcnt, int consline)
214 {
215           int n;
216 
217           /* Initialize our softc structure. */
218 
219           for (n = 0; n < sc->sc_type; n++) {
220                     sc->sc_dz[n].dz_sc = sc;
221                     sc->sc_dz[n].dz_line = n;
222                     sc->sc_dz[n].dz_tty = tty_alloc();
223           }
224 
225           evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
226               device_xname(sc->sc_dev), "rintr");
227           evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
228               device_xname(sc->sc_dev), "tintr");
229 
230           /* Console magic keys */
231           cn_init_magic(&dz_cnm_state);
232           cn_set_magic("\047\001"); /* default magic is BREAK */
233                                           /* VAX will change it in MD code */
234 
235           sc->sc_rxint = sc->sc_brk = 0;
236           sc->sc_consline = consline;
237 
238           sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
239           dz_write2(sc, sc->sc_dr.dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
240           dz_write1(sc, sc->sc_dr.dr_dtr, 0);
241           dz_write1(sc, sc->sc_dr.dr_break, 0);
242           DELAY(10000);
243 
244           /* Alas no interrupt on modem bit changes, so we manually scan */
245           if (dz_timer == 0) {
246                     dz_timer = 1;
247                     callout_init(&dzscan_ch, 0);
248                     callout_reset(&dzscan_ch, hz, dzscan, NULL);
249           }
250           aprint_normal("\n");
251 }
252 
253 /* Receiver Interrupt */
254 
255 void
dzrint(void * arg)256 dzrint(void *arg)
257 {
258           struct dz_softc *sc = arg;
259           struct tty *tp;
260           int cc, mcc, line;
261           unsigned c;
262           int overrun = 0;
263 
264           sc->sc_rxint++;
265 
266           while ((c = dz_read2(sc, sc->sc_dr.dr_rbuf)) & DZ_RBUF_DATA_VALID) {
267                     cc = c & 0xFF;
268                     line = DZ_PORT(c>>8);
269                     tp = sc->sc_dz[line].dz_tty;
270 
271                     /* Must be caught early */
272                     if (sc->sc_dz[line].dz_catch &&
273                         (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
274                               continue;
275 
276                     if ((c & (DZ_RBUF_FRAMING_ERR | 0xff)) == DZ_RBUF_FRAMING_ERR)
277                               mcc = CNC_BREAK;
278                     else
279                               mcc = cc;
280 
281                     cn_check_magic(tp->t_dev, mcc, dz_cnm_state);
282 
283                     if (!(tp->t_state & TS_ISOPEN)) {
284                               cv_broadcast(&tp->t_rawcv);
285                               continue;
286                     }
287 
288                     if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
289                               log(LOG_WARNING, "%s: silo overflow, line %d\n",
290                                   device_xname(sc->sc_dev), line);
291                               overrun = 1;
292                     }
293 
294                     if (c & DZ_RBUF_FRAMING_ERR)
295                               cc |= TTY_FE;
296                     if (c & DZ_RBUF_PARITY_ERR)
297                               cc |= TTY_PE;
298 
299                     (*tp->t_linesw->l_rint)(cc, tp);
300           }
301 }
302 
303 /* Transmitter Interrupt */
304 
305 void
dzxint(void * arg)306 dzxint(void *arg)
307 {
308           struct dz_softc *sc = arg;
309           struct tty *tp;
310           struct clist *cl;
311           int line, ch, csr;
312           u_char tcr;
313 
314           /*
315            * Switch to POLLED mode.
316            *   Some simple measurements indicated that even on
317            *  one port, by freeing the scanner in the controller
318            *  by either providing a character or turning off
319            *  the port when output is complete, the transmitter
320            *  was ready to accept more output when polled again.
321            *   With just two ports running the game "worms,"
322            *  almost every interrupt serviced both transmitters!
323            *   Each UART is double buffered, so if the scanner
324            *  is quick enough and timing works out, we can even
325            *  feed the same port twice.
326            *
327            * Ragge 980517:
328            * Do not need to turn off interrupts, already at interrupt level.
329            * Remove the pdma stuff; no great need of it right now.
330            */
331 
332           for (;;) {
333                     csr = dz_read2(sc, sc->sc_dr.dr_csr);
334                     if ((csr & DZ_CSR_TX_READY) == 0)
335                               break;
336 
337                     line = DZ_PORT(csr >> 8);
338                     tp = sc->sc_dz[line].dz_tty;
339                     cl = &tp->t_outq;
340                     tp->t_state &= ~TS_BUSY;
341 
342                     /* Just send out a char if we have one */
343                     /* As long as we can fill the chip buffer, we just loop here */
344                     if (cl->c_cc) {
345                               tp->t_state |= TS_BUSY;
346                               ch = getc(cl);
347                               dz_write1(sc, sc->sc_dr.dr_tbuf, ch);
348                               continue;
349                     }
350 
351                     /* Nothing to send; clear the scan bit */
352                     /* Clear xmit scanner bit; dzstart may set it again */
353                     tcr = dz_read2(sc, sc->sc_dr.dr_tcrw);
354                     tcr &= 255;
355                     tcr &= ~(1 << line);
356                     dz_write1(sc, sc->sc_dr.dr_tcr, tcr);
357                     if (sc->sc_dz[line].dz_catch)
358                               continue;
359 
360                     if (tp->t_state & TS_FLUSH)
361                               tp->t_state &= ~TS_FLUSH;
362                     else
363                               ndflush (&tp->t_outq, cl->c_cc);
364 
365                     (*tp->t_linesw->l_start)(tp);
366           }
367 }
368 
369 int
dzopen(dev_t dev,int flag,int mode,struct lwp * l)370 dzopen(dev_t dev, int flag, int mode, struct lwp *l)
371 {
372           const int line = DZ_PORT(minor(dev));
373           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
374           struct tty *tp;
375           int error = 0;
376 
377           if (sc == NULL || line >= sc->sc_type)
378                     return ENXIO;
379 
380           /* if some other device is using the line, it's busy */
381           if (sc->sc_dz[line].dz_catch)
382                     return EBUSY;
383 
384           tp = sc->sc_dz[line].dz_tty;
385           if (tp == NULL)
386                     return (ENODEV);
387           tp->t_oproc = dzstart;
388           tp->t_param = dzparam;
389           tp->t_dev = dev;
390 
391           if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
392                     return (EBUSY);
393 
394           if ((tp->t_state & TS_ISOPEN) == 0) {
395                     ttychars(tp);
396                     if (tp->t_ispeed == 0) {
397                               tp->t_iflag = TTYDEF_IFLAG;
398                               tp->t_oflag = TTYDEF_OFLAG;
399                               tp->t_cflag = TTYDEF_CFLAG;
400                               tp->t_lflag = TTYDEF_LFLAG;
401                               tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
402                     }
403                     (void) dzparam(tp, &tp->t_termios);
404                     ttsetwater(tp);
405           }
406 
407           /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
408           if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
409                     tp->t_state |= TS_CARR_ON;
410           ttylock(tp);
411           while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
412                  !(tp->t_state & TS_CARR_ON)) {
413                     tp->t_wopen++;
414                     error = ttysleep(tp, &tp->t_rawcv, true, 0);
415                     tp->t_wopen--;
416                     if (error)
417                               break;
418           }
419           ttyunlock(tp);
420           if (error)
421                     return (error);
422           return ((*tp->t_linesw->l_open)(dev, tp));
423 }
424 
425 /*ARGSUSED*/
426 int
dzclose(dev_t dev,int flag,int mode,struct lwp * l)427 dzclose(dev_t dev, int flag, int mode, struct lwp *l)
428 {
429           const int line = DZ_PORT(minor(dev));
430           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
431           struct tty *tp = sc->sc_dz[line].dz_tty;
432 
433           (*tp->t_linesw->l_close)(tp, flag);
434 
435           /* Make sure a BREAK state is not left enabled. */
436           (void) dzmctl(sc, line, DML_BRK, DMBIC);
437 
438           /* Do a hangup if so required. */
439           if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
440                     (void) dzmctl(sc, line, 0, DMSET);
441 
442           return ttyclose(tp);
443 }
444 
445 int
dzread(dev_t dev,struct uio * uio,int flag)446 dzread(dev_t dev, struct uio *uio, int flag)
447 {
448           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
449           struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
450 
451           return ((*tp->t_linesw->l_read)(tp, uio, flag));
452 }
453 
454 int
dzwrite(dev_t dev,struct uio * uio,int flag)455 dzwrite(dev_t dev, struct uio *uio, int flag)
456 {
457           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
458           struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
459 
460           return ((*tp->t_linesw->l_write)(tp, uio, flag));
461 }
462 
463 int
dzpoll(dev_t dev,int events,struct lwp * l)464 dzpoll(dev_t dev, int events, struct lwp *l)
465 {
466           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
467           struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
468 
469           return ((*tp->t_linesw->l_poll)(tp, events, l));
470 }
471 
472 /*ARGSUSED*/
473 int
dzioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)474 dzioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
475 {
476           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
477           const int line = DZ_PORT(minor(dev));
478           struct tty *tp = sc->sc_dz[line].dz_tty;
479           int error;
480 
481           error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
482           if (error >= 0)
483                     return (error);
484 
485           error = ttioctl(tp, cmd, data, flag, l);
486           if (error >= 0)
487                     return (error);
488 
489           switch (cmd) {
490           case TIOCSBRK:
491                     (void) dzmctl(sc, line, DML_BRK, DMBIS);
492                     break;
493 
494           case TIOCCBRK:
495                     (void) dzmctl(sc, line, DML_BRK, DMBIC);
496                     break;
497 
498           case TIOCSDTR:
499                     (void) dzmctl(sc, line, DML_DTR, DMBIS);
500                     break;
501 
502           case TIOCCDTR:
503                     (void) dzmctl(sc, line, DML_DTR, DMBIC);
504                     break;
505 
506           case TIOCMSET:
507                     (void) dzmctl(sc, line, *(int *)data, DMSET);
508                     break;
509 
510           case TIOCMBIS:
511                     (void) dzmctl(sc, line, *(int *)data, DMBIS);
512                     break;
513 
514           case TIOCMBIC:
515                     (void) dzmctl(sc, line, *(int *)data, DMBIC);
516                     break;
517 
518           case TIOCMGET:
519                     *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
520                     break;
521 
522           default:
523                     return (EPASSTHROUGH);
524           }
525           return (0);
526 }
527 
528 struct tty *
dztty(dev_t dev)529 dztty(dev_t dev)
530 {
531           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
532 
533           return sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
534 }
535 
536 /*ARGSUSED*/
537 void
dzstop(struct tty * tp,int flag)538 dzstop(struct tty *tp, int flag)
539 {
540           if ((tp->t_state & (TS_BUSY | TS_TTSTOP)) == TS_BUSY)
541                     tp->t_state |= TS_FLUSH;
542 }
543 
544 void
dzstart(struct tty * tp)545 dzstart(struct tty *tp)
546 {
547           struct dz_softc *sc;
548           int line;
549           int s;
550           char state;
551 
552           s = spltty();
553           if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
554                     splx(s);
555                     return;
556           }
557           if (!ttypull(tp)) {
558                     splx(s);
559                     return;
560           }
561 
562           line = DZ_PORT(minor(tp->t_dev));
563           sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
564 
565           tp->t_state |= TS_BUSY;
566           state = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
567           if ((state & (1 << line)) == 0)
568                     dz_write1(sc, sc->sc_dr.dr_tcr, state | (1 << line));
569           dzxint(sc);
570           splx(s);
571 }
572 
573 static int
dzparam(struct tty * tp,struct termios * t)574 dzparam(struct tty *tp, struct termios *t)
575 {
576           struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
577           const int line = DZ_PORT(minor(tp->t_dev));
578           int cflag = t->c_cflag;
579           int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
580           int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
581           unsigned lpr;
582           int s;
583 
584           /* check requested parameters */
585         if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
586                 return (EINVAL);
587 
588         tp->t_ispeed = t->c_ispeed;
589         tp->t_ospeed = t->c_ospeed;
590         tp->t_cflag = cflag;
591 
592           if (ospeed == 0) {
593                     (void) dzmctl(sc, line, 0, DMSET);      /* hang up line */
594                     return (0);
595           }
596 
597           s = spltty();
598 
599           /* XXX This is wrong.  Flush output or the chip gets very confused. */
600           ttywait(tp);
601 
602           lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
603 
604           switch (cflag & CSIZE)
605           {
606             case CS5:
607                     lpr |= DZ_LPR_5_BIT_CHAR;
608                     break;
609             case CS6:
610                     lpr |= DZ_LPR_6_BIT_CHAR;
611                     break;
612             case CS7:
613                     lpr |= DZ_LPR_7_BIT_CHAR;
614                     break;
615             default:
616                     lpr |= DZ_LPR_8_BIT_CHAR;
617                     break;
618           }
619           if (cflag & PARENB)
620                     lpr |= DZ_LPR_PARENB;
621           if (cflag & PARODD)
622                     lpr |= DZ_LPR_OPAR;
623           if (cflag & CSTOPB)
624                     lpr |= DZ_LPR_2_STOP;
625 
626           dz_write2(sc, sc->sc_dr.dr_lpr, lpr);
627           (void) splx(s);
628           DELAY(10000);
629 
630           return (0);
631 }
632 
633 static unsigned
dzmctl(struct dz_softc * sc,int line,int bits,int how)634 dzmctl(struct dz_softc *sc, int line, int bits, int how)
635 {
636           unsigned status;
637           unsigned mbits;
638           unsigned bit;
639           int s;
640 
641           s = spltty();
642           mbits = 0;
643           bit = (1 << line);
644 
645           /* external signals as seen from the port */
646           status = dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr;
647           if (status & bit)
648                     mbits |= DML_DCD;
649           status = dz_read1(sc, sc->sc_dr.dr_ring);
650           if (status & bit)
651                     mbits |= DML_RI;
652 
653           /* internal signals/state delivered to port */
654           status = dz_read1(sc, sc->sc_dr.dr_dtr);
655           if (status & bit)
656                     mbits |= DML_DTR;
657           if (sc->sc_brk & bit)
658                     mbits |= DML_BRK;
659 
660           switch (how)
661           {
662             case DMSET:
663                     mbits = bits;
664                     break;
665 
666             case DMBIS:
667                     mbits |= bits;
668                     break;
669 
670             case DMBIC:
671                     mbits &= ~bits;
672                     break;
673 
674             case DMGET:
675                     (void) splx(s);
676                     return (mbits);
677           }
678 
679           if (mbits & DML_DTR) {
680                     dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) | bit);
681           } else {
682                     dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) & ~bit);
683           }
684 
685           if (mbits & DML_BRK) {
686                     sc->sc_brk |= bit;
687                     dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
688           } else {
689                     sc->sc_brk &= ~bit;
690                     dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
691           }
692 
693           (void) splx(s);
694 
695           return (mbits);
696 }
697 
698 /*
699  * This is called by timeout() periodically.
700  * Check to see if modem status bits have changed.
701  */
702 static void
dzscan(void * arg)703 dzscan(void *arg)
704 {
705           struct dz_softc *sc;
706           struct tty *tp;
707           int n, bit, port;
708           unsigned int csr;
709           unsigned int tmp;
710           int s;
711 
712           s = spltty();
713           for (n = 0; n < dz_cd.cd_ndevs; n++) {
714                     if ((sc = device_lookup_private(&dz_cd, n)) == NULL)
715                               continue;
716 
717                     for (port = 0; port < sc->sc_type; port++) {
718                               tp = sc->sc_dz[port].dz_tty;
719                               bit = (1 << port);
720 
721                               if ((dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr) & bit) {
722                                         if (!(tp->t_state & TS_CARR_ON))
723                                                   (*tp->t_linesw->l_modem) (tp, 1);
724                               } else if ((tp->t_state & TS_CARR_ON) &&
725                                   (*tp->t_linesw->l_modem)(tp, 0) == 0) {
726                                         tmp = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
727                                         dz_write1(sc, sc->sc_dr.dr_tcr, tmp & ~bit);
728                               }
729                     }
730 
731                     /*
732                      *  If the RX interrupt rate is this high, switch
733                      *  the controller to Silo Alarm - which means don't
734                      *  interrupt until the RX silo has 16 characters in
735                      *  it (the silo is 64 characters in all).
736                      *  Avoid oscillating SA on and off by not turning
737                      *  if off unless the rate is appropriately low.
738                      */
739                     csr = dz_read2(sc, sc->sc_dr.dr_csr);
740                     tmp = csr;
741                     if (sc->sc_rxint > 16*10)
742                               csr |= DZ_CSR_SAE;
743                     else if (sc->sc_rxint < 10)
744                               csr &= ~DZ_CSR_SAE;
745                     if (csr != tmp)
746                               dz_write2(sc, sc->sc_dr.dr_csr, csr);
747                     sc->sc_rxint = 0;
748 
749                     dzxint(sc);
750                     dzrint(sc);
751           }
752           (void) splx(s);
753           callout_reset(&dzscan_ch, hz, dzscan, NULL);
754 }
755 
756 /*
757  * Called after an ubareset. The DZ card is reset, but the only thing
758  * that must be done is to start the receiver and transmitter again.
759  * No DMA setup to care about.
760  */
761 void
dzreset(device_t dev)762 dzreset(device_t dev)
763 {
764           struct dz_softc *sc = device_private(dev);
765           struct tty *tp;
766           int i;
767 
768           for (i = 0; i < sc->sc_type; i++) {
769                     tp = sc->sc_dz[i].dz_tty;
770 
771                     if (((tp->t_state & TS_ISOPEN) == 0) || (tp->t_wopen == 0))
772                               continue;
773 
774                     dzparam(tp, &tp->t_termios);
775                     dzmctl(sc, i, DML_DTR, DMSET);
776                     tp->t_state &= ~TS_BUSY;
777                     dzstart(tp);        /* Kick off transmitter again */
778           }
779 }
780