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