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