add device magic field so can tell whether boot left us a bootdev
[unix-history] / usr / src / sys / vax / uba / dmz.c
CommitLineData
eda39fa8
KM
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 *
0b35cf68 6 * @(#)dmz.c 6.6 (Berkeley) %G%
eda39fa8
KM
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
eda39fa8
KM
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"
0b35cf68 33#include "proc.h"
eda39fa8
KM
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"
9e8c0c88 44#include "syslog.h"
eda39fa8
KM
45
46#include "ubareg.h"
47#include "ubavar.h"
48#include "dmzreg.h"
a7aacc6a 49#include "dmreg.h"
eda39fa8
KM
50
51int dmzprobe(), dmzattach(), dmzrint(), dmzxint();
52struct uba_device *dmzinfo[NDMZ];
53u_short dmzstd[] = {0, 0};
54struct uba_driver dmzdriver = {
55 dmzprobe, 0, dmzattach, 0, dmzstd, "dmz", dmzinfo
56};
57
58#define NDMZLINES (NDMZ*24)
59
60int ttrstrt();
61struct tty dmz_tty[NDMZLINES];
62
63int dmzsoftCAR[NDMZ];
64
65struct {
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
74char dmz_speeds[] = {
75 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0
76};
77
74bfa0d5
MK
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
eda39fa8
KM
86#ifndef lint
87int ndmz = NDMZLINES; /* Used by pstat/iostat */
88#endif
89
90short dmzact[NDMZ]; /* Mask of active octets on the dmz */
91int 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
9e8c0c88 109int cbase[NUBA]; /* base address in unibus map */
eda39fa8
KM
110int 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 */
115int dmz_dma_on = 1;
eda39fa8
KM
116
117dmzprobe(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
149dmzattach(ui)
150 struct uba_device *ui;
151{
152 dmzsoftCAR[ui->ui_unit] = ui->ui_flags;
cdebba26 153 cbase[ui->ui_ubanum] = -1;
eda39fa8
KM
154}
155
156/* ARGSUSED */
157dmzopen(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;
eda39fa8
KM
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;
eda39fa8
KM
185
186 /*
187 * Set up Unibus map registers. Block uba resets, which can
188 * clear the state.
189 */
190 priority = spl5();
cdebba26 191 if (cbase[ui->ui_ubanum] == -1) {
eda39fa8
KM
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");
9e8c0c88 198 return (ENOMEM);
eda39fa8 199 }
cdebba26 200 cbase[ui->ui_ubanum] = UBAI_ADDR(dmz_ubinfo[ui->ui_ubanum]);
eda39fa8
KM
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);
74bfa0d5
MK
213 tp->t_ispeed = tp->t_ospeed = ISPEED;
214 tp->t_flags = IFLAGS;
eda39fa8
KM
215 dmz_softc[unit].dmz_state = 0;
216 }
a7aacc6a 217 dmzparam(unit);
eda39fa8
KM
218
219 /*
220 * Wait for carrier, then process line discipline specific open.
221 */
a7aacc6a 222 if ((dmzmctl(unit, DMZ_ON, DMSET) & DMZ_CAR) ||
eda39fa8
KM
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
9e8c0c88 232 return ((*linesw[tp->t_line].l_open)(device, tp));
eda39fa8
KM
233}
234
235dmzparam(unit)
236 register int unit;
237{
238 register struct tty *tp;
239 register struct dmzdevice *dmz_addr;
a7aacc6a 240 register int line_parameters;
eda39fa8
KM
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);
eda39fa8
KM
258
259 if ((tp->t_ispeed) == B134)
260 line_parameters |= DMZ_6BT | DMZ_PEN;
a7aacc6a 261 else if (tp->t_flags & (RAW | LITOUT | PASS8))
eda39fa8
KM
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;
eda39fa8 274 splx(priority);
eda39fa8
KM
275}
276
277/* ARGSUSED */
278dmzclose(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];
a7aacc6a 287 (*linesw[tp->t_line].l_close)(tp);
eda39fa8
KM
288
289 /*
a7aacc6a 290 * Clear break, hang-up and close the modem.
eda39fa8
KM
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
299dmzreset(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
eda39fa8
KM
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
cdebba26 316 if (dmz_ubinfo[uban]) {
9e8c0c88
MK
317 dmz_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
318 nclist * sizeof(struct cblock), 0);
cdebba26 319 cbase[uban] = UBAI_ADDR(dmz_ubinfo[uban]);
9e8c0c88
MK
320 }
321
eda39fa8
KM
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
349dmzread(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
361dmzwrite(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
373dmzrinta(controller)
374 int controller;
375{
376 dmzrint(controller, 0);
377}
378
379dmzrintb(controller)
380 int controller;
381{
382 dmzrint(controller, 1);
383}
384
385dmzrintc(controller)
386 int controller;
387{
388 dmzrint(controller, 2);
389}
390
391dmzrint(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;
74bfa0d5 401 int overrun;
eda39fa8
KM
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
cdebba26 414 if (character & DMZ_DSC) {
a7aacc6a
MK
415 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | unit;
416 if (dmz_addr->octet[octet].octet_rmstsc & DMZ_CAR)
74bfa0d5 417 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
cdebba26
MK
418 else if (dmzsoftCAR[controller] &
419 (1 << (octet * 8 + unit)) == 0 &&
420 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
a7aacc6a 421 (void)dmzmctl(tp - dmz_tty, DMZ_OFF, DMSET);
eda39fa8
KM
422 continue;
423 }
424
74bfa0d5
MK
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;
eda39fa8
KM
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) {
9e8c0c88 440 log(LOG_WARNING, "dmz%d: silo overflow\n", controller);
eda39fa8
KM
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
457dmzxinta(controller)
458 int controller;
459{
460 dmzxint(controller, 0);
461}
462
463dmzxintb(controller)
464 int controller;
465{
466 dmzxint(controller, 1);
467}
468
469dmzxintc(controller)
470 int controller;
471{
472 dmzxint(controller, 2);
473}
474
475dmzxint(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
520dmzstart(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;
a7aacc6a 574 if (tp->t_flags & (RAW | LITOUT | PASS8))
eda39fa8
KM
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
625out:
626 splx(priority);
627 return;
628}
629
630/* ARGSUSED */
631dmzstop(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 */
660dmzioctl(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) {
a7aacc6a
MK
676 if (command == TIOCSETP || command == TIOCSETN ||
677 command == TIOCLSET || command == TIOCLBIS ||
678 command == TIOCLBIC)
eda39fa8
KM
679 dmzparam(unit);
680 return (error);
681 }
682
683 switch (command) {
684 case TIOCSBRK:
a7aacc6a 685 (void) dmzmctl(unit, DMZ_BRK, DMBIS);
eda39fa8
KM
686 break;
687 case TIOCCBRK:
a7aacc6a 688 (void) dmzmctl(unit, DMZ_BRK, DMBIC);
eda39fa8
KM
689 break;
690 case TIOCSDTR:
a7aacc6a 691 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIS);
eda39fa8
KM
692 break;
693 case TIOCCDTR:
a7aacc6a 694 (void) dmzmctl(unit, DMZ_DTR | DMZ_RTS, DMBIC);
eda39fa8
KM
695 break;
696 case TIOCMSET:
a7aacc6a 697 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMSET);
eda39fa8
KM
698 break;
699 case TIOCMBIS:
a7aacc6a 700 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIS);
eda39fa8
KM
701 break;
702 case TIOCMBIC:
a7aacc6a 703 (void) dmzmctl(unit, dmtodmz(*(int *)data), DMBIC);
eda39fa8
KM
704 break;
705 case TIOCMGET:
a7aacc6a 706 *(int *)data = dmzmctl(unit, 0, DMGET);
eda39fa8
KM
707 break;
708 default:
709 return (ENOTTY);
710 }
711 return (0);
712}
713
a7aacc6a
MK
714dmzmctl(unit, bits, how)
715 register int unit;
eda39fa8
KM
716 int bits, how;
717{
718 register struct dmzdevice *dmz_addr;
a7aacc6a 719 register int modem_status, line_control;
eda39fa8
KM
720 int priority;
721 int octet;
722
eda39fa8 723 octet = OCTET(unit);
a7aacc6a 724 dmz_addr = (struct dmzdevice *) dmzinfo[DMZ(unit)]->ui_addr;
eda39fa8
KM
725
726 priority = spl5();
a7aacc6a
MK
727 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_RMSTSC | (unit & 07);
728 modem_status = dmz_addr->octet[octet].octet_rmstsc & 0xff00;
eda39fa8
KM
729
730 dmz_addr->octet[octet].octet_csr = DMZ_IE | IR_LCTMR | (unit & 07);
a7aacc6a 731 line_control = dmz_addr->octet[octet].octet_lctmr;
eda39fa8 732
eda39fa8
KM
733
734 switch (how) {
735 case DMSET:
a7aacc6a 736 line_control = bits;
eda39fa8
KM
737 break;
738 case DMBIS:
a7aacc6a 739 line_control |= bits;
eda39fa8
KM
740 break;
741 case DMBIC:
a7aacc6a 742 line_control &= ~bits;
eda39fa8
KM
743 break;
744 case DMGET:
745 (void) splx(priority);
a7aacc6a 746 return (dmztodm(modem_status, line_control));
eda39fa8
KM
747 }
748
eda39fa8
KM
749 dmz_addr->octet[octet].octet_csr =
750 DMZ_IE | IR_LCTMR | (unit & 07);
a7aacc6a 751 dmz_addr->octet[octet].octet_lctmr = line_control;
eda39fa8 752
a7aacc6a 753 splx(priority);
eda39fa8
KM
754 return (modem_status);
755}
756
757/*
a7aacc6a 758 * Routine to convert modem status from dm to dmz lctmr format.
eda39fa8
KM
759 */
760dmtodmz(bits)
761 register int bits;
762{
a7aacc6a
MK
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);
eda39fa8
KM
774}
775
776/*
a7aacc6a
MK
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.
eda39fa8 780 */
a7aacc6a
MK
781dmztodm(rms, lcr)
782 register int rms, lcr;
eda39fa8 783{
a7aacc6a
MK
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);
eda39fa8
KM
794}
795#endif