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