1 /* dmf.c 4.14 82/10/22 */ 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/bk.h" 29 #include "../h/clist.h" 30 #include "../h/file.h" 31 #include "../h/uio.h" 32 33 #include "../vaxuba/ubareg.h" 34 #include "../vaxuba/ubavar.h" 35 36 /* 37 * Definition of the driver for the auto-configuration program. 38 */ 39 int dmfprobe(), dmfattach(), dmfrint(), dmfxint(); 40 struct uba_device *dmfinfo[NDMF]; 41 u_short dmfstd[] = { 0 }; 42 struct 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 */ 50 struct 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 */ 155 char dmf_speeds[] = 156 { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 }; 157 158 struct tty dmf_tty[NDMF*8]; 159 char dmfsoftCAR[NDMF]; 160 #ifndef lint 161 int ndmf = NDMF*8; /* used by iostat */ 162 #endif 163 int dmfact; /* mask of active dmf's */ 164 int dmfstart(), ttrstrt(); 165 166 #ifdef DMFDMA 167 /* 168 * The clist space is mapped by the driver onto each UNIBUS. 169 * The UBACVT macro converts a clist space address for unibus uban 170 * into an i/o space address for the DMA routine. 171 */ 172 int dmf_ubinfo[MAXNUBA]; /* info about allocated unibus map */ 173 static int cbase[MAXNUBA]; /* base address in unibus map */ 174 #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree)) 175 #endif 176 177 /* 178 * Routine for configuration to set dmf interrupt. 179 */ 180 /*ARGSUSED*/ 181 dmfprobe(reg, ctlr) 182 caddr_t reg; 183 int ctlr; 184 { 185 register int br, cvec; /* these are ``value-result'' */ 186 register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg; 187 188 #ifdef lint 189 br = 0; cvec = br; br = cvec; 190 dmfxint(0); dmfrint(0); 191 dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(); 192 #endif 193 br = 0x15; 194 cvec = (uba_hd[numuba].uh_lastiv -= 4*8); 195 dmfaddr->dmfccsr0 = cvec >> 2; 196 /* NEED TO SAVE IT SOMEWHERE FOR OTHER DEVICES */ 197 return (sizeof (struct dmfdevice)); 198 } 199 200 /* 201 * Routine called to attach a dmf. 202 */ 203 dmfattach(ui) 204 struct uba_device *ui; 205 { 206 207 dmfsoftCAR[ui->ui_unit] = ui->ui_flags; 208 } 209 210 211 /* 212 * Open a DMF32 line, mapping the clist onto the uba if this 213 * is the first dmf on this uba. Turn on this dmf if this is 214 * the first use of it. 215 */ 216 /*ARGSUSED*/ 217 dmfopen(dev, flag) 218 dev_t dev; 219 { 220 register struct tty *tp; 221 register int unit, dmf; 222 register struct dmfdevice *addr; 223 register struct uba_device *ui; 224 int s; 225 226 unit = minor(dev); 227 dmf = unit >> 3; 228 if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0) 229 return (ENXIO); 230 tp = &dmf_tty[unit]; 231 if (tp->t_state&TS_XCLUDE && u.u_uid!=0) 232 return (EBUSY); 233 addr = (struct dmfdevice *)ui->ui_addr; 234 tp->t_addr = (caddr_t)addr; 235 tp->t_oproc = dmfstart; 236 tp->t_state |= TS_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&TS_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 |= TS_CARR_ON; 274 s = spl5(); 275 while ((tp->t_state & TS_CARR_ON) == 0) { 276 tp->t_state |= TS_WOPEN; 277 sleep((caddr_t)&tp->t_rawq, TTIPRI); 278 } 279 splx(s); 280 return ((*linesw[tp->t_line].l_open)(dev, tp)); 281 } 282 283 /* 284 * Close a DMF32 line. 285 */ 286 /*ARGSUSED*/ 287 dmfclose(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 (void) dmfmctl(unit, DMF_BRK, DMBIC); 298 if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0) 299 (void) dmfmctl(unit, DMF_OFF, DMSET); 300 ttyclose(tp); 301 } 302 303 dmfread(dev, uio) 304 dev_t dev; 305 struct uio *uio; 306 { 307 register struct tty *tp; 308 309 tp = &dmf_tty[minor(dev)]; 310 return ((*linesw[tp->t_line].l_read)(tp, uio)); 311 } 312 313 dmfwrite(dev, uio) 314 dev_t dev; 315 struct uio *uio; 316 { 317 register struct tty *tp; 318 319 tp = &dmf_tty[minor(dev)]; 320 return ((*linesw[tp->t_line].l_write)(tp, uio)); 321 } 322 323 /* 324 * DMF32 receiver interrupt. 325 */ 326 dmfrint(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) { 350 if ((tp->t_state & TS_CARR_ON) == 0) { 351 wakeup((caddr_t)&tp->t_rawq); 352 tp->t_state |= TS_CARR_ON; 353 } 354 } else { 355 if (tp->t_state & TS_CARR_ON) { 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 } 363 tp->t_state &= ~TS_CARR_ON; 364 } 365 continue; 366 } 367 if ((tp->t_state&TS_ISOPEN)==0) { 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*/ 403 dmfioctl(dev, cmd, data, flag) 404 dev_t dev; 405 caddr_t data; 406 { 407 register struct tty *tp; 408 register int unit = minor(dev); 409 int error; 410 411 tp = &dmf_tty[unit]; 412 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); 413 if (error >= 0) 414 return (error); 415 error = ttioctl(tp, cmd, data, flag); 416 if (error >= 0) { 417 if (cmd == TIOCSETP || cmd == TIOCSETN) 418 dmfparam(unit); 419 return (error); 420 } 421 switch (cmd) { 422 423 case TIOCSBRK: 424 (void) dmfmctl(dev, DMF_BRK, DMBIS); 425 break; 426 427 case TIOCCBRK: 428 (void) dmfmctl(dev, DMF_BRK, DMBIC); 429 break; 430 431 case TIOCSDTR: 432 (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS); 433 break; 434 435 case TIOCCDTR: 436 (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC); 437 break; 438 439 case TIOCMSET: 440 (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET); 441 break; 442 443 case TIOCMBIS: 444 (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS); 445 break; 446 447 case TIOCMBIC: 448 (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC); 449 break; 450 451 case TIOCMGET: 452 *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET)); 453 break; 454 455 default: 456 return (ENOTTY); 457 } 458 return (0); 459 } 460 461 dmtodmf(bits) 462 register int bits; 463 { 464 register int b; 465 466 b = bits & 012; 467 if (bits & DML_ST) b |= DMF_RATE; 468 if (bits & DML_RTS) b |= DMF_RTS; 469 if (bits & DML_USR) b |= DMF_USRW; 470 return(b); 471 } 472 473 dmftodm(bits) 474 register int bits; 475 { 476 register int b; 477 478 b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE; 479 if (bits & DMF_USRR) b |= DML_USR; 480 if (bits & DMF_RTS) b |= DML_RTS; 481 return(b); 482 } 483 484 485 /* 486 * Set parameters from open or stty into the DMF hardware 487 * registers. 488 */ 489 dmfparam(unit) 490 register int unit; 491 { 492 register struct tty *tp; 493 register struct dmfdevice *addr; 494 register int lpar, lcr; 495 int s; 496 497 tp = &dmf_tty[unit]; 498 addr = (struct dmfdevice *)tp->t_addr; 499 /* 500 * Block interrupts so parameters will be set 501 * before the line interrupts. 502 */ 503 s = spl5(); 504 addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE; 505 if ((tp->t_ispeed)==0) { 506 tp->t_state |= TS_HUPCLS; 507 (void) dmfmctl(unit, DMF_OFF, DMSET); 508 return; 509 } 510 lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8); 511 lcr = DMFLCR_ENA; 512 if ((tp->t_ispeed) == B134) 513 lpar |= BITS6|PENABLE; 514 else if ((tp->t_flags&RAW) || (tp->t_local&LLITOUT)) 515 lpar |= BITS8; 516 else { 517 lpar |= BITS7|PENABLE; 518 /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */ 519 } 520 if ((tp->t_flags&EVENP) == 0) 521 lpar |= OPAR; 522 if ((tp->t_ospeed) == B110) 523 lpar |= TWOSB; 524 lpar |= (unit&07); 525 addr->dmflpr = lpar; 526 addr->dmflcr = lcr; 527 splx(s); 528 } 529 530 /* 531 * DMF32 transmitter interrupt. 532 * Restart the idle line. 533 */ 534 dmfxint(dmf) 535 int dmf; 536 { 537 register struct tty *tp; 538 register struct dmfdevice *addr; 539 register struct uba_device *ui; 540 register int unit, t; 541 #ifdef DMFDMA 542 short cntr; 543 #endif 544 545 ui = dmfinfo[dmf]; 546 addr = (struct dmfdevice *)ui->ui_addr; 547 while ((t = addr->dmfcsr) & DMF_TI) { 548 unit = dmf*8 + ((t>>8)&07); 549 tp = &dmf_tty[unit]; 550 tp->t_state &= ~TS_BUSY; 551 if (t & DMF_NXM) { 552 printf("dmf%d: NXM line %d\n", dmf, unit&7); 553 /* SHOULD RESTART OR SOMETHING... */ 554 } 555 if (tp->t_state&TS_FLUSH) 556 tp->t_state &= ~TS_FLUSH; 557 #ifdef DMFDMA 558 else { 559 addr->dmfcsr = DMFIR_TBUF | DMF_IE | (unit&07); 560 if (addr->dmftsc == 0) { 561 /* 562 * Do arithmetic in a short to make up 563 * for lost 16&17 bits. 564 */ 565 addr->dmfcsr = DMFIR_TBA | DMF_IE | (unit&07); 566 cntr = addr->dmftba - 567 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum); 568 ndflush(&tp->t_outq, (int)cntr); 569 } 570 } 571 #endif 572 if (tp->t_line) 573 (*linesw[tp->t_line].l_start)(tp); 574 else 575 dmfstart(tp); 576 } 577 } 578 579 /* 580 * Start (restart) transmission on the given DMF32 line. 581 */ 582 dmfstart(tp) 583 register struct tty *tp; 584 { 585 register struct dmfdevice *addr; 586 register int unit, nch; 587 int s; 588 589 unit = minor(tp->t_dev); 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&(TS_TIMEOUT|TS_BUSY|TS_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 |= TS_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&TS_ASLEEP) && tp->t_outq.c_cc<=TTLOWAT(tp)) { 619 tp->t_state &= ~TS_ASLEEP; 620 wakeup((caddr_t)&tp->t_outq); 621 } 622 /* 623 * Now restart transmission unless the output queue is 624 * empty. 625 */ 626 if (tp->t_outq.c_cc == 0) 627 goto out; 628 if (tp->t_flags&RAW || tp->t_local&LLITOUT) 629 nch = ndqb(&tp->t_outq, 0); 630 else { 631 nch = ndqb(&tp->t_outq, 0200); 632 /* 633 * If first thing on queue is a delay process it. 634 */ 635 if (nch == 0) { 636 nch = getc(&tp->t_outq); 637 timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6); 638 tp->t_state |= TS_TIMEOUT; 639 goto out; 640 } 641 } 642 /* 643 * If characters to transmit, restart transmission. 644 */ 645 if (nch) { 646 #ifdef DMFDMA 647 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 648 addr->dmflcr |= DMF_TE; 649 car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum); 650 addr->dmfcsr = DMF_IE | DMFIR_TBA | unit; 651 addr->dmftba = car; 652 addr->dmftcc = ((car>>2)&0xc000) | nch; 653 #else 654 register char *cp = tp->t_outq.c_cf; 655 register int i; 656 657 nch = MIN(nch, DMF_SILOCNT); 658 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 659 addr->dmflcr |= DMF_TE; 660 addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 661 for (i = 0; i < nch; i++) 662 addr->dmftbuf = *cp++; 663 ndflush(&tp->t_outq, nch); 664 #endif 665 tp->t_state |= TS_BUSY; 666 } 667 out: 668 splx(s); 669 } 670 671 /* 672 * Stop output on a line, e.g. for ^S/^Q or output flush. 673 */ 674 /*ARGSUSED*/ 675 dmfstop(tp, flag) 676 register struct tty *tp; 677 { 678 register struct dmfdevice *addr; 679 register int unit, s; 680 681 addr = (struct dmfdevice *)tp->t_addr; 682 /* 683 * Block input/output interrupts while messing with state. 684 */ 685 s = spl5(); 686 if (tp->t_state & TS_BUSY) { 687 /* 688 * Device is transmitting; stop output 689 * by selecting the line and disabling 690 * the transmitter. If this is a flush 691 * request then flush the output silo, 692 * otherwise we will pick up where we 693 * left off by enabling the transmitter. 694 */ 695 unit = minor(tp->t_dev); 696 addr->dmfcsr = DMFIR_LCR | (unit&07) | DMF_IE; 697 addr->dmflcr &= ~DMF_TE; 698 if ((tp->t_state&TS_TTSTOP)==0) { 699 tp->t_state |= TS_FLUSH; 700 addr->dmflcr |= DMF_FLUSH; 701 } else 702 tp->t_state &= ~TS_BUSY; 703 } 704 splx(s); 705 } 706 707 /* 708 * DMF32 modem control 709 */ 710 dmfmctl(dev, bits, how) 711 dev_t dev; 712 int bits, how; 713 { 714 register struct dmfdevice *dmfaddr; 715 register int unit, mbits, lcr; 716 int s; 717 718 unit = minor(dev); 719 dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr); 720 unit &= 07; 721 s = spl5(); 722 dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit; 723 mbits = dmfaddr->dmfrms << 8; 724 dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit; 725 mbits |= dmfaddr->dmftms; 726 lcr = dmfaddr->dmflcr; 727 switch (how) { 728 case DMSET: 729 mbits = bits; 730 break; 731 732 case DMBIS: 733 mbits |= bits; 734 break; 735 736 case DMBIC: 737 mbits &= ~bits; 738 break; 739 740 case DMGET: 741 (void) splx(s); 742 return(mbits); 743 } 744 dmfaddr->dmftms = mbits&037; 745 if (mbits & DMF_BRK) 746 lcr |= DMF_RBRK; 747 else 748 lcr &= ~DMF_RBRK; 749 dmfaddr->dmflcr = lcr; 750 (void) splx(s); 751 return(mbits); 752 } 753 754 /* 755 * Reset state of driver if UBA reset was necessary. 756 * Reset the csr, lpr, and lcr registers on open lines, and 757 * restart transmitters. 758 */ 759 dmfreset(uban) 760 int uban; 761 { 762 register int dmf, unit; 763 register struct tty *tp; 764 register struct uba_device *ui; 765 register struct dmfdevice *addr; 766 int i; 767 768 #ifdef DMFDMA 769 if (dmf_ubinfo[uban] == 0) 770 return; 771 dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree, 772 nclist*sizeof (struct cblock), 0); 773 cbase[uban] = dmf_ubinfo[uban]&0x3ffff; 774 #endif 775 for (dmf = 0; dmf < NDMF; dmf++) { 776 ui = dmfinfo[dmf]; 777 if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban) 778 continue; 779 printf(" dmf%d", dmf); 780 addr = (struct dmfdevice *)ui->ui_addr; 781 addr->dmfcsr = DMF_IE; 782 addr->dmfrsp = 1; 783 unit = dmf * 8; 784 for (i = 0; i < 8; i++) { 785 tp = &dmf_tty[unit]; 786 if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) { 787 dmfparam(unit); 788 (void) dmfmctl(unit, DMF_ON, DMSET); 789 tp->t_state &= ~TS_BUSY; 790 dmfstart(tp); 791 } 792 unit++; 793 } 794 } 795 } 796 797 /* stubs for interrupt routines for devices not yet supported */ 798 799 dmfsrint() { printf("dmfsrint\n"); } 800 801 dmfsxint() { printf("dmfsxint\n"); } 802 803 dmfdaint() { printf("dmfdaint\n"); } 804 805 dmfdbint() { printf("dmfdbint\n"); } 806 807 dmflint() { printf("dmflint\n"); } 808 #endif 809