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