xref: /csrg-svn/sys/vax/uba/dmz.c (revision 25396)
1 /*
2  * Copyright (c) 1985 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  *	@(#)dmz.c	6.2 (Berkeley) 11/04/85
7  */
8 
9 /*
10  * DMZ-32 driver
11  * HISTORY
12  * 23-Apr-85  Joe Camaratta (jcc) at Siemens RTL
13  *	Driver for DEC's DMZ32 24-line asynchronous multiplexor.
14  *	Based on Chris Maloney's driver for DEC's DMF32
15  *	NOTE: The modem control routines have NOT been tested yet!!!
16  *
17  * 9-Aug-85	Mike Meyer (mwm) at ucb
18  *	Mangled into shape for 4.3.
19  */
20 
21 #include "dmz.h"
22 #if NDMZ > 0
23 
24 
25 #include "../machine/pte.h"
26 
27 
28 #include "bk.h"
29 #include "uba.h"
30 #include "param.h"
31 #include "conf.h"
32 #include "dir.h"
33 #include "user.h"
34 #include "ioctl.h"
35 #include "tty.h"
36 #include "map.h"
37 #include "buf.h"
38 #include "vm.h"
39 #include "bkmac.h"
40 #include "clist.h"
41 #include "file.h"
42 #include "uio.h"
43 #include "kernel.h"
44 
45 #include "ubareg.h"
46 #include "ubavar.h"
47 #include "dmzreg.h"
48 
49 int dmzprobe(), dmzattach(), dmzrint(), dmzxint();
50 struct uba_device *dmzinfo[NDMZ];
51 u_short dmzstd[] = {0, 0};
52 struct uba_driver dmzdriver = {
53 	dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo
54 };
55 
56 #define	NDMZLINES	(NDMZ*24)
57 
58 int ttrstrt();
59 struct tty dmz_tty[NDMZLINES];
60 
61 int dmzsoftCAR[NDMZ];
62 
63 struct {
64 	char dmz_state;		/* dmz state */
65 	int dmz_count;		/* dmz dma count */
66 } dmz_softc[NDMZ*24];
67 
68 #define	ST_TXOFF	(0x01)	/* transmission turned off (^S) */
69 #define	ST_DMA		(0x02)	/* dma inprogress */
70 #define	ST_INBUSY	(0x04)	/* stop transmission in busy */
71 
72 char dmz_speeds[] = {
73 	0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0
74 };
75 
76 #ifndef	PORTSELECTOR
77 #define	ISPEED	B9600
78 #define	IFLAGS	(EVENP|ODDP|ECHO)
79 #else
80 #define	ISPEED	B4800
81 #define	IFLAGS	(EVENP|ODDP)
82 #endif
83 
84 #ifndef lint
85 int ndmz = NDMZLINES;		/* Used by pstat/iostat */
86 #endif
87 
88 short dmzact[NDMZ];		/* Mask of active octets on the dmz */
89 int dmzstart();
90 
91 /*
92  * SILO_TIMEOUT represents the number of milliseconds characters can sit
93  * in the input silo without causing an interrupt.  If data overruns or
94  * slow XON/XOFF occur, set it lower but AT LEAST equal to 1.
95  */
96 #define	SILO_TIMEOUT	(3)
97 
98 /*
99  * DO_DMA_COUNT represents the threshold of the number of output
100  * characters beyond which the driver uses DMA mode.
101  */
102 #define	DO_DMA_COUNT	(10)
103 
104 #define	TRUE		(1)
105 #define	FALSE		(0)
106 
107 static int cbase[NUBA];		/* base address in unibus map */
108 int dmz_ubinfo[NUBA];		/* info about allocated unibus map */
109 
110 #define	UBACVT(x, uban)	    (cbase[uban] + ((x) - (char *)cfree))
111 
112 /* These flags are for debugging purposes only */
113 int dmz_dma_on = 1;
114 int dmz_debug_level;
115 
116 dmzprobe(reg)
117 	caddr_t reg;
118 {
119 	register int br, cvec;
120 	register struct dmzdevice *dmz_addr;
121 	register unsigned int a;
122 
123 	dmz_addr = (struct dmzdevice *)reg;
124 
125 #ifdef lint
126 	br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0);
127 	dmzrinta(0); dmzrintb(0); dmzrintc(0);
128 #endif
129 
130 	br = 0x15;
131 
132 	a = dmz_addr->dmz_config;
133 	if (((a>>12) & ~DMZ_INTERFACE) != 0) {
134 		printf("	Unknown interface type\n");
135 		return (0);
136 	}
137 	if (((a>>8) & DMZ_NOC_MASK) != 3) {
138 		printf("	Not all octets are available\n");
139 		return (0);
140 	}
141 
142 	cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6);
143 	dmz_addr->dmz_config = cvec >> 2;
144 
145 	return (sizeof(struct dmzdevice));
146 }
147 
148 dmzattach(ui)
149 	struct uba_device *ui;
150 {
151 	dmzsoftCAR[ui->ui_unit] = ui->ui_flags;
152 	return;
153 }
154 
155 /* ARGSUSED */
156 dmzopen(device, flag)
157 	dev_t device;
158 	int flag;
159 {
160 	register struct tty *tp;
161 	register int unit, controller;
162 	register struct dmzdevice *dmz_addr;
163 	register struct uba_device *ui;
164 	int priority;
165 	int xstatus;
166 	int octet;
167 
168 	unit = minor(device);
169 	controller = DMZ(unit);
170 	octet = OCTET(unit);
171 
172 	if (unit >= NDMZLINES ||
173 	    (ui = dmzinfo[controller]) == 0 ||
174 	    ui->ui_alive == 0)
175 		return (ENXIO);
176 
177 	tp = &dmz_tty[unit];
178 
179 	if ((tp->t_state & TS_XCLUDE) && u.u_uid != 0)
180 		return (EBUSY);
181 
182 	dmz_addr = (struct dmzdevice *)ui->ui_addr;
183 	tp->t_addr = (caddr_t)dmz_addr;
184 	tp->t_oproc = dmzstart;
185 	tp->t_state |= TS_WOPEN;
186 
187 	/*
188 	 * Set up Unibus map registers.  Block uba resets, which can
189 	 * clear the state.
190 	 */
191 	priority = spl5();
192 	if (dmz_ubinfo[ui->ui_ubanum] == 0) {
193 		dmz_ubinfo[ui->ui_ubanum] =
194 			uballoc(ui->ui_ubanum, (caddr_t)cfree,
195 				nclist * sizeof(struct cblock), 0);
196 		if (dmz_ubinfo[ui->ui_ubanum] == 0) {
197 			splx(priority);
198 			printf("dmz: insufficient unibus map regs\n");
199 			return (-1); /* Is this the right thing to return? */
200 		}
201 		cbase[ui->ui_ubanum] = dmz_ubinfo[ui->ui_ubanum] & 0x3ffff;
202 	}
203 
204 	if ((dmzact[controller] & (1 << octet)) == 0) {
205 		dmz_addr->octet[octet].octet_csr |= DMZ_IE;
206 		dmzact[controller] |= 1 << octet;
207 		dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT;
208 	}
209 
210 	splx(priority);
211 
212 	if ((tp->t_state & TS_ISOPEN) == 0) {
213 		ttychars(tp);
214 		tp->t_ispeed = tp->t_ospeed = ISPEED;
215 		tp->t_flags = IFLAGS;
216 		dmzparam(unit);
217 		dmz_softc[unit].dmz_state = 0;
218 	}
219 
220 	/*
221 	 * Wait for carrier, then process line discipline specific open.
222 	 */
223 	if ((dmzmctl(device, DMZ_ON, DMSET) & (DMZ_CAR << 8)) ||
224 	    (dmzsoftCAR[controller] & (1 << (unit % 24))))
225 		tp->t_state |= TS_CARR_ON;
226 	priority = spl5();
227 	while ((tp->t_state & TS_CARR_ON) == 0) {
228 		tp->t_state |= TS_WOPEN;
229 		sleep((caddr_t) &tp->t_rawq, TTIPRI);
230 	}
231 	splx(priority);
232 
233 	xstatus = (*linesw[tp->t_line].l_open)(device, tp);
234 	return (xstatus);
235 }
236 
237 dmzparam(unit)
238 	register int unit;
239 {
240 	register struct tty *tp;
241 	register struct dmzdevice *dmz_addr;
242 	register int line_parameters, line_control;
243 	register int octet;
244 	int priority;
245 
246 	octet = OCTET(unit);
247 
248 	tp = &dmz_tty[unit];
249 	dmz_addr = (struct dmzdevice *)tp->t_addr;
250 
251 	priority = spl5();
252 	if ((tp->t_ispeed) == 0) {
253 		tp->t_state |= TS_HUPCLS;
254 		(void) dmzmctl(unit, DMZ_OFF, DMSET);
255 		splx(priority);
256 		return;
257 	}
258 
259 	line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8);
260 	line_control = DMZ_LCE;
261 
262 	if ((tp->t_ispeed) == B134)
263 		line_parameters |= DMZ_6BT | DMZ_PEN;
264 	else if (tp->t_flags & (RAW | LITOUT))
265 		line_parameters |= DMZ_8BT;
266 	else
267 		line_parameters |= DMZ_7BT | DMZ_PEN;
268 
269 	if (tp->t_flags & EVENP)
270 		line_parameters |= DMZ_EPR;
271 	if ((tp->t_ospeed) == B110)
272 		line_parameters |= DMZ_SCD;
273 
274 	line_parameters |= (unit & 07);
275 
276 	dmz_addr->octet[octet].octet_lprm = line_parameters;
277 	dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07);
278 	dmz_addr->octet[octet].octet_lctmr =
279 	    (dmz_addr->octet[octet].octet_lctmr | (line_control & 0xff));
280 
281 	splx(priority);
282 	return;
283 }
284 
285 /* ARGSUSED */
286 dmzclose(device, flag)
287 	dev_t device;
288 	int flag;
289 {
290 	register struct  tty *tp;
291 	register int unit;
292 
293 	unit = minor(device);
294 	tp = &dmz_tty[unit];
295 
296 	/*
297 	 * Break, hang-up and close the modem.
298 	 */
299 	(void) dmzmctl(unit, DMZ_BRK, DMBIC);
300 	if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
301 		(void) dmzmctl(unit, DMZ_OFF, DMSET);
302 	ttyclose(tp);
303 	return;
304 }
305 
306 dmzreset(uban)
307 	int uban;
308 {
309 	register int controller, unit;
310 	register struct tty *tp;
311 	register struct uba_device *ui;
312 	register struct dmzdevice *dmz_addr;
313 	int i;
314 	int octet;
315 
316 	if (dmz_ubinfo[uban] == 0)
317 		return;
318 
319 	dmz_ubinfo[uban] = uballoc(uban, (caddr_t) cfree, nclist * sizeof(struct cblock), 0);
320 	cbase[uban] = dmz_ubinfo[uban] & 0x3ffff;
321 
322 	for (controller = 0; controller < NDMZ; controller++) {
323 		ui = dmzinfo[controller];
324 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
325 			continue;
326 		printf("dmz%d ", controller);
327 		dmz_addr = (struct dmzdevice *) ui->ui_addr;
328 
329 		for (octet = 0; octet < 3; octet++)
330 			if ((dmzact[controller] & (1 << octet)) != 0) {
331 				dmz_addr->octet[octet].octet_csr |= DMZ_IE;
332 				dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT;
333 			}
334 
335 		unit = controller * 24;
336 
337 		/*
338 		 * If a unit is open or waiting for open to complete,
339 		 * reset it.
340 		 */
341 		for (i = 0; i < 24; i++) {
342 			dmz_softc[unit].dmz_state = 0;
343 			tp = &dmz_tty[unit];
344 			if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) {
345 				dmzparam(unit);
346 				(void) dmzmctl(unit, DMZ_ON, DMSET);
347 				tp->t_state &= ~TS_BUSY;
348 				dmzstart(tp);
349 			}
350 			unit++;
351 		}
352 	}
353 	return;
354 }
355 
356 dmzread(device, uio)
357 	dev_t device;
358 	struct uio *uio;
359 {
360 	register struct tty *tp;
361 	int xstatus;
362 
363 	tp = &dmz_tty[minor(device)];
364 	xstatus = (*linesw[tp->t_line].l_read)(tp, uio);
365 	return (xstatus);
366 }
367 
368 dmzwrite(device, uio)
369 	dev_t device;
370 	struct uio *uio;
371 {
372 	register struct tty *tp;
373 	int xstatus;
374 
375 	tp = &dmz_tty[minor(device)];
376 	xstatus = (*linesw[tp->t_line].l_write)(tp, uio);
377 	return (xstatus);
378 }
379 
380 dmzrinta(controller)
381 	int controller;
382 {
383 	dmzrint(controller, 0);
384 }
385 
386 dmzrintb(controller)
387 	int controller;
388 {
389 	dmzrint(controller, 1);
390 }
391 
392 dmzrintc(controller)
393 	int controller;
394 {
395 	dmzrint(controller, 2);
396 }
397 
398 dmzrint(controller, octet)
399 	int controller;
400 	register int octet;
401 {
402 	register struct tty *tp;
403 	register int character;
404 	register struct dmzdevice *dmz_addr;
405 	register struct tty *tp0;
406 	register int unit;
407 	register struct uba_device *ui;
408 	int overrun;
409 
410 	overrun = 0;
411 	ui = dmzinfo[controller];
412 	if (ui == 0 || ui->ui_alive == 0)
413 		return;
414 	dmz_addr = (struct dmzdevice *) ui->ui_addr;
415 	tp0 = &dmz_tty[controller * 24];
416 
417 	while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) {
418 		unit = (character >> 8) & 07;	/* unit is bits 8-10 of rb */
419 		tp = tp0 + (octet * 8 + unit);
420 
421 		if (character & DMZ_DSC &&
422 		    (dmzsoftCAR[controller] & (1 << (octet * 8 + unit))) == 0) {
423 			dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMS | unit;
424 			if (dmz_addr->octet[octet].octet_rms & DMZ_CAR)
425 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
426 			else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
427 				dmz_addr->octet[octet].octet_csr =
428 				   DMZ_IE | IR_LCTMR | unit;
429 				dmz_addr->octet[octet].octet_lctmr =
430 				   dmz_addr->octet[octet].octet_lctmr &
431 				   ((DMZ_OFF<<8) | 0xff);
432 			}
433 			continue;
434 		}
435 
436 		if ((tp->t_state&TS_ISOPEN)==0) {
437 			wakeup((caddr_t)&tp->t_rawq);
438 #ifdef PORTSELECTOR
439 			if ((tp->t_state&TS_WOPEN) == 0)
440 #endif
441 				continue;
442 		}
443 
444 		if (character & DMZ_PE) {
445 			if ((tp->t_flags & (EVENP | ODDP)) == EVENP ||
446 			    (tp->t_flags & (EVENP | ODDP)) == ODDP)
447 				continue;
448 		}
449 
450 		if ((character & DMZ_DO) && overrun == 0) {
451 			printf("dmz%d: silo overflow\n", controller);
452 			overrun = 1;
453 		}
454 
455 		if (character & DMZ_FE) {
456 			if (tp->t_flags & RAW)
457 				character = 0;
458 			else
459 				character = tp->t_intrc;
460 		}
461 
462 		(*linesw[tp->t_line].l_rint)(character, tp);
463 	}
464 
465 	return;
466 }
467 
468 dmzxinta(controller)
469 	int controller;
470 {
471 	dmzxint(controller, 0);
472 }
473 
474 dmzxintb(controller)
475 	int controller;
476 {
477 	dmzxint(controller, 1);
478 }
479 
480 dmzxintc(controller)
481 	int controller;
482 {
483 	dmzxint(controller, 2);
484 }
485 
486 dmzxint(controller, octet)
487 	int controller;
488 	register int octet;
489 {
490 	register struct tty *tp;
491 	register struct dmzdevice *dmz_addr;
492 	register struct uba_device *ui;
493 	register int unit, t;
494 	int priority;
495 
496 	ui = dmzinfo[controller];
497 	dmz_addr = (struct dmzdevice *)ui->ui_addr;
498 
499 	priority = spl5();
500 
501 	while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) {
502 		unit = controller * 24 + (octet * 8 + ((t>>8) & 07));
503 		tp = &dmz_tty[unit];
504 		tp->t_state &= ~TS_BUSY;
505 
506 		if (t & DMZ_NXM)
507 			printf("dmz%d: NXM line %d\n", controller,
508 				octet * 8 + (unit & 07));
509 
510 		if (tp->t_state & TS_FLUSH) {
511 			tp->t_state &= ~TS_FLUSH;
512 			dmz_addr->octet[octet].octet_csr =
513 				DMZ_IE | IR_LCTMR | (unit & 07);
514 			dmz_addr->octet[octet].octet_lctmr =
515 				(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
516 		} else
517 			if (dmz_softc[unit].dmz_state & ST_DMA)
518 				ndflush(&tp->t_outq, dmz_softc[unit].dmz_count);
519 		dmz_softc[unit].dmz_state = 0;
520 
521 		if (tp->t_line)
522 			(*linesw[tp->t_line].l_start)(tp);
523 		else
524 			dmzstart(tp);
525 	}
526 
527 	splx(priority);
528 	return;
529 }
530 
531 dmzstart(tp)
532 	register struct tty *tp;
533 {
534 	register struct dmzdevice *dmz_addr;
535 	register int unit, nch, room;
536 	int controller, octet;
537 	int priority, car, use_dma;
538 	register int i;
539 	register char *cp;
540 
541 	unit = minor(tp->t_dev);
542 	controller = DMZ(unit);
543 	octet = OCTET(unit);
544 	dmz_addr = (struct dmzdevice *)tp->t_addr;
545 
546 	priority = spl5();
547 
548 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
549 		goto out;
550 
551 	/*
552 	 * If the transmitter has been disabled, reenable it.
553 	 * If the transmitter was disabled before the xint (the
554 	 * ST_INBUSY was still on), then reset the BUSY state and
555 	 * we will wait for the interrupt.  If !TS_BUSY, we already
556 	 * saw the interrupt so we can start another transmission.
557 	 */
558 	if (dmz_softc[unit].dmz_state & ST_TXOFF) {
559 		dmz_addr->octet[octet].octet_csr =
560 			DMZ_IE | IR_LCTMR | (unit & 07);
561 		dmz_addr->octet[octet].octet_lctmr =
562 			(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
563 		dmz_softc[unit].dmz_state &= ~ST_TXOFF;
564 		if (dmz_softc[unit].dmz_state & ST_INBUSY) {
565 			dmz_softc[unit].dmz_state &= ~ST_INBUSY;
566 			tp->t_state |= TS_BUSY;
567 			goto out;
568 		}
569 	}
570 
571 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
572 		if (tp->t_state & TS_ASLEEP) {
573 			tp->t_state &= ~TS_ASLEEP;
574 			wakeup((caddr_t)&tp->t_outq);
575 		}
576 		if (tp->t_wsel) {
577 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
578 			tp->t_wsel = 0;
579 			tp->t_state &= ~TS_WCOLL;
580 		}
581 	}
582 
583 	if (tp->t_outq.c_cc == 0)
584 		goto out;
585 	if (tp->t_flags & (RAW | LITOUT))
586 		nch = ndqb(&tp->t_outq, 0);
587 	else {
588 		nch = ndqb(&tp->t_outq, 0200);
589 		if (nch == 0) {
590 			nch = getc(&tp->t_outq);
591 			timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6);
592 			tp->t_state |= TS_TIMEOUT;
593 			goto out;
594 		}
595 	}
596 
597 	/*
598 	 * Should we use DMA or SILO mode?
599 	 * If nch is greater than DO_DMA_COUNT then DMA.
600 	 */
601 	if (nch) {
602 		dmz_addr->octet[octet].octet_csr =
603 			DMZ_IE | IR_LCTMR | (unit & 07);
604 		dmz_addr->octet[octet].octet_lctmr =
605 			(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
606 		tp->t_state |= TS_BUSY;
607 
608 		use_dma = FALSE;
609 		room = DMZ_SIZ;
610 
611 		if (nch > DO_DMA_COUNT)
612 			use_dma = TRUE;
613 
614 		if (use_dma && dmz_dma_on) {
615 			car = UBACVT(tp->t_outq.c_cf,
616 				dmzinfo[controller]->ui_ubanum);
617 			dmz_softc[unit].dmz_count = nch;
618 			dmz_softc[unit].dmz_state |= ST_DMA;
619 			dmz_addr->octet[octet].octet_csr =
620 				DMZ_IE | IR_TBA | (unit & 07);
621 			dmz_addr->octet[octet].octet_tba = car;
622 			dmz_addr->octet[octet].octet_tcc =
623 				((car >> 2) & 0xc000) | nch;
624 		} else {
625 			dmz_softc[unit].dmz_state &= ~ST_DMA;
626 			cp = tp->t_outq.c_cf;
627 			nch = MIN(nch, room);
628 			dmz_addr->octet[octet].octet_csr =
629 				DMZ_IE | IR_TBUF | (unit & 07);
630 			for (i = 0; i < nch; i++)
631 				dmz_addr->octet[octet].octet_tbf = *cp++ ;
632 			ndflush(&tp->t_outq, nch);
633 		}
634 	}
635 
636 out:
637 	splx(priority);
638 	return;
639 }
640 
641 /* ARGSUSED */
642 dmzstop(tp, flag)
643 	register struct tty *tp;
644 {
645 	register struct dmzdevice *dmz_addr;
646 	register int unit, priority, octet;
647 
648 	priority = spl5();
649 	dmz_addr = (struct dmzdevice *) tp->t_addr;
650 	unit = minor(tp->t_dev);
651 	octet = OCTET(unit);
652 
653 	dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE;
654 	dmz_addr->octet[octet].octet_lctmr =
655 		(dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE);
656 	dmz_softc[unit].dmz_state |= ST_TXOFF;
657 	if ((tp->t_state & TS_TTSTOP) == 0) {
658 		tp->t_state |= (TS_FLUSH | TS_BUSY);
659 		dmz_addr->octet[octet].octet_lctmr =
660 			(dmz_addr->octet[octet].octet_lctmr | DMZ_FLS);
661 	} else if (tp->t_state & TS_BUSY) {
662 		dmz_softc[unit].dmz_state |= ST_INBUSY;
663 		tp->t_state &= ~TS_BUSY;
664 	}
665 
666 	splx(priority);
667 	return;
668 }
669 
670 /* ARGSUSED */
671 dmzioctl(device, command, data, flag)
672 	dev_t device;
673 	caddr_t data;
674 {
675 	register struct tty *tp;
676 	register int unit;
677 	int error;
678 
679 	unit = minor(device);
680 	tp = &dmz_tty[unit];
681 
682 	error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag);
683 	if (error >= 0)
684 		return (error);
685 	error = ttioctl(tp, command, data, flag);
686 	if (error >= 0) {
687 		if (command == TIOCSETP || command == TIOCSETN)
688 			dmzparam(unit);
689 		return (error);
690 	}
691 
692 	switch (command) {
693 		case TIOCSBRK:
694 			(void) dmzmctl(device, DMZ_BRK, DMBIS);
695 			break;
696 		case TIOCCBRK:
697 			(void) dmzmctl(device, DMZ_BRK, DMBIC);
698 			break;
699 		case TIOCSDTR:
700 			(void) dmzmctl(device, DMZ_DTR | DMZ_RTS, DMBIS);
701 			break;
702 		case TIOCCDTR:
703 			(void) dmzmctl(device, DMZ_DTR | DMZ_RTS, DMBIC);
704 			break;
705 		case TIOCMSET:
706 			(void) dmzmctl(device, dmtodmz(*(int *)data), DMSET);
707 			break;
708 		case TIOCMBIS:
709 			(void) dmzmctl(device, dmtodmz(*(int *)data), DMBIS);
710 			break;
711 		case TIOCMBIC:
712 			(void) dmzmctl(device, dmtodmz(*(int *)data), DMBIC);
713 			break;
714 		case TIOCMGET:
715 			*(int *)data = dmztodm(dmzmctl(device, 0, DMGET));
716 			break;
717 		default:
718 			return (ENOTTY);
719 	}
720 	return (0);
721 }
722 
723 dmzmctl(device, bits, how)
724 	dev_t device;
725 	int bits, how;
726 {
727 	register struct dmzdevice *dmz_addr;
728 	register int unit, modem_status, line_control;
729 	register int temp;
730 	int priority;
731 	int octet;
732 
733 	unit = minor(device);
734 	octet = OCTET(unit);
735 	dmz_addr = (struct dmzdevice *) dmz_tty[unit].t_addr;
736 
737 	priority = spl5();
738 	dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMS | (unit & 07);
739 	modem_status = dmz_addr->octet[octet].octet_rms << 8;
740 
741 	dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07);
742 	temp = dmz_addr->octet[octet].octet_lctmr;
743 	modem_status |= ((temp>>8) & (0x1f));
744 	line_control = (temp & (0x3f));
745 
746 	if (line_control & DMZ_BRK)
747 		modem_status |= DMZ_BRK;
748 
749 	switch (how) {
750 		case DMSET:
751 			modem_status = (modem_status & 0xff00) | bits;
752 			break;
753 		case DMBIS:
754 			modem_status |= bits;
755 			break;
756 		case DMBIC:
757 			modem_status &= ~bits;
758 			break;
759 		case DMGET:
760 			(void) splx(priority);
761 			return (modem_status);
762 	}
763 
764 	if (modem_status & DMZ_BRK)
765 		line_control |= DMZ_RBK;
766 	else
767 		line_control &= ~DMZ_RBK;
768 	modem_status &= ~DMZ_BRK;
769 
770 	dmz_addr->octet[octet].octet_csr =
771 		DMZ_IE | IR_LCTMR | (unit & 07);
772 	dmz_addr->octet[octet].octet_lctmr =
773 		((modem_status & 0x1f) << 8) | (line_control & 0x3f);
774 
775 	(void) splx(priority);
776 	return (modem_status);
777 }
778 
779 /*
780  * Routine to convert modem status from dm to dmz format.
781  * Pull bits 1 & 3 through unchanged. If dm secondary transmit bit is set,
782  * and/or dm request to send bit is set, and/or dm user modem signal bit
783  * is set, set the corresponding dmz bits.
784  */
785 dmtodmz(bits)
786 	register int bits;
787 {
788 	register int b;
789 
790 	b = bits & 012;
791 	if (bits & DM_ST)
792 		b |= DMZ_RAT;
793 	if (bits & DM_RTS)
794 		b |= DMZ_RTS;
795 	if (bits & DM_USR)
796 		b |= DMZ_USW;
797 	return (b);
798 }
799 
800 /*
801  * Routine to convert modem status from dmz to dm format.  Pull bits 1 & 3
802  * through unchanged. Pull bits 11 - 15 through as bits 4 - 8 and set bit
803  * 0 to dm line enable.  If dmz user modem signal bit set, and/or  dmz
804  * request to send bit set, then set the corresponding dm bit also.
805  */
806 dmztodm(bits)
807 	register int bits;
808 {
809 	register int b;
810 
811 	b = (bits & 012) | ((bits >> 7) & 0760) | DM_LE;
812 	if (bits & DMZ_USR)
813 		b |= DM_USR;
814 	if (bits & DMZ_RTS)
815 		b |= DM_RTS;
816 	return (b);
817 }
818 #endif
819