|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.