date and time created 82/05/26 15:16:01 by sam
[unix-history] / usr / src / sys / vax / uba / dmf.c
CommitLineData
7a17d042
SL
1/* dmf.c 4.1 82/05/26 */
2
3#include "dmf.h"
4#if NDMF > 0
5/*
6 * DMF32 driver
7 *
8 * TODO:
9 * test with modem
10 * load as much as possible into silo
11 * get correct numbers for receive silo parameter timeout
12 * use auto XON/XOFF
13 * test reset code
14 * test with more than one unit
15 * optimize for efficient DMA and dynamically
16 * decide between silo and DMA mode
17 */
18#include "bk.h"
19#include "../h/param.h"
20#include "../h/conf.h"
21#include "../h/dir.h"
22#include "../h/user.h"
23#include "../h/tty.h"
24#include "../h/map.h"
25#include "../h/pte.h"
26#include "../h/buf.h"
27#include "../h/vm.h"
28#include "../h/ubareg.h"
29#include "../h/ubavar.h"
30#include "../h/bk.h"
31#include "../h/clist.h"
32#include "../h/mx.h"
33#include "../h/file.h"
34
35/*
36 * Definition of the driver for the auto-configuration program.
37 */
38int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
39struct uba_device *dmfinfo[NDMF];
40u_short dmfstd[] = { 0 };
41struct uba_driver dmfdriver =
42 { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
43
44/*
45 * In this driver, "dmf" (unqualified) refers to the async portion
46 * of the dmf32, "dmfc" to the combo portion, "dmfs" to the sync
47 * portion, "dmfl" to the lp portion, and "dmfd" to the dr portion.
48 */
49struct dmfdevice
50{
51 short dmfccsr0; /* combo csr 0 */
52 short dmfccsr1; /* combo csr 1 */
53 short dmfs[4];
54 short dmfcsr; /* control-status register */
55 short dmflpr; /* line parameter register */
56 short dmfrbuf; /* receiver buffer (ro) */
57 union {
58 u_short dmfirw; /* indirect register word */
59 u_char dmfirc[2]; /* " " bytes */
60 } dmfun;
61 short dmfl[2];
62 short dmfd[4];
63};
64
65#define dmfrsp dmfrbuf /* receive silo parameter register (wo) */
66#define dmftbuf dmfun.dmfirc[0] /* transmit buffer */
67#define dmftsc dmfun.dmfirc[0] /* transmit silo count */
68#define dmfrms dmfun.dmfirc[1] /* receive modem status */
69#define dmflcr dmfun.dmfirc[0] /* line control register */
70#define dmftms dmfun.dmfirc[1] /* transmit modem status */
71#define dmftba dmfun.dmfirw /* transmit buffer address */
72#define dmftcc dmfun.dmfirw /* transmit character count */
73
74/* bits in dmfcsr */
75#define DMF_TI 0100000 /* transmit interrupt */
76#define DMF_TIE 0040000 /* transmit interrupt enable */
77#define DMF_NXM 0020000 /* non-existant memory */
78#define DMF_LIN 0003400 /* transmit line number */
79#define DMF_RI 0000200 /* receiver interrupt */
80#define DMF_RIE 0000100 /* receiver interrupt enable */
81#define DMF_CLR 0000040 /* master reset */
82#define DMF_IAD 0000037 /* indirect address register */
83
84#define DMFIR_TBUF 000 /* select tbuf indirect register */
85#define DMFIR_LCR 010 /* select lcr indirect register */
86#define DMFIR_TBA 020 /* select tba indirect register */
87#define DMFIR_TCC 030 /* select tcc indirect register */
88
89/* bits in dmflpr */
90#define BITS6 (01<<3)
91#define BITS7 (02<<3)
92#define BITS8 (03<<3)
93#define TWOSB 0200
94#define PENABLE 040
95/* DEC manuals incorrectly say this bit causes generation of even parity. */
96#define OPAR 0100
97
98#define DMF_IE (DMF_TIE|DMF_RIE)
99
100#define DMF_SILOCNT 32 /* size of DMF output silo (per line) */
101
102/* bits in dmfrbuf */
103#define DMF_DSC 0004000 /* data set change */
104#define DMF_PE 0010000 /* parity error */
105#define DMF_FE 0020000 /* framing error */
106#define DMF_DO 0040000 /* data overrun */
107
108/* bits in dmfrms */
109#define DMF_USRR 0004 /* user modem signal (pin 25) */
110#define DMF_SR 0010 /* secondary receive */
111#define DMF_CTS 0020 /* clear to send */
112#define DMF_CAR 0040 /* carrier detect */
113#define DMF_RNG 0100 /* ring */
114#define DMF_DSR 0200 /* data set ready */
115
116/* bits in dmftms */
117#define DMF_USRW 0001 /* user modem signal (pin 18) */
118#define DMF_DTR 0002 /* data terminal ready */
119#define DMF_RATE 0004 /* data signal rate select */
120#define DMF_ST 0010 /* secondary transmit */
121#define DMF_RTS 0020 /* request to send */
122#define DMF_BRK 0040 /* pseudo break bit */
123#define DMF_PREEMPT 0200 /* preempt output */
124
125/* flags for modem control */
126#define DMF_ON (DMF_DTR|DMF_RTS)
127#define DMF_OFF 0
128
129/* bits in dmflcr */
130#define DMF_MIE 0040 /* modem interrupt enable */
131#define DMF_FLUSH 0020 /* flush transmit silo */
132#define DMF_RBRK 0010 /* real break bit */
133#define DMF_RE 0004 /* receive enable */
134#define DMF_AUTOX 0002 /* auto XON/XOFF */
135#define DMF_TE 0001 /* transmit enable */
136
137#define DMFLCR_ENA (DMF_MIE|DMF_RE|DMF_TE)
138
139/* bits in dm lsr, copied from dh.c */
140#define DML_USR 0001000 /* usr modem sig, not a real DM bit */
141#define DML_DSR 0000400 /* data set ready, not a real DM bit */
142#define DML_RNG 0000200 /* ring */
143#define DML_CAR 0000100 /* carrier detect */
144#define DML_CTS 0000040 /* clear to send */
145#define DML_SR 0000020 /* secondary receive */
146#define DML_ST 0000010 /* secondary transmit */
147#define DML_RTS 0000004 /* request to send */
148#define DML_DTR 0000002 /* data terminal ready */
149#define DML_LE 0000001 /* line enable */
150
151/*
152 * Local variables for the driver
153 */
154char dmf_speeds[] =
155 { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
156
157struct tty dmf_tty[NDMF*8];
158char dmfsoftCAR[NDMF];
159int ndmf = NDMF*8;
160int dmfact; /* mask of active dmf's */
161int dmfstart(), ttrstrt();
162
163#ifdef DMFDMA
164/*
165 * The clist space is mapped by the driver onto each UNIBUS.
166 * The UBACVT macro converts a clist space address for unibus uban
167 * into an i/o space address for the DMA routine.
168 */
169int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */
170static int cbase[MAXNUBA]; /* base address in unibus map */
171#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
172#endif
173
174/*
175 * Routine for configuration to set dmf interrupt.
176 */
177/*ARGSUSED*/
178dmfprobe(reg, ctlr)
179 caddr_t reg;
180 int ctlr;
181{
182 register int br, cvec; /* these are ``value-result'' */
183 register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
184
185#ifdef lint
186 br = 0; cvec = br; br = cvec;
187#endif
188 br = 0x15;
189 cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
190 dmfaddr->dmfccsr0 = cvec >> 2;
191 /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */
192 return (1);
193}
194
195/*
196 * Routine called to attach a dmf.
197 */
198dmfattach(ui)
199 struct uba_device *ui;
200{
201
202 dmfsoftCAR[ui->ui_unit] = ui->ui_flags;
203}
204
205
206/*
207 * Open a DMF32 line, mapping the clist onto the uba if this
208 * is the first dmf on this uba. Turn on this dmf if this is
209 * the first use of it.
210 */
211/*ARGSUSED*/
212dmfopen(dev, flag)
213 dev_t dev;
214{
215 register struct tty *tp;
216 register int unit, dmf;
217 register struct dmfdevice *addr;
218 register struct uba_device *ui;
219 int s;
220
221 unit = minor(dev);
222 dmf = unit >> 3;
223 if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) {
224 u.u_error = ENXIO;
225 return;
226 }
227 tp = &dmf_tty[unit];
228 if (tp->t_state&XCLUDE && u.u_uid!=0) {
229 u.u_error = EBUSY;
230 return;
231 }
232 addr = (struct dmfdevice *)ui->ui_addr;
233 tp->t_addr = (caddr_t)addr;
234 tp->t_oproc = dmfstart;
235 tp->t_iproc = NULL;
236 tp->t_state |= WOPEN;
237 /*
238 * While setting up state for this uba and this dmf,
239 * block uba resets which can clear the state.
240 */
241 s = spl5();
242#ifdef DMFDMA
243 if (dmf_ubinfo[ui->ui_ubanum] == 0) {
244 dmf_ubinfo[ui->ui_ubanum] =
245 uballoc(ui->ui_ubanum, (caddr_t)cfree,
246 nclist*sizeof(struct cblock), 0);
247 cbase[ui->ui_ubanum] = dmf_ubinfo[ui->ui_ubanum]&0x3ffff;
248 }
249#endif
250 if ((dmfact&(1<<dmf)) == 0) {
251 addr->dmfcsr |= DMF_IE;
252 dmfact |= (1<<dmf);
253 addr->dmfrsp = 1; /* DON'T KNOW WHAT TO SET IT TO YET */
254 }
255 splx(s);
256 /*
257 * If this is first open, initialze tty state to default.
258 */
259 if ((tp->t_state&ISOPEN) == 0) {
260 ttychars(tp);
261 if (tp->t_ispeed == 0) {
262 tp->t_ispeed = B300;
263 tp->t_ospeed = B300;
264 tp->t_flags = ODDP|EVENP|ECHO;
265 }
266 dmfparam(unit);
267 }
268 /*
269 * Wait for carrier, then process line discipline specific open.
270 */
271 if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
272 (dmfsoftCAR[dmf] & (1<<(unit&07))))
273 tp->t_state |= CARR_ON;
274 s = spl5();
275 while ((tp->t_state & CARR_ON) == 0) {
276 tp->t_state |= WOPEN;
277 sleep((caddr_t)&tp->t_rawq, TTIPRI);
278 }
279 splx(s);
280 (*linesw[tp->t_line].l_open)(dev, tp);
281}
282
283/*
284 * Close a DMF32 line.
285 */
286/*ARGSUSED*/
287dmfclose(dev, flag)
288 dev_t dev;
289 int flag;
290{
291 register struct tty *tp;
292 register unit;
293
294 unit = minor(dev);
295 tp = &dmf_tty[unit];
296 (*linesw[tp->t_line].l_close)(tp);
297 dmfmctl(unit, DMF_BRK, DMBIC);
298 if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
299 dmfmctl(unit, DMF_OFF, DMSET);
300 ttyclose(tp);
301}
302
303dmfread(dev)
304 dev_t dev;
305{
306 register struct tty *tp;
307
308 tp = &dmf_tty[minor(dev)];
309 (*linesw[tp->t_line].l_read)(tp);
310}
311
312dmfwrite(dev)
313 dev_t dev;
314{
315 register struct tty *tp;
316
317 tp = &dmf_tty[minor(dev)];
318 (*linesw[tp->t_line].l_write)(tp);
319}
320
321/*
322 * DMF32 receiver interrupt.
323 */
324dmfrint(dmf)
325 int dmf;
326{
327 register struct tty *tp;
328 register c;
329 register struct dmfdevice *addr;
330 register struct tty *tp0;
331 register struct uba_device *ui;
332 int overrun = 0;
333
334 ui = dmfinfo[dmf];
335 if (ui == 0 || ui->ui_alive == 0)
336 return;
337 addr = (struct dmfdevice *)ui->ui_addr;
338 tp0 = &dmf_tty[dmf<<3];
339 /*
340 * Loop fetching characters from the silo for this
341 * dmf until there are no more in the silo.
342 */
343 while ((c = addr->dmfrbuf) < 0) {
344 tp = tp0 + ((c>>8)&07);
345 if (c & DMF_DSC) {
346 addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07);
347 if (addr->dmfrms & DMF_CAR) {
348 if ((tp->t_state & CARR_ON) == 0) {
349 wakeup((caddr_t)&tp->t_rawq);
350 tp->t_state |= CARR_ON;
351 }
352 } else {
353 if (tp->t_state & CARR_ON) {
354 gsignal(tp->t_pgrp, SIGHUP);
355 gsignal(tp->t_pgrp, SIGCONT);
356 addr->dmfcsr = DMF_IE | DMFIR_LCR |
357 ((c>>8)&07);
358 addr->dmftms = 0;
359 flushtty(tp, FREAD|FWRITE);
360 }
361 tp->t_state &= ~CARR_ON;
362 }
363 continue;
364 }
365 if ((tp->t_state&ISOPEN)==0) {
366 wakeup((caddr_t)tp);
367 continue;
368 }
369 if (c & DMF_PE)
370 if ((tp->t_flags&(EVENP|ODDP))==EVENP
371 || (tp->t_flags&(EVENP|ODDP))==ODDP )
372 continue;
373 if ((c & DMF_DO) && overrun == 0) {
374 printf("dmf%d: silo overflow\n", dmf);
375 overrun = 1;
376 }
377 if (c & DMF_FE)
378 /*
379 * At framing error (break) generate
380 * a null (in raw mode, for getty), or a
381 * interrupt (in cooked/cbreak mode).
382 */
383 if (tp->t_flags&RAW)
384 c = 0;
385 else
386 c = tun.t_intrc;
387#if NBK > 0
388 if (tp->t_line == NETLDISC) {
389 c &= 0177;
390 BKINPUT(c, tp);
391 } else
392#endif
393 (*linesw[tp->t_line].l_rint)(c, tp);
394 }
395}
396
397/*
398 * Ioctl for DMF32.
399 */
400/*ARGSUSED*/
401dmfioctl(dev, cmd, addr, flag)
402 dev_t dev;
403 caddr_t addr;
404{
405 register struct tty *tp;
406 register int unit = minor(dev);
407 register int dmf = unit >> 3;
408 register struct device *dmfaddr;
409 int temp;
410
411 tp = &dmf_tty[unit];
412 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
413 if (cmd == 0)
414 return;
415 if (ttioctl(tp, cmd, addr, flag)) {
416 if (cmd==TIOCSETP || cmd==TIOCSETN)
417 dmfparam(unit);
418 } else switch(cmd) {
419
420 case TIOCSBRK:
421 dmfmctl(dev, DMF_BRK, DMBIS);
422 break;
423 case TIOCCBRK:
424 dmfmctl(dev, DMF_BRK, DMBIC);
425 break;
426 case TIOCSDTR:
427 dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
428 break;
429 case TIOCCDTR:
430 dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
431 break;
432 case TIOCMSET:
433 if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
434 u.u_error = EFAULT;
435 else
436 dmfmctl(dev, dmtodmf(temp), DMSET);
437 break;
438 case TIOCMBIS:
439 if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
440 u.u_error = EFAULT;
441 else
442 dmfmctl(dev, dmtodmf(temp), DMBIS);
443 break;
444 case TIOCMBIC:
445 if (copyin(addr, (caddr_t) &temp, sizeof(temp)))
446 u.u_error = EFAULT;
447 else
448 dmfmctl(dev, dmtodmf(temp), DMBIC);
449 break;
450 case TIOCMGET:
451 temp = dmftodm(dmfmctl(dev, 0, DMGET));
452 if (copyout((caddr_t) &temp, addr, sizeof(temp)))
453 u.u_error = EFAULT;
454 break;
455 default:
456 u.u_error = ENOTTY;
457 }
458}
459
460dmtodmf(bits)
461 register int bits;
462{
463 register int b;
464
465 b = bits & 012;
466 if (bits & DML_ST) b |= DMF_RATE;
467 if (bits & DML_RTS) b |= DMF_RTS;
468 if (bits & DML_USR) b |= DMF_USRW;
469 return(b);
470}
471
472dmftodm(bits)
473 register int bits;
474{
475 register int b;
476
477 b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
478 if (bits & DMF_USRR) b |= DML_USR;
479 if (bits & DMF_RTS) b |= DML_RTS;
480 return(b);
481}
482
483
484/*
485 * Set parameters from open or stty into the DMF hardware
486 * registers.
487 */
488dmfparam(unit)
489 register int unit;
490{
491 register struct tty *tp;
492 register struct dmfdevice *addr;
493 register int lpar, lcr;
494 int s;
495
496 tp = &dmf_tty[unit];
497 addr = (struct dmfdevice *)tp->t_addr;
498 /*
499 * Block interrupts so parameters will be set
500 * before the line interrupts.
501 */
502 s = spl5();
503 addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
504 if ((tp->t_ispeed)==0) {
505 tp->t_state |= HUPCLS;
506 dmfmctl(unit, DMF_OFF, DMSET);
507 return;
508 }
509 lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
510 lcr = DMFLCR_ENA;
511 if ((tp->t_ispeed) == B134)
512 lpar |= BITS6|PENABLE;
513 else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
514 lpar |= BITS8;
515 else {
516 lpar |= BITS7|PENABLE;
517 /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
518 }
519 if ((tp->t_flags&EVENP) == 0)
520 lpar |= OPAR;
521 if ((tp->t_ospeed) == B110)
522 lpar |= TWOSB;
523 lpar |= (unit&07);
524 addr->dmflpr = lpar;
525 addr->dmflcr = lcr;
526 splx(s);
527}
528
529/*
530 * DMF32 transmitter interrupt.
531 * Restart the idle line.
532 */
533dmfxint(dmf)
534 int dmf;
535{
536 register struct tty *tp;
537 register struct dmfdevice *addr;
538 register struct uba_device *ui;
539 register int unit, t;
540#ifdef DMFDMA
541 short cntr;
542#endif
543
544 ui = dmfinfo[dmf];
545 addr = (struct dmfdevice *)ui->ui_addr;
546 while ((t = addr->dmfcsr) & DMF_TI) {
547 unit = dmf*8 + ((t>>8)&07);
548 tp = &dmf_tty[unit];
549 tp->t_state &= ~BUSY;
550 if (t & DMF_NXM) {
551 printf("dmf%d: NXM line %d\n", dmf, unit&7);
552 /* SHOULD RESTART OR SOMETHING... */
553 }
554 if (tp->t_state&FLUSH)
555 tp->t_state &= ~FLUSH;
556#ifdef DMFDMA
557 else {
558 addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07);
559 if (addr->dmftsc == 0) {
560 /*
561 * Do arithmetic in a short to make up
562 * for lost 16&17 bits.
563 */
564 addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07);
565 cntr = addr->dmftba -
566 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
567 ndflush(&tp->t_outq, (int)cntr);
568 }
569 }
570#endif
571 if (tp->t_line)
572 (*linesw[tp->t_line].l_start)(tp);
573 else
574 dmfstart(tp);
575 }
576}
577
578/*
579 * Start (restart) transmission on the given DMF32 line.
580 */
581dmfstart(tp)
582 register struct tty *tp;
583{
584 register struct dmfdevice *addr;
585 register int car, dmf, unit, nch;
586 int s;
587
588 unit = minor(tp->t_dev);
589 dmf = unit >> 3;
590 unit &= 07;
591 addr = (struct dmfdevice *)tp->t_addr;
592
593 /*
594 * Must hold interrupts in following code to prevent
595 * state of the tp from changing.
596 */
597 s = spl5();
598 /*
599 * If it's currently active, or delaying, no need to do anything.
600 */
601 if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
602 goto out;
603 /*
604 * If there are still characters in the silo,
605 * just reenable the transmitter.
606 */
607 addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
608 if (addr->dmftsc) {
609 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
610 addr->dmflcr |= DMF_TE;
611 tp->t_state |= BUSY;
612 goto out;
613 }
614 /*
615 * If there are sleepers, and output has drained below low
616 * water mark, wake up the sleepers.
617 */
618 if ((tp->t_state&ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) {
619 tp->t_state &= ~ASLEEP;
620 if (tp->t_chan)
621 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
622 else
623 wakeup((caddr_t)&tp->t_outq);
624 }
625 /*
626 * Now restart transmission unless the output queue is
627 * empty.
628 */
629 if (tp->t_outq.c_cc == 0)
630 goto out;
631 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
632 nch = ndqb(&tp->t_outq, 0);
633 else {
634 nch = ndqb(&tp->t_outq, 0200);
635 /*
636 * If first thing on queue is a delay process it.
637 */
638 if (nch == 0) {
639 nch = getc(&tp->t_outq);
640 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
641 tp->t_state |= TIMEOUT;
642 goto out;
643 }
644 }
645 /*
646 * If characters to transmit, restart transmission.
647 */
648 if (nch) {
649#ifdef DMFDMA
650 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
651 addr->dmflcr |= DMF_TE;
652 car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
653 addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
654 addr->dmftba = car;
655 addr->dmftcc = ((car>>2)&0xc000) | nch;
656#else
657 register char *cp = tp->t_outq.c_cf;
658 register int i;
659
660 nch = MIN(nch, DMF_SILOCNT);
661 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
662 addr->dmflcr |= DMF_TE;
663 addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
664 for (i = 0; i < nch; i++)
665 addr->dmftbuf = *cp++;
666 ndflush(&tp->t_outq, nch);
667#endif
668 tp->t_state |= BUSY;
669 }
670out:
671 splx(s);
672}
673
674/*
675 * Stop output on a line, e.g. for ^S/^Q or output flush.
676 */
677/*ARGSUSED*/
678dmfstop(tp, flag)
679 register struct tty *tp;
680{
681 register struct dmfdevice *addr;
682 register int unit, s;
683
684 addr = (struct dmfdevice *)tp->t_addr;
685 /*
686 * Block input/output interrupts while messing with state.
687 */
688 s = spl5();
689 if (tp->t_state & BUSY) {
690 /*
691 * Device is transmitting; stop output
692 * by selecting the line and disabling
693 * the transmitter. If this is a flush
694 * request then flush the output silo,
695 * otherwise we will pick up where we
696 * left off by enabling the transmitter.
697 */
698 unit = minor(tp->t_dev);
699 addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE;
700 addr->dmflcr &= ~DMF_TE;
701 if ((tp->t_state&TTSTOP)==0) {
702 tp->t_state |= FLUSH;
703 addr->dmflcr |= DMF_FLUSH;
704 } else
705 tp->t_state &= ~BUSY;
706 }
707 splx(s);
708}
709
710/*
711 * DMF32 modem control
712 */
713dmfmctl(dev, bits, how)
714 dev_t dev;
715 int bits, how;
716{
717 register struct dmfdevice *dmfaddr;
718 register int unit, mbits, lcr;
719 int s;
720
721 unit = minor(dev);
722 dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
723 unit &= 07;
724 s = spl5();
725 dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
726 mbits = dmfaddr->dmfrms << 8;
727 dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
728 mbits |= dmfaddr->dmftms;
729 lcr = dmfaddr->dmflcr;
730 switch (how) {
731 case DMSET:
732 mbits = bits;
733 break;
734
735 case DMBIS:
736 mbits |= bits;
737 break;
738
739 case DMBIC:
740 mbits &= ~bits;
741 break;
742
743 case DMGET:
744 (void) splx(s);
745 return(mbits);
746 }
747 dmfaddr->dmftms = mbits&037;
748 if (mbits & DMF_BRK)
749 lcr |= DMF_RBRK;
750 else
751 lcr &= ~DMF_RBRK;
752 dmfaddr->dmflcr = lcr;
753 (void) splx(s);
754 return(mbits);
755}
756
757/*
758 * Reset state of driver if UBA reset was necessary.
759 * Reset the csr, lpr, and lcr registers on open lines, and
760 * restart transmitters.
761 */
762dmfreset(uban)
763 int uban;
764{
765 register int dmf, unit;
766 register struct tty *tp;
767 register struct uba_device *ui;
768 register struct dmfdevice *addr;
769 int i;
770
771#ifdef DMFDMA
772 if (dmf_ubinfo[uban] == 0)
773 return;
774 ubarelse(uban, &dmf_ubinfo[uban]);
775 dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
776 nclist*sizeof (struct cblock), 0);
777 cbase[uban] = dmf_ubinfo[uban]&0x3ffff;
778#endif
779 for (dmf = 0; dmf < NDMF; dmf++) {
780 ui = dmfinfo[dmf];
781 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
782 continue;
783 printf(" dmf%d", dmf);
784 addr = (struct dmfdevice *)ui->ui_addr;
785 addr->dmfcsr = DMF_IE;
786 addr->dmfrsp = 1;
787 unit = dmf * 8;
788 for (i = 0; i < 8; i++) {
789 tp = &dmf_tty[unit];
790 if (tp->t_state & (ISOPEN|WOPEN)) {
791 dmfparam(unit);
792 dmfmctl(unit, DMF_ON, DMSET);
793 tp->t_state &= ~BUSY;
794 dmfstart(tp);
795 }
796 unit++;
797 }
798 }
799}
800
801/* stubs for interrupt routines for devices not yet supported */
802
803dmfsrint() { printf("dmfsrint\n"); }
804
805dmfsxint() { printf("dmfsxint\n"); }
806
807dmfdaint() { printf("dmfdaint\n"); }
808
809dmfdbint() { printf("dmfdbint\n"); }
810
811dmflint() { printf("dmflint\n"); }
812#endif