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