1 /*
2 * Copyright (c) 1982, 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)dmx.c 7.7 (Berkeley) 05/16/91
7 */
8
9 /*
10 * Common code for DMF32 and DMZ32 drivers
11 */
12 #include "dmf.h"
13 #include "dmz.h"
14 #if NDMF + NDMZ > 0
15
16 #include "../include/pte.h"
17
18 #include "sys/param.h"
19 #include "uba.h"
20 #include "sys/conf.h"
21 #include "sys/user.h"
22 #include "sys/proc.h"
23 #include "sys/ioctl.h"
24 #include "sys/tty.h"
25 #include "sys/map.h"
26 #include "sys/buf.h"
27 #include "sys/vm.h"
28 #include "sys/clist.h"
29 #include "sys/file.h"
30 #include "sys/uio.h"
31 #include "sys/kernel.h"
32 #include "sys/syslog.h"
33
34 #include "dmx.h"
35 #include "ubareg.h"
36 #include "ubavar.h"
37 #include "dmxreg.h"
38 #include "dmreg.h"
39
40 #ifndef PORTSELECTOR
41 #define ISPEED TTYDEF_SPEED
42 #define LFLAG TTYDEF_LFLAG
43 #else
44 #define ISPEED B4800
45 #define IFLAGS (TTYDEF_LFLAG&~ECHO)
46 #endif
47
48 #ifndef DMX_TIMEOUT
49 #define DMX_TIMEOUT 10
50 #endif
51 int dmx_timeout = DMX_TIMEOUT; /* silo timeout, in ms */
52 int dmx_mindma = 4; /* don't dma below this point */
53
54 struct speedtab dmxspeedtab[] = {
55 0, 0,
56 75, 1,
57 110, 2,
58 134, 3,
59 150, 4,
60 300, 5,
61 600, 6,
62 1200, 7,
63 1800, 010,
64 2400, 012,
65 4800, 014,
66 9600, 016,
67 19200, 017,
68 EXTA, 017,
69 -1, -1
70 };
71 /*
72 * The clist space is mapped by the drivers onto each UNIBUS.
73 * The UBACVT macro converts a clist space address for unibus uban
74 * into an I/O space address for the DMA routine.
75 */
76 int cbase[NUBA]; /* base address in unibus map */
77 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
78
79 int ttrstrt();
80
81 /*
82 * DMF/DMZ open common code
83 */
dmxopen(tp,sc,flag)84 dmxopen(tp, sc, flag)
85 register struct tty *tp;
86 register struct dmx_softc *sc;
87 {
88 int s, unit, error = 0;
89 int dmxparam();
90
91 s = spltty();
92 if ((sc->dmx_flags & DMX_ACTIVE) == 0) {
93 sc->dmx_octet->csr |= DMF_IE;
94 sc->dmx_flags |= DMX_ACTIVE;
95 sc->dmx_octet->rsp = dmx_timeout;
96 }
97 splx(s);
98 if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
99 return (EBUSY);
100 /*
101 * If this is first open, initialize tty state to default.
102 */
103 if ((tp->t_state&TS_ISOPEN) == 0) {
104 tp->t_state |= TS_WOPEN;
105 ttychars(tp);
106 #ifndef PORTSELECTOR
107 if (tp->t_ispeed == 0) {
108 #endif
109 tp->t_iflag = TTYDEF_IFLAG;
110 tp->t_oflag = TTYDEF_OFLAG;
111 tp->t_cflag = TTYDEF_CFLAG;
112 tp->t_lflag = LFLAG;
113 tp->t_ispeed = tp->t_ospeed = ISPEED;
114 #ifdef PORTSELECTOR
115 tp->t_cflag |= HUPCL;
116 #else
117 }
118 #endif
119 }
120 dmxparam(tp, &tp->t_termios);
121
122 unit = minor(tp->t_dev) & 07;
123 /*
124 * Wait for carrier, then process line discipline specific open.
125 */
126 s = spltty();
127 for (;;) {
128 if ((dmxmctl(tp, DMF_ON, DMSET) & DMF_CAR) ||
129 (sc->dmx_softCAR & (1 << unit)))
130 tp->t_state |= TS_CARR_ON;
131 if (tp->t_state&TS_CARR_ON || flag&O_NONBLOCK ||
132 tp->t_cflag&CLOCAL)
133 break;
134 tp->t_state |= TS_WOPEN;
135 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
136 ttopen, 0))
137 break;
138 }
139 splx(s);
140 if (error)
141 return (error);
142 return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp));
143 }
144
145 dmxclose(tp, flag)
146 struct tty *tp;
147 int flag;
148 {
149
150 (*linesw[tp->t_line].l_close)(tp, flag);
151 (void) dmxmctl(tp, DMF_BRK, DMBIC);
152 if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)
153 (void) dmxmctl(tp, DMF_OFF, DMSET);
154 return (ttyclose(tp));
155 }
156
dmxrint(sc)157 dmxrint(sc)
158 register struct dmx_softc *sc;
159 {
160 register c, cc;
161 register struct tty *tp;
162 register struct dmx_octet *addr;
163 int unit;
164 int overrun = 0;
165
166 addr = (struct dmx_octet *)sc->dmx_octet;
167 /*
168 * Loop fetching characters from the silo for this
169 * octet until there are no more in the silo.
170 */
171 while ((c = addr->rbuf) < 0) {
172 cc = c&0xff;
173 unit = (c >> 8) & 07;
174 tp = sc->dmx_tty + unit;
175 if (c & DMF_DSC) {
176 addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
177 if (addr->rmstsc & DMF_CAR)
178 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
179 else if ((sc->dmx_softCAR & (1 << unit)) == 0 &&
180 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
181 addr->csr = DMF_IE | DMFIR_LCR | unit;
182 addr->lctms = DMF_ENA;
183 }
184 continue;
185 }
186 if ((tp->t_state&TS_ISOPEN) == 0) {
187 wakeup((caddr_t)&tp->t_rawq);
188 #ifdef PORTSELECTOR
189 if ((tp->t_state & TS_WOPEN) == 0)
190 #endif
191 continue;
192 }
193 if (c & (DMF_PE|DMF_DO|DMF_FE)) {
194 if (c & DMF_PE)
195 cc |= TTY_PE;
196 if ((c & DMF_DO) && overrun == 0) {
197 log(LOG_WARNING,
198 "dm%c%d: silo overflow, line %d\n",
199 sc->dmx_type, sc->dmx_unit,
200 sc->dmx_unit0 + unit);
201 overrun = 1;
202 }
203 if (c & DMF_FE)
204 cc |= TTY_FE;
205 }
206 (*linesw[tp->t_line].l_rint)(cc, tp);
207 }
208 }
209
dmxioctl(tp,cmd,data,flag)210 dmxioctl(tp, cmd, data, flag)
211 register struct tty *tp;
212 caddr_t data;
213 {
214 int error;
215
216 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
217 if (error >= 0)
218 return (error);
219 error = ttioctl(tp, cmd, data, flag);
220 if (error >= 0)
221 return (error);
222
223 switch (cmd) {
224
225 case TIOCSBRK:
226 (void) dmxmctl(tp, DMF_BRK, DMBIS);
227 break;
228
229 case TIOCCBRK:
230 (void) dmxmctl(tp, DMF_BRK, DMBIC);
231 break;
232
233 case TIOCSDTR:
234 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS);
235 break;
236
237 case TIOCCDTR:
238 (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC);
239 break;
240
241 case TIOCMSET:
242 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET);
243 break;
244
245 case TIOCMBIS:
246 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS);
247 break;
248
249 case TIOCMBIC:
250 (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC);
251 break;
252
253 case TIOCMGET:
254 *(int *)data = dmxmctl(tp, 0, DMGET);
255 break;
256
257 default:
258 return (ENOTTY);
259 }
260 return (0);
261 }
262
263 /*
264 * modem control
265 * "bits" are dmf/dmz lcr format;
266 * return of DMGET is DM11 format.
267 */
268 dmxmctl(tp, bits, how)
269 struct tty *tp;
270 int bits, how;
271 {
272 register struct dmx_octet *addr;
273 register int unit, mbits, lcr;
274 int s;
275
276 unit = minor(tp->t_dev) & 07;
277 addr = (struct dmx_octet *)(tp->t_addr);
278
279 s = spltty();
280 addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
281 mbits = addr->rmstsc & 0xff00;
282 addr->csr = DMF_IE | DMFIR_LCR | unit;
283 lcr = addr->lctms;
284
285 switch (how) {
286 case DMSET:
287 lcr = bits;
288 break;
289
290 case DMBIS:
291 lcr |= bits;
292 break;
293
294 case DMBIC:
295 lcr &= ~bits;
296 break;
297
298 case DMGET:
299 splx(s);
300 return (dmxtodm(mbits, lcr));
301 }
302 addr->lctms = lcr;
303 (void) splx(s);
304 return (mbits);
305 }
306
307 /*
308 * Routine to convert modem status from dm to dmf/dmz lctmr format.
309 */
dmtodmx(bits)310 dmtodmx(bits)
311 register int bits;
312 {
313 register int lcr = DMF_ENA;
314
315 if (bits & DML_DTR)
316 lcr |= DMF_DTR;
317 if (bits & DML_RTS)
318 lcr |= DMF_RTS;
319 if (bits & DML_ST)
320 lcr |= DMF_SRTS;
321 if (bits & DML_USR)
322 lcr |= DMF_USRW;
323 return (lcr);
324 }
325
326 /*
327 * Routine to convert modem status from dmf/dmz receive modem status
328 * and line control register to dm format.
329 * If dmf/dmz user modem read bit set, set DML_USR.
330 */
dmxtodm(mstat,lcr)331 dmxtodm(mstat, lcr)
332 register int mstat, lcr;
333 {
334
335 mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) |
336 ((mstat & DMF_USRR) >> 1) | DML_LE;
337 if (lcr & DMF_DTR)
338 mstat |= DML_DTR;
339 if (lcr & DMF_SRTS)
340 mstat |= DML_ST;
341 if (lcr & DMF_RTS)
342 mstat |= DML_RTS;
343 return (mstat);
344 }
345
346
347 /*
348 * Set parameters from open or ioctl into the hardware registers.
349 */
dmxparam(tp,t)350 dmxparam(tp, t)
351 register struct tty *tp;
352 register struct termios *t;
353 {
354 register struct dmx_octet *addr;
355 register int lpar, lcr;
356 register int cflag = t->c_cflag;
357 int s, unit;
358 int ispeed = ttspeedtab(t->c_ispeed, dmxspeedtab);
359 int ospeed = ttspeedtab(t->c_ospeed, dmxspeedtab);
360
361 /* check requested parameters */
362 if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5)
363 return(EINVAL);
364 if (ispeed == 0)
365 ispeed = ospeed;
366 /* and copy to tty */
367 tp->t_ispeed = t->c_ispeed;
368 tp->t_ospeed = t->c_ospeed;
369 tp->t_cflag = cflag;
370
371 addr = (struct dmx_octet *)tp->t_addr;
372 unit = minor(tp->t_dev) & 07;
373 /*
374 * Block interrupts so parameters will be set
375 * before the line interrupts.
376 */
377 s = spltty();
378 addr->csr = unit | DMFIR_LCR | DMF_IE;
379 if (ospeed == 0) {
380 tp->t_cflag |= HUPCL;
381 (void) dmxmctl(tp, DMF_OFF, DMSET);
382 splx(s);
383 return;
384 }
385 lpar = (ospeed<<12) | (ispeed<<8);
386 lcr = DMF_ENA;
387 switch (cflag&CSIZE) {
388 case CS6: lpar |= BITS6; break;
389 case CS7: lpar |= BITS7; break;
390 case CS8: lpar |= BITS8; break;
391 }
392 if (cflag&PARENB)
393 lpar |= PENABLE;
394 if (!(cflag&PARODD))
395 lpar |= EPAR;
396 if (cflag&CSTOPB)
397 lpar |= TWOSB;
398
399 lpar |= (unit&07);
400 addr->lpr = lpar;
401 addr->lctms = (addr->lctms &~ 0xff) | lcr;
402 splx(s);
403 return 0;
404 }
405
406 /*
407 * Process a transmit interrupt on an octet.
408 */
dmxxint(sc)409 dmxxint(sc)
410 register struct dmx_softc *sc;
411 {
412 register struct tty *tp;
413 register struct dmx_octet *addr;
414 register int t;
415
416 addr = (struct dmx_octet *)sc->dmx_octet;
417 while ((t = addr->csr) & DMF_TI) {
418 if (t & DMF_NXM)
419 /* SHOULD RESTART OR SOMETHING... */
420 printf("dm%c%d: NXM line %d\n", sc->dmx_type,
421 sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7));
422 t = t >> 8 & 7;
423 tp = sc->dmx_tty + t;
424 tp->t_state &= ~TS_BUSY;
425 if (tp->t_state & TS_FLUSH)
426 tp->t_state &= ~TS_FLUSH;
427 #define new
428 #ifndef new
429 else if (sc->dmx_dmacount[t]) {
430 short cntr;
431
432 /*
433 * Do arithmetic in a short to make up
434 * for lost 16&17 bits.
435 */
436 addr->csr = DMFIR_TBA | DMF_IE | t;
437 cntr = addr->tba -
438 UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
439 ndflush(&tp->t_outq, (int)cntr);
440 }
441 #else
442 else if (sc->dmx_dmacount[t])
443 ndflush(&tp->t_outq, sc->dmx_dmacount[t]);
444 sc->dmx_dmacount[t] = 0;
445 #endif
446 (*linesw[tp->t_line].l_start)(tp);
447 }
448 }
449
dmxstart(tp,sc)450 dmxstart(tp, sc)
451 register struct tty *tp;
452 struct dmx_softc *sc;
453 {
454 register struct dmx_octet *addr;
455 register int unit, nch;
456 int s;
457
458 unit = minor(tp->t_dev) & 07;
459 addr = (struct dmx_octet *)tp->t_addr;
460
461 /*
462 * Must hold interrupts in following code to prevent
463 * state of the tp from changing.
464 */
465 s = spltty();
466 /*
467 * If it's currently active, or delaying, no need to do anything.
468 */
469 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
470 goto out;
471 /*
472 * If there are still characters to dma or in the silo,
473 * just reenable the transmitter.
474 */
475 addr->csr = DMF_IE | DMFIR_TBUF | unit;
476 #ifdef new
477 if (addr->tsc || sc->dmx_dmacount[unit]) {
478 #else
479 if (addr->tsc) {
480 #endif
481 addr->csr = DMF_IE | DMFIR_LCR | unit;
482 addr->lctms = addr->lctms | DMF_TE;
483 tp->t_state |= TS_BUSY;
484 goto out;
485 }
486 /*
487 * If there are sleepers, and output has drained below low
488 * water mark, wake up the sleepers.
489 */
490 if (tp->t_outq.c_cc <= tp->t_lowat) {
491 if (tp->t_state & TS_ASLEEP) {
492 tp->t_state &= ~TS_ASLEEP;
493 wakeup((caddr_t)&tp->t_outq);
494 }
495 if (tp->t_wsel) {
496 selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
497 tp->t_wsel = 0;
498 tp->t_state &= ~TS_WCOLL;
499 }
500 }
501 /*
502 * Now restart transmission unless the output queue is
503 * empty.
504 */
505 if (tp->t_outq.c_cc == 0)
506 goto out;
507 if (1 || !(tp->t_oflag&OPOST)) /*XXX*/
508 nch = ndqb(&tp->t_outq, 0);
509 else {
510 if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
511 /*
512 * If first thing on queue is a delay process it.
513 */
514 nch = getc(&tp->t_outq);
515 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
516 tp->t_state |= TS_TIMEOUT;
517 goto out;
518 }
519 }
520 /*
521 * If characters to transmit, restart transmission.
522 */
523 if (nch >= dmx_mindma) {
524 register car;
525
526 sc->dmx_dmacount[unit] = nch;
527 addr->csr = DMF_IE | DMFIR_LCR | unit;
528 addr->lctms = addr->lctms | DMF_TE;
529 car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
530 addr->csr = DMF_IE | DMFIR_TBA | unit;
531 addr->tba = car;
532 addr->tcc = ((car >> 2) & 0xc000) | nch;
533 tp->t_state |= TS_BUSY;
534 } else if (nch) {
535 register char *cp = tp->t_outq.c_cf;
536 register int i;
537
538 #ifndef new
539 sc->dmx_dmacount[unit] = 0;
540 #endif
541 nch = MIN(nch, DMF_SILOCNT);
542 addr->csr = DMF_IE | DMFIR_LCR | unit;
543 addr->lctms = addr->lctms | DMF_TE;
544 addr->csr = DMF_IE | DMFIR_TBUF | unit;
545 for (i = 0; i < nch; i++)
546 addr->tbuf = *cp++;
547 ndflush(&tp->t_outq, nch);
548 tp->t_state |= TS_BUSY;
549 }
550 out:
551 splx(s);
552 }
553
dmxstop(tp,sc,flag)554 dmxstop(tp, sc, flag)
555 register struct tty *tp;
556 struct dmx_softc *sc;
557 {
558 register struct dmx_octet *addr;
559 register unit = minor(tp->t_dev) & 7;
560 int s;
561
562 addr = (struct dmx_octet *)tp->t_addr;
563 /*
564 * Block input/output interrupts while messing with state.
565 */
566 s = spltty();
567 if (flag) {
568 addr->csr = DMF_IE | DMFIR_TBUF | unit;
569 if (addr->tsc) {
570 /*
571 * Flush regardless of whether we're transmitting
572 * (TS_BUSY), if the silo contains untransmitted
573 * characters.
574 */
575 addr->csr = DMFIR_LCR | unit | DMF_IE;
576 addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH;
577 /* this will interrupt so let dmxxint handle the rest */
578 tp->t_state |= TS_FLUSH|TS_BUSY;
579 }
580 /*#ifdef new*/
581 sc->dmx_dmacount[unit] = 0;
582 /*#endif*/
583 } else {
584 /*
585 * Stop transmission by disabling
586 * the transmitter. We'll pick up where we
587 * left off by reenabling in dmxstart.
588 */
589 addr->csr = DMFIR_LCR | unit | DMF_IE;
590 addr->lctms = addr->lctms &~ DMF_TE;
591 /* no interrupt here */
592 tp->t_state &= ~TS_BUSY;
593 }
594 splx(s);
595 }
596 #endif NDMF + NDMZ
597