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