1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)dh.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "dh.h"
  10: #if NDH > 0
  11: /*
  12:  * DH-11/DM-11 driver
  13:  */
  14: #include "../machine/pte.h"
  15: 
  16: #include "bk.h"
  17: #include "uba.h"
  18: #include "param.h"
  19: #include "conf.h"
  20: #include "dir.h"
  21: #include "user.h"
  22: #include "proc.h"
  23: #include "ioctl.h"
  24: #include "tty.h"
  25: #include "map.h"
  26: #include "buf.h"
  27: #include "vm.h"
  28: #include "kernel.h"
  29: #include "syslog.h"
  30: 
  31: #include "ubareg.h"
  32: #include "ubavar.h"
  33: #include "dhreg.h"
  34: #include "dmreg.h"
  35: 
  36: #include "bkmac.h"
  37: #include "clist.h"
  38: #include "file.h"
  39: #include "uio.h"
  40: 
  41: /*
  42:  * Definition of the driver for the auto-configuration program.
  43:  * There is one definition for the dh and one for the dm.
  44:  */
  45: int dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer();
  46: struct  uba_device *dhinfo[NDH];
  47: u_short dhstd[] = { 0 };
  48: struct  uba_driver dhdriver =
  49:     { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
  50: 
  51: int dmprobe(), dmattach(), dmintr();
  52: struct  uba_device *dminfo[NDH];
  53: u_short dmstd[] = { 0 };
  54: struct  uba_driver dmdriver =
  55:     { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
  56: 
  57: #ifndef PORTSELECTOR
  58: #define ISPEED  B9600
  59: #define IFLAGS  (EVENP|ODDP|ECHO)
  60: #else
  61: #define ISPEED  B4800
  62: #define IFLAGS  (EVENP|ODDP)
  63: #endif
  64: 
  65: #define FASTTIMER   (hz/30)     /* scan rate with silos on */
  66: 
  67: /*
  68:  * Local variables for the driver
  69:  */
  70: short   dhsar[NDH];         /* software copy of last bar */
  71: short   dhsoftCAR[NDH];
  72: 
  73: struct  tty dh11[NDH*16];
  74: int ndh11   = NDH*16;
  75: int dhact;              /* mask of active dh's */
  76: int dhsilos;            /* mask of dh's with silo in use */
  77: int dhchars[NDH];           /* recent input count */
  78: int dhrate[NDH];            /* smoothed input count */
  79: int dhhighrate = 100;       /* silo on if dhchars > dhhighrate */
  80: int dhlowrate = 75;         /* silo off if dhrate < dhlowrate */
  81: static short timerstarted;
  82: int dhstart(), ttrstrt();
  83: 
  84: /*
  85:  * The clist space is mapped by the driver onto each UNIBUS.
  86:  * The UBACVT macro converts a clist space address for unibus uban
  87:  * into an i/o space address for the DMA routine.
  88:  */
  89: int dh_ubinfo[NUBA];        /* info about allocated unibus map */
  90: int cbase[NUBA];            /* base address in unibus map */
  91: #define UBACVT(x, uban)     (cbase[uban] + ((x)-(char *)cfree))
  92: 
  93: /*
  94:  * Routine for configuration to force a dh to interrupt.
  95:  * Set to transmit at 9600 baud, and cause a transmitter interrupt.
  96:  */
  97: /*ARGSUSED*/
  98: dhprobe(reg)
  99:     caddr_t reg;
 100: {
 101:     register int br, cvec;      /* these are ``value-result'' */
 102:     register struct dhdevice *dhaddr = (struct dhdevice *)reg;
 103: 
 104: #ifdef lint
 105:     br = 0; cvec = br; br = cvec;
 106:     if (ndh11 == 0) ndh11 = 1;
 107:     dhrint(0); dhxint(0);
 108: #endif
 109: #ifndef notdef
 110:     dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
 111:     DELAY(1000);
 112:     dhaddr->un.dhcsr &= ~DH_RI;
 113:     dhaddr->un.dhcsr = 0;
 114: #else
 115:     dhaddr->un.dhcsr = DH_TIE;
 116:     DELAY(5);
 117:     dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
 118:     dhaddr->dhbcr = -1;
 119:     dhaddr->dhcar = 0;
 120:     dhaddr->dhbar = 1;
 121:     DELAY(100000);      /* wait 1/10'th of a sec for interrupt */
 122:     dhaddr->un.dhcsr = 0;
 123:     if (cvec && cvec != 0x200)
 124:         cvec -= 4;      /* transmit -> receive */
 125: #endif
 126:     return (sizeof (struct dhdevice));
 127: }
 128: 
 129: /*
 130:  * Routine called to attach a dh.
 131:  */
 132: dhattach(ui)
 133:     struct uba_device *ui;
 134: {
 135: 
 136:     dhsoftCAR[ui->ui_unit] = ui->ui_flags;
 137:     cbase[ui->ui_ubanum] = -1;
 138: }
 139: 
 140: /*
 141:  * Configuration routine to cause a dm to interrupt.
 142:  */
 143: dmprobe(reg)
 144:     caddr_t reg;
 145: {
 146:     register int br, vec;           /* value-result */
 147:     register struct dmdevice *dmaddr = (struct dmdevice *)reg;
 148: 
 149: #ifdef lint
 150:     br = 0; vec = br; br = vec;
 151:     dmintr(0);
 152: #endif
 153:     dmaddr->dmcsr = DM_DONE|DM_IE;
 154:     DELAY(20);
 155:     dmaddr->dmcsr = 0;
 156:     return (1);
 157: }
 158: 
 159: /*ARGSUSED*/
 160: dmattach(ui)
 161:     struct uba_device *ui;
 162: {
 163: 
 164:     /* no local state to set up */
 165: }
 166: 
 167: /*
 168:  * Open a DH11 line, mapping the clist onto the uba if this
 169:  * is the first dh on this uba.  Turn on this dh if this is
 170:  * the first use of it.  Also do a dmopen to wait for carrier.
 171:  */
 172: /*ARGSUSED*/
 173: dhopen(dev, flag)
 174:     dev_t dev;
 175: {
 176:     register struct tty *tp;
 177:     register int unit, dh;
 178:     register struct dhdevice *addr;
 179:     register struct uba_device *ui;
 180:     int s;
 181: 
 182:     unit = minor(dev);
 183:     dh = unit >> 4;
 184:     if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
 185:         return (ENXIO);
 186:     tp = &dh11[unit];
 187:     if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
 188:         return (EBUSY);
 189:     addr = (struct dhdevice *)ui->ui_addr;
 190:     tp->t_addr = (caddr_t)addr;
 191:     tp->t_oproc = dhstart;
 192:     tp->t_state |= TS_WOPEN;
 193:     /*
 194: 	 * While setting up state for this uba and this dh,
 195: 	 * block uba resets which can clear the state.
 196: 	 */
 197:     s = spl5();
 198:     if (cbase[ui->ui_ubanum] == -1) {
 199:         dh_ubinfo[ui->ui_ubanum] =
 200:             uballoc(ui->ui_ubanum, (caddr_t)cfree,
 201:             nclist*sizeof(struct cblock), 0);
 202:         cbase[ui->ui_ubanum] = UBAI_ADDR(dh_ubinfo[ui->ui_ubanum]);
 203:     }
 204:     if (timerstarted == 0) {
 205:         timerstarted++;
 206:         timeout(dhtimer, (caddr_t) 0, hz);
 207:     }
 208:     if ((dhact&(1<<dh)) == 0) {
 209:         addr->un.dhcsr |= DH_IE;
 210:         dhact |= (1<<dh);
 211:         addr->dhsilo = 0;
 212:     }
 213:     splx(s);
 214:     /*
 215: 	 * If this is first open, initialize tty state to default.
 216: 	 */
 217:     if ((tp->t_state&TS_ISOPEN) == 0) {
 218:         ttychars(tp);
 219: #ifndef PORTSELECTOR
 220:         if (tp->t_ispeed == 0) {
 221: #else
 222:             tp->t_state |= TS_HUPCLS;
 223: #endif PORTSELECTOR
 224:             tp->t_ispeed = ISPEED;
 225:             tp->t_ospeed = ISPEED;
 226:             tp->t_flags = IFLAGS;
 227: #ifndef PORTSELECTOR
 228:         }
 229: #endif PORTSELECTOR
 230:         dhparam(unit);
 231:     }
 232:     /*
 233: 	 * Wait for carrier, then process line discipline specific open.
 234: 	 */
 235:     dmopen(dev);
 236:     return ((*linesw[tp->t_line].l_open)(dev, tp));
 237: }
 238: 
 239: /*
 240:  * Close a DH11 line, turning off the DM11.
 241:  */
 242: /*ARGSUSED*/
 243: dhclose(dev, flag)
 244:     dev_t dev;
 245:     int flag;
 246: {
 247:     register struct tty *tp;
 248:     register unit;
 249: 
 250:     unit = minor(dev);
 251:     tp = &dh11[unit];
 252:     (*linesw[tp->t_line].l_close)(tp);
 253:     ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
 254:     if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
 255:         dmctl(unit, DML_OFF, DMSET);
 256:     ttyclose(tp);
 257: }
 258: 
 259: dhread(dev, uio)
 260:     dev_t dev;
 261:     struct uio *uio;
 262: {
 263:     register struct tty *tp = &dh11[minor(dev)];
 264: 
 265:     return ((*linesw[tp->t_line].l_read)(tp, uio));
 266: }
 267: 
 268: dhwrite(dev, uio)
 269:     dev_t dev;
 270:     struct uio *uio;
 271: {
 272:     register struct tty *tp = &dh11[minor(dev)];
 273: 
 274:     return ((*linesw[tp->t_line].l_write)(tp, uio));
 275: }
 276: 
 277: /*
 278:  * DH11 receiver interrupt.
 279:  */
 280: dhrint(dh)
 281:     int dh;
 282: {
 283:     register struct tty *tp;
 284:     register c;
 285:     register struct dhdevice *addr;
 286:     register struct tty *tp0;
 287:     register struct uba_device *ui;
 288:     int overrun = 0;
 289: 
 290:     ui = dhinfo[dh];
 291:     if (ui == 0 || ui->ui_alive == 0)
 292:         return;
 293:     addr = (struct dhdevice *)ui->ui_addr;
 294:     tp0 = &dh11[dh<<4];
 295:     /*
 296: 	 * Loop fetching characters from the silo for this
 297: 	 * dh until there are no more in the silo.
 298: 	 */
 299:     while ((c = addr->dhrcr) < 0) {
 300:         tp = tp0 + ((c>>8)&0xf);
 301:         dhchars[dh]++;
 302:         if ((tp->t_state&TS_ISOPEN)==0) {
 303:             wakeup((caddr_t)&tp->t_rawq);
 304: #ifdef PORTSELECTOR
 305:             if ((tp->t_state&TS_WOPEN) == 0)
 306: #endif
 307:                 continue;
 308:         }
 309:         if (c & DH_PE)
 310:             if ((tp->t_flags&(EVENP|ODDP))==EVENP
 311:              || (tp->t_flags&(EVENP|ODDP))==ODDP )
 312:                 continue;
 313:         if ((c & DH_DO) && overrun == 0) {
 314:             log(LOG_WARNING, "dh%d: silo overflow\n", dh);
 315:             overrun = 1;
 316:         }
 317:         if (c & DH_FE)
 318:             /*
 319: 			 * At framing error (break) generate
 320: 			 * a null (in raw mode, for getty), or a
 321: 			 * interrupt (in cooked/cbreak mode).
 322: 			 */
 323:             if (tp->t_flags&RAW)
 324:                 c = 0;
 325:             else
 326:                 c = tp->t_intrc;
 327: #if NBK > 0
 328:         if (tp->t_line == NETLDISC) {
 329:             c &= 0177;
 330:             BKINPUT(c, tp);
 331:         } else
 332: #endif
 333:             (*linesw[tp->t_line].l_rint)(c, tp);
 334:     }
 335: }
 336: 
 337: /*
 338:  * Ioctl for DH11.
 339:  */
 340: /*ARGSUSED*/
 341: dhioctl(dev, cmd, data, flag)
 342:     caddr_t data;
 343: {
 344:     register struct tty *tp;
 345:     register int unit = minor(dev);
 346:     int error;
 347: 
 348:     tp = &dh11[unit];
 349:     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 350:     if (error >= 0)
 351:         return (error);
 352:     error = ttioctl(tp, cmd, data, flag);
 353:     if (error >= 0) {
 354:         if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
 355:             cmd == TIOCLBIC || cmd == TIOCLSET)
 356:             dhparam(unit);
 357:         return (error);
 358:     }
 359:     switch (cmd) {
 360: 
 361:     case TIOCSBRK:
 362:         ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
 363:         break;
 364: 
 365:     case TIOCCBRK:
 366:         ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
 367:         break;
 368: 
 369:     case TIOCSDTR:
 370:         dmctl(unit, DML_DTR|DML_RTS, DMBIS);
 371:         break;
 372: 
 373:     case TIOCCDTR:
 374:         dmctl(unit, DML_DTR|DML_RTS, DMBIC);
 375:         break;
 376: 
 377:     default:
 378:         return (ENOTTY);
 379:     }
 380:     return (0);
 381: }
 382: 
 383: /*
 384:  * Set parameters from open or stty into the DH hardware
 385:  * registers.
 386:  */
 387: dhparam(unit)
 388:     register int unit;
 389: {
 390:     register struct tty *tp;
 391:     register struct dhdevice *addr;
 392:     register int lpar;
 393:     int s;
 394: 
 395:     tp = &dh11[unit];
 396:     addr = (struct dhdevice *)tp->t_addr;
 397:     /*
 398: 	 * Block interrupts so parameters will be set
 399: 	 * before the line interrupts.
 400: 	 */
 401:     s = spl5();
 402:     addr->un.dhcsrl = (unit&0xf) | DH_IE;
 403:     if ((tp->t_ispeed)==0) {
 404:         tp->t_state |= TS_HUPCLS;
 405:         dmctl(unit, DML_OFF, DMSET);
 406:         splx(s);
 407:         return;
 408:     }
 409:     lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
 410:     if ((tp->t_ispeed) == B134)
 411:         lpar |= BITS6|PENABLE|HDUPLX;
 412:     else if (tp->t_flags & (RAW|LITOUT|PASS8))
 413:         lpar |= BITS8;
 414:     else
 415:         lpar |= BITS7|PENABLE;
 416:     if ((tp->t_flags&EVENP) == 0)
 417:         lpar |= OPAR;
 418:     if ((tp->t_ospeed) == B110)
 419:         lpar |= TWOSB;
 420:     addr->dhlpr = lpar;
 421:     splx(s);
 422: }
 423: 
 424: /*
 425:  * DH11 transmitter interrupt.
 426:  * Restart each line which used to be active but has
 427:  * terminated transmission since the last interrupt.
 428:  */
 429: dhxint(dh)
 430:     int dh;
 431: {
 432:     register struct tty *tp;
 433:     register struct dhdevice *addr;
 434:     short ttybit, bar, *sbar;
 435:     register struct uba_device *ui;
 436:     register int unit;
 437:     u_short cntr;
 438: 
 439:     ui = dhinfo[dh];
 440:     addr = (struct dhdevice *)ui->ui_addr;
 441:     if (addr->un.dhcsr & DH_NXM) {
 442:         addr->un.dhcsr |= DH_CNI;
 443:         printf("dh%d: NXM\n", dh);
 444:     }
 445:     sbar = &dhsar[dh];
 446:     bar = *sbar & ~addr->dhbar;
 447:     unit = dh * 16; ttybit = 1;
 448:     addr->un.dhcsr &= (short)~DH_TI;
 449:     for (; bar; unit++, ttybit <<= 1) {
 450:         if (bar & ttybit) {
 451:             *sbar &= ~ttybit;
 452:             bar &= ~ttybit;
 453:             tp = &dh11[unit];
 454:             tp->t_state &= ~TS_BUSY;
 455:             if (tp->t_state&TS_FLUSH)
 456:                 tp->t_state &= ~TS_FLUSH;
 457:             else {
 458:                 addr->un.dhcsrl = (unit&017)|DH_IE;
 459:                 /*
 460: 				 * Do arithmetic in a short to make up
 461: 				 * for lost 16&17 bits.
 462: 				 */
 463:                 cntr = addr->dhcar -
 464:                     UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
 465:                 ndflush(&tp->t_outq, (int)cntr);
 466:             }
 467:             if (tp->t_line)
 468:                 (*linesw[tp->t_line].l_start)(tp);
 469:             else
 470:                 dhstart(tp);
 471:         }
 472:     }
 473: }
 474: 
 475: /*
 476:  * Start (restart) transmission on the given DH11 line.
 477:  */
 478: dhstart(tp)
 479:     register struct tty *tp;
 480: {
 481:     register struct dhdevice *addr;
 482:     register int car, dh, unit, nch;
 483:     int s;
 484: 
 485:     unit = minor(tp->t_dev);
 486:     dh = unit >> 4;
 487:     unit &= 0xf;
 488:     addr = (struct dhdevice *)tp->t_addr;
 489: 
 490:     /*
 491: 	 * Must hold interrupts in following code to prevent
 492: 	 * state of the tp from changing.
 493: 	 */
 494:     s = spl5();
 495:     /*
 496: 	 * If it's currently active, or delaying, no need to do anything.
 497: 	 */
 498:     if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 499:         goto out;
 500:     /*
 501: 	 * If there are sleepers, and output has drained below low
 502: 	 * water mark, wake up the sleepers.
 503: 	 */
 504:     if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
 505:         if (tp->t_state&TS_ASLEEP) {
 506:             tp->t_state &= ~TS_ASLEEP;
 507:             wakeup((caddr_t)&tp->t_outq);
 508:         }
 509:         if (tp->t_wsel) {
 510:             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
 511:             tp->t_wsel = 0;
 512:             tp->t_state &= ~TS_WCOLL;
 513:         }
 514:     }
 515:     /*
 516: 	 * Now restart transmission unless the output queue is
 517: 	 * empty.
 518: 	 */
 519:     if (tp->t_outq.c_cc == 0)
 520:         goto out;
 521:     if (tp->t_flags & (RAW|LITOUT))
 522:         nch = ndqb(&tp->t_outq, 0);
 523:     else {
 524:         nch = ndqb(&tp->t_outq, 0200);
 525:         /*
 526: 		 * If first thing on queue is a delay process it.
 527: 		 */
 528:         if (nch == 0) {
 529:             nch = getc(&tp->t_outq);
 530:             timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
 531:             tp->t_state |= TS_TIMEOUT;
 532:             goto out;
 533:         }
 534:     }
 535:     /*
 536: 	 * If characters to transmit, restart transmission.
 537: 	 */
 538:     if (nch) {
 539:         car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
 540:         addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
 541:         /*
 542: 		 * The following nonsense with short word
 543: 		 * is to make sure the dhbar |= word below
 544: 		 * is done with an interlocking bisw2 instruction.
 545: 		 */
 546:         { short word = 1 << unit;
 547:         dhsar[dh] |= word;
 548:         addr->dhcar = car;
 549:         addr->dhbcr = -nch;
 550:         addr->dhbar |= word;
 551:         }
 552:         tp->t_state |= TS_BUSY;
 553:     }
 554: out:
 555:     splx(s);
 556: }
 557: 
 558: /*
 559:  * Stop output on a line, e.g. for ^S/^Q or output flush.
 560:  */
 561: /*ARGSUSED*/
 562: dhstop(tp, flag)
 563:     register struct tty *tp;
 564: {
 565:     register struct dhdevice *addr;
 566:     register int unit, s;
 567: 
 568:     addr = (struct dhdevice *)tp->t_addr;
 569:     /*
 570: 	 * Block input/output interrupts while messing with state.
 571: 	 */
 572:     s = spl5();
 573:     if (tp->t_state & TS_BUSY) {
 574:         /*
 575: 		 * Device is transmitting; stop output
 576: 		 * by selecting the line and setting the byte
 577: 		 * count to -1.  We will clean up later
 578: 		 * by examining the address where the dh stopped.
 579: 		 */
 580:         unit = minor(tp->t_dev);
 581:         addr->un.dhcsrl = (unit&017) | DH_IE;
 582:         if ((tp->t_state&TS_TTSTOP)==0)
 583:             tp->t_state |= TS_FLUSH;
 584:         addr->dhbcr = -1;
 585:     }
 586:     splx(s);
 587: }
 588: 
 589: /*
 590:  * Reset state of driver if UBA reset was necessary.
 591:  * Reset the csrl and lpr registers on open lines, and
 592:  * restart transmitters.
 593:  */
 594: dhreset(uban)
 595:     int uban;
 596: {
 597:     register int dh, unit;
 598:     register struct tty *tp;
 599:     register struct uba_device *ui;
 600:     int i;
 601: 
 602:     dh = 0;
 603:     for (dh = 0; dh < NDH; dh++) {
 604:         ui = dhinfo[dh];
 605:         if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
 606:             continue;
 607:         printf(" dh%d", dh);
 608:         if (dh_ubinfo[uban]) {
 609:             dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
 610:                 nclist*sizeof (struct cblock), 0);
 611:             cbase[uban] = UBAI_ADDR(dh_ubinfo[uban]);
 612:         }
 613:         ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
 614:         ((struct dhdevice *)ui->ui_addr)->dhsilo = 0;
 615:         unit = dh * 16;
 616:         for (i = 0; i < 16; i++) {
 617:             tp = &dh11[unit];
 618:             if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
 619:                 dhparam(unit);
 620:                 dmctl(unit, DML_ON, DMSET);
 621:                 tp->t_state &= ~TS_BUSY;
 622:                 dhstart(tp);
 623:             }
 624:             unit++;
 625:         }
 626:     }
 627:     dhsilos = 0;
 628: }
 629: 
 630: int dhtransitions, dhslowtimers, dhfasttimers;      /*DEBUG*/
 631: /*
 632:  * At software clock interrupt time, check status.
 633:  * Empty all the dh silos that are in use, and decide whether
 634:  * to turn any silos off or on.
 635:  */
 636: dhtimer()
 637: {
 638:     register int dh, s;
 639:     static int timercalls;
 640: 
 641:     if (dhsilos) {
 642:         dhfasttimers++;     /*DEBUG*/
 643:         timercalls++;
 644:         s = spl5();
 645:         for (dh = 0; dh < NDH; dh++)
 646:             if (dhsilos & (1 << dh))
 647:                 dhrint(dh);
 648:         splx(s);
 649:     }
 650:     if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) {
 651:         dhslowtimers++;     /*DEBUG*/
 652:         timercalls = 0;
 653:         for (dh = 0; dh < NDH; dh++) {
 654:             ave(dhrate[dh], dhchars[dh], 8);
 655:             if ((dhchars[dh] > dhhighrate) &&
 656:               ((dhsilos & (1 << dh)) == 0)) {
 657:             ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo =
 658:                 (dhchars[dh] > 500? 32 : 16);
 659:             dhsilos |= (1 << dh);
 660:             dhtransitions++;        /*DEBUG*/
 661:             } else if ((dhsilos & (1 << dh)) &&
 662:               (dhrate[dh] < dhlowrate)) {
 663:             ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0;
 664:             dhsilos &= ~(1 << dh);
 665:             }
 666:             dhchars[dh] = 0;
 667:         }
 668:     }
 669:     timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz);
 670: }
 671: 
 672: /*
 673:  * Turn on the line associated with dh dev.
 674:  */
 675: dmopen(dev)
 676:     dev_t dev;
 677: {
 678:     register struct tty *tp;
 679:     register struct dmdevice *addr;
 680:     register struct uba_device *ui;
 681:     register int unit;
 682:     register int dm;
 683:     int s;
 684: 
 685:     unit = minor(dev);
 686:     dm = unit >> 4;
 687:     tp = &dh11[unit];
 688:     unit &= 0xf;
 689:     if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) {
 690:         tp->t_state |= TS_CARR_ON;
 691:         return;
 692:     }
 693:     addr = (struct dmdevice *)ui->ui_addr;
 694:     s = spl5();
 695:     addr->dmcsr &= ~DM_SE;
 696:     while (addr->dmcsr & DM_BUSY)
 697:         ;
 698:     addr->dmcsr = unit;
 699:     addr->dmlstat = DML_ON;
 700:     if ((addr->dmlstat&DML_CAR) || (dhsoftCAR[dm]&(1<<unit)))
 701:         tp->t_state |= TS_CARR_ON;
 702:     addr->dmcsr = DM_IE|DM_SE;
 703:     while ((tp->t_state&TS_CARR_ON)==0)
 704:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
 705:     splx(s);
 706: }
 707: 
 708: /*
 709:  * Dump control bits into the DM registers.
 710:  */
 711: dmctl(dev, bits, how)
 712:     dev_t dev;
 713:     int bits, how;
 714: {
 715:     register struct uba_device *ui;
 716:     register struct dmdevice *addr;
 717:     register int unit, s;
 718:     int dm;
 719: 
 720:     unit = minor(dev);
 721:     dm = unit >> 4;
 722:     if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
 723:         return;
 724:     addr = (struct dmdevice *)ui->ui_addr;
 725:     s = spl5();
 726:     addr->dmcsr &= ~DM_SE;
 727:     while (addr->dmcsr & DM_BUSY)
 728:         ;
 729:     addr->dmcsr = unit & 0xf;
 730:     switch(how) {
 731:     case DMSET:
 732:         addr->dmlstat = bits;
 733:         break;
 734:     case DMBIS:
 735:         addr->dmlstat |= bits;
 736:         break;
 737:     case DMBIC:
 738:         addr->dmlstat &= ~bits;
 739:         break;
 740:     }
 741:     addr->dmcsr = DM_IE|DM_SE;
 742:     splx(s);
 743: }
 744: 
 745: /*
 746:  * DM11 interrupt; deal with carrier transitions.
 747:  */
 748: dmintr(dm)
 749:     register int dm;
 750: {
 751:     register struct uba_device *ui;
 752:     register struct tty *tp;
 753:     register struct dmdevice *addr;
 754:     int unit;
 755: 
 756:     ui = dminfo[dm];
 757:     if (ui == 0)
 758:         return;
 759:     addr = (struct dmdevice *)ui->ui_addr;
 760:     if (addr->dmcsr&DM_DONE) {
 761:         if (addr->dmcsr&DM_CF) {
 762:             unit = addr->dmcsr & 0xf;
 763:             tp = &dh11[(dm << 4) + unit];
 764:             if (addr->dmlstat & DML_CAR)
 765:                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 766:             else if ((dhsoftCAR[dm] & (1<<unit)) == 0 &&
 767:                 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
 768:                 addr->dmlstat = 0;
 769:         }
 770:         addr->dmcsr = DM_IE|DM_SE;
 771:     }
 772: }
 773: #endif

Defined functions

dhattach defined in line 132; used 2 times
dhclose defined in line 243; never used
dhioctl defined in line 341; never used
dhopen defined in line 173; never used
dhparam defined in line 387; used 3 times
dhprobe defined in line 98; used 2 times
dhread defined in line 259; never used
dhreset defined in line 594; never used
dhrint defined in line 280; used 5 times
dhstart defined in line 478; used 4 times
dhstop defined in line 562; never used
dhtimer defined in line 636; used 3 times
dhwrite defined in line 268; never used
dhxint defined in line 429; used 4 times
dmattach defined in line 160; used 2 times
dmctl defined in line 711; used 5 times
dmintr defined in line 748; used 3 times
dmopen defined in line 675; used 1 times
dmprobe defined in line 143; used 2 times

Defined variables

cbase defined in line 90; used 5 times
dh11 defined in line 73; used 11 times
dh_ubinfo defined in line 89; used 5 times
dhact defined in line 75; used 2 times
dhchars defined in line 77; used 5 times
dhdriver defined in line 48; used 2 times
dhfasttimers defined in line 630; used 1 times
dhhighrate defined in line 79; used 1 times
dhinfo defined in line 46; used 8 times
dhlowrate defined in line 80; used 1 times
dhrate defined in line 78; used 2 times
dhsar defined in line 70; used 2 times
dhsilos defined in line 76; used 9 times
dhslowtimers defined in line 630; used 1 times
dhsoftCAR defined in line 71; used 3 times
dhstd defined in line 47; used 1 times
  • in line 49
dhtransitions defined in line 630; used 1 times
dmdriver defined in line 54; used 1 times
dminfo defined in line 52; used 4 times
dmstd defined in line 53; used 1 times
  • in line 55
ndh11 defined in line 74; used 2 times
  • in line 106(2)
timerstarted defined in line 81; used 2 times

Defined macros

FASTTIMER defined in line 65; used 2 times
IFLAGS defined in line 62; used 1 times
ISPEED defined in line 61; used 2 times
UBACVT defined in line 91; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2825
Valid CSS Valid XHTML 1.0 Strict