1: /*
   2:  * Copyright (c) 1985, 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:  *	@(#)dhu.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: /*
  10:  * based on	dh.c 6.3	84/03/15
  11:  * and on	dmf.c	6.2	84/02/16
  12:  *
  13:  * Dave Johnson, Brown University Computer Science
  14:  *	ddj%brown@csnet-relay
  15:  */
  16: 
  17: #include "dhu.h"
  18: #if NDHU > 0
  19: /*
  20:  * DHU-11 driver
  21:  */
  22: #include "../machine/pte.h"
  23: 
  24: #include "bk.h"
  25: #include "param.h"
  26: #include "conf.h"
  27: #include "dir.h"
  28: #include "user.h"
  29: #include "proc.h"
  30: #include "ioctl.h"
  31: #include "tty.h"
  32: #include "map.h"
  33: #include "buf.h"
  34: #include "vm.h"
  35: #include "kernel.h"
  36: #include "syslog.h"
  37: 
  38: #include "uba.h"
  39: #include "ubareg.h"
  40: #include "ubavar.h"
  41: #include "dhureg.h"
  42: 
  43: #include "bkmac.h"
  44: #include "clist.h"
  45: #include "file.h"
  46: #include "uio.h"
  47: 
  48: /*
  49:  * Definition of the driver for the auto-configuration program.
  50:  */
  51: int dhuprobe(), dhuattach(), dhurint(), dhuxint();
  52: struct  uba_device *dhuinfo[NDHU];
  53: u_short dhustd[] = { 160440, 160500, 0 };   /* some common addresses */
  54: struct  uba_driver dhudriver =
  55:     { dhuprobe, 0, dhuattach, 0, dhustd, "dhu", dhuinfo };
  56: 
  57: #define NDHULINE    (NDHU*16)
  58: 
  59: #define UNIT(x) (minor(x))
  60: 
  61: #ifndef PORTSELECTOR
  62: #define ISPEED  B9600
  63: #define IFLAGS  (EVENP|ODDP|ECHO)
  64: #else
  65: #define ISPEED  B4800
  66: #define IFLAGS  (EVENP|ODDP)
  67: #endif
  68: 
  69: /*
  70:  * default receive silo timeout value -- valid values are 2..255
  71:  * number of ms. to delay between first char received and receive interrupt
  72:  *
  73:  * A value of 20 gives same response as ABLE dh/dm with silo alarm = 0
  74:  */
  75: #define DHU_DEF_TIMO    20
  76: 
  77: /*
  78:  * Other values for silo timeout register defined here but not used:
  79:  * receive interrupt only on modem control or silo alarm (3/4 full)
  80:  */
  81: #define DHU_POLL_TIMO   0
  82: /*
  83:  * receive interrupt immediately on receive character
  84:  */
  85: #define DHU_NO_TIMO 1
  86: 
  87: /*
  88:  * Local variables for the driver
  89:  */
  90: /*
  91:  * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B".
  92:  *	EXTA => 19200 baud
  93:  *	EXTB => 2000 baud
  94:  */
  95: char    dhu_speeds[] =
  96:     { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 };
  97: 
  98: short   dhusoftCAR[NDHU];
  99: 
 100: struct  tty dhu_tty[NDHULINE];
 101: int ndhu = NDHULINE;
 102: int dhuact;             /* mask of active dhu's */
 103: int dhustart(), ttrstrt();
 104: 
 105: /*
 106:  * The clist space is mapped by the driver onto each UNIBUS.
 107:  * The UBACVT macro converts a clist space address for unibus uban
 108:  * into an i/o space address for the DMA routine.
 109:  */
 110: int dhu_ubinfo[NUBA];   /* info about allocated unibus map */
 111: int cbase[NUBA];        /* base address in unibus map */
 112: #define UBACVT(x, uban)     (cbase[uban] + ((x)-(char *)cfree))
 113: 
 114: /*
 115:  * Routine for configuration to force a dhu to interrupt.
 116:  */
 117: /*ARGSUSED*/
 118: dhuprobe(reg)
 119:     caddr_t reg;
 120: {
 121:     register int br, cvec;      /* these are ``value-result'' */
 122:     register struct dhudevice *dhuaddr = (struct dhudevice *)reg;
 123:     int i;
 124: 
 125: #ifdef lint
 126:     br = 0; cvec = br; br = cvec;
 127:     if (ndhu == 0) ndhu = 1;
 128:     dhurint(0); dhuxint(0);
 129: #endif
 130:     /*
 131: 	 * The basic idea here is:
 132: 	 *	do a self-test by setting the Master-Reset bit
 133: 	 *	if this fails, then return
 134: 	 *	if successful, there will be 8 diagnostic codes in RX FIFO
 135: 	 *	therefore ask for a  Received-Data-Available interrupt
 136: 	 *	wait for it...
 137: 	 *	reset the interrupt-enable bit and flush out the diag. codes
 138: 	 */
 139:     dhuaddr->dhucsr = DHU_CS_MCLR;
 140:     for (i = 0; i < 1000; i++) {
 141:         DELAY(10000);
 142:         if ((dhuaddr->dhucsr&DHU_CS_MCLR) == 0)
 143:             break;
 144:     }
 145:     if (dhuaddr->dhucsr&DHU_CS_MCLR)
 146:         return(0);
 147:     if (dhuaddr->dhucsr&DHU_CS_DFAIL)
 148:         return(0);
 149:     dhuaddr->dhucsr = DHU_CS_RIE;
 150:     DELAY(1000);
 151:     dhuaddr->dhucsr = 0;
 152:     while (dhuaddr->dhurbuf < 0)
 153:         /* void */;
 154:     return (sizeof(struct dhudevice));
 155: }
 156: 
 157: /*
 158:  * Routine called to attach a dhu.
 159:  */
 160: dhuattach(ui)
 161:     struct uba_device *ui;
 162: {
 163: 
 164:     dhusoftCAR[ui->ui_unit] = ui->ui_flags;
 165:     cbase[ui->ui_ubanum] = -1;
 166: }
 167: 
 168: /*
 169:  * Open a DHU11 line, mapping the clist onto the uba if this
 170:  * is the first dhu on this uba.  Turn on this dhu if this is
 171:  * the first use of it.
 172:  */
 173: /*ARGSUSED*/
 174: dhuopen(dev, flag)
 175:     dev_t dev;
 176: {
 177:     register struct tty *tp;
 178:     register int unit, dhu;
 179:     register struct dhudevice *addr;
 180:     register struct uba_device *ui;
 181:     int s;
 182: 
 183:     unit = UNIT(dev);
 184:     dhu = unit >> 4;
 185:     if (unit >= NDHULINE || (ui = dhuinfo[dhu])== 0 || ui->ui_alive == 0)
 186:         return (ENXIO);
 187:     tp = &dhu_tty[unit];
 188:     if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
 189:         return (EBUSY);
 190:     addr = (struct dhudevice *)ui->ui_addr;
 191:     tp->t_addr = (caddr_t)addr;
 192:     tp->t_oproc = dhustart;
 193:     /*
 194: 	 * While setting up state for this uba and this dhu,
 195: 	 * block uba resets which can clear the state.
 196: 	 */
 197:     s = spl5();
 198:     if (cbase[ui->ui_ubanum] == -1) {
 199:         dhu_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(dhu_ubinfo[ui->ui_ubanum]);
 203:     }
 204:     if ((dhuact&(1<<dhu)) == 0) {
 205:         addr->dhucsr = DHU_SELECT(0) | DHU_IE;
 206:         addr->dhutimo = DHU_DEF_TIMO;
 207:         dhuact |= (1<<dhu);
 208:         /* anything else to configure whole board */
 209:     }
 210:     (void) splx(s);
 211:     /*
 212: 	 * If this is first open, initialize tty state to default.
 213: 	 */
 214:     if ((tp->t_state&TS_ISOPEN) == 0) {
 215:         ttychars(tp);
 216: #ifndef PORTSELECTOR
 217:         if (tp->t_ispeed == 0) {
 218: #else
 219:             tp->t_state |= TS_HUPCLS;
 220: #endif PORTSELECTOR
 221:             tp->t_ispeed = ISPEED;
 222:             tp->t_ospeed = ISPEED;
 223:             tp->t_flags = IFLAGS;
 224: #ifndef PORTSELECTOR
 225:         }
 226: #endif PORTSELECTOR
 227:         tp->t_dev = dev;
 228:         dhuparam(unit);
 229:     }
 230:     /*
 231: 	 * Wait for carrier, then process line discipline specific open.
 232: 	 */
 233:     s = spl5();
 234:     if ((dhumctl(dev, DHU_ON, DMSET) & DHU_CAR) ||
 235:         (dhusoftCAR[dhu] & (1<<(unit&0xf))))
 236:         tp->t_state |= TS_CARR_ON;
 237:     while ((tp->t_state & TS_CARR_ON) == 0) {
 238:         tp->t_state |= TS_WOPEN;
 239:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
 240:     }
 241:     (void) splx(s);
 242:     return ((*linesw[tp->t_line].l_open)(dev, tp));
 243: }
 244: 
 245: /*
 246:  * Close a DHU11 line, turning off the modem control.
 247:  */
 248: /*ARGSUSED*/
 249: dhuclose(dev, flag)
 250:     dev_t dev;
 251:     int flag;
 252: {
 253:     register struct tty *tp;
 254:     register unit;
 255: 
 256:     unit = UNIT(dev);
 257:     tp = &dhu_tty[unit];
 258:     (*linesw[tp->t_line].l_close)(tp);
 259:     (void) dhumctl(unit, DHU_BRK, DMBIC);
 260:     if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN)==0)
 261: #ifdef PORTSELECTOR
 262:     {
 263:         extern int wakeup();
 264: 
 265:         (void) dhumctl(unit, DHU_OFF, DMSET);
 266:         /* Hold DTR low for 0.5 seconds */
 267:         timeout(wakeup, (caddr_t) &tp->t_dev, hz/2);
 268:         sleep((caddr_t) &tp->t_dev, PZERO);
 269:     }
 270: #else
 271:         (void) dhumctl(unit, DHU_OFF, DMSET);
 272: #endif PORTSELECTOR
 273:     ttyclose(tp);
 274: }
 275: 
 276: dhuread(dev, uio)
 277:     dev_t dev;
 278:     struct uio *uio;
 279: {
 280:     register struct tty *tp = &dhu_tty[UNIT(dev)];
 281: 
 282:     return ((*linesw[tp->t_line].l_read)(tp, uio));
 283: }
 284: 
 285: dhuwrite(dev, uio)
 286:     dev_t dev;
 287:     struct uio *uio;
 288: {
 289:     register struct tty *tp = &dhu_tty[UNIT(dev)];
 290: 
 291:     return ((*linesw[tp->t_line].l_write)(tp, uio));
 292: }
 293: 
 294: /*
 295:  * DHU11 receiver interrupt.
 296:  */
 297: dhurint(dhu)
 298:     int dhu;
 299: {
 300:     register struct tty *tp;
 301:     register c;
 302:     register struct dhudevice *addr;
 303:     register struct tty *tp0;
 304:     register struct uba_device *ui;
 305:     register line;
 306:     int overrun = 0;
 307: 
 308: #ifdef VAX630
 309:     (void) spl5();
 310: #endif
 311:     ui = dhuinfo[dhu];
 312:     if (ui == 0 || ui->ui_alive == 0)
 313:         return;
 314:     addr = (struct dhudevice *)ui->ui_addr;
 315:     tp0 = &dhu_tty[dhu<<4];
 316:     /*
 317: 	 * Loop fetching characters from the silo for this
 318: 	 * dhu until there are no more in the silo.
 319: 	 */
 320:     while ((c = addr->dhurbuf) < 0) {   /* (c & DHU_RB_VALID) == on */
 321:         line = DHU_RX_LINE(c);
 322:         tp = tp0 + line;
 323:         if ((c & DHU_RB_STAT) == DHU_RB_STAT) {
 324:             /*
 325: 			 * modem changed or diag info
 326: 			 */
 327:             if (c & DHU_RB_DIAG) {
 328:                 /* decode diagnostic messages */
 329:                 continue;
 330:             }
 331:             if (c & DHU_ST_DCD)
 332:                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 333:             else if ((dhusoftCAR[dhu] & (1<<line)) == 0 &&
 334:                 (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
 335:                 (void) dhumctl((dhu<<4)|line, DHU_OFF, DMSET);
 336:             continue;
 337:         }
 338:         if ((tp->t_state&TS_ISOPEN) == 0) {
 339:             wakeup((caddr_t)&tp->t_rawq);
 340: #ifdef PORTSELECTOR
 341:             if ((tp->t_state&TS_WOPEN) == 0)
 342: #endif
 343:                 continue;
 344:         }
 345:         if (c & DHU_RB_PE)
 346:             if ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
 347:                 (tp->t_flags&(EVENP|ODDP)) == ODDP)
 348:                 continue;
 349:         if ((c & DHU_RB_DO) && overrun == 0) {
 350:             log(LOG_WARNING, "dhu%d: silo overflow\n", dhu);
 351:             overrun = 1;
 352:         }
 353:         if (c & DHU_RB_FE)
 354:             /*
 355: 			 * At framing error (break) generate
 356: 			 * a null (in raw mode, for getty), or a
 357: 			 * interrupt (in cooked/cbreak mode).
 358: 			 */
 359:             if (tp->t_flags&RAW)
 360:                 c = 0;
 361:             else
 362:                 c = tp->t_intrc;
 363: #if NBK > 0
 364:         if (tp->t_line == NETLDISC) {
 365:             c &= 0x7f;
 366:             BKINPUT(c, tp);
 367:         } else
 368: #endif
 369:             (*linesw[tp->t_line].l_rint)(c, tp);
 370:     }
 371: }
 372: 
 373: /*
 374:  * Ioctl for DHU11.
 375:  */
 376: /*ARGSUSED*/
 377: dhuioctl(dev, cmd, data, flag)
 378:     caddr_t data;
 379: {
 380:     register struct tty *tp;
 381:     register int unit = UNIT(dev);
 382:     int error;
 383: 
 384:     tp = &dhu_tty[unit];
 385:     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 386:     if (error >= 0)
 387:         return (error);
 388:     error = ttioctl(tp, cmd, data, flag);
 389:     if (error >= 0) {
 390:         if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET ||
 391:             cmd == TIOCLBIC || cmd == TIOCLBIS)
 392:             dhuparam(unit);
 393:         return (error);
 394:     }
 395: 
 396:     switch (cmd) {
 397:     case TIOCSBRK:
 398:         (void) dhumctl(unit, DHU_BRK, DMBIS);
 399:         break;
 400: 
 401:     case TIOCCBRK:
 402:         (void) dhumctl(unit, DHU_BRK, DMBIC);
 403:         break;
 404: 
 405:     case TIOCSDTR:
 406:         (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIS);
 407:         break;
 408: 
 409:     case TIOCCDTR:
 410:         (void) dhumctl(unit, DHU_DTR|DHU_RTS, DMBIC);
 411:         break;
 412: 
 413:     case TIOCMSET:
 414:         (void) dhumctl(dev, dmtodhu(*(int *)data), DMSET);
 415:         break;
 416: 
 417:     case TIOCMBIS:
 418:         (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIS);
 419:         break;
 420: 
 421:     case TIOCMBIC:
 422:         (void) dhumctl(dev, dmtodhu(*(int *)data), DMBIC);
 423:         break;
 424: 
 425:     case TIOCMGET:
 426:         *(int *)data = dhutodm(dhumctl(dev, 0, DMGET));
 427:         break;
 428:     default:
 429:         return (ENOTTY);
 430:     }
 431:     return (0);
 432: }
 433: 
 434: dmtodhu(bits)
 435:     register int bits;
 436: {
 437:     register int b = 0;
 438: 
 439:     if (bits & DML_RTS) b |= DHU_RTS;
 440:     if (bits & DML_DTR) b |= DHU_DTR;
 441:     if (bits & DML_LE) b |= DHU_LE;
 442:     return(b);
 443: }
 444: 
 445: dhutodm(bits)
 446:     register int bits;
 447: {
 448:     register int b = 0;
 449: 
 450:     if (bits & DHU_DSR) b |= DML_DSR;
 451:     if (bits & DHU_RNG) b |= DML_RNG;
 452:     if (bits & DHU_CAR) b |= DML_CAR;
 453:     if (bits & DHU_CTS) b |= DML_CTS;
 454:     if (bits & DHU_RTS) b |= DML_RTS;
 455:     if (bits & DHU_DTR) b |= DML_DTR;
 456:     if (bits & DHU_LE) b |= DML_LE;
 457:     return(b);
 458: }
 459: 
 460: 
 461: /*
 462:  * Set parameters from open or stty into the DHU hardware
 463:  * registers.
 464:  */
 465: dhuparam(unit)
 466:     register int unit;
 467: {
 468:     register struct tty *tp;
 469:     register struct dhudevice *addr;
 470:     register int lpar;
 471:     int s;
 472: 
 473:     tp = &dhu_tty[unit];
 474:     addr = (struct dhudevice *)tp->t_addr;
 475:     /*
 476: 	 * Block interrupts so parameters will be set
 477: 	 * before the line interrupts.
 478: 	 */
 479:     s = spl5();
 480:     if ((tp->t_ispeed) == 0) {
 481:         tp->t_state |= TS_HUPCLS;
 482:         (void)dhumctl(unit, DHU_OFF, DMSET);
 483:         splx(s);
 484:         return;
 485:     }
 486:     lpar = (dhu_speeds[tp->t_ospeed]<<12) | (dhu_speeds[tp->t_ispeed]<<8);
 487:     if ((tp->t_ispeed) == B134)
 488:         lpar |= DHU_LP_BITS6|DHU_LP_PENABLE;
 489:     else if (tp->t_flags & (RAW|LITOUT|PASS8))
 490:         lpar |= DHU_LP_BITS8;
 491:     else
 492:         lpar |= DHU_LP_BITS7|DHU_LP_PENABLE;
 493:     if (tp->t_flags&EVENP)
 494:         lpar |= DHU_LP_EPAR;
 495:     if ((tp->t_ospeed) == B110)
 496:         lpar |= DHU_LP_TWOSB;
 497:     addr->dhucsr = DHU_SELECT(unit) | DHU_IE;
 498:     addr->dhulpr = lpar;
 499:     splx(s);
 500: }
 501: 
 502: /*
 503:  * DHU11 transmitter interrupt.
 504:  * Restart each line which used to be active but has
 505:  * terminated transmission since the last interrupt.
 506:  */
 507: dhuxint(dhu)
 508:     int dhu;
 509: {
 510:     register struct tty *tp;
 511:     register struct dhudevice *addr;
 512:     register struct tty *tp0;
 513:     register struct uba_device *ui;
 514:     register int line, t;
 515:     u_short cntr;
 516: 
 517: #ifdef VAX630
 518:     (void) spl5();
 519: #endif
 520:     ui = dhuinfo[dhu];
 521:     tp0 = &dhu_tty[dhu<<4];
 522:     addr = (struct dhudevice *)ui->ui_addr;
 523:     while ((t = addr->dhucsrh) & DHU_CSH_TI) {
 524:         line = DHU_TX_LINE(t);
 525:         tp = tp0 + line;
 526:         tp->t_state &= ~TS_BUSY;
 527:         if (t & DHU_CSH_NXM) {
 528:             printf("dhu(%d,%d): NXM fault\n", dhu, line);
 529:             /* SHOULD RESTART OR SOMETHING... */
 530:         }
 531:         if (tp->t_state&TS_FLUSH)
 532:             tp->t_state &= ~TS_FLUSH;
 533:         else {
 534:             addr->dhucsrl = DHU_SELECT(line) | DHU_IE;
 535:             /*
 536: 			 * Do arithmetic in a short to make up
 537: 			 * for lost 16&17 bits.
 538: 			 */
 539:             cntr = addr->dhubar1 -
 540:                 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
 541:             ndflush(&tp->t_outq, (int)cntr);
 542:         }
 543:         if (tp->t_line)
 544:             (*linesw[tp->t_line].l_start)(tp);
 545:         else
 546:             dhustart(tp);
 547:     }
 548: }
 549: 
 550: /*
 551:  * Start (restart) transmission on the given DHU11 line.
 552:  */
 553: dhustart(tp)
 554:     register struct tty *tp;
 555: {
 556:     register struct dhudevice *addr;
 557:     register int car, dhu, unit, nch;
 558:     int s;
 559: 
 560:     unit = minor(tp->t_dev);
 561:     dhu = unit >> 4;
 562:     unit &= 0xf;
 563:     addr = (struct dhudevice *)tp->t_addr;
 564: 
 565:     /*
 566: 	 * Must hold interrupts in following code to prevent
 567: 	 * state of the tp from changing.
 568: 	 */
 569:     s = spl5();
 570:     /*
 571: 	 * If it's currently active, or delaying, no need to do anything.
 572: 	 */
 573:     if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 574:         goto out;
 575:     /*
 576: 	 * If there are sleepers, and output has drained below low
 577: 	 * water mark, wake up the sleepers..
 578: 	 */
 579:     if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
 580:         if (tp->t_state&TS_ASLEEP) {
 581:             tp->t_state &= ~TS_ASLEEP;
 582:             wakeup((caddr_t)&tp->t_outq);
 583:         }
 584:         if (tp->t_wsel) {
 585:             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
 586:             tp->t_wsel = 0;
 587:             tp->t_state &= ~TS_WCOLL;
 588:         }
 589:     }
 590:     /*
 591: 	 * Now restart transmission unless the output queue is
 592: 	 * empty.
 593: 	 */
 594:     if (tp->t_outq.c_cc == 0)
 595:         goto out;
 596:     if (tp->t_flags & (RAW|LITOUT))
 597:         nch = ndqb(&tp->t_outq, 0);
 598:     else {
 599:         nch = ndqb(&tp->t_outq, 0200);
 600:         /*
 601: 		 * If first thing on queue is a delay process it.
 602: 		 */
 603:         if (nch == 0) {
 604:             nch = getc(&tp->t_outq);
 605:             timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
 606:             tp->t_state |= TS_TIMEOUT;
 607:             goto out;
 608:         }
 609:     }
 610:     /*
 611: 	 * If characters to transmit, restart transmission.
 612: 	 */
 613:     if (nch) {
 614:         car = UBACVT(tp->t_outq.c_cf, dhuinfo[dhu]->ui_ubanum);
 615:         addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
 616:         addr->dhulcr &= ~DHU_LC_TXABORT;
 617:         addr->dhubcr = nch;
 618:         addr->dhubar1 = car;
 619:         addr->dhubar2 = ((car >> DHU_XBA_SHIFT) & DHU_BA2_XBA) |
 620:                     DHU_BA2_DMAGO;
 621:         tp->t_state |= TS_BUSY;
 622:     }
 623: out:
 624:     splx(s);
 625: }
 626: 
 627: /*
 628:  * Stop output on a line, e.g. for ^S/^Q or output flush.
 629:  */
 630: /*ARGSUSED*/
 631: dhustop(tp, flag)
 632:     register struct tty *tp;
 633: {
 634:     register struct dhudevice *addr;
 635:     register int unit, s;
 636: 
 637:     addr = (struct dhudevice *)tp->t_addr;
 638:     /*
 639: 	 * Block input/output interrupts while messing with state.
 640: 	 */
 641:     s = spl5();
 642:     if (tp->t_state & TS_BUSY) {
 643:         /*
 644: 		 * Device is transmitting; stop output
 645: 		 * by selecting the line and setting the
 646: 		 * abort xmit bit.  We will get an xmit interrupt,
 647: 		 * where we will figure out where to continue the
 648: 		 * next time the transmitter is enabled.  If
 649: 		 * TS_FLUSH is set, the outq will be flushed.
 650: 		 * In either case, dhustart will clear the TXABORT bit.
 651: 		 */
 652:         unit = minor(tp->t_dev);
 653:         addr->dhucsrl = DHU_SELECT(unit) | DHU_IE;
 654:         addr->dhulcr |= DHU_LC_TXABORT;
 655:         if ((tp->t_state&TS_TTSTOP)==0)
 656:             tp->t_state |= TS_FLUSH;
 657:     }
 658:     (void) splx(s);
 659: }
 660: 
 661: /*
 662:  * DHU11 modem control
 663:  */
 664: dhumctl(dev, bits, how)
 665:     dev_t dev;
 666:     int bits, how;
 667: {
 668:     register struct dhudevice *dhuaddr;
 669:     register int unit, mbits;
 670:     int s;
 671: 
 672:     unit = UNIT(dev);
 673:     dhuaddr = (struct dhudevice *)(dhu_tty[unit].t_addr);
 674:     unit &= 0xf;
 675:     s = spl5();
 676:     dhuaddr->dhucsr = DHU_SELECT(unit) | DHU_IE;
 677:     /*
 678: 	 * combine byte from stat register (read only, bits 16..23)
 679: 	 * with lcr register (read write, bits 0..15).
 680: 	 */
 681:     mbits = dhuaddr->dhulcr | (dhuaddr->dhustat << 16);
 682:     switch (how) {
 683:     case DMSET:
 684:         mbits = (mbits & 0xff0000) | bits;
 685:         break;
 686: 
 687:     case DMBIS:
 688:         mbits |= bits;
 689:         break;
 690: 
 691:     case DMBIC:
 692:         mbits &= ~bits;
 693:         break;
 694: 
 695:     case DMGET:
 696:         (void) splx(s);
 697:         return(mbits);
 698:     }
 699:     dhuaddr->dhulcr = (mbits & 0xffff) | DHU_LC_RXEN;
 700:     dhuaddr->dhulcr2 = DHU_LC2_TXEN;
 701:     (void) splx(s);
 702:     return(mbits);
 703: }
 704: 
 705: /*
 706:  * Reset state of driver if UBA reset was necessary.
 707:  * Reset the line and modem control registers.
 708:  * restart transmitters.
 709:  */
 710: dhureset(uban)
 711:     int uban;
 712: {
 713:     register int dhu, unit;
 714:     register struct tty *tp;
 715:     register struct uba_device *ui;
 716:     register struct dhudevice *addr;
 717:     int i;
 718: 
 719:     for (dhu = 0; dhu < NDHU; dhu++) {
 720:         ui = dhuinfo[dhu];
 721:         if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
 722:             continue;
 723:         printf(" dhu%d", dhu);
 724:         if (dhu_ubinfo[uban]) {
 725:             dhu_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
 726:                         nclist*sizeof (struct cblock), 0);
 727:             cbase[uban] = UBAI_ADDR(dhu_ubinfo[uban]);
 728:         }
 729:         addr = (struct dhudevice *)ui->ui_addr;
 730:         addr->dhucsr = DHU_SELECT(0) | DHU_IE;
 731:         addr->dhutimo = DHU_DEF_TIMO;
 732:         unit = dhu * 16;
 733:         for (i = 0; i < 16; i++) {
 734:             tp = &dhu_tty[unit];
 735:             if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
 736:                 dhuparam(unit);
 737:                 (void)dhumctl(unit, DHU_ON, DMSET);
 738:                 tp->t_state &= ~TS_BUSY;
 739:                 dhustart(tp);
 740:             }
 741:             unit++;
 742:         }
 743:     }
 744: }
 745: #endif

Defined functions

dhuattach defined in line 160; used 2 times
dhuclose defined in line 249; never used
dhuioctl defined in line 377; never used
dhumctl defined in line 664; used 15 times
dhuopen defined in line 174; never used
dhuparam defined in line 465; used 3 times
dhuprobe defined in line 118; used 2 times
dhuread defined in line 276; never used
dhureset defined in line 710; never used
dhurint defined in line 297; used 3 times
dhustart defined in line 553; used 4 times
dhustop defined in line 631; never used
dhutodm defined in line 445; used 1 times
dhuwrite defined in line 285; never used
dhuxint defined in line 507; used 3 times
dmtodhu defined in line 434; used 3 times

Defined variables

cbase defined in line 111; used 5 times
dhu_speeds defined in line 95; used 2 times
  • in line 486(2)
dhu_tty defined in line 100; used 10 times
dhu_ubinfo defined in line 110; used 5 times
dhuact defined in line 102; used 2 times
dhudriver defined in line 54; used 1 times
dhuinfo defined in line 52; used 6 times
dhusoftCAR defined in line 98; used 3 times
dhustd defined in line 53; used 1 times
  • in line 55
ndhu defined in line 101; used 2 times
  • in line 127(2)

Defined macros

DHU_DEF_TIMO defined in line 75; used 2 times
DHU_NO_TIMO defined in line 85; never used
DHU_POLL_TIMO defined in line 81; never used
IFLAGS defined in line 66; used 1 times
ISPEED defined in line 65; used 2 times
NDHULINE defined in line 57; used 3 times
UBACVT defined in line 112; used 2 times
UNIT defined in line 59; used 6 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2729
Valid CSS Valid XHTML 1.0 Strict