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:  *	@(#)dhv.c	2.4 (2.11BSD 2.11BSD) 1997/5/31
   7:  */
   8: 
   9: /*
  10:  * Rewritten to implement hardware flowcontrol. A lot of clean up was done
  11:  * and the formatting style change to aid in debugging.  1997/4/25 - sms
  12:  *
  13:  * ported to 2.11BSD (uio logic added) 12/22/91 - SMS
  14:  * based on	dh.c 6.3	84/03/15
  15:  * and on	dmf.c	6.2	84/02/16
  16:  *
  17:  * REAL(tm) dhv driver derived from dhu.c by
  18:  * Steve Nuchia at Baylor 22 November 1987
  19:  *	steve@eyeball.bcm.tmc.edu
  20:  *
  21:  * Dave Johnson, Brown University Computer Science
  22:  *	ddj%brown@csnet-relay
  23:  */
  24: 
  25: #include "dhv.h"
  26: #if NDHV > 0
  27: /*
  28:  * DHV-11 driver
  29:  */
  30: #include "param.h"
  31: #include "dhvreg.h"
  32: #include "conf.h"
  33: #include "user.h"
  34: #include "file.h"
  35: #include "proc.h"
  36: #include "ioctl.h"
  37: #include "tty.h"
  38: #include "ttychars.h"
  39: #include "clist.h"
  40: #include "map.h"
  41: #include "uba.h"
  42: #include "ubavar.h"
  43: #include "systm.h"
  44: #include "syslog.h"
  45: #include <sys/kernel.h>
  46: 
  47: struct  uba_device dhvinfo[NDHV];
  48: 
  49: #define NDHVLINE    (NDHV*8)
  50: 
  51: /*
  52:  * The minor device number is used as follows:
  53:  *
  54:  *  bits	meaning
  55:  *  0-2		unit number within board
  56:  *  3-5		board number (max of 8)
  57:  *  6		RTS/CTS flow control enabled
  58:  *  7		softcarrier (hardwired line)
  59: */
  60: #define UNIT(x) (minor(x) & 077)
  61: #define SOFTCAR 0x80
  62: #define HWFLOW  0x40
  63: 
  64: #define IFLAGS  (EVENP|ODDP|ECHO)
  65: 
  66: /*
  67:  * DHV's don't have a very good interrupt facility - you get an
  68:  * interrupt when the first character is put into the silo
  69:  * and nothing after that.  Previously an attempt was made to
  70:  * delay a couple of clock ticks with receive interrupts disabled.
  71:  *
  72:  * Unfortunately the code was ineffective because the number of ticks
  73:  * to delay was decremented if a full (90%) or overrun silo was encountered.
  74:  * After two such events the driver was back in interrupt per character
  75:  * mode thus wasting/negating the whole effort.
  76:  */
  77: 
  78: char    dhv_hwxon[NDHVLINE];    /* hardware xon/xoff enabled, per line */
  79: 
  80: /*
  81:  * Baud rates: no 50, 200, or 38400 baud; all other rates are from "Group B".
  82:  *	EXTA => 19200 baud
  83:  *	EXTB => 2000 baud
  84:  */
  85: char    dhv_speeds[] =
  86:     { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 10, 11, 13, 14, 9 };
  87: 
  88: struct  tty dhv_tty[NDHVLINE];
  89: int ndhv = NDHVLINE;
  90: int dhvact;             /* mask of active dhv's */
  91: int dhv_overrun[NDHVLINE];
  92: int dhvstart();
  93: long    dhvmctl(),dmtodhv();
  94: extern  int wakeup();
  95: 
  96: #if defined(UCB_CLIST)
  97: extern  ubadr_t clstaddr;
  98: #define cpaddr(x)   (clstaddr + (ubadr_t)((x) - (char *)cfree))
  99: #else
 100: #define cpaddr(x)   ((u_short)(x))
 101: #endif
 102: 
 103: /*
 104:  * Routine called to attach a dhv.
 105:  */
 106: dhvattach(addr,unit)
 107:     register caddr_t addr;
 108:     register u_int unit;
 109: {
 110:     if (addr && unit < NDHV && !dhvinfo[unit].ui_addr)
 111:     {
 112:     dhvinfo[unit].ui_unit = unit;
 113:     dhvinfo[unit].ui_addr = addr;
 114:     dhvinfo[unit].ui_alive = 1;
 115:     return (1);
 116:     }
 117:     return (0);
 118: }
 119: 
 120: /*
 121:  * Open a DHV11 line, mapping the clist onto the uba if this
 122:  * is the first dhv on this uba.  Turn on this dhv if this is
 123:  * the first use of it.
 124:  */
 125: /*ARGSUSED*/
 126: dhvopen(dev, flag)
 127:     dev_t dev;
 128:     int     flag;
 129:     {
 130:     register struct tty *tp;
 131:     register int unit;
 132:     int dhv, error, s;
 133:     register struct dhvdevice *addr;
 134:     struct uba_device *ui;
 135: 
 136:     unit = UNIT(dev);
 137:     dhv = unit >> 3;
 138:     if  (unit >= NDHVLINE || (ui = &dhvinfo[dhv])->ui_alive == 0)
 139:         return(ENXIO);
 140:     tp = &dhv_tty[unit];
 141:     addr = (struct dhvdevice *)ui->ui_addr;
 142:     tp->t_addr = (caddr_t)addr;
 143:     tp->t_oproc = dhvstart;
 144: 
 145:     if  ((dhvact & (1<<dhv)) == 0)
 146:         {
 147:         addr->dhvcsr = DHV_SELECT(0) | DHV_IE;
 148:         dhvact |= (1<<dhv);
 149:         /* anything else to configure whole board */
 150:         }
 151: 
 152:     s = spltty();
 153:     if  ((tp->t_state & TS_ISOPEN) == 0)
 154:         {
 155:         tp->t_state |= TS_WOPEN;
 156:         if  (tp->t_ispeed == 0)
 157:             {
 158:             tp->t_state |= TS_HUPCLS;
 159:             tp->t_ispeed = B9600;
 160:             tp->t_ospeed = B9600;
 161:             tp->t_flags = IFLAGS;
 162:             }
 163:         ttychars(tp);
 164:         tp->t_dev = dev;
 165:         if  (dev & HWFLOW)
 166:             tp->t_flags |= RTSCTS;
 167:         else
 168:             tp->t_flags &= ~RTSCTS;
 169:         dhvparam(unit);
 170:         }
 171:     else if ((tp->t_state & TS_XCLUDE) && u.u_uid)
 172:         {
 173:         error = EBUSY;
 174:         goto out;
 175:         }
 176:     dhvmctl(dev, (long)DHV_ON, DMSET);
 177:     addr->dhvcsr = DHV_SELECT(dev) | DHV_IE;
 178:     if  ((addr->dhvstat & DHV_ST_DCD) || (dev & SOFTCAR))
 179:         tp->t_state |= TS_CARR_ON;
 180:     while   ((tp->t_state & TS_CARR_ON) == 0 &&
 181:          (flag & O_NONBLOCK) == 0)
 182:         {
 183:         tp->t_state |= TS_WOPEN;
 184:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
 185:         }
 186:     error = (*linesw[tp->t_line].l_open)(dev, tp);
 187: out:
 188:     splx(s);
 189:     return(error);
 190:     }
 191: 
 192: /*
 193:  * Close a DHV11 line, turning off the modem control.
 194:  */
 195: /*ARGSUSED*/
 196: dhvclose(dev, flag)
 197:     dev_t dev;
 198:     int flag;
 199:     {
 200:     register struct tty *tp;
 201:     register int unit;
 202: 
 203:     unit = UNIT(dev);
 204:     tp = &dhv_tty[unit];
 205:     if  (!(tp->t_state & (TS_WOPEN|TS_ISOPEN)))
 206:         return(0);
 207:     (*linesw[tp->t_line].l_close)(tp, flag);
 208:     (void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
 209:     (void) dhvmctl(unit, (long)DHV_OFF, DMSET);
 210:     ttyclose(tp);
 211:     if  (dhv_overrun[unit])
 212:         {
 213:         log(LOG_NOTICE,"dhv%d %d overruns\n",unit,dhv_overrun[unit]);
 214:         dhv_overrun[unit] = 0;
 215:         }
 216:     return(0);
 217:     }
 218: 
 219: dhvselect(dev, rw)
 220:     dev_t   dev;
 221:     int rw;
 222:     {
 223:     struct  tty *tp = &dhv_tty[UNIT(dev)];
 224: 
 225:     return(ttyselect(tp, rw));
 226:     }
 227: 
 228: dhvread(dev, uio, flag)
 229:     dev_t dev;
 230:     struct uio *uio;
 231:     int flag;
 232:     {
 233:     register struct tty *tp = &dhv_tty[UNIT(dev)];
 234: 
 235:     return((*linesw[tp->t_line].l_read) (tp, uio, flag));
 236:     }
 237: 
 238: dhvwrite(dev, uio, flag)
 239:     dev_t dev;
 240:     struct uio *uio;
 241:     int flag;
 242:     {
 243:     register struct tty *tp = &dhv_tty[UNIT(dev)];
 244: 
 245:     return((*linesw[tp->t_line].l_write) (tp, uio, flag));
 246:     }
 247: 
 248: /*
 249:  * DHV11 receiver interrupt.
 250:  */
 251: 
 252: dhvrint(dhv)
 253:     int dhv;
 254:     {
 255:     register struct tty *tp;
 256:     register int    c;
 257:     register struct dhvdevice *addr;
 258:     struct tty *tp0;
 259:     struct uba_device *ui;
 260:     int line, p;
 261: 
 262:     ui = &dhvinfo[dhv];
 263:     addr = (struct dhvdevice *)ui->ui_addr;
 264:     if  (!addr)
 265:         return;
 266:     tp0 = &dhv_tty[dhv<<3];
 267: 
 268:     /*
 269: 	 * Loop fetching characters from the silo for this
 270: 	 * dhv until there are no more in the silo.
 271: 	 */
 272:     while   ((c = addr->dhvrbuf) & DHV_RB_VALID)
 273:         {
 274:         line = DHV_RX_LINE(c);
 275:         tp = tp0 + line;
 276:         if  ((c & DHV_RB_STAT) == DHV_RB_STAT)
 277:             {
 278:             /*
 279: 			 * modem changed or diag info
 280: 			 */
 281:             if  (c & DHV_RB_DIAG)
 282:                 {
 283:                 if  ((c & 0xff) > 0201)
 284:                     log(LOG_NOTICE,"dhv%d diag %o\n",dhv, c&0xff);
 285:                     continue;
 286:                 }
 287:             if  (!(tp->t_dev & SOFTCAR) ||
 288:                   (tp->t_flags & MDMBUF))
 289:                     (*linesw[tp->t_line].l_modem)(tp,
 290:                             (c & DHV_ST_DCD) != 0);
 291:             if  (tp->t_flags & RTSCTS)
 292:                 {
 293:                 if  (c & DHV_ST_CTS)
 294:                         {
 295:                     tp->t_state &= ~TS_TTSTOP;
 296:                     ttstart(tp);
 297:                         }
 298:                 else
 299:                     {
 300:                     tp->t_state |= TS_TTSTOP;
 301:                     dhvstop(tp, 0);
 302:                         }
 303:                 }
 304:             continue;
 305:             }
 306:         if  ((tp->t_state&TS_ISOPEN) == 0)
 307:             {
 308:                 wakeup((caddr_t)&tp->t_rawq);
 309:             continue;
 310:             }
 311:         if  (c & (DHV_RB_PE|DHV_RB_DO|DHV_RB_FE))
 312:             {
 313:                 if  (c & DHV_RB_PE)
 314:                 {
 315:                 p = tp->t_flags & (EVENP|ODDP);
 316:                 if  (p == EVENP || p == ODDP)
 317:                     continue;
 318:                 }
 319:             if  (c & DHV_RB_DO)
 320:                 {
 321:                 dhv_overrun[(dhv << 3) + line]++;
 322:                 /* bit-bucket the silo to free the cpu */
 323:                 while   (addr->dhvrbuf & DHV_RB_VALID)
 324:                     ;
 325:                 break;
 326:                 }
 327:             if  (c & DHV_RB_FE)
 328:                 {
 329: /*
 330:  * At framing error (break) generate an interrupt in cooked/cbreak mode.
 331:  * Let the char through in RAW mode for autobauding getty's.  The
 332:  * DH driver * has been using the 'brkc' character for years - see
 333:  * the comment in dh.c
 334: */
 335:                 if  (!(tp->t_flags&RAW))
 336: #ifdef  OLDWAY
 337:                     c = tp->t_intrc;
 338: #else
 339:                     c = tp->t_brkc;
 340:                 }
 341: #endif
 342:             }
 343: #if NBK > 0
 344:         if  (tp->t_line == NETLDISC)
 345:             {
 346:             c &= 0x7f;
 347:             BKINPUT(c, tp);
 348:             }
 349:         else
 350: #endif
 351:             {
 352:             if  (!(c & DHV_RB_PE) && dhv_hwxon[(dhv<<3)+line] &&
 353:                  ((c & 0x7f) == CSTOP || (c & 0x7f) == CSTART))
 354:                 continue;
 355:             (*linesw[tp->t_line].l_rint)(c, tp);
 356:             }
 357:         }
 358:     }
 359: 
 360: /*
 361:  * Ioctl for DHV11.
 362:  */
 363: /*ARGSUSED*/
 364: dhvioctl(dev, cmd, data, flag)
 365:     register dev_t dev;
 366:     u_int cmd;
 367:     caddr_t data;
 368:     {
 369:     register struct tty *tp;
 370:     register int unit = UNIT(dev);
 371:     int error;
 372: 
 373:     tp = &dhv_tty[unit];
 374:     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 375:     if  (error >= 0)
 376:         return(error);
 377:     error = ttioctl(tp, cmd, data, flag);
 378:     if  (error >= 0)
 379:         {
 380:         if  (cmd == TIOCSETP || cmd == TIOCSETN ||
 381:              cmd == TIOCLSET || cmd == TIOCLBIC ||
 382:              cmd == TIOCLBIS || cmd == TIOCSETD || cmd == TIOCSETC)
 383:             dhvparam(unit);
 384:         return(error);
 385:         }
 386: 
 387:     switch  (cmd)
 388:         {
 389:         case    TIOCSBRK:
 390:             (void) dhvmctl(unit, (long)DHV_BRK, DMBIS);
 391:             break;
 392:         case    TIOCCBRK:
 393:             (void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
 394:             break;
 395:         case    TIOCSDTR:
 396:             (void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIS);
 397:             break;
 398:         case    TIOCCDTR:
 399:             (void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIC);
 400:             break;
 401:         case    TIOCMSET:
 402:             (void) dhvmctl(dev, dmtodhv(*(int *)data), DMSET);
 403:             break;
 404:         case    TIOCMBIS:
 405:             (void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIS);
 406:             break;
 407:         case    TIOCMBIC:
 408:             (void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIC);
 409:             break;
 410:         case    TIOCMGET:
 411:             *(int *)data = dhvtodm(dhvmctl(dev, 0L, DMGET));
 412:             break;
 413:         default:
 414:             return(ENOTTY);
 415:         }
 416:     return(0);
 417:     }
 418: 
 419: static long
 420: dmtodhv(bits)
 421:     register int bits;
 422:     {
 423:     long b = 0;
 424: 
 425:     if  (bits & TIOCM_RTS) b |= DHV_RTS;
 426:     if  (bits & TIOCM_DTR) b |= DHV_DTR;
 427:     if  (bits & TIOCM_LE) b |= DHV_LE;
 428:     return(b);
 429:     }
 430: 
 431: static
 432: dhvtodm(bits)
 433:     long bits;
 434:     {
 435:     register int b = 0;
 436: 
 437:     if  (bits & DHV_DSR) b |= TIOCM_DSR;
 438:     if  (bits & DHV_RNG) b |= TIOCM_RNG;
 439:     if  (bits & DHV_CAR) b |= TIOCM_CAR;
 440:     if  (bits & DHV_CTS) b |= TIOCM_CTS;
 441:     if  (bits & DHV_RTS) b |= TIOCM_RTS;
 442:     if  (bits & DHV_DTR) b |= TIOCM_DTR;
 443:     if  (bits & DHV_LE) b |= TIOCM_LE;
 444:     return(b);
 445:     }
 446: 
 447: /*
 448:  * Set parameters from open or stty into the DHV hardware
 449:  * registers.
 450:  */
 451: static
 452: dhvparam(unit)
 453:     int unit;
 454:     {
 455:     register struct tty *tp;
 456:     register struct dhvdevice *addr;
 457:     register int lpar;
 458:     int s;
 459: 
 460:     tp = &dhv_tty[unit];
 461:     addr = (struct dhvdevice *)tp->t_addr;
 462:     /*
 463: 	 * Block interrupts so parameters will be set
 464: 	 * before the line interrupts.
 465: 	 */
 466:     s = spltty();
 467:     if  ((tp->t_ispeed) == 0)
 468:         {
 469:         tp->t_state |= TS_HUPCLS;
 470:         (void)dhvmctl(unit, (long)DHV_OFF, DMSET);
 471:         goto out;
 472:         }
 473:     lpar = (dhv_speeds[tp->t_ospeed]<<12) | (dhv_speeds[tp->t_ispeed]<<8);
 474:     if  (tp->t_ispeed == B134)
 475:         lpar |= DHV_LP_BITS6|DHV_LP_PENABLE;
 476:     else if (tp->t_flags & (RAW|LITOUT|PASS8))
 477:         lpar |= DHV_LP_BITS8;
 478:     else
 479:         lpar |= DHV_LP_BITS7|DHV_LP_PENABLE;
 480:     if  (tp->t_flags&EVENP)
 481:         lpar |= DHV_LP_EPAR;
 482:     if  ((tp->t_flags & EVENP) && (tp->t_flags & ODDP))
 483:         {
 484:         /* hack alert.  assume "allow both" means don't care */
 485:         /* trying to make xon/xoff work with evenp+oddp */
 486:         lpar |= DHV_LP_BITS8;
 487:         lpar &= ~DHV_LP_PENABLE;
 488:         }
 489:     if  ((tp->t_ospeed) == B110)
 490:         lpar |= DHV_LP_TWOSB;
 491:     addr->dhvcsr = DHV_SELECT(unit) | DHV_IE;
 492:     addr->dhvlpr = lpar;
 493:     dhv_hwxon[unit] = !(tp->t_flags & RAW) &&
 494:         (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC) &&
 495:         tp->t_stopc == CSTOP && tp->t_startc == CSTART;
 496: 
 497:     if  (dhv_hwxon[unit])
 498:         addr->dhvlcr |= DHV_LC_OAUTOF;
 499:     else
 500:         {
 501:         addr->dhvlcr &= ~DHV_LC_OAUTOF;
 502:         delay(25L); /* see the dhv manual, sec 3.3.6 */
 503:         addr->dhvlcr2 |= DHV_LC2_TXEN;
 504:         }
 505: out:
 506:     splx(s);
 507:     return;
 508:     }
 509: 
 510: /*
 511:  * DHV11 transmitter interrupt.
 512:  * Restart each line which used to be active but has
 513:  * terminated transmission since the last interrupt.
 514:  */
 515: dhvxint(dhv)
 516:     int dhv;
 517:     {
 518:     register struct tty *tp;
 519:     register struct dhvdevice *addr;
 520:     struct tty *tp0;
 521:     struct uba_device *ui;
 522:     register int line, t;
 523:     u_short cntr;
 524:     ubadr_t base;
 525: 
 526:     ui = &dhvinfo[dhv];
 527:     tp0 = &dhv_tty[dhv<<4];
 528:     addr = (struct dhvdevice *)ui->ui_addr;
 529:     while   ((t = addr->dhvcsrh) & DHV_CSH_TI)
 530:         {
 531:         line = DHV_TX_LINE(t);
 532:         tp = tp0 + line;
 533:         tp->t_state &= ~TS_BUSY;
 534:         if  (t & DHV_CSH_NXM)
 535:             {
 536:             log(LOG_NOTICE, "dhv%d,%d NXM\n", dhv, line);
 537:             /* SHOULD RESTART OR SOMETHING... */
 538:             }
 539:         if  (tp->t_state&TS_FLUSH)
 540:             tp->t_state &= ~TS_FLUSH;
 541:         else
 542:             {
 543:             addr->dhvcsrl = DHV_SELECT(line) | DHV_IE;
 544:             base = (ubadr_t) addr->dhvbar1;
 545:             /*
 546: 			 * Clists are either:
 547: 			 *	1)  in kernel virtual space,
 548: 			 *	    which in turn lies in the
 549: 			 *	    first 64K of physical memory or
 550: 			 *	2)  at UNIBUS virtual address 0.
 551: 			 *
 552: 			 * In either case, the extension bits are 0.
 553: 			 */
 554:             if  (!ubmap)
 555:                 base |= (ubadr_t)((addr->dhvbar2 & 037) << 16);
 556:                 cntr = base - cpaddr(tp->t_outq.c_cf);
 557:             ndflush(&tp->t_outq,cntr);
 558:             }
 559:         if  (tp->t_line)
 560:             (*linesw[tp->t_line].l_start)(tp);
 561:         else
 562:             dhvstart(tp);
 563:         }
 564:     }
 565: 
 566: /*
 567:  * Start (restart) transmission on the given DHV11 line.
 568:  */
 569: dhvstart(tp)
 570:     register struct tty *tp;
 571:     {
 572:     register struct dhvdevice *addr;
 573:     register int unit, nch;
 574:     ubadr_t car;
 575:     int s;
 576: 
 577:     unit = UNIT(tp->t_dev);
 578:     addr = (struct dhvdevice *)tp->t_addr;
 579: 
 580:     /*
 581: 	 * Must hold interrupts in following code to prevent
 582: 	 * state of the tp from changing.
 583: 	 */
 584:     s = spltty();
 585:     /*
 586: 	 * If it's currently active, or delaying, no need to do anything.
 587: 	 */
 588:     if  (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 589:         goto out;
 590:     /*
 591: 	 * If there are sleepers, and output has drained below low
 592: 	 * water mark, wake up the sleepers..
 593: 	 */
 594:     ttyowake(tp);
 595: 
 596:     /*
 597: 	 * Now restart transmission unless the output queue is
 598: 	 * empty.
 599: 	 */
 600:     if  (tp->t_outq.c_cc == 0)
 601:         goto out;
 602:     addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
 603: /*
 604:  * If CTS is off and we're doing hardware flow control then mark the output
 605:  * as stopped and do not transmit anything.
 606: */
 607:     if  ((addr->dhvstat & DHV_ST_CTS) == 0 && (tp->t_flags & RTSCTS))
 608:         {
 609:         tp->t_state |= TS_TTSTOP;
 610:         goto out;
 611:         }
 612: /*
 613:  * This is where any per character delay handling for special characters
 614:  * would go if ever implemented again.  The call to ndqb would be replaced
 615:  * with a scan for special characters and then the appropriate sleep/wakeup
 616:  * done.
 617: */
 618:     nch = ndqb(&tp->t_outq, 0);
 619:     /*
 620: 	 * If characters to transmit, restart transmission.
 621: 	 */
 622:     if  (nch)
 623:         {
 624:         car = cpaddr(tp->t_outq.c_cf);
 625:         addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
 626:         addr->dhvlcr &= ~DHV_LC_TXABORT;
 627:         addr->dhvbcr = nch;
 628:         addr->dhvbar1 = loint(car);
 629:         if  (ubmap)
 630:             addr->dhvbar2 = (hiint(car) & DHV_BA2_XBA) | DHV_BA2_DMAGO;
 631:         else
 632:             addr->dhvbar2 = (hiint(car) & 037) | DHV_BA2_DMAGO;
 633:         tp->t_state |= TS_BUSY;
 634:         }
 635: out:
 636:     splx(s);
 637:     }
 638: 
 639: /*
 640:  * Stop output on a line, e.g. for ^S/^Q or output flush.
 641:  */
 642: /*ARGSUSED*/
 643: dhvstop(tp, flag)
 644:     register struct tty *tp;
 645:     {
 646:     register struct dhvdevice *addr;
 647:     register int unit, s;
 648: 
 649:     addr = (struct dhvdevice *)tp->t_addr;
 650:     /*
 651: 	 * Block input/output interrupts while messing with state.
 652: 	 */
 653:     s = spltty();
 654:     if  (tp->t_state & TS_BUSY)
 655:         {
 656:         /*
 657: 		 * Device is transmitting; stop output
 658: 		 * by selecting the line and setting the
 659: 		 * abort xmit bit.  We will get an xmit interrupt,
 660: 		 * where we will figure out where to continue the
 661: 		 * next time the transmitter is enabled.  If
 662: 		 * TS_FLUSH is set, the outq will be flushed.
 663: 		 * In either case, dhvstart will clear the TXABORT bit.
 664: 		 */
 665:         unit = UNIT(tp->t_dev);
 666:         addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
 667:         addr->dhvlcr |= DHV_LC_TXABORT;
 668:         delay(25L); /* see the dhv manual, sec 3.3.6 */
 669:         addr->dhvlcr2 |= DHV_LC2_TXEN;
 670:         if  ((tp->t_state&TS_TTSTOP)==0)
 671:             tp->t_state |= TS_FLUSH;
 672:         }
 673:     (void) splx(s);
 674:     }
 675: 
 676: /*
 677:  * DHV11 modem control
 678:  */
 679: static long
 680: dhvmctl(dev, bits, how)
 681:     dev_t dev;
 682:     long bits;
 683:     int how;
 684:     {
 685:     register struct dhvdevice *dhvaddr;
 686:     register int unit;
 687:     register struct tty *tp;
 688:     long mbits;
 689:     int s;
 690: 
 691:     unit = UNIT(dev);
 692:     tp = dhv_tty + unit;
 693:     dhvaddr = (struct dhvdevice *) tp->t_addr;
 694:     s = spltty();
 695:     dhvaddr->dhvcsr = DHV_SELECT(unit) | DHV_IE;
 696:     /*
 697: 	 * combine byte from stat register (read only, bits 16..23)
 698: 	 * with lcr register (read write, bits 0..15).
 699: 	 */
 700:     mbits = (u_short)dhvaddr->dhvlcr | ((long)dhvaddr->dhvstat << 16);
 701:     switch  (how)
 702:         {
 703:         case    DMSET:
 704:             mbits = (mbits & 0xff0000L) | bits;
 705:             break;
 706:         case    DMBIS:
 707:             mbits |= bits;
 708:             break;
 709:         case    DMBIC:
 710:             mbits &= ~bits;
 711:             break;
 712:         case    DMGET:
 713:             (void) splx(s);
 714:             return(mbits);
 715:         }
 716:     dhvaddr->dhvlcr = (mbits & 0xffff) | DHV_LC_RXEN;
 717:     if  (dhv_hwxon[unit])
 718:         dhvaddr->dhvlcr |= DHV_LC_OAUTOF;
 719:     dhvaddr->dhvlcr2 = DHV_LC2_TXEN;
 720:     (void) splx(s);
 721:     return(mbits);
 722:     }
 723: #endif

Defined functions

dhvattach defined in line 106; never used
dhvclose defined in line 196; never used
dhvioctl defined in line 364; never used
dhvmctl defined in line 679; used 13 times
dhvopen defined in line 126; never used
dhvparam defined in line 451; used 2 times
dhvread defined in line 228; never used
dhvrint defined in line 252; used 1 times
dhvselect defined in line 219; never used
dhvstart defined in line 569; used 3 times
dhvstop defined in line 643; used 1 times
dhvtodm defined in line 431; used 1 times
dhvwrite defined in line 238; never used
dhvxint defined in line 515; used 1 times
dmtodhv defined in line 419; used 4 times

Defined variables

dhv_hwxon defined in line 78; used 4 times
dhv_overrun defined in line 91; used 4 times
dhv_speeds defined in line 85; used 2 times
  • in line 473(2)
dhv_tty defined in line 88; used 10 times
dhvact defined in line 90; used 2 times
dhvinfo defined in line 47; used 7 times
ndhv defined in line 89; never used

Defined macros

HWFLOW defined in line 62; used 1 times
IFLAGS defined in line 64; used 1 times
NDHVLINE defined in line 49; used 5 times
SOFTCAR defined in line 61; used 2 times
UNIT defined in line 60; used 9 times
cpaddr defined in line 100; used 2 times
Last modified: 1997-06-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4865
Valid CSS Valid XHTML 1.0 Strict