1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)dmf.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: #include "dmf.h"
  10: #if NDMF > 0
  11: /*
  12:  * DMF32 driver
  13:  *
  14:  *
  15:  * TODO:
  16:  *	test with modem
  17:  *	load as much as possible into silo
  18:  *	use auto XON/XOFF
  19:  *	test reset code
  20:  ****************************
  21:  * DMF32 line printer driver
  22:  *
  23:  * the line printer on dmfx is indicated by a minor device code of 128+x
  24:  *
  25:  * the flags field of the config file is interpreted like so:
  26:  * bits		meaning
  27:  * ----		-------
  28:  * 0-7		soft carrier bits for ttys part of dmf32
  29:  * 8-15		number of cols/line on the line printer
  30:  *			if 0, 132 will be used.
  31:  * 16-23	number of lines/page on the line printer
  32:  *			if 0, 66 will be used.
  33:  * 24		if 1 DO NOT use the auto format mode of the
  34:  *			line printer parallel port
  35:  */
  36: #include "../machine/pte.h"
  37: 
  38: #include "bk.h"
  39: #include "uba.h"
  40: #include "param.h"
  41: #include "conf.h"
  42: #include "dir.h"
  43: #include "user.h"
  44: #include "proc.h"
  45: #include "ioctl.h"
  46: #include "tty.h"
  47: #include "map.h"
  48: #include "buf.h"
  49: #include "vm.h"
  50: #include "bkmac.h"
  51: #include "clist.h"
  52: #include "file.h"
  53: #include "uio.h"
  54: #include "kernel.h"
  55: #include "syslog.h"
  56: 
  57: #include "ubareg.h"
  58: #include "ubavar.h"
  59: #include "dmfreg.h"
  60: 
  61: /*
  62:  * Definition of the driver for the auto-configuration program.
  63:  */
  64: int dmfprobe(), dmfattach(), dmfrint(), dmfxint();
  65: int dmflint();
  66: struct  uba_device *dmfinfo[NDMF];
  67: u_short dmfstd[] = { 0 };
  68: struct  uba_driver dmfdriver =
  69:     { dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
  70: 
  71: int dmf_timeout = 10;       /* silo timeout, in ms */
  72: int dmf_mindma = 4;         /* don't dma below this point */
  73: 
  74: /*
  75:  * Local variables for the driver
  76:  */
  77: char    dmf_speeds[] =
  78:     { 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 010, 012, 014, 016, 017, 0 };
  79: 
  80: #ifndef PORTSELECTOR
  81: #define ISPEED  B9600
  82: #define IFLAGS  (EVENP|ODDP|ECHO)
  83: #else
  84: #define ISPEED  B4800
  85: #define IFLAGS  (EVENP|ODDP)
  86: #endif
  87: 
  88: struct  tty dmf_tty[NDMF*8];
  89: char    dmfsoftCAR[NDMF];
  90: 
  91: struct dmfl_softc {
  92:     u_int   dmfl_state;         /* soft state bits */
  93:     int dmfl_info;      /* uba info */
  94:     u_short dmfl_lines;     /* lines per page (66 def.) */
  95:     u_short dmfl_cols;      /* cols per line (132 def.) */
  96:     u_short dmfl_format;        /* fflag for auto form feed */
  97:     char    dmfl_buf[DMFL_BUFSIZ];
  98: } dmfl_softc[NDMF];
  99: 
 100: /*
 101:  * convert device number into DMF line printer unit number
 102:  */
 103: #define DMFL_UNIT(d)    (minor(d)&0xF)  /* up to 16 DMFs */
 104: 
 105: #define ASLP 1      /* waiting for interrupt from dmf */
 106: #define OPEN 2      /* line printer is open */
 107: #define ERROR 4     /* error while printing, driver
 108: 			 refuses to do anything till closed */
 109: #define MOREIO 8    /* more data for printer */
 110: 
 111: #ifndef lint
 112: int ndmf = NDMF*8;          /* used by iostat */
 113: #endif
 114: int dmfact;             /* mask of active dmf's */
 115: int dmfstart(), ttrstrt();
 116: 
 117: /*
 118:  * The clist space is mapped by the driver onto each UNIBUS.
 119:  * The UBACVT macro converts a clist space address for unibus uban
 120:  * into an i/o space address for the DMA routine.
 121:  */
 122: int dmf_ubinfo[NUBA];       /* info about allocated unibus map */
 123: int cbase[NUBA];            /* base address in unibus map */
 124: #define UBACVT(x, uban)     (cbase[uban] + ((x)-(char *)cfree))
 125: char    dmf_dma[NDMF*8];
 126: 
 127: /*
 128:  * Routine for configuration to set dmf interrupt.
 129:  */
 130: /*ARGSUSED*/
 131: dmfprobe(reg, ctlr)
 132:     caddr_t reg;
 133:     struct uba_device *ctlr;
 134: {
 135:     register int br, cvec;      /* these are ``value-result'' */
 136:     register struct dmfdevice *dmfaddr = (struct dmfdevice *)reg;
 137:     register int i;
 138:     register unsigned int a;
 139:     static char *dmfdevs[]=
 140:         {"parallel","printer","synch","asynch"};
 141:     unsigned int dmfoptions;
 142:     static int (*intrv[3])() = { (int (*)())0, (int (*)())0, (int (*)())0 };
 143: 
 144: #ifdef lint
 145:     br = 0; cvec = br; br = cvec;
 146:     dmfxint(0); dmfrint(0);
 147:     dmfsrint(); dmfsxint(); dmfdaint(); dmfdbint(); dmflint(0);
 148: #endif
 149:     /*
 150: 	 * Pick the usual size DMF vector here (don't decrement it here).
 151: 	 * grab configuration; note that the DMF32
 152: 	 * doesn't seem to put the right bits in this
 153: 	 * register until AFTER the interrupt vector is set.
 154: 	 */
 155:     br = 0x15;
 156:     cvec = (uba_hd[numuba].uh_lastiv - 4*8);
 157:     dmfaddr->dmfccsr0 = (cvec >> 2);
 158:     dmfoptions = dmfaddr->dmfccsr0 & DMFC_CONFMASK;
 159: 
 160:     /* catch a couple of special cases:  Able vmz/32n and vmz/lp	*/
 161:     if (dmfoptions == DMFC_ASYNC) {
 162:         /* Async portion only */
 163: 
 164:         cvec = (uba_hd[numuba].uh_lastiv -= 8);
 165:         dmfaddr->dmfccsr0 = (cvec - 2*8) >> 2;
 166:         intrv[0] = ctlr->ui_intr[4];
 167:         intrv[1] = ctlr->ui_intr[5];
 168:         ctlr->ui_intr = intrv;
 169:     } else if (dmfoptions == DMFC_LP) {
 170:         /* LP portion only */
 171: 
 172:         cvec = (uba_hd[numuba].uh_lastiv -= 8);
 173:         ctlr->ui_intr = &ctlr->ui_intr[6];
 174:     } else if (dmfoptions == (DMFC_LP|DMFC_ASYNC)) {
 175:         /* LP ans Async portions only */
 176: 
 177:         cvec = (uba_hd[numuba].uh_lastiv -= 2*8);
 178:         ctlr->ui_intr = &ctlr->ui_intr[4];
 179:     } else {
 180:         /* All other configurations get everything */
 181: 
 182:         cvec = (uba_hd[numuba].uh_lastiv -= 4*8);
 183:     }
 184:     a = (dmfoptions >> 12) & 0xf;
 185:     printf("dmf%d:", ctlr->ui_unit);
 186:     for (i = 0; a != 0; ++i, a >>= 1) {
 187:         if (a & 1)
 188:             printf(" %s",dmfdevs[i]);
 189:     }
 190:     printf(".\n");
 191: 
 192:     if (dmfoptions & DMFC_LP)
 193:         dmfaddr->dmfl_ctrl = DMFL_RESET;
 194:     return (sizeof (struct dmfdevice));
 195: }
 196: 
 197: /*
 198:  * Routine called to attach a dmf.
 199:  */
 200: dmfattach(ui)
 201:     struct uba_device *ui;
 202: {
 203:     register int cols = (ui->ui_flags>>8) & 0xff;
 204:     register int lines = (ui->ui_flags>>16) & 0xff;
 205: 
 206:     dmfsoftCAR[ui->ui_unit] = ui->ui_flags & 0xff;
 207:     dmfl_softc[ui->ui_unit].dmfl_cols = cols == 0 ? DMFL_DEFCOLS : cols;
 208:     dmfl_softc[ui->ui_unit].dmfl_lines = lines == 0 ? DMFL_DEFLINES : lines;
 209:     if ((ui->ui_flags >> 24) & 0x1)
 210:         dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8);
 211:     else
 212:         dmfl_softc[ui->ui_unit].dmfl_format = (2 << 8) | DMFL_FORMAT;
 213:     cbase[ui->ui_ubanum] = -1;
 214: }
 215: 
 216: 
 217: /*
 218:  * Open a DMF32 line, mapping the clist onto the uba if this
 219:  * is the first dmf on this uba.  Turn on this dmf if this is
 220:  * the first use of it.
 221:  */
 222: /*ARGSUSED*/
 223: dmfopen(dev, flag)
 224:     dev_t dev;
 225: {
 226:     register struct tty *tp;
 227:     register int unit, dmf;
 228:     register struct dmfdevice *addr;
 229:     register struct uba_device *ui;
 230:     int s;
 231: 
 232:     unit = minor(dev);
 233:     if (unit & 0200)
 234:         return (dmflopen(dev,flag));
 235:     dmf = unit >> 3;
 236:     if (unit >= NDMF*8 || (ui = dmfinfo[dmf])== 0 || ui->ui_alive == 0)
 237:         return (ENXIO);
 238:     tp = &dmf_tty[unit];
 239:     if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
 240:         return (EBUSY);
 241:     addr = (struct dmfdevice *)ui->ui_addr;
 242:     tp->t_addr = (caddr_t)addr;
 243:     tp->t_oproc = dmfstart;
 244:     tp->t_state |= TS_WOPEN;
 245:     /*
 246: 	 * While setting up state for this uba and this dmf,
 247: 	 * block uba resets which can clear the state.
 248: 	 */
 249:     s = spltty();
 250:     if (cbase[ui->ui_ubanum] == -1) {
 251:         dmf_ubinfo[ui->ui_ubanum] =
 252:             uballoc(ui->ui_ubanum, (caddr_t)cfree,
 253:             nclist*sizeof(struct cblock), 0);
 254:         cbase[ui->ui_ubanum] = UBAI_ADDR(dmf_ubinfo[ui->ui_ubanum]);
 255:     }
 256:     if ((dmfact&(1<<dmf)) == 0) {
 257:         addr->dmfcsr |= DMF_IE;
 258:         dmfact |= (1<<dmf);
 259:         addr->dmfrsp = dmf_timeout;
 260:     }
 261:     splx(s);
 262:     /*
 263: 	 * If this is first open, initialize tty state to default.
 264: 	 */
 265:     if ((tp->t_state&TS_ISOPEN) == 0) {
 266:         ttychars(tp);
 267: #ifndef PORTSELECTOR
 268:         if (tp->t_ispeed == 0) {
 269: #else
 270:             tp->t_state |= TS_HUPCLS;
 271: #endif PORTSELECTOR
 272:             tp->t_ispeed = ISPEED;
 273:             tp->t_ospeed = ISPEED;
 274:             tp->t_flags = IFLAGS;
 275: #ifndef PORTSELECTOR
 276:         }
 277: #endif PORTSELECTOR
 278:         dmfparam(unit);
 279:     }
 280:     /*
 281: 	 * Wait for carrier, then process line discipline specific open.
 282: 	 */
 283:     s = spltty();
 284:     for (;;) {
 285:         if ((dmfmctl(dev, DMF_ON, DMSET) & (DMF_CAR<<8)) ||
 286:             (dmfsoftCAR[dmf] & (1<<(unit&07))))
 287:             tp->t_state |= TS_CARR_ON;
 288:         if (tp->t_state & TS_CARR_ON)
 289:             break;
 290:         tp->t_state |= TS_WOPEN;
 291:         sleep((caddr_t)&tp->t_rawq, TTIPRI);
 292:     }
 293:     splx(s);
 294:     return ((*linesw[tp->t_line].l_open)(dev, tp));
 295: }
 296: 
 297: /*
 298:  * Close a DMF32 line.
 299:  */
 300: /*ARGSUSED*/
 301: dmfclose(dev, flag)
 302:     dev_t dev;
 303:     int flag;
 304: {
 305:     register struct tty *tp;
 306:     register unit;
 307: 
 308:     unit = minor(dev);
 309:     if (unit & 0200) {
 310:         dmflclose(dev,flag);
 311:         return;
 312:     }
 313: 
 314:     tp = &dmf_tty[unit];
 315:     (*linesw[tp->t_line].l_close)(tp);
 316:     (void) dmfmctl(unit, DMF_BRK, DMBIC);
 317:     if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
 318:         (void) dmfmctl(unit, DMF_OFF, DMSET);
 319:     ttyclose(tp);
 320: }
 321: 
 322: dmfread(dev, uio)
 323:     dev_t dev;
 324:     struct uio *uio;
 325: {
 326:     register struct tty *tp;
 327: 
 328:     if (minor(dev) & 0200)
 329:         return(ENXIO);
 330:     tp = &dmf_tty[minor(dev)];
 331:     return ((*linesw[tp->t_line].l_read)(tp, uio));
 332: }
 333: 
 334: dmfwrite(dev, uio)
 335:     dev_t dev;
 336:     struct uio *uio;
 337: {
 338:     register struct tty *tp;
 339: 
 340:     if (minor(dev) & 0200)
 341:         return (dmflwrite(dev,uio));
 342:     tp = &dmf_tty[minor(dev)];
 343:     return ((*linesw[tp->t_line].l_write)(tp, uio));
 344: }
 345: 
 346: /*
 347:  * DMF32 receiver interrupt.
 348:  */
 349: dmfrint(dmf)
 350:     int dmf;
 351: {
 352:     register c;
 353:     register struct tty *tp;
 354:     register struct dmfdevice *addr;
 355:     register struct tty *tp0;
 356:     int unit;
 357:     int overrun = 0;
 358:     register struct uba_device *ui;
 359: 
 360:     ui = dmfinfo[dmf];
 361:     if (ui == 0 || ui->ui_alive == 0)
 362:         return;
 363:     addr = (struct dmfdevice *)ui->ui_addr;
 364:     tp0 = &dmf_tty[dmf * 8];
 365:     /*
 366: 	 * Loop fetching characters from the silo for this
 367: 	 * dmf until there are no more in the silo.
 368: 	 */
 369:     while ((c = addr->dmfrbuf) < 0) {
 370: 
 371:         unit = (c >> 8) & 07;
 372:         tp = tp0 + unit;
 373:         if (c & DMF_DSC) {
 374:             addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
 375:             if (addr->dmfrms & DMF_CAR)
 376:                 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
 377:             else if ((dmfsoftCAR[dmf] & (1 << unit)) == 0 &&
 378:                 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
 379:                 addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
 380:                 addr->dmflctms = DMFLCR_ENA;
 381:             }
 382:             continue;
 383:         }
 384:         if ((tp->t_state&TS_ISOPEN) == 0) {
 385:             wakeup((caddr_t)&tp->t_rawq);
 386: #ifdef PORTSELECTOR
 387:             if ((tp->t_state & TS_WOPEN) == 0)
 388: #endif
 389:                 continue;
 390:         }
 391:         if (c & (DMF_PE|DMF_DO|DMF_FE)) {
 392:             if (c & DMF_PE)
 393:                 if ((tp->t_flags & (EVENP|ODDP)) == EVENP
 394:                 || (tp->t_flags & (EVENP|ODDP)) == ODDP)
 395:                     continue;
 396:             if ((c & DMF_DO) && overrun == 0) {
 397:                 log(LOG_WARNING, "dmf%d: silo overflow\n", dmf);
 398:                 overrun = 1;
 399:             }
 400:             if (c & DMF_FE)
 401:                 /*
 402: 			 	* At framing error (break) generate
 403: 			 	* a null (in raw mode, for getty), or a
 404: 			 	* interrupt (in cooked/cbreak mode).
 405: 			 	*/
 406:                 if (tp->t_flags & RAW)
 407:                     c = 0;
 408:                 else
 409:                     c = tp->t_intrc;
 410:         }
 411: #if NBK > 0
 412:         if (tp->t_line == NETLDISC) {
 413:             c &= 0177;
 414:             BKINPUT(c, tp);
 415:         } else
 416: #endif
 417:             (*linesw[tp->t_line].l_rint)(c, tp);
 418:     }
 419: }
 420: 
 421: /*
 422:  * Ioctl for DMF32.
 423:  */
 424: /*ARGSUSED*/
 425: dmfioctl(dev, cmd, data, flag)
 426:     dev_t dev;
 427:     caddr_t data;
 428: {
 429:     register struct tty *tp;
 430:     register int unit = minor(dev);
 431:     int error;
 432: 
 433:     if (unit & 0200)
 434:         return (ENOTTY);
 435:     tp = &dmf_tty[unit];
 436:     error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
 437:     if (error >= 0)
 438:         return (error);
 439:     error = ttioctl(tp, cmd, data, flag);
 440:     if (error >= 0) {
 441:         if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
 442:             cmd == TIOCLBIC || cmd == TIOCLSET)
 443:             dmfparam(unit);
 444:         return (error);
 445:     }
 446:     switch (cmd) {
 447: 
 448:     case TIOCSBRK:
 449:         (void) dmfmctl(dev, DMF_BRK, DMBIS);
 450:         break;
 451: 
 452:     case TIOCCBRK:
 453:         (void) dmfmctl(dev, DMF_BRK, DMBIC);
 454:         break;
 455: 
 456:     case TIOCSDTR:
 457:         (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIS);
 458:         break;
 459: 
 460:     case TIOCCDTR:
 461:         (void) dmfmctl(dev, DMF_DTR|DMF_RTS, DMBIC);
 462:         break;
 463: 
 464:     case TIOCMSET:
 465:         (void) dmfmctl(dev, dmtodmf(*(int *)data), DMSET);
 466:         break;
 467: 
 468:     case TIOCMBIS:
 469:         (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIS);
 470:         break;
 471: 
 472:     case TIOCMBIC:
 473:         (void) dmfmctl(dev, dmtodmf(*(int *)data), DMBIC);
 474:         break;
 475: 
 476:     case TIOCMGET:
 477:         *(int *)data = dmftodm(dmfmctl(dev, 0, DMGET));
 478:         break;
 479: 
 480:     default:
 481:         return (ENOTTY);
 482:     }
 483:     return (0);
 484: }
 485: 
 486: dmtodmf(bits)
 487:     register int bits;
 488: {
 489:     register int b;
 490: 
 491:     b = bits & 012;
 492:     if (bits & DML_ST) b |= DMF_RATE;
 493:     if (bits & DML_RTS) b |= DMF_RTS;
 494:     if (bits & DML_USR) b |= DMF_USRW;
 495:     return(b);
 496: }
 497: 
 498: dmftodm(bits)
 499:     register int bits;
 500: {
 501:     register int b;
 502: 
 503:     b = (bits & 012) | ((bits >> 7) & 0760) | DML_LE;
 504:     if (bits & DMF_USRR) b |= DML_USR;
 505:     if (bits & DMF_RTS) b |= DML_RTS;
 506:     return(b);
 507: }
 508: 
 509: 
 510: /*
 511:  * Set parameters from open or stty into the DMF hardware
 512:  * registers.
 513:  */
 514: dmfparam(unit)
 515:     register int unit;
 516: {
 517:     register struct tty *tp;
 518:     register struct dmfdevice *addr;
 519:     register int lpar, lcr;
 520:     int s;
 521: 
 522:     tp = &dmf_tty[unit];
 523:     addr = (struct dmfdevice *)tp->t_addr;
 524:     /*
 525: 	 * Block interrupts so parameters will be set
 526: 	 * before the line interrupts.
 527: 	 */
 528:     s = spltty();
 529:     addr->dmfcsr = (unit&07) | DMFIR_LCR | DMF_IE;
 530:     if ((tp->t_ispeed)==0) {
 531:         tp->t_state |= TS_HUPCLS;
 532:         (void) dmfmctl(unit, DMF_OFF, DMSET);
 533:         splx(s);
 534:         return;
 535:     }
 536:     lpar = (dmf_speeds[tp->t_ospeed]<<12) | (dmf_speeds[tp->t_ispeed]<<8);
 537:     lcr = DMFLCR_ENA;
 538:     if ((tp->t_ispeed) == B134)
 539:         lpar |= BITS6|PENABLE;
 540:     else if (tp->t_flags & (RAW|LITOUT|PASS8))
 541:         lpar |= BITS8;
 542:     else {
 543:         lpar |= BITS7|PENABLE;
 544:         /* CHECK FOR XON/XOFF AND SET lcr |= DMF_AUTOX; */
 545:     }
 546:     if (tp->t_flags&EVENP)
 547:         lpar |= EPAR;
 548:     if ((tp->t_ospeed) == B110)
 549:         lpar |= TWOSB;
 550:     lpar |= (unit&07);
 551:     addr->dmflpr = lpar;
 552:     addr->dmflctms = (addr->dmflctms &~ 0xff) | lcr;
 553:     splx(s);
 554: }
 555: 
 556: /*
 557:  * DMF32 transmitter interrupt.
 558:  * Restart the idle line.
 559:  */
 560: dmfxint(dmf)
 561:     int dmf;
 562: {
 563:     int unit0 = dmf * 8;
 564:     struct tty *tp0 = &dmf_tty[unit0];
 565:     register struct tty *tp;
 566:     register struct dmfdevice *addr;
 567:     register struct uba_device *ui;
 568:     register int t;
 569:     short cntr;
 570: 
 571:     ui = dmfinfo[dmf];
 572:     addr = (struct dmfdevice *)ui->ui_addr;
 573:     while ((t = addr->dmfcsr) & DMF_TI) {
 574:         if (t & DMF_NXM)
 575:             /* SHOULD RESTART OR SOMETHING... */
 576:             printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
 577:         t = t >> 8 & 7;
 578:         tp = tp0 + t;
 579:         tp->t_state &= ~TS_BUSY;
 580:         if (tp->t_state&TS_FLUSH)
 581:             tp->t_state &= ~TS_FLUSH;
 582:         else if (dmf_dma[unit0 + t]) {
 583:             /*
 584: 			 * Do arithmetic in a short to make up
 585: 			 * for lost 16&17 bits.
 586: 			 */
 587:             addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
 588:             cntr = addr->dmftba -
 589:                 UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
 590:             ndflush(&tp->t_outq, (int)cntr);
 591:         }
 592:         if (tp->t_line)
 593:             (*linesw[tp->t_line].l_start)(tp);
 594:         else
 595:             dmfstart(tp);
 596:     }
 597: }
 598: 
 599: /*
 600:  * Start (restart) transmission on the given DMF32 line.
 601:  */
 602: dmfstart(tp)
 603:     register struct tty *tp;
 604: {
 605:     register struct dmfdevice *addr;
 606:     register int unit, nch;
 607:     int s;
 608:     register int dmf;
 609: 
 610:     unit = minor(tp->t_dev);
 611:     dmf = unit >> 3;
 612:     unit &= 07;
 613:     addr = (struct dmfdevice *)tp->t_addr;
 614: 
 615:     /*
 616: 	 * Must hold interrupts in following code to prevent
 617: 	 * state of the tp from changing.
 618: 	 */
 619:     s = spltty();
 620:     /*
 621: 	 * If it's currently active, or delaying, no need to do anything.
 622: 	 */
 623:     if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
 624:         goto out;
 625:     /*
 626: 	 * If there are still characters in the silo,
 627: 	 * just reenable the transmitter.
 628: 	 */
 629:     addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
 630:     if (addr->dmftsc) {
 631:         addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
 632:         addr->dmflctms = addr->dmflctms | DMF_TE;
 633:         tp->t_state |= TS_BUSY;
 634:         goto out;
 635:     }
 636:     /*
 637: 	 * If there are sleepers, and output has drained below low
 638: 	 * water mark, wake up the sleepers.
 639: 	 */
 640:     if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
 641:         if (tp->t_state&TS_ASLEEP) {
 642:             tp->t_state &= ~TS_ASLEEP;
 643:             wakeup((caddr_t)&tp->t_outq);
 644:         }
 645:         if (tp->t_wsel) {
 646:             selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
 647:             tp->t_wsel = 0;
 648:             tp->t_state &= ~TS_WCOLL;
 649:         }
 650:     }
 651:     /*
 652: 	 * Now restart transmission unless the output queue is
 653: 	 * empty.
 654: 	 */
 655:     if (tp->t_outq.c_cc == 0)
 656:         goto out;
 657:     if (tp->t_flags & (RAW|LITOUT))
 658:         nch = ndqb(&tp->t_outq, 0);
 659:     else {
 660:         if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
 661:             /*
 662: 		 	* If first thing on queue is a delay process it.
 663: 		 	*/
 664:             nch = getc(&tp->t_outq);
 665:             timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
 666:             tp->t_state |= TS_TIMEOUT;
 667:             goto out;
 668:         }
 669:     }
 670:     /*
 671: 	 * If characters to transmit, restart transmission.
 672: 	 */
 673:     if (nch >= dmf_mindma) {
 674:         register car;
 675: 
 676:         dmf_dma[minor(tp->t_dev)] = 1;
 677:         addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
 678:         addr->dmflctms = addr->dmflctms | DMF_TE;
 679:         car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
 680:         addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
 681:         addr->dmftba = car;
 682:         addr->dmftcc = ((car >> 2) & 0xc000) | nch;
 683:         tp->t_state |= TS_BUSY;
 684:     } else if (nch) {
 685:         register char *cp = tp->t_outq.c_cf;
 686:         register int i;
 687: 
 688:         dmf_dma[minor(tp->t_dev)] = 0;
 689:         nch = MIN(nch, DMF_SILOCNT);
 690:         addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
 691:         addr->dmflctms = addr->dmflctms | DMF_TE;
 692:         addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
 693:         for (i = 0; i < nch; i++)
 694:             addr->dmftbuf = *cp++;
 695:         ndflush(&tp->t_outq, nch);
 696:         tp->t_state |= TS_BUSY;
 697:     }
 698: out:
 699:     splx(s);
 700: }
 701: 
 702: /*
 703:  * Stop output on a line, e.g. for ^S/^Q or output flush.
 704:  */
 705: /*ARGSUSED*/
 706: dmfstop(tp, flag)
 707:     register struct tty *tp;
 708: {
 709:     register struct dmfdevice *addr;
 710:     register unit = minor(tp->t_dev) & 7;
 711:     int s;
 712: 
 713:     addr = (struct dmfdevice *)tp->t_addr;
 714:     /*
 715: 	 * Block input/output interrupts while messing with state.
 716: 	 */
 717:     s = spltty();
 718:     if (flag) {
 719:         addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
 720:         if (addr->dmftsc) {
 721:             /*
 722: 			 * Flush regardless of whether we're transmitting
 723: 			 * (TS_BUSY), if the silo contains untransmitted
 724: 			 * characters.
 725: 			 */
 726:             addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
 727:             addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
 728:             /* this will interrupt so let dmfxint handle the rest */
 729:             tp->t_state |= TS_FLUSH|TS_BUSY;
 730:         }
 731:     } else {
 732:         if (tp->t_state & TS_BUSY) {
 733:             /*
 734: 			 * Stop transmission by disabling
 735: 			 * the transmitter.  We'll pick up where we
 736: 			 * left off by reenabling in dmfstart.
 737: 			 */
 738:             addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
 739:             addr->dmflctms = addr->dmflctms &~ DMF_TE;
 740:             /* no interrupt here */
 741:             tp->t_state &= ~TS_BUSY;
 742:         }
 743:     }
 744:     splx(s);
 745: }
 746: 
 747: /*
 748:  * DMF32 modem control
 749:  */
 750: dmfmctl(dev, bits, how)
 751:     dev_t dev;
 752:     int bits, how;
 753: {
 754:     register struct dmfdevice *dmfaddr;
 755:     register int unit, mbits, lcr;
 756:     int s;
 757: 
 758:     unit = minor(dev);
 759:     dmfaddr = (struct dmfdevice *)(dmf_tty[unit].t_addr);
 760:     unit &= 07;
 761:     s = spltty();
 762:     dmfaddr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
 763:     mbits = dmfaddr->dmfrms << 8;
 764:     dmfaddr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
 765:     lcr = dmfaddr->dmflctms;
 766:     mbits |= (lcr & 0xff00) >> 8;
 767:     switch (how) {
 768:     case DMSET:
 769:         mbits = (mbits &0xff00) | bits;
 770:         break;
 771: 
 772:     case DMBIS:
 773:         mbits |= bits;
 774:         break;
 775: 
 776:     case DMBIC:
 777:         mbits &= ~bits;
 778:         break;
 779: 
 780:     case DMGET:
 781:         (void) splx(s);
 782:         return(mbits);
 783:     }
 784:     if (mbits & DMF_BRK)
 785:         lcr |= DMF_RBRK;
 786:     else
 787:         lcr &= ~DMF_RBRK;
 788:     dmfaddr->dmflctms = ((mbits & 037) << 8) | (lcr & 0xff);
 789:     (void) splx(s);
 790:     return(mbits);
 791: }
 792: 
 793: /*
 794:  * Reset state of driver if UBA reset was necessary.
 795:  * Reset the csr, lpr, and lcr registers on open lines, and
 796:  * restart transmitters.
 797:  */
 798: dmfreset(uban)
 799:     int uban;
 800: {
 801:     register int dmf, unit;
 802:     register struct tty *tp;
 803:     register struct uba_device *ui;
 804:     register struct dmfdevice *addr;
 805:     int i;
 806: 
 807:     for (dmf = 0; dmf < NDMF; dmf++) {
 808:         ui = dmfinfo[dmf];
 809:         if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
 810:             continue;
 811:         printf(" dmf%d", dmf);
 812:         if (dmf_ubinfo[uban]) {
 813:             dmf_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
 814:                 nclist*sizeof (struct cblock), 0);
 815:             cbase[uban] = UBAI_ADDR(dmf_ubinfo[uban]);
 816:         }
 817:         addr = (struct dmfdevice *)ui->ui_addr;
 818:         addr->dmfcsr = DMF_IE;
 819:         addr->dmfrsp = dmf_timeout;
 820:         unit = dmf * 8;
 821:         for (i = 0; i < 8; i++) {
 822:             tp = &dmf_tty[unit];
 823:             if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
 824:                 dmfparam(unit);
 825:                 (void) dmfmctl(unit, DMF_ON, DMSET);
 826:                 tp->t_state &= ~TS_BUSY;
 827:                 dmfstart(tp);
 828:             }
 829:             unit++;
 830:         }
 831:     }
 832: }
 833: 
 834: /*
 835:  * dmflopen -- open the line printer port on a dmf32
 836:  */
 837: /* ARGSUSED */
 838: dmflopen(dev, flag)
 839:     dev_t dev;
 840:     int flag;
 841: {
 842:     register int dmf;
 843:     register struct dmfl_softc *sc;
 844:     register struct uba_device *ui;
 845:     register struct dmfdevice *addr;
 846: 
 847:     dmf = DMFL_UNIT(dev);
 848:     if (dmf >= NDMF || (ui = dmfinfo[dmf]) == 0 || ui->ui_alive == 0)
 849:         return (ENXIO);
 850:     sc = &dmfl_softc[dmf];
 851:     if (sc->dmfl_state & OPEN)
 852:         return (EBUSY);
 853:     addr = (struct dmfdevice *)ui->ui_addr;
 854:     if (addr->dmfl_ctrl & DMFL_OFFLINE) {
 855: #ifdef notdef
 856:         log(LOG_WARNING, "dmf%d: line printer offline/jammed\n",
 857:             dmf);
 858: #endif
 859:         return (EIO);
 860:     }
 861:     if ((addr->dmfl_ctrl & DMFL_CONV)) {
 862:         log(LOG_WARNING, "dmf%d: line printer disconnected\n", dmf);
 863:         return (EIO);
 864:     }
 865: 
 866:     addr->dmfl_ctrl = 0;
 867:     sc->dmfl_state |= OPEN;
 868:     return (0);
 869: }
 870: 
 871: /* ARGSUSED */
 872: dmflclose(dev, flag)
 873:     dev_t dev;
 874:     int flag;
 875: {
 876:     register int dmf = DMFL_UNIT(dev);
 877:     register struct dmfl_softc *sc = &dmfl_softc[dmf];
 878:     register struct uba_device *ui = dmfinfo[dmf];
 879: 
 880:     sc->dmfl_state = 0;
 881:     if (sc->dmfl_info != 0)
 882:         ubarelse((int)ui->ui_ubanum, &sc->dmfl_info);
 883: 
 884:     ((struct dmfdevice *)ui->ui_addr)->dmfl_ctrl = 0;
 885: }
 886: 
 887: dmflwrite(dev, uio)
 888:     dev_t dev;
 889:     struct uio *uio;
 890: {
 891:     register int n;
 892:     register int error;
 893:     register struct dmfl_softc *sc;
 894: 
 895:     sc = &dmfl_softc[DMFL_UNIT(dev)];
 896:     if (sc->dmfl_state & ERROR)
 897:         return (EIO);
 898:     while (n = (unsigned)uio->uio_resid) {
 899:         if (n > DMFL_BUFSIZ) {
 900:             n = DMFL_BUFSIZ;
 901:             sc->dmfl_state |= MOREIO;
 902:         } else
 903:             sc->dmfl_state &= ~MOREIO;
 904:         if (error = uiomove(sc->dmfl_buf, (int)n, UIO_WRITE, uio))
 905:             return (error);
 906:         if (error = dmflout(dev, sc->dmfl_buf, n))
 907:             return (error);
 908:     }
 909:     return (0);
 910: }
 911: 
 912: 
 913: /*
 914:  * dmflout -- start io operation to dmf line printer
 915:  *		cp is addr of buf of n chars to be sent.
 916:  *
 917:  *	-- dmf will be put in formatted output mode, this will
 918:  *		be selectable from an ioctl if the
 919:  *		need ever arises.
 920:  */
 921: dmflout(dev, cp, n)
 922:     dev_t dev;
 923:     char *cp;
 924:     int n;
 925: {
 926:     register struct dmfl_softc *sc;
 927:     register int dmf;
 928:     register struct uba_device *ui;
 929:     register struct dmfdevice *d;
 930:     int s;
 931: 
 932:     dmf = DMFL_UNIT(dev);
 933:     sc = &dmfl_softc[dmf];
 934:     if (sc->dmfl_state & ERROR)
 935:         return (EIO);
 936:     ui = dmfinfo[dmf];
 937:     /*
 938: 	 * allocate unibus resources, will be released when io
 939: 	 * operation is done.
 940: 	 */
 941:     if (sc->dmfl_info == 0)
 942:         sc->dmfl_info = uballoc(ui->ui_ubanum, cp, n, 0);
 943:     d = (struct dmfdevice *)ui->ui_addr;
 944:     d->dmfl_ctrl = sc->dmfl_format;     /* indir reg 2 */
 945:     /* indir reg auto increments on r/w */
 946:     /* SO DON'T CHANGE THE ORDER OF THIS CODE */
 947:     d->dmfl_indrct = 0;         /* prefix chars & num */
 948:     d->dmfl_indrct = 0;         /* suffix chars & num */
 949:     d->dmfl_indrct = sc->dmfl_info;     /* dma lo 16 bits addr */
 950:     d->dmfl_indrct = -n;            /* number of chars */
 951: 
 952:     d->dmfl_indrct = ((sc->dmfl_info>>16)&3) | DMFL_OPTIONS;
 953:                         /* dma hi 2 bits addr */
 954:     d->dmfl_indrct = sc->dmfl_lines     /* lines per page */
 955:         | (sc->dmfl_cols<<8);       /* carriage width */
 956:     sc->dmfl_state |= ASLP;
 957:     s = spltty();
 958:     d->dmfl_ctrl |= DMFL_PEN | DMFL_IE;
 959:     while (sc->dmfl_state & ASLP) {
 960:         sleep(sc->dmfl_buf, PZERO + 8);
 961:         while (sc->dmfl_state & ERROR) {
 962:             timeout(dmflint, (caddr_t)dmf, 10 * hz);
 963:             sleep((caddr_t)&sc->dmfl_state, PZERO + 8);
 964:         }
 965:     }
 966:     splx(s);
 967:     return (0);
 968: }
 969: 
 970: /*
 971:  * dmflint -- handle an interrupt from the line printer part of the dmf32
 972:  */
 973: dmflint(dmf)
 974:     int dmf;
 975: {
 976:     register struct uba_device *ui;
 977:     register struct dmfl_softc *sc;
 978:     register struct dmfdevice *d;
 979:     short dmfl_stats;
 980: 
 981:     ui = dmfinfo[dmf];
 982:     sc = &dmfl_softc[dmf];
 983:     d = (struct dmfdevice *)ui->ui_addr;
 984: 
 985:     d->dmfl_ctrl &= ~DMFL_IE;
 986:     dmfl_stats = d->dmfl_ctrl;
 987:     if (sc->dmfl_state & ERROR) {
 988:         if ((dmfl_stats & DMFL_OFFLINE) == 0)
 989:             sc->dmfl_state &= ~ERROR;
 990:         wakeup((caddr_t)&sc->dmfl_state);
 991:         return;
 992:     }
 993:     if (dmfl_stats & DMFL_DMAERR)
 994:         log(LOG_WARNING, "dmf%d: NXM\n", dmf);
 995:     if (dmfl_stats & DMFL_OFFLINE) {
 996:         log(LOG_WARNING, "dmf%d: printer error\n", dmf);
 997:         sc->dmfl_state |= ERROR;
 998:     }
 999: #ifdef notdef
1000:     if (dmfl_stats & DMFL_PDONE) {
1001:         printf("bytes= %d\n", d->dmfl_indrct);
1002:         printf("lines= %d\n", d->dmfl_indrct);
1003:     }
1004: #endif
1005:     sc->dmfl_state &= ~ASLP;
1006:     wakeup((caddr_t)sc->dmfl_buf);
1007:     if (sc->dmfl_info && (sc->dmfl_state & MOREIO) == 0)
1008:         ubarelse(ui->ui_ubanum, &sc->dmfl_info);
1009: }
1010: 
1011: /* stubs for interrupt routines for devices not yet supported */
1012: 
1013: dmfsrint()
1014: {
1015:     printf("dmfsrint\n");
1016: }
1017: 
1018: dmfsxint()
1019: {
1020:     printf("dmfsxint\n");
1021: }
1022: 
1023: dmfdaint()
1024: {
1025:     printf("dmfdaint\n");
1026: }
1027: 
1028: dmfdbint()
1029: {
1030:     printf("dmfdbint\n");
1031: }
1032: #endif NDMF

Defined functions

dmfattach defined in line 200; used 2 times
dmfclose defined in line 301; never used
dmfdaint defined in line 1023; used 2 times
dmfdbint defined in line 1028; used 2 times
dmfioctl defined in line 425; never used
dmflclose defined in line 872; used 1 times
dmflint defined in line 973; used 4 times
dmflopen defined in line 838; used 1 times
dmflout defined in line 921; used 1 times
dmflwrite defined in line 887; used 1 times
dmfmctl defined in line 750; used 13 times
dmfopen defined in line 223; never used
dmfparam defined in line 514; used 3 times
dmfprobe defined in line 131; used 2 times
dmfread defined in line 322; never used
dmfreset defined in line 798; never used
dmfrint defined in line 349; used 3 times
dmfsrint defined in line 1013; used 2 times
dmfstart defined in line 602; used 4 times
dmfstop defined in line 706; never used
dmfsxint defined in line 1018; used 2 times
dmftodm defined in line 498; used 1 times
dmfwrite defined in line 334; never used
dmfxint defined in line 560; used 3 times
dmtodmf defined in line 486; used 3 times

Defined variables

cbase defined in line 123; used 5 times
dmf_dma defined in line 125; used 3 times
dmf_mindma defined in line 72; used 1 times
dmf_speeds defined in line 77; used 2 times
  • in line 536(2)
dmf_timeout defined in line 71; used 2 times
dmf_tty defined in line 88; used 10 times
dmf_ubinfo defined in line 122; used 5 times
dmfact defined in line 114; used 2 times
dmfdriver defined in line 68; used 1 times
dmfinfo defined in line 66; used 10 times
dmfl_softc defined in line 98; used 9 times
dmfsoftCAR defined in line 89; used 3 times
dmfstd defined in line 67; used 1 times
  • in line 69
ndmf defined in line 112; never used

Defined struct's

dmfl_softc defined in line 91; used 10 times

Defined macros

ASLP defined in line 105; used 3 times
DMFL_UNIT defined in line 103; used 4 times
ERROR defined in line 107; used 6 times
IFLAGS defined in line 85; used 1 times
ISPEED defined in line 84; used 2 times
MOREIO defined in line 109; used 3 times
OPEN defined in line 106; used 2 times
UBACVT defined in line 124; used 2 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3370
Valid CSS Valid XHTML 1.0 Strict