rearrange header files
[unix-history] / usr / src / sys / vax / uba / dmf.c
CommitLineData
896962b1 1/* dmf.c 4.8 82/10/10 */
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;
224 if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) {
225 u.u_error = ENXIO;
226 return;
227 }
228 tp = &dmf_tty[unit];
c38b985f 229 if (tp->t_state&TS_XCLUDE && u.u_uid!=0) {
7a17d042
SL
230 u.u_error = EBUSY;
231 return;
232 }
233 addr = (struct dmfdevice *)ui->ui_addr;
234 tp->t_addr = (caddr_t)addr;
235 tp->t_oproc = dmfstart;
c38b985f 236 tp->t_state |= TS_WOPEN;
7a17d042
SL
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 */
c38b985f 259 if ((tp->t_state&TS_ISOPEN) == 0) {
7a17d042
SL
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))))
c38b985f 273 tp->t_state |= TS_CARR_ON;
7a17d042 274 s = spl5();
c38b985f
SL
275 while ((tp->t_state & TS_CARR_ON) == 0) {
276 tp->t_state |= TS_WOPEN;
7a17d042
SL
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);
c38b985f 298 if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
7a17d042
SL
299 dmfmctl(unit, DMF_OFF, DMSET);
300 ttyclose(tp);
301}
302
740e4029 303dmfread(dev, uio)
7a17d042 304 dev_t dev;
740e4029 305 struct uio *uio;
7a17d042
SL
306{
307 register struct tty *tp;
308
309 tp = &dmf_tty[minor(dev)];
740e4029 310 return ((*linesw[tp->t_line].l_read)(tp, uio));
7a17d042
SL
311}
312
406ddcbe 313dmfwrite(dev, uio)
7a17d042 314 dev_t dev;
406ddcbe 315 struct uio *uio;
7a17d042
SL
316{
317 register struct tty *tp;
318
319 tp = &dmf_tty[minor(dev)];
406ddcbe 320 (*linesw[tp->t_line].l_write)(tp, uio);
7a17d042
SL
321}
322
323/*
324 * DMF32 receiver interrupt.
325 */
326dmfrint(dmf)
327 int dmf;
328{
329 register struct tty *tp;
330 register c;
331 register struct dmfdevice *addr;
332 register struct tty *tp0;
333 register struct uba_device *ui;
334 int overrun = 0;
335
336 ui = dmfinfo[dmf];
337 if (ui == 0 || ui->ui_alive == 0)
338 return;
339 addr = (struct dmfdevice *)ui->ui_addr;
340 tp0 = &dmf_tty[dmf<<3];
341 /*
342 * Loop fetching characters from the silo for this
343 * dmf until there are no more in the silo.
344 */
345 while ((c = addr->dmfrbuf) < 0) {
346 tp = tp0 + ((c>>8)&07);
347 if (c & DMF_DSC) {
348 addr->dmfcsr = DMF_IE | DMFIR_TBUF | ((c>>8)&07);
349 if (addr->dmfrms & DMF_CAR) {
c38b985f 350 if ((tp->t_state & TS_CARR_ON) == 0) {
7a17d042 351 wakeup((caddr_t)&tp->t_rawq);
c38b985f 352 tp->t_state |= TS_CARR_ON;
7a17d042
SL
353 }
354 } else {
c38b985f 355 if (tp->t_state & TS_CARR_ON) {
7a17d042
SL
356 gsignal(tp->t_pgrp, SIGHUP);
357 gsignal(tp->t_pgrp, SIGCONT);
358 addr->dmfcsr = DMF_IE | DMFIR_LCR |
359 ((c>>8)&07);
360 addr->dmftms = 0;
361 flushtty(tp, FREAD|FWRITE);
362 }
c38b985f 363 tp->t_state &= ~TS_CARR_ON;
7a17d042
SL
364 }
365 continue;
366 }
c38b985f 367 if ((tp->t_state&TS_ISOPEN)==0) {
7a17d042
SL
368 wakeup((caddr_t)tp);
369 continue;
370 }
371 if (c & DMF_PE)
372 if ((tp->t_flags&(EVENP|ODDP))==EVENP
373 || (tp->t_flags&(EVENP|ODDP))==ODDP )
374 continue;
375 if ((c & DMF_DO) && overrun == 0) {
376 printf("dmf%d: silo overflow\n", dmf);
377 overrun = 1;
378 }
379 if (c & DMF_FE)
380 /*
381 * At framing error (break) generate
382 * a null (in raw mode, for getty), or a
383 * interrupt (in cooked/cbreak mode).
384 */
385 if (tp->t_flags&RAW)
386 c = 0;
387 else
388 c = tun.t_intrc;
389#if NBK > 0
390 if (tp->t_line == NETLDISC) {
391 c &= 0177;
392 BKINPUT(c, tp);
393 } else
394#endif
395 (*linesw[tp->t_line].l_rint)(c, tp);
396 }
397}
398
399/*
400 * Ioctl for DMF32.
401 */
402/*ARGSUSED*/
942f05a9 403dmfioctl(dev, cmd, data, flag)
7a17d042 404 dev_t dev;
942f05a9 405 caddr_t data;
7a17d042
SL
406{
407 register struct tty *tp;
408 register int unit = minor(dev);
409 register int dmf = unit >> 3;
410 register struct device *dmfaddr;
7a17d042
SL
411
412 tp = &dmf_tty[unit];
942f05a9 413 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
7a17d042
SL
414 if (cmd == 0)
415 return;
942f05a9
SL
416 if (ttioctl(tp, cmd, data, flag)) {
417 if (cmd == TIOCSETP || cmd == TIOCSETN)
7a17d042
SL
418 dmfparam(unit);
419 } else switch(cmd) {
420
421 case TIOCSBRK:
422 dmfmctl(dev, DMF_BRK, DMBIS);
423 break;
942f05a9 424
7a17d042
SL
425 case TIOCCBRK:
426 dmfmctl(dev, DMF_BRK, DMBIC);
427 break;
942f05a9 428
7a17d042
SL
429 case TIOCSDTR:
430 dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
431 break;
942f05a9 432
7a17d042
SL
433 case TIOCCDTR:
434 dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
435 break;
942f05a9 436
7a17d042 437 case TIOCMSET:
942f05a9 438 dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
7a17d042 439 break;
942f05a9 440
7a17d042 441 case TIOCMBIS:
942f05a9 442 dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
7a17d042 443 break;
942f05a9 444
7a17d042 445 case TIOCMBIC:
942f05a9 446 dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
7a17d042 447 break;
942f05a9 448
7a17d042 449 case TIOCMGET:
942f05a9 450 *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
7a17d042 451 break;
942f05a9 452
7a17d042
SL
453 default:
454 u.u_error = ENOTTY;
455 }
456}
457
458dmtodmf(bits)
459 register int bits;
460{
461 register int b;
462
463 b = bits & 012;
464 if (bits & DML_ST) b |= DMF_RATE;
465 if (bits & DML_RTS) b |= DMF_RTS;
466 if (bits & DML_USR) b |= DMF_USRW;
467 return(b);
468}
469
470dmftodm(bits)
471 register int bits;
472{
473 register int b;
474
475 b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
476 if (bits & DMF_USRR) b |= DML_USR;
477 if (bits & DMF_RTS) b |= DML_RTS;
478 return(b);
479}
480
481
482/*
483 * Set parameters from open or stty into the DMF hardware
484 * registers.
485 */
486dmfparam(unit)
487 register int unit;
488{
489 register struct tty *tp;
490 register struct dmfdevice *addr;
491 register int lpar, lcr;
492 int s;
493
494 tp = &dmf_tty[unit];
495 addr = (struct dmfdevice *)tp->t_addr;
496 /*
497 * Block interrupts so parameters will be set
498 * before the line interrupts.
499 */
500 s = spl5();
501 addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
502 if ((tp->t_ispeed)==0) {
c38b985f 503 tp->t_state |= TS_HUPCLS;
7a17d042
SL
504 dmfmctl(unit, DMF_OFF, DMSET);
505 return;
506 }
507 lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
508 lcr = DMFLCR_ENA;
509 if ((tp->t_ispeed) == B134)
510 lpar |= BITS6|PENABLE;
511 else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT))
512 lpar |= BITS8;
513 else {
514 lpar |= BITS7|PENABLE;
515 /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
516 }
517 if ((tp->t_flags&EVENP) == 0)
518 lpar |= OPAR;
519 if ((tp->t_ospeed) == B110)
520 lpar |= TWOSB;
521 lpar |= (unit&07);
522 addr->dmflpr = lpar;
523 addr->dmflcr = lcr;
524 splx(s);
525}
526
527/*
528 * DMF32 transmitter interrupt.
529 * Restart the idle line.
530 */
531dmfxint(dmf)
532 int dmf;
533{
534 register struct tty *tp;
535 register struct dmfdevice *addr;
536 register struct uba_device *ui;
537 register int unit, t;
538#ifdef DMFDMA
539 short cntr;
540#endif
541
542 ui = dmfinfo[dmf];
543 addr = (struct dmfdevice *)ui->ui_addr;
544 while ((t = addr->dmfcsr) & DMF_TI) {
545 unit = dmf*8 + ((t>>8)&07);
546 tp = &dmf_tty[unit];
c38b985f 547 tp->t_state &= ~TS_BUSY;
7a17d042
SL
548 if (t & DMF_NXM) {
549 printf("dmf%d: NXM line %d\n", dmf, unit&7);
550 /* SHOULD RESTART OR SOMETHING... */
551 }
c38b985f
SL
552 if (tp->t_state&TS_FLUSH)
553 tp->t_state &= ~TS_FLUSH;
7a17d042
SL
554#ifdef DMFDMA
555 else {
556 addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07);
557 if (addr->dmftsc == 0) {
558 /*
559 * Do arithmetic in a short to make up
560 * for lost 16&17 bits.
561 */
562 addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07);
563 cntr = addr->dmftba -
564 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
565 ndflush(&tp->t_outq, (int)cntr);
566 }
567 }
568#endif
569 if (tp->t_line)
570 (*linesw[tp->t_line].l_start)(tp);
571 else
572 dmfstart(tp);
573 }
574}
575
576/*
577 * Start (restart) transmission on the given DMF32 line.
578 */
579dmfstart(tp)
580 register struct tty *tp;
581{
582 register struct dmfdevice *addr;
583 register int car, dmf, unit, nch;
584 int s;
585
586 unit = minor(tp->t_dev);
587 dmf = unit >> 3;
588 unit &= 07;
589 addr = (struct dmfdevice *)tp->t_addr;
590
591 /*
592 * Must hold interrupts in following code to prevent
593 * state of the tp from changing.
594 */
595 s = spl5();
596 /*
597 * If it's currently active, or delaying, no need to do anything.
598 */
c38b985f 599 if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
7a17d042
SL
600 goto out;
601 /*
602 * If there are still characters in the silo,
603 * just reenable the transmitter.
604 */
605 addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
606 if (addr->dmftsc) {
607 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
608 addr->dmflcr |= DMF_TE;
c38b985f 609 tp->t_state |= TS_BUSY;
7a17d042
SL
610 goto out;
611 }
612 /*
613 * If there are sleepers, and output has drained below low
614 * water mark, wake up the sleepers.
615 */
c38b985f
SL
616 if ((tp->t_state&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) {
617 tp->t_state &= ~TS_ASLEEP;
e9c71764 618 wakeup((caddr_t)&tp->t_outq);
7a17d042
SL
619 }
620 /*
621 * Now restart transmission unless the output queue is
622 * empty.
623 */
624 if (tp->t_outq.c_cc == 0)
625 goto out;
626 if (tp->t_flags&RAW || tp->t_local&LLITOUT)
627 nch = ndqb(&tp->t_outq, 0);
628 else {
629 nch = ndqb(&tp->t_outq, 0200);
630 /*
631 * If first thing on queue is a delay process it.
632 */
633 if (nch == 0) {
634 nch = getc(&tp->t_outq);
635 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
c38b985f 636 tp->t_state |= TS_TIMEOUT;
7a17d042
SL
637 goto out;
638 }
639 }
640 /*
641 * If characters to transmit, restart transmission.
642 */
643 if (nch) {
644#ifdef DMFDMA
645 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
646 addr->dmflcr |= DMF_TE;
647 car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
648 addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
649 addr->dmftba = car;
650 addr->dmftcc = ((car>>2)&0xc000) | nch;
651#else
652 register char *cp = tp->t_outq.c_cf;
653 register int i;
654
655 nch = MIN(nch, DMF_SILOCNT);
656 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
657 addr->dmflcr |= DMF_TE;
658 addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
659 for (i = 0; i < nch; i++)
660 addr->dmftbuf = *cp++;
661 ndflush(&tp->t_outq, nch);
662#endif
c38b985f 663 tp->t_state |= TS_BUSY;
7a17d042
SL
664 }
665out:
666 splx(s);
667}
668
669/*
670 * Stop output on a line, e.g. for ^S/^Q or output flush.
671 */
672/*ARGSUSED*/
673dmfstop(tp, flag)
674 register struct tty *tp;
675{
676 register struct dmfdevice *addr;
677 register int unit, s;
678
679 addr = (struct dmfdevice *)tp->t_addr;
680 /*
681 * Block input/output interrupts while messing with state.
682 */
683 s = spl5();
c38b985f 684 if (tp->t_state & TS_BUSY) {
7a17d042
SL
685 /*
686 * Device is transmitting; stop output
687 * by selecting the line and disabling
688 * the transmitter. If this is a flush
689 * request then flush the output silo,
690 * otherwise we will pick up where we
691 * left off by enabling the transmitter.
692 */
693 unit = minor(tp->t_dev);
694 addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE;
695 addr->dmflcr &= ~DMF_TE;
c38b985f
SL
696 if ((tp->t_state&TS_TTSTOP)==0) {
697 tp->t_state |= TS_FLUSH;
7a17d042
SL
698 addr->dmflcr |= DMF_FLUSH;
699 } else
c38b985f 700 tp->t_state &= ~TS_BUSY;
7a17d042
SL
701 }
702 splx(s);
703}
704
705/*
706 * DMF32 modem control
707 */
708dmfmctl(dev, bits, how)
709 dev_t dev;
710 int bits, how;
711{
712 register struct dmfdevice *dmfaddr;
713 register int unit, mbits, lcr;
714 int s;
715
716 unit = minor(dev);
717 dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
718 unit &= 07;
719 s = spl5();
720 dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
721 mbits = dmfaddr->dmfrms << 8;
722 dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
723 mbits |= dmfaddr->dmftms;
724 lcr = dmfaddr->dmflcr;
725 switch (how) {
726 case DMSET:
727 mbits = bits;
728 break;
729
730 case DMBIS:
731 mbits |= bits;
732 break;
733
734 case DMBIC:
735 mbits &= ~bits;
736 break;
737
738 case DMGET:
739 (void) splx(s);
740 return(mbits);
741 }
742 dmfaddr->dmftms = mbits&037;
743 if (mbits & DMF_BRK)
744 lcr |= DMF_RBRK;
745 else
746 lcr &= ~DMF_RBRK;
747 dmfaddr->dmflcr = lcr;
748 (void) splx(s);
749 return(mbits);
750}
751
752/*
753 * Reset state of driver if UBA reset was necessary.
754 * Reset the csr, lpr, and lcr registers on open lines, and
755 * restart transmitters.
756 */
757dmfreset(uban)
758 int uban;
759{
760 register int dmf, unit;
761 register struct tty *tp;
762 register struct uba_device *ui;
763 register struct dmfdevice *addr;
764 int i;
765
766#ifdef DMFDMA
767 if (dmf_ubinfo[uban] == 0)
768 return;
769 ubarelse(uban, &dmf_ubinfo[uban]);
770 dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
771 nclist*sizeof (struct cblock), 0);
772 cbase[uban] = dmf_ubinfo[uban]&0x3ffff;
773#endif
774 for (dmf = 0; dmf < NDMF; dmf++) {
775 ui = dmfinfo[dmf];
776 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
777 continue;
778 printf(" dmf%d", dmf);
779 addr = (struct dmfdevice *)ui->ui_addr;
780 addr->dmfcsr = DMF_IE;
781 addr->dmfrsp = 1;
782 unit = dmf * 8;
783 for (i = 0; i < 8; i++) {
784 tp = &dmf_tty[unit];
c38b985f 785 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
7a17d042
SL
786 dmfparam(unit);
787 dmfmctl(unit, DMF_ON, DMSET);
c38b985f 788 tp->t_state &= ~TS_BUSY;
7a17d042
SL
789 dmfstart(tp);
790 }
791 unit++;
792 }
793 }
794}
795
796/* stubs for interrupt routines for devices not yet supported */
797
798dmfsrint() { printf("dmfsrint\n"); }
799
800dmfsxint() { printf("dmfsxint\n"); }
801
802dmfdaint() { printf("dmfdaint\n"); }
803
804dmfdbint() { printf("dmfdbint\n"); }
805
806dmflint() { printf("dmflint\n"); }
807#endif