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

Defined functions

dhattach defined in line 83; never used
dhclose defined in line 191; never used
dhioctl defined in line 307; never used
dhopen defined in line 121; never used
dhparam defined in line 393; used 2 times
dhread defined in line 221; never used
dhrint defined in line 243; used 2 times
dhselect defined in line 214; never used
dhstart defined in line 500; used 3 times
dhstop defined in line 571; used 1 times
dhtimer defined in line 605; used 3 times
dhtodm defined in line 374; used 2 times
dhwrite defined in line 231; never used
dhxint defined in line 437; used 1 times
dmattach defined in line 100; never used
dmctl defined in line 666; used 10 times
dmintr defined in line 708; used 1 times
dmopen defined in line 644; used 1 times
dmtodh defined in line 362; used 4 times

Defined variables

dh11 defined in line 54; used 11 times
dh_overrun defined in line 55; used 4 times
dhact defined in line 59; used 2 times
dhchars defined in line 61; used 5 times
dhfasttimers defined in line 599; used 1 times
dhhighrate defined in line 63; used 1 times
dhinfo defined in line 37; used 7 times
dhlowrate defined in line 64; used 1 times
dhrate defined in line 62; used 2 times
dhsar defined in line 52; used 2 times
dhsilos defined in line 60; used 8 times
dhslowtimers defined in line 599; used 1 times
dhtransitions defined in line 599; used 1 times
dminfo defined in line 38; used 7 times
ndh11 defined in line 58; never used
timerstarted defined in line 65; used 2 times

Defined macros

FASTTIMER defined in line 47; used 2 times
HWFLOW defined in line 78; used 1 times
IFLAGS defined in line 40; used 1 times
SOFTCAR defined in line 77; used 2 times
UNIT defined in line 76; used 9 times
cpaddr defined in line 73; used 2 times
Last modified: 1997-06-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5565
Valid CSS Valid XHTML 1.0 Strict