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:  *	@(#)dz.c	1.4 (2.11BSD GTE) 1997/2/14
   7:  */
   8: 
   9: /*
  10:  * DZ11 device driver
  11:  *
  12:  * This driver mimics dh.c; see it for explanation of common code.
  13:  */
  14: #include "dz.h"
  15: 
  16: #if NDZ > 0
  17: #include "param.h"
  18: #include "user.h"
  19: #include "file.h"
  20: #include "conf.h"
  21: #include "ioctl.h"
  22: #include "tty.h"
  23: #include "dzreg.h"
  24: #include "pdma.h"
  25: #include "proc.h"
  26: #include "ubavar.h"
  27: #include "vm.h"
  28: #include "kernel.h"
  29: #include "syslog.h"
  30: #include "systm.h"
  31: 
  32: struct  uba_device dzinfo[NDZ];
  33: 
  34: #define NDZLINE     (NDZ*8)
  35: #define FASTTIMER   2   /* rate to drain silos, when in use */
  36: 
  37: int dzstart(), dzxint(), dzdma();
  38: int ttrstrt();
  39: struct  tty dz_tty[NDZLINE];
  40: int dz_cnt = { NDZLINE };
  41: int dzact;
  42: int dzsilos;            /* mask of dz's with silo in use */
  43: int dzchars[NDZ];           /* recent input count */
  44: int dzrate[NDZ];            /* smoothed input count */
  45: int dztimerintvl;           /* time interval for dztimer */
  46: int dzhighrate = 100;       /* silo on if dzchars > dzhighrate */
  47: int dzlowrate = 75;         /* silo off if dzrate < dzlowrate */
  48: 
  49: #define dzwait(x)   while (((x)->dzlcs & DZ_ACK) == 0)
  50: 
  51: /*
  52:  * Software copy of dzbrk since it isn't readable
  53:  */
  54: char    dz_brk[NDZ];
  55: char    dzsoftCAR[NDZ];
  56: char    dz_lnen[NDZ];   /* saved line enable bits for DZ32 */
  57: 
  58: /*
  59:  * The dz11 doesn't interrupt on carrier transitions, so
  60:  * we have to use a timer to watch it.
  61:  */
  62: char    dz_timer;       /* timer started? */
  63: 
  64: /*
  65:  * Pdma structures for fast output code
  66:  */
  67: struct  pdma dzpdma[NDZLINE];
  68: 
  69: char    dz_speeds[] =
  70:     { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
  71: 
  72: #ifndef PORTSELECTOR
  73: #define ISPEED  B9600
  74: #define IFLAGS  (EVENP|ODDP|ECHO)
  75: #else
  76: #define ISPEED  B4800
  77: #define IFLAGS  (EVENP|ODDP)
  78: #endif
  79: 
  80: #define UNIT(x) (minor(x)&0177)
  81: 
  82: dzattach(addr, unit)
  83:     caddr_t addr;
  84:     u_int unit;
  85: {
  86:     extern dzscan();
  87: 
  88:     if (!addr || unit >= NDZ || dzinfo[unit].ui_addr)
  89:         return (0);
  90:     {
  91:         register struct uba_device *ui;
  92: 
  93:         ui = &dzinfo[unit];
  94:         ui->ui_unit = unit;
  95:         ui->ui_addr = addr;
  96:         ui->ui_alive = 1;
  97:     }
  98:     {
  99:         register struct pdma *pdp = &dzpdma[unit*8];
 100:         register struct tty *tp = &dz_tty[unit*8];
 101:         register int cntr;
 102: 
 103:         for (cntr = 0; cntr < 8; cntr++) {
 104:             pdp->pd_addr = (struct dzdevice *)addr;
 105:             pdp->p_arg = tp;
 106:             pdp++, tp++;
 107:         }
 108:     }
 109:     if (dz_timer == 0) {
 110:         dz_timer++;
 111:         timeout(dzscan, (caddr_t)0, hz);
 112:         dztimerintvl = FASTTIMER;
 113:     }
 114:     return (1);
 115: }
 116: 
 117: /*ARGSUSED*/
 118: dzopen(dev, flag)
 119:     register dev_t dev;
 120: {
 121:     register struct tty *tp;
 122:     register int unit;
 123: 
 124:     unit = UNIT(dev);
 125:     if (unit >= NDZLINE || dzpdma[unit].pd_addr == 0)
 126:         return (ENXIO);
 127:     tp = &dz_tty[unit];
 128:     tp->t_addr = (caddr_t)&dzpdma[unit];
 129:     tp->t_oproc = dzstart;
 130:     if ((tp->t_state & TS_ISOPEN) == 0) {
 131:         ttychars(tp);
 132: #ifndef PORTSELECTOR
 133:         if (tp->t_ispeed == 0) {
 134: #else
 135:             tp->t_state |= TS_HUPCLS;
 136: #endif PORTSELECTOR
 137: 
 138:             tp->t_ispeed = ISPEED;
 139:             tp->t_ospeed = ISPEED;
 140:             tp->t_flags = IFLAGS;
 141: #ifndef PORTSELECTOR
 142:         }
 143: #endif PORTSELECTOR
 144:         dzparam(unit);
 145:     } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
 146:         return (EBUSY);
 147:     (void) dzmctl(dev, DZ_ON, DMSET);
 148: #ifdef pdp11
 149:     if (dev & 0200) {
 150:         dzsoftCAR[unit >> 3] |= (1<<(unit&07));
 151:         tp->t_state |= TS_CARR_ON;
 152:     }
 153:     else
 154:         dzsoftCAR[unit >> 3] &= ~(1<<(unit&07));
 155: #endif
 156:     (void) _spl5();
 157:     while ((tp->t_state & TS_CARR_ON) == 0) {
 158:         tp->t_state |= TS_WOPEN;
 159:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
 160:     }
 161:     (void) _spl0();
 162:     return ((*linesw[tp->t_line].l_open)(dev, tp));
 163: }
 164: 
 165: /*ARGSUSED*/
 166: dzclose(dev, flag)
 167:     dev_t dev;
 168:     int flag;
 169: {
 170:     register struct tty *tp;
 171:     register int unit;
 172:     struct dzdevice *dzaddr;
 173:     register int dz;
 174: 
 175:     unit = UNIT(dev);
 176:     dz = unit >> 3;
 177:     tp = &dz_tty[unit];
 178:     (*linesw[tp->t_line].l_close)(tp, flag);
 179:     dzaddr = dzpdma[unit].pd_addr;
 180:     dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
 181:     if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
 182:         (void) dzmctl(dev, DZ_OFF, DMSET);
 183:     ttyclose(tp);
 184: }
 185: 
 186: dzread(dev, uio, flag)
 187:     register dev_t  dev;
 188:     struct uio *uio;
 189:     int flag;
 190: {
 191:     register struct tty *tp;
 192: 
 193:     tp = &dz_tty[UNIT(dev)];
 194:     return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
 195: }
 196: 
 197: dzwrite(dev, uio, flag)
 198:     register dev_t  dev;
 199:     struct uio *uio;
 200:     int flag;
 201: {
 202:     register struct tty *tp;
 203: 
 204:     tp = &dz_tty[UNIT(dev)];
 205:     return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
 206: }
 207: 
 208: /*ARGSUSED*/
 209: dzrint(dz)
 210:     int dz;
 211: {
 212:     register struct tty *tp;
 213:     register int c;
 214:     register struct dzdevice *dzaddr;
 215:     struct tty *tp0;
 216:     register int unit;
 217:     int overrun = 0;
 218: 
 219:     if ((dzact & (1<<dz)) == 0)
 220:         return;
 221:     unit = dz * 8;
 222:     dzaddr = dzpdma[unit].pd_addr;
 223:     tp0 = &dz_tty[unit];
 224:     while ((c = dzaddr->dzrbuf) < 0) {  /* char present */
 225:         dzchars[dz]++;
 226:         tp = tp0 + ((c>>8)&07);
 227:         if (tp >= &dz_tty[NDZLINE])
 228:             continue;
 229:         if ((tp->t_state & TS_ISOPEN) == 0) {
 230:             wakeup((caddr_t)&tp->t_rawq);
 231: #ifdef PORTSELECTOR
 232:             if ((tp->t_state&TS_WOPEN) == 0)
 233: #endif
 234:                 continue;
 235:         }
 236:         if (c&DZ_FE)
 237:             if (tp->t_flags & RAW)
 238:                 c = 0;
 239:             else
 240: #ifdef  OLDWAY
 241:                 c = tp->t_intrc;
 242: #else
 243:                 c = tp->t_brkc;
 244: #endif
 245:         if (c&DZ_DO && overrun == 0) {
 246:             log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
 247:             overrun = 1;
 248:         }
 249:         if (c&DZ_PE)
 250:             if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
 251:               || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
 252:                 continue;
 253: #if NBK > 0
 254:         if (tp->t_line == NETLDISC) {
 255:             c &= 0177;
 256:             BKINPUT(c, tp);
 257:         } else
 258: #endif
 259:             (*linesw[tp->t_line].l_rint)(c, tp);
 260:     }
 261: }
 262: 
 263: /*ARGSUSED*/
 264: dzioctl(dev, cmd, data, flag)
 265:     dev_t dev;
 266:     u_int cmd;
 267:     caddr_t data;
 268: {
 269:     register struct tty *tp;
 270:     register int unit = UNIT(dev);
 271:     int dz = unit >> 3;
 272:     register struct dzdevice *dzaddr;
 273:     register int error;
 274: 
 275:     tp = &dz_tty[unit];
 276:     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 277:     if (error >= 0)
 278:         return (error);
 279:     error = ttioctl(tp, cmd, data, flag);
 280:     if (error >= 0) {
 281:         if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
 282:             cmd == TIOCLBIC || cmd == TIOCLSET)
 283:             dzparam(unit);
 284:         return (error);
 285:     }
 286:     switch (cmd) {
 287: 
 288:     case TIOCSBRK:
 289:         dzaddr = ((struct pdma *)(tp->t_addr))->pd_addr;
 290:         dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
 291:         break;
 292: 
 293:     case TIOCCBRK:
 294:         dzaddr = ((struct pdma *)(tp->t_addr))->pd_addr;
 295:         dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
 296:         break;
 297: 
 298:     case TIOCSDTR:
 299:         (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
 300:         break;
 301: 
 302:     case TIOCCDTR:
 303:         (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
 304:         break;
 305: 
 306:     case TIOCMSET:
 307:         (void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
 308:         break;
 309: 
 310:     case TIOCMBIS:
 311:         (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
 312:         break;
 313: 
 314:     case TIOCMBIC:
 315:         (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
 316:         break;
 317: 
 318:     case TIOCMGET:
 319:         *(int *)data = dztodm(dzmctl(dev, 0, DMGET));
 320:         break;
 321: 
 322:     default:
 323:         return (ENOTTY);
 324:     }
 325:     return (0);
 326: }
 327: 
 328: static
 329: dmtodz(bits)
 330:     register int bits;
 331: {
 332:     register int b;
 333: 
 334:     b = (bits >>1) & 0370;
 335:     if (bits & DML_ST) b |= DZ_ST;
 336:     if (bits & DML_RTS) b |= DZ_RTS;
 337:     if (bits & DML_DTR) b |= DZ_DTR;
 338:     if (bits & DML_LE) b |= DZ_LE;
 339:     return(b);
 340: }
 341: 
 342: static
 343: dztodm(bits)
 344:     register int bits;
 345: {
 346:     register int b;
 347: 
 348:     b = (bits << 1) & 0360;
 349:     if (bits & DZ_DSR) b |= DML_DSR;
 350:     if (bits & DZ_DTR) b |= DML_DTR;
 351:     if (bits & DZ_ST) b |= DML_ST;
 352:     if (bits & DZ_RTS) b |= DML_RTS;
 353:     return(b);
 354: }
 355: 
 356: dzparam(unit)
 357:     int unit;
 358: {
 359:     register struct tty *tp;
 360:     register struct dzdevice *dzaddr;
 361:     register int lpr;
 362: 
 363:     tp = &dz_tty[unit];
 364:     dzaddr = dzpdma[unit].pd_addr;
 365:     if (dzsilos & (1 << (unit >> 3)))
 366:         dzaddr->dzcsr = DZ_IEN | DZ_SAE;
 367:     else
 368:         dzaddr->dzcsr = DZ_IEN;
 369:     dzact |= (1<<(unit>>3));
 370:     if (tp->t_ispeed == 0) {
 371:         (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */
 372:         return;
 373:     }
 374:     lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
 375:     if (tp->t_flags & (RAW|LITOUT|PASS8))
 376:         lpr |= BITS8;
 377:     else
 378:         lpr |= (BITS7|PENABLE);
 379:     if ((tp->t_flags & EVENP) == 0)
 380:         lpr |= OPAR;
 381:     if (tp->t_ispeed == B110)
 382:         lpr |= TWOSB;
 383:     dzaddr->dzlpr = lpr;
 384: }
 385: 
 386: dzxint(tp)
 387:     register struct tty *tp;
 388: {
 389:     register struct pdma *dp;
 390: 
 391:     dp = (struct pdma *)tp->t_addr;
 392:     tp->t_state &= ~TS_BUSY;
 393:     if (tp->t_state & TS_FLUSH)
 394:         tp->t_state &= ~TS_FLUSH;
 395:     else {
 396:         ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
 397:         dp->p_end = dp->p_mem = tp->t_outq.c_cf;
 398:     }
 399:     if (tp->t_line)
 400:         (*linesw[tp->t_line].l_start)(tp);
 401:     else
 402:         dzstart(tp);
 403:     if ((tp->t_outq.c_cc == 0) || (tp->t_state&TS_BUSY)==0)
 404:         dp->pd_addr->dztcr &= ~(1 << (UNIT(tp->t_dev) & 07));
 405: }
 406: 
 407: dzstart(tp)
 408:     register struct tty *tp;
 409: {
 410:     register struct pdma *dp;
 411:     struct dzdevice *dzaddr;
 412:     register int cc;
 413:     int s;
 414: 
 415:     dp = (struct pdma *)tp->t_addr;
 416:     dzaddr = dp->pd_addr;
 417:     s = spl5();
 418:     if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 419:         goto out;
 420:     if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
 421:         if (tp->t_state&TS_ASLEEP) {
 422:             tp->t_state &= ~TS_ASLEEP;
 423:             wakeup((caddr_t) &tp->t_outq);
 424:         }
 425:         if (tp->t_wsel) {
 426:             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
 427:             tp->t_wsel = 0;
 428:             tp->t_state &= ~TS_WCOLL;
 429:         }
 430:     }
 431:     if (tp->t_outq.c_cc == 0)
 432:         goto out;
 433:     if (tp->t_flags & (RAW|LITOUT))
 434:         cc = ndqb(&tp->t_outq, 0);
 435:     else {
 436:         cc = ndqb(&tp->t_outq, 0200);
 437:         if (cc == 0) {
 438:             cc = getc(&tp->t_outq);
 439:             timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
 440:             tp->t_state |= TS_TIMEOUT;
 441:             goto out;
 442:         }
 443:     }
 444:     tp->t_state |= TS_BUSY;
 445:     dp->p_end = dp->p_mem = tp->t_outq.c_cf;
 446:     dp->p_end += cc;
 447:     dzaddr->dztcr |= (1 << (UNIT(tp->t_dev) & 7));
 448: out:
 449:     splx(s);
 450: }
 451: 
 452: /*
 453:  * Stop output on a line.
 454:  */
 455: /*ARGSUSED*/
 456: dzstop(tp, flag)
 457:     register struct tty *tp;
 458: {
 459:     register struct pdma *dp;
 460:     register int s;
 461: 
 462:     dp = (struct pdma *)tp->t_addr;
 463:     s = spl5();
 464:     if (tp->t_state & TS_BUSY) {
 465:         dp->p_end = dp->p_mem;
 466:         if ((tp->t_state & TS_TTSTOP)==0)
 467:             tp->t_state |= TS_FLUSH;
 468:     }
 469:     splx(s);
 470: }
 471: 
 472: static
 473: dzmctl(dev, bits, how)
 474:     dev_t dev;
 475:     int bits, how;
 476: {
 477:     register struct dzdevice *dzaddr;
 478:     register int unit, mbits;
 479:     int b, s;
 480: 
 481:     unit = UNIT(dev);
 482:     b = 1<<(unit&7);
 483:     dzaddr = dzpdma[unit].pd_addr;
 484:     s = spl5();
 485:     mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
 486:     mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
 487:     mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
 488:     switch (how) {
 489:     case DMSET:
 490:         mbits = bits;
 491:         break;
 492: 
 493:     case DMBIS:
 494:         mbits |= bits;
 495:         break;
 496: 
 497:     case DMBIC:
 498:         mbits &= ~bits;
 499:         break;
 500: 
 501:     case DMGET:
 502:         (void) splx(s);
 503:         return(mbits);
 504:     }
 505:     if (mbits & DZ_DTR)
 506:         dzaddr->dzdtr |= b;
 507:     else
 508:         dzaddr->dzdtr &= ~b;
 509:     (void) splx(s);
 510:     return(mbits);
 511: }
 512: 
 513: int dztransitions, dzfasttimers;        /*DEBUG*/
 514: dzscan()
 515: {
 516:     register i;
 517:     register struct dzdevice *dzaddr;
 518:     register bit;
 519:     register struct tty *tp;
 520:     register car;
 521:     int olddzsilos = dzsilos;
 522:     int dztimer();
 523: 
 524:     for (i = 0; i < NDZLINE; i++) {
 525:         dzaddr = dzpdma[i].pd_addr;
 526:         if (dzaddr == 0)
 527:             continue;
 528:         tp = &dz_tty[i];
 529:         bit = 1<<(i&07);
 530:         car = 0;
 531:         if (dzsoftCAR[i>>3]&bit)
 532:             car = 1;
 533:         else if (dzaddr->dzcsr & DZ_32) {
 534:             dzaddr->dzlcs = i&07;
 535:             dzwait(dzaddr);
 536:             car = dzaddr->dzlcs & DZ_CD;
 537:         } else
 538:             car = dzaddr->dzmsr&bit;
 539:         if (car) {
 540:             /* carrier present */
 541:             if ((tp->t_state & TS_CARR_ON) == 0)
 542:                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 543:         } else if ((tp->t_state&TS_CARR_ON) &&
 544:             (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
 545:             dzaddr->dzdtr &= ~bit;
 546:     }
 547:     for (i = 0; i < NDZ; i++) {
 548:         ave(dzrate[i], dzchars[i], 8);
 549:         if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
 550:             dzpdma[i << 3].pd_addr->dzcsr = DZ_IEN | DZ_SAE;
 551:             dzsilos |= (1 << i);
 552:             dztransitions++;        /*DEBUG*/
 553:         } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
 554:             dzpdma[i << 3].pd_addr->dzcsr = DZ_IEN;
 555:             dzsilos &= ~(1 << i);
 556:         }
 557:         dzchars[i] = 0;
 558:     }
 559:     if (dzsilos && !olddzsilos)
 560:         timeout(dztimer, (caddr_t)0, dztimerintvl);
 561:     timeout(dzscan, (caddr_t)0, hz);
 562: }
 563: 
 564: dztimer()
 565: {
 566:     register int dz;
 567:     register int s;
 568: 
 569:     if (dzsilos == 0)
 570:         return;
 571:     s = spl5();
 572:     dzfasttimers++;     /*DEBUG*/
 573:     for (dz = 0; dz < NDZ; dz++)
 574:         if (dzsilos & (1 << dz))
 575:             dzrint(dz);
 576:     splx(s);
 577:     timeout(dztimer, (caddr_t) 0, dztimerintvl);
 578: }
 579: #endif

Defined functions

dmtodz defined in line 328; used 3 times
dzattach defined in line 82; never used
dzclose defined in line 166; never used
dzioctl defined in line 264; never used
dzmctl defined in line 472; used 9 times
dzopen defined in line 118; never used
dzparam defined in line 356; used 2 times
dzread defined in line 186; never used
dzrint defined in line 209; used 2 times
dzscan defined in line 514; used 3 times
dzstart defined in line 407; used 3 times
dzstop defined in line 456; never used
dztimer defined in line 564; used 3 times
dztodm defined in line 342; used 1 times
dzwrite defined in line 197; never used
dzxint defined in line 386; used 2 times

Defined variables

dz_brk defined in line 54; used 3 times
dz_cnt defined in line 40; never used
dz_lnen defined in line 56; never used
dz_speeds defined in line 69; used 1 times
dz_timer defined in line 62; used 2 times
dz_tty defined in line 39; used 10 times
dzact defined in line 41; used 2 times
dzchars defined in line 43; used 4 times
dzfasttimers defined in line 513; used 1 times
dzhighrate defined in line 46; used 1 times
dzinfo defined in line 32; used 2 times
dzlowrate defined in line 47; used 1 times
dzpdma defined in line 67; used 11 times
dzrate defined in line 44; used 2 times
dzsilos defined in line 42; used 9 times
dzsoftCAR defined in line 55; used 3 times
dztimerintvl defined in line 45; used 3 times
dztransitions defined in line 513; used 1 times

Defined macros

FASTTIMER defined in line 35; used 1 times
IFLAGS defined in line 77; used 1 times
ISPEED defined in line 76; used 2 times
NDZLINE defined in line 34; used 6 times
UNIT defined in line 80; used 8 times
dzwait defined in line 49; used 1 times
Last modified: 1997-02-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5427
Valid CSS Valid XHTML 1.0 Strict