xref: /csrg-svn/sys/vax/uba/dmz.c (revision 25655)
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.4 (Berkeley) 12/19/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 #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 int dmz_debug_level;
117 
118 dmzprobe(reg)
119 	caddr_t reg;
120 {
121 	register int br, cvec;
122 	register struct dmzdevice *dmz_addr;
123 	register unsigned int a;
124 
125 	dmz_addr = (struct dmzdevice *)reg;
126 
127 #ifdef lint
128 	br = 0; cvec = br; br = cvec; dmzxinta(0); dmzxintb(0); dmzxintc(0);
129 	dmzrinta(0); dmzrintb(0); dmzrintc(0);
130 #endif
131 
132 	br = 0x15;
133 
134 	a = dmz_addr->dmz_config;
135 	if (((a>>12) & ~DMZ_INTERFACE) != 0) {
136 		printf("	Unknown interface type\n");
137 		return (0);
138 	}
139 	if (((a>>8) & DMZ_NOC_MASK) != 3) {
140 		printf("	Not all octets are available\n");
141 		return (0);
142 	}
143 
144 	cvec = (uba_hd[numuba].uh_lastiv -= 4 * 6);
145 	dmz_addr->dmz_config = cvec >> 2;
146 
147 	return (sizeof(struct dmzdevice));
148 }
149 
150 dmzattach(ui)
151 	struct uba_device *ui;
152 {
153 	dmzsoftCAR[ui->ui_unit] = ui->ui_flags;
154 	return;
155 }
156 
157 /* ARGSUSED */
158 dmzopen(device, flag)
159 	dev_t device;
160 	int flag;
161 {
162 	register struct tty *tp;
163 	register int unit, controller;
164 	register struct dmzdevice *dmz_addr;
165 	register struct uba_device *ui;
166 	int priority;
167 	int octet;
168 
169 	unit = minor(device);
170 	controller = DMZ(unit);
171 	octet = OCTET(unit);
172 
173 	if (unit >= NDMZLINES ||
174 	    (ui = dmzinfo[controller]) == 0 ||
175 	    ui->ui_alive == 0)
176 		return (ENXIO);
177 
178 	tp = &dmz_tty[unit];
179 
180 	if ((tp->t_state & TS_XCLUDE) && u.u_uid != 0)
181 		return (EBUSY);
182 
183 	dmz_addr = (struct dmzdevice *)ui->ui_addr;
184 	tp->t_addr = (caddr_t)dmz_addr;
185 	tp->t_oproc = dmzstart;
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 		dmz_softc[unit].dmz_state = 0;
217 	}
218 	dmzparam(unit);
219 
220 	/*
221 	 * Wait for carrier, then process line discipline specific open.
222 	 */
223 	if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) ||
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;
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 
260 	if ((tp->t_ispeed) == B134)
261 		line_parameters |= DMZ_6BT | DMZ_PEN;
262 	else if (tp->t_flags & (RAW | LITOUT | PASS8))
263 		line_parameters |= DMZ_8BT;
264 	else
265 		line_parameters |= DMZ_7BT | DMZ_PEN;
266 
267 	if (tp->t_flags & EVENP)
268 		line_parameters |= DMZ_EPR;
269 	if ((tp->t_ospeed) == B110)
270 		line_parameters |= DMZ_SCD;
271 
272 	line_parameters |= (unit & 07);
273 
274 	dmz_addr->octet[octet].octet_lprm = line_parameters;
275 	splx(priority);
276 }
277 
278 /* ARGSUSED */
279 dmzclose(device, flag)
280 	dev_t device;
281 	int flag;
282 {
283 	register struct  tty *tp;
284 	register int unit;
285 
286 	unit = minor(device);
287 	tp = &dmz_tty[unit];
288 	(*linesw[tp->t_line].l_close)(tp);
289 
290 	/*
291 	 * Clear break, hang-up and close the modem.
292 	 */
293 	(void) dmzmctl(unit, DMZ_BRK, DMBIC);
294 	if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0)
295 		(void) dmzmctl(unit, DMZ_OFF, DMSET);
296 	ttyclose(tp);
297 	return;
298 }
299 
300 dmzreset(uban)
301 	int uban;
302 {
303 	register int controller, unit;
304 	register struct tty *tp;
305 	register struct uba_device *ui;
306 	register struct dmzdevice *dmz_addr;
307 	int i;
308 	int octet;
309 
310 	for (controller = 0; controller < NDMZ; controller++) {
311 		ui = dmzinfo[controller];
312 		if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
313 			continue;
314 		printf("dmz%d ", controller);
315 		dmz_addr = (struct dmzdevice *) ui->ui_addr;
316 
317 		if (cbase[uban] == 0) {
318 			dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
319 				nclist * sizeof(struct cblock), 0);
320 			cbase[uban] = dmz_ubinfo[uban] & 0x3ffff;
321 		}
322 
323 		for (octet = 0; octet < 3; octet++)
324 			if ((dmzact[controller] & (1 << octet)) != 0) {
325 				dmz_addr->octet[octet].octet_csr |= DMZ_IE;
326 				dmz_addr->octet[octet].octet_receive.octet_sato = SILO_TIMEOUT;
327 			}
328 
329 		unit = controller * 24;
330 
331 		/*
332 		 * If a unit is open or waiting for open to complete,
333 		 * reset it.
334 		 */
335 		for (i = 0; i < 24; i++) {
336 			dmz_softc[unit].dmz_state = 0;
337 			tp = &dmz_tty[unit];
338 			if (tp->t_state & (TS_ISOPEN | TS_WOPEN)) {
339 				dmzparam(unit);
340 				(void) dmzmctl(unit, DMZ_ON, DMSET);
341 				tp->t_state &= ~TS_BUSY;
342 				dmzstart(tp);
343 			}
344 			unit++;
345 		}
346 	}
347 	return;
348 }
349 
350 dmzread(device, uio)
351 	dev_t device;
352 	struct uio *uio;
353 {
354 	register struct tty *tp;
355 	int xstatus;
356 
357 	tp = &dmz_tty[minor(device)];
358 	xstatus = (*linesw[tp->t_line].l_read)(tp, uio);
359 	return (xstatus);
360 }
361 
362 dmzwrite(device, uio)
363 	dev_t device;
364 	struct uio *uio;
365 {
366 	register struct tty *tp;
367 	int xstatus;
368 
369 	tp = &dmz_tty[minor(device)];
370 	xstatus = (*linesw[tp->t_line].l_write)(tp, uio);
371 	return (xstatus);
372 }
373 
374 dmzrinta(controller)
375 	int controller;
376 {
377 	dmzrint(controller, 0);
378 }
379 
380 dmzrintb(controller)
381 	int controller;
382 {
383 	dmzrint(controller, 1);
384 }
385 
386 dmzrintc(controller)
387 	int controller;
388 {
389 	dmzrint(controller, 2);
390 }
391 
392 dmzrint(controller, octet)
393 	int controller;
394 	register int octet;
395 {
396 	register struct tty *tp;
397 	register int character;
398 	register struct dmzdevice *dmz_addr;
399 	register struct tty *tp0;
400 	register int unit;
401 	register struct uba_device *ui;
402 	int overrun;
403 
404 	overrun = 0;
405 	ui = dmzinfo[controller];
406 	if (ui == 0 || ui->ui_alive == 0)
407 		return;
408 	dmz_addr = (struct dmzdevice *) ui->ui_addr;
409 	tp0 = &dmz_tty[controller * 24];
410 
411 	while ((character = dmz_addr->octet[octet].octet_receive.octet_rb) < 0) {
412 		unit = (character >> 8) & 07;	/* unit is bits 8-10 of rb */
413 		tp = tp0 + (octet * 8 + unit);
414 
415 		if (character & DMZ_DSC &&
416 		    (dmzsoftCAR[controller] & (1 << (octet * 8 + unit))) == 0) {
417 			dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit;
418 			if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR)
419 				(void)(*linesw[tp->t_line].l_modem)(tp, 1);
420 			else if ((*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