xref: /csrg-svn/sys/vax/uba/dmz.c (revision 26218)
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.5 (Berkeley) 02/17/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 "ioctl.h"
34 #include "tty.h"
35 #include "map.h"
36 #include "buf.h"
37 #include "vm.h"
38 #include "bkmac.h"
39 #include "clist.h"
40 #include "file.h"
41 #include "uio.h"
42 #include "kernel.h"
43 #include "syslog.h"
44 
45 #include "ubareg.h"
46 #include "ubavar.h"
47 #include "dmzreg.h"
48 #include "dmreg.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 	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 		tp->t_ispeed = tp->t_ospeed = ISPEED;
214 		tp->t_flags = IFLAGS;
215 		dmz_softc[unit].dmz_state = 0;
216 	}
217 	dmzparam(unit);
218 
219 	/*
220 	 * Wait for carrier, then process line discipline specific open.
221 	 */
222 	if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) ||
223 	    (dmzsoftCAR[controller] & (1 << (unit % 24))))
224 		tp->t_state |= TS_CARR_ON;
225 	priority = spl5();
226 	while ((tp->t_state & TS_CARR_ON) == 0) {
227 		tp->t_state |= TS_WOPEN;
228 		sleep((caddr_t) &tp->t_rawq, TTIPRI);
229 	}
230 	splx(priority);
231 
232 	return ((*linesw[tp->t_line].l_open)(device, tp));
233 }
234 
235 dmzparam(unit)
236 	register int unit;
237 {
238 	register struct tty *tp;
239 	register struct dmzdevice *dmz_addr;
240 	register int line_parameters;
241 	register int octet;
242 	int priority;
243 
244 	octet = OCTET(unit);
245 
246 	tp = &dmz_tty[unit];
247 	dmz_addr = (struct dmzdevice *)tp->t_addr;
248 
249 	priority = spl5();
250 	if ((tp->t_ispeed) == 0) {
251 		tp->t_state |= TS_HUPCLS;
252 		(void) dmzmctl(unit, DMZ_OFF, DMSET);
253 		splx(priority);
254 		return;
255 	}
256 
257 	line_parameters = (dmz_speeds[tp->t_ospeed] << 12) | (dmz_speeds[tp->t_ispeed] << 8);
258 
259 	if ((tp->t_ispeed) == B134)
260 		line_parameters |= DMZ_6BT | DMZ_PEN;
261 	else if (tp->t_flags & (RAW | LITOUT | PASS8))
262 		line_parameters |= DMZ_8BT;
263 	else
264 		line_parameters |= DMZ_7BT | DMZ_PEN;
265 
266 	if (tp->t_flags & EVENP)
267 		line_parameters |= DMZ_EPR;
268 	if ((tp->t_ospeed) == B110)
269 		line_parameters |= DMZ_SCD;
270 
271 	line_parameters |= (unit & 07);
272 
273 	dmz_addr->octet[octet].octet_lprm = line_parameters;
274 	splx(priority);
275 }
276 
277 /* ARGSUSED */
278 dmzclose(device, flag)
279 	dev_t device;
280 	int flag;
281 {
282 	register struct  tty *tp;
283 	register int unit;
284 
285 	unit = minor(device);
286 	tp = &dmz_tty[unit];
287 	(*linesw[tp->t_line].l_close)(tp);
288 
289 	/*
290 	 * Clear break, hang-up and close the modem.
291 	 */
292 	(void) dmzmctl(unit, DMZ_BRK, DMBIC);
293 	if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
294 		(void) dmzmctl(unit, DMZ_OFF, DMSET);
295 	ttyclose(tp);
296 	return;
297 }
298 
299 dmzreset(uban)
300 	int uban;
301 {
302 	register int controller, unit;
303 	register struct tty *tp;
304 	register struct uba_device *ui;
305 	register struct dmzdevice *dmz_addr;
306 	int i;
307 	int octet;
308 
309 	for (controller = 0; controller < NDMZ; controller++) {
310 		ui = dmzinfo[controller];
311 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
312 			continue;
313 		printf("dmz%d ", controller);
314 		dmz_addr = (struct dmzdevice *) ui->ui_addr;
315 
316 		if (dmz_ubinfo[uban]) {
317 			dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
318 				nclist * sizeof(struct cblock), 0);
319 			cbase[uban] = UBAI_ADDR(dmz_ubinfo[uban]);
320 		}
321 
322 		for (octet = 0; octet < 3; octet++)
323 			if ((dmzact[controller] & (1 << octet)) != 0) {
324 				dmz_addr->octet[octet].octet_csr |= DMZ_IE;
325 				dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT;
326 			}
327 
328 		unit = controller * 24;
329 
330 		/*
331 		 * If a unit is open or waiting for open to complete,
332 		 * reset it.
333 		 */
334 		for (i = 0; i < 24; i++) {
335 			dmz_softc[unit].dmz_state = 0;
336 			tp = &dmz_tty[unit];
337 			if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) {
338 				dmzparam(unit);
339 				(void) dmzmctl(unit, DMZ_ON, DMSET);
340 				tp->t_state &= ~TS_BUSY;
341 				dmzstart(tp);
342 			}
343 			unit++;
344 		}
345 	}
346 	return;
347 }
348 
349 dmzread(device, uio)
350 	dev_t device;
351 	struct uio *uio;
352 {
353 	register struct tty *tp;
354 	int xstatus;
355 
356 	tp = &dmz_tty[minor(device)];
357 	xstatus = (*linesw[tp->t_line].l_read)(tp, uio);
358 	return (xstatus);
359 }
360 
361 dmzwrite(device, uio)
362 	dev_t device;
363 	struct uio *uio;
364 {
365 	register struct tty *tp;
366 	int xstatus;
367 
368 	tp = &dmz_tty[minor(device)];
369 	xstatus = (*linesw[tp->t_line].l_write)(tp, uio);
370 	return (xstatus);
371 }
372 
373 dmzrinta(controller)
374 	int controller;
375 {
376 	dmzrint(controller, 0);
377 }
378 
379 dmzrintb(controller)
380 	int controller;
381 {
382 	dmzrint(controller, 1);
383 }
384 
385 dmzrintc(controller)
386 	int controller;
387 {
388 	dmzrint(controller, 2);
389 }
390 
391 dmzrint(controller, octet)
392 	int controller;
393 	register int octet;
394 {
395 	register struct tty *tp;
396 	register int character;
397 	register struct dmzdevice *dmz_addr;
398 	register struct tty *tp0;
399 	register int unit;
400 	register struct uba_device *ui;
401 	int overrun;
402 
403 	overrun = 0;
404 	ui = dmzinfo[controller];
405 	if (ui == 0 || ui->ui_alive == 0)
406 		return;
407 	dmz_addr = (struct dmzdevice *) ui->ui_addr;
408 	tp0 = &dmz_tty[controller * 24];
409 
410 	while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) {
411 		unit = (character >> 8) & 07;	/* unit is bits 8-10 of rb */
412 		tp = tp0 + (octet * 8 + unit);
413 
414 		if (character & DMZ_DSC) {
415 			dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit;
416 			if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR)
417 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
418 			else if (dmzsoftCAR[controller] &
419 			  (1 << (octet * 8 + unit)) == 0 &&
420 			    (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
421 				(void)dmzmctl(tp - dmz_tty, DMZ_OFF, DMSET);
422 			continue;
423 		}
424 
425 		if ((tp->t_state&TS_ISOPEN)==0) {
426 			wakeup((caddr_t)&tp->t_rawq);
427 #ifdef PORTSELECTOR
428 			if ((tp->t_state&TS_WOPEN) == 0)
429 #endif
430 				continue;
431 		}
432 
433 		if (character & DMZ_PE) {
434 			if ((tp->t_flags & (EVENP | ODDP)) == EVENP ||
435 			    (tp->t_flags & (EVENP | ODDP)) == ODDP)
436 				continue;
437 		}
438 
439 		if ((character & DMZ_DO) && overrun == 0) {
440 			log(LOG_WARNING, "dmz%d: silo overflow\n", controller);
441 			overrun = 1;
442 		}
443 
444 		if (character & DMZ_FE) {
445 			if (tp->t_flags & RAW)
446 				character = 0;
447 			else
448 				character = tp->t_intrc;
449 		}
450 
451 		(*linesw[tp->t_line].l_rint)(character, tp);
452 	}
453 
454 	return;
455 }
456 
457 dmzxinta(controller)
458 	int controller;
459 {
460 	dmzxint(controller, 0);
461 }
462 
463 dmzxintb(controller)
464 	int controller;
465 {
466 	dmzxint(controller, 1);
467 }
468 
469 dmzxintc(controller)
470 	int controller;
471 {
472 	dmzxint(controller, 2);
473 }
474 
475 dmzxint(controller, octet)
476 	int controller;
477 	register int octet;
478 {
479 	register struct tty *tp;
480 	register struct dmzdevice *dmz_addr;
481 	register struct uba_device *ui;
482 	register int unit, t;
483 	int priority;
484 
485 	ui = dmzinfo[controller];
486 	dmz_addr = (struct dmzdevice *)ui->ui_addr;
487 
488 	priority = spl5();
489 
490 	while ((t = dmz_addr->octet[octet].octet_csr) & DMZ_TRDY) {
491 		unit = controller * 24 + (octet * 8 + ((t>>8) & 07));
492 		tp = &dmz_tty[unit];
493 		tp->t_state &= ~TS_BUSY;
494 
495 		if (t & DMZ_NXM)
496 			printf("dmz%d: NXM line %d\n", controller,
497 				octet * 8 + (unit & 07));
498 
499 		if (tp->t_state & TS_FLUSH) {
500 			tp->t_state &= ~TS_FLUSH;
501 			dmz_addr->octet[octet].octet_csr =
502 				DMZ_IE | IR_LCTMR | (unit & 07);
503 			dmz_addr->octet[octet].octet_lctmr =
504 				(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
505 		} else
506 			if (dmz_softc[unit].dmz_state & ST_DMA)
507 				ndflush(&tp->t_outq, dmz_softc[unit].dmz_count);
508 		dmz_softc[unit].dmz_state = 0;
509 
510 		if (tp->t_line)
511 			(*linesw[tp->t_line].l_start)(tp);
512 		else
513 			dmzstart(tp);
514 	}
515 
516 	splx(priority);
517 	return;
518 }
519 
520 dmzstart(tp)
521 	register struct tty *tp;
522 {
523 	register struct dmzdevice *dmz_addr;
524 	register int unit, nch, room;
525 	int controller, octet;
526 	int priority, car, use_dma;
527 	register int i;
528 	register char *cp;
529 
530 	unit = minor(tp->t_dev);
531 	controller = DMZ(unit);
532 	octet = OCTET(unit);
533 	dmz_addr = (struct dmzdevice *)tp->t_addr;
534 
535 	priority = spl5();
536 
537 	if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))
538 		goto out;
539 
540 	/*
541 	 * If the transmitter has been disabled, reenable it.
542 	 * If the transmitter was disabled before the xint (the
543 	 * ST_INBUSY was still on), then reset the BUSY state and
544 	 * we will wait for the interrupt.  If !TS_BUSY, we already
545 	 * saw the interrupt so we can start another transmission.
546 	 */
547 	if (dmz_softc[unit].dmz_state & ST_TXOFF) {
548 		dmz_addr->octet[octet].octet_csr =
549 			DMZ_IE | IR_LCTMR | (unit & 07);
550 		dmz_addr->octet[octet].octet_lctmr =
551 			(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
552 		dmz_softc[unit].dmz_state &= ~ST_TXOFF;
553 		if (dmz_softc[unit].dmz_state & ST_INBUSY) {
554 			dmz_softc[unit].dmz_state &= ~ST_INBUSY;
555 			tp->t_state |= TS_BUSY;
556 			goto out;
557 		}
558 	}
559 
560 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
561 		if (tp->t_state & TS_ASLEEP) {
562 			tp->t_state &= ~TS_ASLEEP;
563 			wakeup((caddr_t)&tp->t_outq);
564 		}
565 		if (tp->t_wsel) {
566 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
567 			tp->t_wsel = 0;
568 			tp->t_state &= ~TS_WCOLL;
569 		}
570 	}
571 
572 	if (tp->t_outq.c_cc == 0)
573 		goto out;
574 	if (tp->t_flags & (RAW | LITOUT | PASS8))
575 		nch = ndqb(&tp->t_outq, 0);
576 	else {
577 		nch = ndqb(&tp->t_outq, 0200);
578 		if (nch == 0) {
579 			nch = getc(&tp->t_outq);
580 			timeout(ttrstrt, (caddr_t)tp, (nch & 0x7f)+6);
581 			tp->t_state |= TS_TIMEOUT;
582 			goto out;
583 		}
584 	}
585 
586 	/*
587 	 * Should we use DMA or SILO mode?
588 	 * If nch is greater than DO_DMA_COUNT then DMA.
589 	 */
590 	if (nch) {
591 		dmz_addr->octet[octet].octet_csr =
592 			DMZ_IE | IR_LCTMR | (unit & 07);
593 		dmz_addr->octet[octet].octet_lctmr =
594 			(dmz_addr->octet[octet].octet_lctmr | DMZ_TE);
595 		tp->t_state |= TS_BUSY;
596 
597 		use_dma = FALSE;
598 		room = DMZ_SIZ;
599 
600 		if (nch > DO_DMA_COUNT)
601 			use_dma = TRUE;
602 
603 		if (use_dma && dmz_dma_on) {
604 			car = UBACVT(tp->t_outq.c_cf,
605 				dmzinfo[controller]->ui_ubanum);
606 			dmz_softc[unit].dmz_count = nch;
607 			dmz_softc[unit].dmz_state |= ST_DMA;
608 			dmz_addr->octet[octet].octet_csr =
609 				DMZ_IE | IR_TBA | (unit & 07);
610 			dmz_addr->octet[octet].octet_tba = car;
611 			dmz_addr->octet[octet].octet_tcc =
612 				((car >> 2) & 0xc000) | nch;
613 		} else {
614 			dmz_softc[unit].dmz_state &= ~ST_DMA;
615 			cp = tp->t_outq.c_cf;
616 			nch = MIN(nch, room);
617 			dmz_addr->octet[octet].octet_csr =
618 				DMZ_IE | IR_TBUF | (unit & 07);
619 			for (i = 0; i < nch; i++)
620 				dmz_addr->octet[octet].octet_tbf = *cp++ ;
621 			ndflush(&tp->t_outq, nch);
622 		}
623 	}
624 
625 out:
626 	splx(priority);
627 	return;
628 }
629 
630 /* ARGSUSED */
631 dmzstop(tp, flag)
632 	register struct tty *tp;
633 {
634 	register struct dmzdevice *dmz_addr;
635 	register int unit, priority, octet;
636 
637 	priority = spl5();
638 	dmz_addr = (struct dmzdevice *) tp->t_addr;
639 	unit = minor(tp->t_dev);
640 	octet = OCTET(unit);
641 
642 	dmz_addr->octet[octet].octet_csr = IR_LCTMR | (unit & 07) | DMZ_IE;
643 	dmz_addr->octet[octet].octet_lctmr =
644 		(dmz_addr->octet[octet].octet_lctmr & ~DMZ_TE);
645 	dmz_softc[unit].dmz_state |= ST_TXOFF;
646 	if ((tp->t_state & TS_TTSTOP) == 0) {
647 		tp->t_state |= (TS_FLUSH | TS_BUSY);
648 		dmz_addr->octet[octet].octet_lctmr =
649 			(dmz_addr->octet[octet].octet_lctmr | DMZ_FLS);
650 	} else if (tp->t_state & TS_BUSY) {
651 		dmz_softc[unit].dmz_state |= ST_INBUSY;
652 		tp->t_state &= ~TS_BUSY;
653 	}
654 
655 	splx(priority);
656 	return;
657 }
658 
659 /* ARGSUSED */
660 dmzioctl(device, command, data, flag)
661 	dev_t device;
662 	caddr_t data;
663 {
664 	register struct tty *tp;
665 	register int unit;
666 	int error;
667 
668 	unit = minor(device);
669 	tp = &dmz_tty[unit];
670 
671 	error = (*linesw[tp->t_line].l_ioctl)(tp, command, data, flag);
672 	if (error >= 0)
673 		return (error);
674 	error = ttioctl(tp, command, data, flag);
675 	if (error >= 0) {
676 		if (command == TIOCSETP || command == TIOCSETN ||
677 		    command == TIOCLSET || command == TIOCLBIS ||
678 		    command == TIOCLBIC)
679 			dmzparam(unit);
680 		return (error);
681 	}
682 
683 	switch (command) {
684 		case TIOCSBRK:
685 			(void) dmzmctl(unit, DMZ_BRK, DMBIS);
686 			break;
687 		case TIOCCBRK:
688 			(void) dmzmctl(unit, DMZ_BRK, DMBIC);
689 			break;
690 		case TIOCSDTR:
691 			(void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIS);
692 			break;
693 		case TIOCCDTR:
694 			(void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIC);
695 			break;
696 		case TIOCMSET:
697 			(void) dmzmctl(unit, dmtodmz(*(int *)data), DMSET);
698 			break;
699 		case TIOCMBIS:
700 			(void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIS);
701 			break;
702 		case TIOCMBIC:
703 			(void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIC);
704 			break;
705 		case TIOCMGET:
706 			*(int *)data = dmzmctl(unit, 0, DMGET);
707 			break;
708 		default:
709 			return (ENOTTY);
710 	}
711 	return (0);
712 }
713 
714 dmzmctl(unit, bits, how)
715 	register int unit;
716 	int bits, how;
717 {
718 	register struct dmzdevice *dmz_addr;
719 	register int modem_status, line_control;
720 	int priority;
721 	int octet;
722 
723 	octet = OCTET(unit);
724 	dmz_addr = (struct dmzdevice *) dmzinfo[DMZ(unit)]->ui_addr;
725 
726 	priority = spl5();
727 	dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | (unit & 07);
728 	modem_status = dmz_addr->octet[octet].octet_rmstsc & 0xff00;
729 
730 	dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07);
731 	line_control = dmz_addr->octet[octet].octet_lctmr;
732 
733 
734 	switch (how) {
735 		case DMSET:
736 			line_control = bits;
737 			break;
738 		case DMBIS:
739 			line_control |= bits;
740 			break;
741 		case DMBIC:
742 			line_control &= ~bits;
743 			break;
744 		case DMGET:
745 			(void) splx(priority);
746 			return (dmztodm(modem_status, line_control));
747 	}
748 
749 	dmz_addr->octet[octet].octet_csr =
750 		DMZ_IE | IR_LCTMR | (unit & 07);
751 	dmz_addr->octet[octet].octet_lctmr = line_control;
752 
753 	splx(priority);
754 	return (modem_status);
755 }
756 
757 /*
758  * Routine to convert modem status from dm to dmz lctmr format.
759  */
760 dmtodmz(bits)
761 	register int bits;
762 {
763 	register int lcr = DMZ_LCE;
764 
765 	if (bits & DML_DTR)
766 		lcr |= DMZ_DTR;
767 	if (bits & DML_RTS)
768 		lcr |= DMZ_RTS;
769 	if (bits & DML_ST)
770 		lcr |= DMF_ST;
771 	if (bits & DML_USR)
772 		lcr |= DMZ_USRW;
773 	return (lcr);
774 }
775 
776 /*
777  * Routine to convert modem status from dmz receive modem status
778  * and line control register to dm format.
779  * If dmz user modem read bit set, set DML_USR.
780  */
781 dmztodm(rms, lcr)
782 	register int rms, lcr;
783 {
784 
785 	rms = ((rms & (DMZ_DSR|DMZ_RNG|DMZ_CAR|DMZ_CTS|DMF_SR)) >> 7) |
786 		((rms & DMZ_USRR) >> 1) | DML_LE;
787 	if (lcr & DMZ_DTR)
788 		rms |= DML_DTR;
789 	if (lcr & DMF_ST)
790 		rms |= DML_ST;
791 	if (lcr & DMZ_RTS)
792 		rms |= DML_RTS;
793 	return (rms);
794 }
795 #endif
796