|
|
1.1 ! root 1: /* ! 2: * This file is derived from version 7.2 of the VX driver to create ! 3: * a driver compatible with the 4.3BSD-tahoe release. ! 4: */ ! 5: ! 6: /* ! 7: * Copyright (c) 1988 Regents of the University of California. ! 8: * All rights reserved. ! 9: * ! 10: * This code is derived from software contributed to Berkeley by ! 11: * Computer Consoles Inc. ! 12: * ! 13: * Redistribution and use in source and binary forms are permitted ! 14: * provided that the above copyright notice and this paragraph are ! 15: * duplicated in all such forms and that any documentation, ! 16: * advertising materials, and other materials related to such ! 17: * distribution and use acknowledge that the software was developed ! 18: * by the University of California, Berkeley. The name of the ! 19: * University may not be used to endorse or promote products derived ! 20: * from this software without specific prior written permission. ! 21: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 22: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 23: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 24: * ! 25: * @(#)vx.c 7.2 (Berkeley) 7/9/88 ! 26: */ ! 27: ! 28: #include "vx.h" ! 29: #if NVX > 0 ! 30: /* ! 31: * VIOC-X driver ! 32: */ ! 33: #ifdef VXPERF ! 34: #define DOSCOPE ! 35: #endif ! 36: ! 37: #include "param.h" ! 38: #include "ioctl.h" ! 39: #include "tty.h" ! 40: #include "dir.h" ! 41: #include "user.h" ! 42: #include "map.h" ! 43: #include "buf.h" ! 44: #include "conf.h" ! 45: #include "file.h" ! 46: #include "uio.h" ! 47: #include "proc.h" ! 48: #include "vm.h" ! 49: #include "kernel.h" ! 50: #include "syslog.h" ! 51: ! 52: #include "../tahoe/pte.h" ! 53: ! 54: #include "../tahoevba/vbavar.h" ! 55: #include "../tahoevba/vbaparam.h" ! 56: #include "../tahoevba/vxreg.h" ! 57: #include "../tahoevba/scope.h" ! 58: ! 59: #ifdef VX_DEBUG ! 60: long vxintr4 = 0; ! 61: #define VXERR4 1 ! 62: #define VXNOBUF 2 ! 63: long vxdebug = 0; ! 64: #define VXVCM 1 ! 65: #define VXVCC 2 ! 66: #define VXVCX 4 ! 67: #endif ! 68: ! 69: /* ! 70: * Interrupt type bits passed to vinthandl(). ! 71: */ ! 72: #define CMDquals 0 /* command completed interrupt */ ! 73: #define RSPquals 1 /* command response interrupt */ ! 74: #define UNSquals 2 /* unsolicited interrupt */ ! 75: ! 76: #define VXUNIT(n) ((n) >> 4) ! 77: #define VXPORT(n) ((n) & 0xf) ! 78: ! 79: struct tty vx_tty[NVX*16]; ! 80: #ifndef lint ! 81: int nvx = NVX*16; ! 82: #endif ! 83: int vxstart(), ttrstrt(); ! 84: struct vxcmd *vobtain(), *nextcmd(); ! 85: ! 86: /* ! 87: * Driver information for auto-configuration stuff. ! 88: */ ! 89: int vxprobe(), vxattach(), vxrint(); ! 90: struct vba_device *vxinfo[NVX]; ! 91: long vxstd[] = { 0 }; ! 92: struct vba_driver vxdriver = ! 93: { vxprobe, 0, vxattach, 0, vxstd, "vx", vxinfo }; ! 94: ! 95: struct vx_softc { ! 96: u_char vs_type; /* 0: viox-x/vioc-b, 1: vioc-bop */ ! 97: u_char vs_bop; /* bop board # for vioc-bop's */ ! 98: u_char vs_loport; /* low port nbr */ ! 99: u_char vs_hiport; /* high port nbr */ ! 100: u_short vs_nbr; /* viocx number */ ! 101: u_short vs_maxcmd; /* max number of concurrent cmds */ ! 102: u_short vs_silosiz; /* silo size */ ! 103: short vs_vers; /* vioc/pvioc version */ ! 104: #define VXV_OLD 0 /* PVIOCX | VIOCX */ ! 105: #define VXV_NEW 1 /* NPVIOCX | NVIOCX */ ! 106: short vs_xmtcnt; /* xmit commands pending */ ! 107: short vs_brkreq; /* send break requests pending */ ! 108: short vs_state; /* controller state */ ! 109: #define VXS_READY 0 /* ready for commands */ ! 110: #define VXS_RESET 1 /* in process of reseting */ ! 111: u_short vs_softCAR; /* soft carrier */ ! 112: caddr_t vs_mricmd; /* most recent issued cmd */ ! 113: u_int vs_ivec; /* interrupt vector base */ ! 114: struct vxcmd *vs_avail;/* next available command buffer */ ! 115: struct vxcmd *vs_build; ! 116: struct vxcmd vs_lst[NVCXBUFS]; ! 117: struct vcmds vs_cmds; ! 118: } vx_softc[NVX]; ! 119: ! 120: vxprobe(reg, vi) ! 121: caddr_t reg; ! 122: struct vba_device *vi; ! 123: { ! 124: register int br, cvec; /* must be r12, r11 */ ! 125: register struct vxdevice *vp; ! 126: register struct vx_softc *vs; ! 127: struct pte *dummypte; ! 128: ! 129: #ifdef lint ! 130: br = 0; cvec = br; br = cvec; ! 131: vackint(0); vunsol(0); vcmdrsp(0); vxfreset(0); ! 132: #endif ! 133: if (!VBIOMAPPED(reg) && !vbmemalloc(16, reg, &dummypte, ®)) { ! 134: printf("vx%d: vbmemalloc failed.\n", vi->ui_unit); ! 135: return(0); ! 136: } ! 137: vp = (struct vxdevice *)reg; ! 138: if (badaddr((caddr_t)vp, 1)) ! 139: return (0); ! 140: vi->ui_addr = reg; ! 141: vp->v_fault = 0; ! 142: vp->v_vioc = V_BSY; ! 143: vp->v_hdwre = V_RESET; /* reset interrupt */ ! 144: DELAY(4000000); ! 145: if (vp->v_fault != VXF_READY) ! 146: return (0); ! 147: vs = &vx_softc[vi->ui_unit]; ! 148: #ifdef notdef ! 149: /* ! 150: * Align vioc interrupt vector base to 4 vector ! 151: * boundary and fitting in 8 bits (is this necessary, ! 152: * wish we had documentation). ! 153: */ ! 154: if ((vi->ui_hd->vh_lastiv -= 3) > 0xff) ! 155: vi->ui_hd->vh_lastiv = 0xff; ! 156: vs->vs_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x3; ! 157: #else ! 158: vs->vs_ivec = 0x40+vi->ui_unit*4; ! 159: #endif ! 160: br = 0x18, cvec = vs->vs_ivec; /* XXX */ ! 161: return (sizeof (struct vxdevice)); ! 162: } ! 163: ! 164: vxattach(vi) ! 165: register struct vba_device *vi; ! 166: { ! 167: ! 168: vx_softc[vi->ui_unit].vs_softCAR = vi->ui_flags; ! 169: vxinit(vi->ui_unit, 1); ! 170: } ! 171: ! 172: /* ! 173: * Open a VX line. ! 174: */ ! 175: /*ARGSUSED*/ ! 176: vxopen(dev, flag) ! 177: dev_t dev; ! 178: int flag; ! 179: { ! 180: register struct tty *tp; /* pointer to tty struct for port */ ! 181: register struct vx_softc *vs; ! 182: register struct vba_device *vi; ! 183: int unit, vx, s, error; ! 184: ! 185: unit = minor(dev); ! 186: vx = VXUNIT(unit); ! 187: if (vx >= NVX || (vi = vxinfo[vx])== 0 || vi->ui_alive == 0) ! 188: return (ENXIO); ! 189: vs = &vx_softc[vx]; ! 190: tp = &vx_tty[unit]; ! 191: unit = VXPORT(unit); ! 192: if (tp->t_state&TS_XCLUDE && u.u_uid != 0) ! 193: return (EBUSY); ! 194: if (unit < vs->vs_loport || unit > vs->vs_hiport) ! 195: return (ENXIO); ! 196: tp->t_addr = (caddr_t)vs; ! 197: tp->t_oproc = vxstart; ! 198: tp->t_dev = dev; ! 199: s = spl8(); ! 200: tp->t_state |= TS_WOPEN; ! 201: if ((tp->t_state&TS_ISOPEN) == 0) { ! 202: ttychars(tp); ! 203: if (tp->t_ispeed == 0) { ! 204: tp->t_ispeed = SSPEED; ! 205: tp->t_ospeed = SSPEED; ! 206: tp->t_flags |= ODDP|EVENP|ECHO; ! 207: } ! 208: vxparam(dev); ! 209: } ! 210: vcmodem(dev, VMOD_ON); ! 211: while ((tp->t_state&TS_CARR_ON) == 0) ! 212: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 213: error = (*linesw[tp->t_line].l_open)(dev,tp); ! 214: splx(s); ! 215: return (error); ! 216: } ! 217: ! 218: /* ! 219: * Close a VX line. ! 220: */ ! 221: /*ARGSUSED*/ ! 222: vxclose(dev, flag) ! 223: dev_t dev; ! 224: int flag; ! 225: { ! 226: register struct tty *tp; ! 227: int unit, s; ! 228: ! 229: unit = minor(dev); ! 230: tp = &vx_tty[unit]; ! 231: s = spl8(); ! 232: (*linesw[tp->t_line].l_close)(tp); ! 233: if (tp->t_state & TS_HUPCLS || (tp->t_state & TS_ISOPEN) == 0) ! 234: vcmodem(dev, VMOD_OFF); ! 235: /* wait for the last response */ ! 236: while (tp->t_state&TS_FLUSH) ! 237: sleep((caddr_t)&tp->t_state, TTOPRI); ! 238: ttyclose(tp); ! 239: splx(s); ! 240: } ! 241: ! 242: /* ! 243: * Read from a VX line. ! 244: */ ! 245: vxread(dev, uio) ! 246: dev_t dev; ! 247: struct uio *uio; ! 248: { ! 249: struct tty *tp = &vx_tty[minor(dev)]; ! 250: ! 251: return ((*linesw[tp->t_line].l_read)(tp, uio)); ! 252: } ! 253: ! 254: /* ! 255: * write on a VX line ! 256: */ ! 257: vxwrite(dev, uio) ! 258: dev_t dev; ! 259: struct uio *uio; ! 260: { ! 261: register struct tty *tp = &vx_tty[minor(dev)]; ! 262: ! 263: return ((*linesw[tp->t_line].l_write)(tp, uio)); ! 264: } ! 265: ! 266: /* ! 267: * VIOCX unsolicited interrupt. ! 268: */ ! 269: vxrint(vx) ! 270: register vx; ! 271: { ! 272: register struct tty *tp, *tp0; ! 273: register struct vxdevice *addr; ! 274: register struct vx_softc *vs; ! 275: struct vba_device *vi; ! 276: register int nc, c; ! 277: register struct silo { ! 278: char data, port; ! 279: } *sp; ! 280: short *osp; ! 281: int overrun = 0; ! 282: ! 283: vi = vxinfo[vx]; ! 284: if (vi == 0 || vi->ui_alive == 0) ! 285: return; ! 286: addr = (struct vxdevice *)vi->ui_addr; ! 287: switch (addr->v_uqual&037) { ! 288: case 0: ! 289: break; ! 290: case 2: ! 291: printf("vx%d: vc proc err, ustat %x\n", vx, addr->v_ustat); ! 292: vxstreset(vx); ! 293: return; ! 294: case 3: ! 295: vcmintr(vx); ! 296: return; ! 297: case 4: ! 298: return; ! 299: default: ! 300: printf("vx%d: vc uqual err, uqual %x\n", vx, addr->v_uqual); ! 301: vxstreset(vx); ! 302: return; ! 303: } ! 304: vs = &vx_softc[vx]; ! 305: if (vs->vs_vers == VXV_NEW) ! 306: sp = (struct silo *)((caddr_t)addr + *(short *)addr->v_usdata); ! 307: else ! 308: sp = (struct silo *)((caddr_t)addr+VX_SILO+(addr->v_usdata[0]<<6)); ! 309: nc = *(osp = (short *)sp); ! 310: if (nc == 0) ! 311: return; ! 312: if (vs->vs_vers == VXV_NEW && nc > vs->vs_silosiz) { ! 313: printf("vx%d: %d exceeds silo size\n", nc); ! 314: nc = vs->vs_silosiz; ! 315: } ! 316: tp0 = &vx_tty[vx*16]; ! 317: sp = (struct silo *)(((short *)sp)+1); ! 318: for (; nc > 0; nc--, sp = (struct silo *)(((short *)sp)+1)) { ! 319: c = sp->port & 017; ! 320: if (vs->vs_loport > c || c > vs->vs_hiport) ! 321: continue; ! 322: tp = tp0 + c; ! 323: if( (tp->t_state&TS_ISOPEN) == 0) { ! 324: wakeup((caddr_t)&tp->t_rawq); ! 325: continue; ! 326: } ! 327: c = sp->data; ! 328: if ((sp->port&VX_RO) == VX_RO && !overrun) { ! 329: log(LOG_ERR, "vx%d: receiver overrun\n", vi->ui_unit); ! 330: overrun = 1; ! 331: continue; ! 332: } ! 333: if (sp->port&VX_PE) ! 334: if ((tp->t_flags&(EVENP|ODDP)) == EVENP || ! 335: (tp->t_flags&(EVENP|ODDP)) == ODDP) ! 336: continue; ! 337: if ((tp->t_flags & (RAW | PASS8)) == 0) ! 338: c &= 0177; ! 339: if (sp->port&VX_FE) { ! 340: /* ! 341: * At framing error (break) generate ! 342: * a null (in raw mode, for getty), or a ! 343: * interrupt (in cooked/cbreak mode). ! 344: */ ! 345: if (tp->t_flags&RAW) ! 346: c = 0; ! 347: else ! 348: c = tp->t_intrc; ! 349: } ! 350: (*linesw[tp->t_line].l_rint)(c, tp); ! 351: } ! 352: *osp = 0; ! 353: } ! 354: ! 355: /* ! 356: * Ioctl for VX. ! 357: */ ! 358: vxioctl(dev, cmd, data, flag) ! 359: dev_t dev; ! 360: caddr_t data; ! 361: { ! 362: register struct tty *tp; ! 363: int error; ! 364: ! 365: tp = &vx_tty[minor(dev)]; ! 366: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 367: if (error == 0) ! 368: return (error); ! 369: error = ttioctl(tp, cmd, data, flag); ! 370: if (error >= 0) { ! 371: if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS || ! 372: cmd == TIOCLBIC || cmd == TIOCLSET) ! 373: vxparam(dev); ! 374: return (error); ! 375: } ! 376: return (ENOTTY); ! 377: } ! 378: ! 379: vxparam(dev) ! 380: dev_t dev; ! 381: { ! 382: ! 383: vxcparam(dev, 1); ! 384: } ! 385: ! 386: /* ! 387: * Set parameters from open or stty into the VX hardware ! 388: * registers. ! 389: */ ! 390: vxcparam(dev, wait) ! 391: dev_t dev; ! 392: int wait; ! 393: { ! 394: register struct tty *tp; ! 395: register struct vx_softc *vs; ! 396: register struct vxcmd *cp; ! 397: int s, unit = minor(dev); ! 398: ! 399: tp = &vx_tty[unit]; ! 400: if ((tp->t_ispeed)==0) { ! 401: tp->t_state |= TS_HUPCLS; ! 402: vcmodem(dev, VMOD_OFF); ! 403: return; ! 404: } ! 405: vs = (struct vx_softc *)tp->t_addr; ! 406: cp = vobtain(vs); ! 407: s = spl8(); ! 408: /* ! 409: * Construct ``load parameters'' command block ! 410: * to setup baud rates, xon-xoff chars, parity, ! 411: * and stop bits for the specified port. ! 412: */ ! 413: cp->cmd = VXC_LPARAX; ! 414: cp->par[1] = VXPORT(unit); ! 415: cp->par[2] = (tp->t_flags&RAW) ? 0 : tp->t_startc; ! 416: cp->par[3] = (tp->t_flags&RAW) ? 0 : tp->t_stopc; ! 417: #ifdef notnow ! 418: if (tp->t_flags & (RAW|LITOUT|PASS8)) { ! 419: #endif ! 420: cp->par[4] = BITS8; /* 8 bits of data */ ! 421: cp->par[7] = VNOPARITY; /* no parity */ ! 422: #ifdef notnow ! 423: } else { ! 424: cp->par[4] = BITS7; /* 7 bits of data */ ! 425: if ((tp->t_flags&(EVENP|ODDP)) == ODDP) ! 426: cp->par[7] = VODDP; /* odd parity */ ! 427: else ! 428: cp->par[7] = VEVENP; /* even parity */ ! 429: } ! 430: #endif ! 431: if (tp->t_ospeed == B110) ! 432: cp->par[5] = VSTOP2; /* 2 stop bits */ ! 433: else ! 434: cp->par[5] = VSTOP1; /* 1 stop bit */ ! 435: if (tp->t_ospeed == EXTA || tp->t_ospeed == EXTB) ! 436: cp->par[6] = V19200; ! 437: else ! 438: cp->par[6] = tp->t_ospeed; ! 439: if (vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd) && wait) ! 440: sleep((caddr_t)cp,TTIPRI); ! 441: splx(s); ! 442: } ! 443: ! 444: /* ! 445: * VIOCX command response interrupt. ! 446: * For transmission, restart output to any active port. ! 447: * For all other commands, just clean up. ! 448: */ ! 449: vxxint(vx, cp) ! 450: register int vx; ! 451: register struct vxcmd *cp; ! 452: { ! 453: register struct vxmit *vp; ! 454: register struct tty *tp, *tp0; ! 455: register struct vx_softc *vs; ! 456: ! 457: vs = &vx_softc[vx]; ! 458: cp = (struct vxcmd *)((long *)cp-1); ! 459: ! 460: switch (cp->cmd&0xff00) { ! 461: ! 462: case VXC_LIDENT: /* initialization complete */ ! 463: if (vs->vs_state == VXS_RESET) { ! 464: vxfnreset(vx, cp); ! 465: vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR); ! 466: } ! 467: cp->cmd++; ! 468: return; ! 469: ! 470: case VXC_XMITDTA: ! 471: case VXC_XMITIMM: ! 472: break; ! 473: ! 474: case VXC_LPARAX: ! 475: wakeup((caddr_t)cp); ! 476: /* fall thru... */ ! 477: default: /* VXC_MDMCTL or VXC_FDTATOX */ ! 478: vrelease(vs, cp); ! 479: if (vs->vs_state == VXS_RESET) ! 480: vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR); ! 481: return; ! 482: } ! 483: tp0 = &vx_tty[vx*16]; ! 484: vp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit)); ! 485: for (; vp >= (struct vxmit *)cp->par; vp--) { ! 486: tp = tp0 + (vp->line & 017); ! 487: tp->t_state &= ~TS_BUSY; ! 488: if (tp->t_state & TS_FLUSH) { ! 489: tp->t_state &= ~TS_FLUSH; ! 490: wakeup((caddr_t)&tp->t_state); ! 491: } else ! 492: ndflush(&tp->t_outq, vp->bcount+1); ! 493: } ! 494: vrelease(vs, cp); ! 495: if (vs->vs_vers == VXV_NEW) ! 496: (*linesw[tp->t_line].l_start)(tp); ! 497: else { ! 498: tp0 = &vx_tty[vx*16 + vs->vs_hiport]; ! 499: for(tp = &vx_tty[vx*16 + vs->vs_loport]; tp <= tp0; tp++) ! 500: (*linesw[tp->t_line].l_start)(tp); ! 501: if ((cp = nextcmd(vs)) != NULL) { /* command to send? */ ! 502: vs->vs_xmtcnt++; ! 503: (void) vcmd(vx, (caddr_t)&cp->cmd); ! 504: } ! 505: } ! 506: vs->vs_xmtcnt--; ! 507: } ! 508: ! 509: /* ! 510: * Force out partial XMIT command after timeout ! 511: */ ! 512: vxforce(vs) ! 513: register struct vx_softc *vs; ! 514: { ! 515: register struct vxcmd *cp; ! 516: int s; ! 517: ! 518: s = spl8(); ! 519: if ((cp = nextcmd(vs)) != NULL) { ! 520: vs->vs_xmtcnt++; ! 521: (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd); ! 522: } ! 523: splx(s); ! 524: } ! 525: ! 526: /* ! 527: * Start (restart) transmission on the given VX line. ! 528: */ ! 529: vxstart(tp) ! 530: register struct tty *tp; ! 531: { ! 532: register short n; ! 533: register struct vx_softc *vs; ! 534: int s, port; ! 535: ! 536: s = spl8(); ! 537: port = minor(tp->t_dev) & 017; ! 538: vs = (struct vx_softc *)tp->t_addr; ! 539: if ((tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) == 0) { ! 540: if (tp->t_outq.c_cc <= TTLOWAT(tp)) { ! 541: if (tp->t_state&TS_ASLEEP) { ! 542: tp->t_state &= ~TS_ASLEEP; ! 543: wakeup((caddr_t)&tp->t_outq); ! 544: } ! 545: if (tp->t_wsel) { ! 546: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); ! 547: tp->t_wsel = 0; ! 548: tp->t_state &= ~TS_WCOLL; ! 549: } ! 550: } ! 551: if (tp->t_outq.c_cc == 0) { ! 552: splx(s); ! 553: return; ! 554: } ! 555: scope_out(3); ! 556: if (tp->t_flags & (RAW|LITOUT)) ! 557: n = ndqb(&tp->t_outq, 0); ! 558: else { ! 559: n = ndqb(&tp->t_outq, 0200); ! 560: if (n == 0) { ! 561: n = getc(&tp->t_outq); ! 562: timeout(ttrstrt, (caddr_t)tp, (n&0177)+6); ! 563: tp->t_state |= TS_TIMEOUT; ! 564: n = 0; ! 565: } ! 566: } ! 567: if (n) { ! 568: tp->t_state |= TS_BUSY; ! 569: vsetq(vs, port, (char *)tp->t_outq.c_cf, n); ! 570: } ! 571: } ! 572: splx(s); ! 573: } ! 574: ! 575: /* ! 576: * Stop output on a line. ! 577: */ ! 578: vxstop(tp) ! 579: register struct tty *tp; ! 580: { ! 581: int s; ! 582: ! 583: s = spl8(); ! 584: if (tp->t_state&TS_BUSY) ! 585: if ((tp->t_state&TS_TTSTOP) == 0) ! 586: tp->t_state |= TS_FLUSH; ! 587: splx(s); ! 588: } ! 589: ! 590: static int vxbbno = -1; ! 591: /* ! 592: * VIOCX Initialization. Makes free lists of command buffers. ! 593: * Resets all viocx's. Issues a LIDENT command to each ! 594: * viocx to establish interrupt vectors and logical port numbers. ! 595: */ ! 596: vxinit(vx, wait) ! 597: register int vx; ! 598: int wait; ! 599: { ! 600: register struct vx_softc *vs; ! 601: register struct vxdevice *addr; ! 602: register struct vxcmd *cp; ! 603: register char *resp; ! 604: register int j; ! 605: char type, *typestring; ! 606: ! 607: vs = &vx_softc[vx]; ! 608: vs->vs_type = 0; /* vioc-x by default */ ! 609: addr = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 610: type = addr->v_ident; ! 611: vs->vs_vers = (type&VXT_NEW) ? VXV_NEW : VXV_OLD; ! 612: if (vs->vs_vers == VXV_NEW) ! 613: vs->vs_silosiz = addr->v_maxsilo; ! 614: switch (type) { ! 615: ! 616: case VXT_VIOCX: ! 617: case VXT_VIOCX|VXT_NEW: ! 618: typestring = "VIOC-X"; ! 619: /* set soft carrier for printer ports */ ! 620: for (j = 0; j < 16; j++) ! 621: if (addr->v_portyp[j] == VXT_PARALLEL) { ! 622: vs->vs_softCAR |= 1 << j; ! 623: addr->v_dcd |= 1 << j; ! 624: } ! 625: break; ! 626: ! 627: case VXT_PVIOCX: ! 628: case VXT_PVIOCX|VXT_NEW: ! 629: typestring = "VIOC-X (old connector panel)"; ! 630: break; ! 631: case VXT_VIOCBOP: /* VIOC-BOP */ ! 632: vs->vs_type = 1; ! 633: vs->vs_bop = ++vxbbno; ! 634: printf("VIOC-BOP no. %d at %x\n", vs->vs_bop, addr); ! 635: ! 636: default: ! 637: printf("vx%d: unknown type %x\n", vx, type); ! 638: vxinfo[vx]->ui_alive = 0; ! 639: return; ! 640: } ! 641: vs->vs_nbr = -1; ! 642: vs->vs_maxcmd = (vs->vs_vers == VXV_NEW) ? 24 : 4; ! 643: /* ! 644: * Initialize all cmd buffers by linking them ! 645: * into a free list. ! 646: */ ! 647: for (j = 0; j < NVCXBUFS; j++) { ! 648: cp = &vs->vs_lst[j]; ! 649: cp->c_fwd = &vs->vs_lst[j+1]; ! 650: } ! 651: vs->vs_avail = &vs->vs_lst[0]; /* set idx to 1st free buf */ ! 652: cp->c_fwd = (struct vxcmd *)0; /* mark last buf in free list */ ! 653: ! 654: /* ! 655: * Establish the interrupt vectors and define the port numbers. ! 656: */ ! 657: cp = vobtain(vs); ! 658: cp->cmd = VXC_LIDENT; ! 659: cp->par[0] = vs->vs_ivec; /* ack vector */ ! 660: cp->par[1] = cp->par[0]+1; /* cmd resp vector */ ! 661: cp->par[3] = cp->par[0]+2; /* unsol intr vector */ ! 662: cp->par[4] = 15; /* max ports, no longer used */ ! 663: cp->par[5] = 0; /* set 1st port number */ ! 664: (void) vcmd(vx, (caddr_t)&cp->cmd); ! 665: if (!wait) ! 666: return; ! 667: for (j = 0; cp->cmd == VXC_LIDENT && j < 4000000; j++) ! 668: ; ! 669: if (j >= 4000000) ! 670: printf("vx%d: didn't respond to LIDENT\n", vx); ! 671: ! 672: /* calculate address of response buffer */ ! 673: resp = (char *)addr + (addr->v_rspoff&0x3fff); ! 674: if (resp[0] != 0 && (resp[0]&0177) != 3) { ! 675: vrelease(vs, cp); /* init failed */ ! 676: return; ! 677: } ! 678: vs->vs_loport = cp->par[5]; ! 679: vs->vs_hiport = cp->par[7]; ! 680: printf("vx%d: %s%s, ports %d-%d\n", vx, ! 681: (vs->vs_vers == VXV_NEW) ? "" : "old ", typestring, ! 682: vs->vs_loport, vs->vs_hiport); ! 683: vrelease(vs, cp); ! 684: vs->vs_nbr = vx; /* assign board number */ ! 685: } ! 686: ! 687: /* ! 688: * Obtain a command buffer ! 689: */ ! 690: struct vxcmd * ! 691: vobtain(vs) ! 692: register struct vx_softc *vs; ! 693: { ! 694: register struct vxcmd *p; ! 695: int s; ! 696: ! 697: s = spl8(); ! 698: p = vs->vs_avail; ! 699: if (p == (struct vxcmd *)0) { ! 700: #ifdef VX_DEBUG ! 701: if (vxintr4&VXNOBUF) ! 702: vxintr4 &= ~VXNOBUF; ! 703: #endif ! 704: printf("vx%d: no buffers\n", vs - vx_softc); ! 705: vxstreset(vs - vx_softc); ! 706: splx(s); ! 707: return (vobtain(vs)); ! 708: } ! 709: vs->vs_avail = p->c_fwd; ! 710: splx(s); ! 711: return ((struct vxcmd *)p); ! 712: } ! 713: ! 714: /* ! 715: * Release a command buffer ! 716: */ ! 717: vrelease(vs, cp) ! 718: register struct vx_softc *vs; ! 719: register struct vxcmd *cp; ! 720: { ! 721: int s; ! 722: ! 723: #ifdef VX_DEBUG ! 724: if (vxintr4&VXNOBUF) ! 725: return; ! 726: #endif ! 727: s = spl8(); ! 728: cp->c_fwd = vs->vs_avail; ! 729: vs->vs_avail = cp; ! 730: splx(s); ! 731: } ! 732: ! 733: struct vxcmd * ! 734: nextcmd(vs) ! 735: register struct vx_softc *vs; ! 736: { ! 737: register struct vxcmd *cp; ! 738: int s; ! 739: ! 740: s = spl8(); ! 741: cp = vs->vs_build; ! 742: vs->vs_build = (struct vxcmd *)0; ! 743: splx(s); ! 744: return (cp); ! 745: } ! 746: ! 747: /* ! 748: * Assemble transmits into a multiple command; ! 749: * up to 8 transmits to 8 lines can be assembled together ! 750: * (on PVIOCX only). ! 751: */ ! 752: vsetq(vs, line, addr, n) ! 753: register struct vx_softc *vs; ! 754: caddr_t addr; ! 755: { ! 756: register struct vxcmd *cp; ! 757: register struct vxmit *mp; ! 758: ! 759: /* ! 760: * Grab a new command buffer or append ! 761: * to the current one being built. ! 762: */ ! 763: cp = vs->vs_build; ! 764: if (cp == (struct vxcmd *)0) { ! 765: cp = vobtain(vs); ! 766: vs->vs_build = cp; ! 767: cp->cmd = VXC_XMITDTA; ! 768: } else { ! 769: if ((cp->cmd & 07) == 07 || vs->vs_vers == VXV_NEW) { ! 770: printf("vx%d: setq overflow\n", vs-vx_softc); ! 771: vxstreset((int)vs->vs_nbr); ! 772: return; ! 773: } ! 774: cp->cmd++; ! 775: } ! 776: /* ! 777: * Select the next vxmit buffer and copy the ! 778: * characters into the buffer (if there's room ! 779: * and the device supports ``immediate mode'', ! 780: * or store an indirect pointer to the data. ! 781: */ ! 782: mp = (struct vxmit *)(cp->par + (cp->cmd & 07)*sizeof (struct vxmit)); ! 783: mp->bcount = n-1; ! 784: mp->line = line; ! 785: if (vs->vs_vers == VXV_NEW && n <= sizeof (mp->ostream)) { ! 786: cp->cmd = VXC_XMITIMM; ! 787: bcopy(addr, mp->ostream, (unsigned)n); ! 788: } else { ! 789: /* get system address of clist block */ ! 790: addr = (caddr_t)vtoph((struct proc *)0, (unsigned)addr); ! 791: bcopy((caddr_t)&addr, mp->ostream, sizeof (addr)); ! 792: } ! 793: /* ! 794: * We send the data immediately if a VIOCX, ! 795: * the command buffer is full, or if we've nothing ! 796: * currently outstanding. If we don't send it, ! 797: * set a timeout to force the data to be sent soon. ! 798: */ ! 799: if (vs->vs_vers == VXV_NEW || (cp->cmd & 07) == 7 || ! 800: vs->vs_xmtcnt == 0) { ! 801: vs->vs_xmtcnt++; ! 802: (void) vcmd((int)vs->vs_nbr, (char *)&cp->cmd); ! 803: vs->vs_build = 0; ! 804: } else ! 805: timeout(vxforce, (caddr_t)vs, 3); ! 806: } ! 807: ! 808: /* ! 809: * Write a command out to the VIOC ! 810: */ ! 811: vcmd(vx, cmdad) ! 812: register int vx; ! 813: register caddr_t cmdad; ! 814: { ! 815: register struct vcmds *cp; ! 816: register struct vx_softc *vs; ! 817: int s; ! 818: ! 819: s = spl8(); ! 820: vs = &vx_softc[vx]; ! 821: /* ! 822: * When the vioc is resetting, don't process ! 823: * anything other than VXC_LIDENT commands. ! 824: */ ! 825: if (vs->vs_state == VXS_RESET && cmdad != NULL) { ! 826: struct vxcmd *vcp = (struct vxcmd *)(cmdad-sizeof (vcp->c_fwd)); ! 827: ! 828: if (vcp->cmd != VXC_LIDENT) { ! 829: vrelease(vs, vcp); ! 830: return (0); ! 831: } ! 832: } ! 833: cp = &vs->vs_cmds; ! 834: if (cmdad != (caddr_t)0) { ! 835: cp->cmdbuf[cp->v_fill] = cmdad; ! 836: if (++cp->v_fill >= VC_CMDBUFL) ! 837: cp->v_fill = 0; ! 838: if (cp->v_fill == cp->v_empty) { ! 839: printf("vx%d: cmd q overflow\n", vx); ! 840: vxstreset(vx); ! 841: splx(s); ! 842: return (0); ! 843: } ! 844: cp->v_cmdsem++; ! 845: } ! 846: if (cp->v_cmdsem && cp->v_curcnt < vs->vs_maxcmd) { ! 847: cp->v_cmdsem--; ! 848: cp->v_curcnt++; ! 849: vinthandl(vx, ((V_BSY|CMDquals) << 8)|V_INTR); ! 850: } ! 851: splx(s); ! 852: return (1); ! 853: } ! 854: ! 855: /* ! 856: * VIOC acknowledge interrupt. The VIOC has received the new ! 857: * command. If no errors, the new command becomes one of 16 (max) ! 858: * current commands being executed. ! 859: */ ! 860: vackint(vx) ! 861: register vx; ! 862: { ! 863: register struct vxdevice *vp; ! 864: register struct vcmds *cp; ! 865: struct vx_softc *vs; ! 866: int s; ! 867: ! 868: scope_out(5); ! 869: vs = &vx_softc[vx]; ! 870: if (vs->vs_type) /* Its a BOP */ ! 871: return; ! 872: s = spl8(); ! 873: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 874: cp = &vs->vs_cmds; ! 875: if (vp->v_vcid&V_ERR) { ! 876: register char *resp; ! 877: register i; ! 878: ! 879: printf("vx%d: ackint error type %x v_dcd %x\n", vx, ! 880: vp->v_vcid & 07, vp->v_dcd & 0xff); ! 881: resp = (char *)vs->vs_mricmd; ! 882: for (i = 0; i < 16; i++) ! 883: printf("%x ", resp[i]&0xff); ! 884: printf("\n"); ! 885: splx(s); ! 886: vxstreset(vx); ! 887: return; ! 888: } ! 889: if ((vp->v_hdwre&017) == CMDquals) { ! 890: #ifdef VX_DEBUG ! 891: if (vxintr4 & VXERR4) { /* causes VIOC INTR ERR 4 */ ! 892: struct vxcmd *cp1, *cp0; ! 893: ! 894: cp0 = (struct vxcmd *) ! 895: ((caddr_t)cp->cmdbuf[cp->v_empty]-sizeof (cp0->c_fwd)); ! 896: if (cp0->cmd == VXC_XMITDTA || cp0->cmd == VXC_XMITIMM) { ! 897: cp1 = vobtain(vs); ! 898: *cp1 = *cp0; ! 899: vxintr4 &= ~VXERR4; ! 900: (void) vcmd(vx, &cp1->cmd); ! 901: } ! 902: } ! 903: #endif ! 904: cp->v_curcmd[vp->v_vcid & VCMDLEN-1] = cp->cmdbuf[cp->v_empty]; ! 905: if (++cp->v_empty >= VC_CMDBUFL) ! 906: cp->v_empty = 0; ! 907: } ! 908: if (++cp->v_itrempt >= VC_IQLEN) ! 909: cp->v_itrempt = 0; ! 910: vintempt(vx); ! 911: splx(s); ! 912: (void) vcmd(vx, (caddr_t)0); /* queue next cmd, if any */ ! 913: } ! 914: ! 915: /* ! 916: * Command Response interrupt. The Vioc has completed ! 917: * a command. The command may now be returned to ! 918: * the appropriate device driver. ! 919: */ ! 920: vcmdrsp(vx) ! 921: register vx; ! 922: { ! 923: register struct vxdevice *vp; ! 924: register struct vcmds *cp; ! 925: register caddr_t cmd; ! 926: register struct vx_softc *vs; ! 927: register char *resp; ! 928: register k; ! 929: register int s; ! 930: ! 931: scope_out(6); ! 932: vs = &vx_softc[vx]; ! 933: if (vs->vs_type) { /* Its a BOP */ ! 934: printf("vx%d: vcmdrsp interrupt\n", vx); ! 935: return; ! 936: } ! 937: s = spl8(); ! 938: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 939: cp = &vs->vs_cmds; ! 940: resp = (char *)vp + (vp->v_rspoff&0x7fff); ! 941: if (((k = resp[1])&V_UNBSY) == 0) { ! 942: printf("vx%d: cmdresp debug\n", vx); ! 943: splx(s); ! 944: vxstreset(vx); ! 945: return; ! 946: } ! 947: k &= VCMDLEN-1; ! 948: cmd = cp->v_curcmd[k]; ! 949: cp->v_curcmd[k] = (caddr_t)0; ! 950: cp->v_curcnt--; ! 951: k = *((short *)&resp[4]); /* cmd operation code */ ! 952: if ((k&0xff00) == VXC_LIDENT) /* want hiport number */ ! 953: for (k = 0; k < VRESPLEN; k++) ! 954: cmd[k] = resp[k+4]; ! 955: resp[1] = 0; ! 956: vxxint(vx, (struct vxcmd *)cmd); ! 957: if (vs->vs_state == VXS_READY) ! 958: vinthandl(vx, ((V_BSY|RSPquals) << 8)|V_INTR); ! 959: splx(s); ! 960: } ! 961: ! 962: /* ! 963: * Unsolicited interrupt. ! 964: */ ! 965: vunsol(vx) ! 966: register vx; ! 967: { ! 968: register struct vxdevice *vp; ! 969: struct vx_softc *vs; ! 970: int s; ! 971: ! 972: scope_out(1); ! 973: vs = &vx_softc[vx]; ! 974: if (vs->vs_type) { /* Its a BOP */ ! 975: printf("vx%d: vunsol from BOP\n", vx); ! 976: return; ! 977: } ! 978: s = spl8(); ! 979: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 980: if (vp->v_uqual&V_UNBSY) { ! 981: vxrint(vx); ! 982: vinthandl(vx, ((V_BSY|UNSquals) << 8)|V_INTR); ! 983: #ifdef notdef ! 984: } else { ! 985: printf("vx%d: unsolicited interrupt error\n", vx); ! 986: splx(s); ! 987: vxstreset(vx); ! 988: #endif ! 989: } ! 990: splx(s); ! 991: } ! 992: ! 993: /* ! 994: * Enqueue an interrupt. ! 995: */ ! 996: vinthandl(vx, item) ! 997: register int vx; ! 998: register item; ! 999: { ! 1000: register struct vcmds *cp; ! 1001: int empty; ! 1002: ! 1003: cp = &vx_softc[vx].vs_cmds; ! 1004: empty = (cp->v_itrfill == cp->v_itrempt); ! 1005: cp->v_itrqueu[cp->v_itrfill] = item; ! 1006: if (++cp->v_itrfill >= VC_IQLEN) ! 1007: cp->v_itrfill = 0; ! 1008: if (cp->v_itrfill == cp->v_itrempt) { ! 1009: printf("vx%d: interrupt q overflow\n", vx); ! 1010: vxstreset(vx); ! 1011: } else if (empty) ! 1012: vintempt(vx); ! 1013: } ! 1014: ! 1015: vintempt(vx) ! 1016: register int vx; ! 1017: { ! 1018: register struct vcmds *cp; ! 1019: register struct vxdevice *vp; ! 1020: register short item; ! 1021: register short *intr; ! 1022: ! 1023: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 1024: if (vp->v_vioc&V_BSY) ! 1025: return; ! 1026: cp = &vx_softc[vx].vs_cmds; ! 1027: if (cp->v_itrempt == cp->v_itrfill) ! 1028: return; ! 1029: item = cp->v_itrqueu[cp->v_itrempt]; ! 1030: intr = (short *)&vp->v_vioc; ! 1031: switch ((item >> 8)&03) { ! 1032: ! 1033: case CMDquals: { /* command */ ! 1034: int phys; ! 1035: ! 1036: if (cp->v_empty == cp->v_fill || vp->v_vcbsy&V_BSY) ! 1037: break; ! 1038: vx_softc[vx].vs_mricmd = (caddr_t)cp->cmdbuf[cp->v_empty]; ! 1039: phys = vtoph((struct proc *)0, ! 1040: (unsigned)cp->cmdbuf[cp->v_empty]); ! 1041: vp->v_vcp[0] = ((short *)&phys)[0]; ! 1042: vp->v_vcp[1] = ((short *)&phys)[1]; ! 1043: vp->v_vcbsy = V_BSY; ! 1044: *intr = item; ! 1045: scope_out(4); ! 1046: break; ! 1047: } ! 1048: ! 1049: case RSPquals: /* command response */ ! 1050: *intr = item; ! 1051: scope_out(7); ! 1052: break; ! 1053: ! 1054: case UNSquals: /* unsolicited interrupt */ ! 1055: vp->v_uqual = 0; ! 1056: *intr = item; ! 1057: scope_out(2); ! 1058: break; ! 1059: } ! 1060: } ! 1061: ! 1062: /* ! 1063: * Start a reset on a vioc after error (hopefully) ! 1064: */ ! 1065: vxstreset(vx) ! 1066: register vx; ! 1067: { ! 1068: register struct vx_softc *vs; ! 1069: register struct vxdevice *vp; ! 1070: register struct vxcmd *cp; ! 1071: register int j; ! 1072: extern int vxinreset(); ! 1073: int s; ! 1074: ! 1075: s = spl8() ; ! 1076: vs = &vx_softc[vx]; ! 1077: if (vs->vs_state == VXS_RESET) { /* avoid recursion */ ! 1078: splx(s); ! 1079: return; ! 1080: } ! 1081: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 1082: /* ! 1083: * Zero out the vioc structures, mark the vioc as being ! 1084: * reset, reinitialize the free command list, reset the vioc ! 1085: * and start a timer to check on the progress of the reset. ! 1086: */ ! 1087: bzero((caddr_t)vs, (unsigned)sizeof (*vs)); ! 1088: ! 1089: /* ! 1090: * Setting VXS_RESET prevents others from issuing ! 1091: * commands while allowing currently queued commands to ! 1092: * be passed to the VIOC. ! 1093: */ ! 1094: vs->vs_state = VXS_RESET; ! 1095: /* init all cmd buffers */ ! 1096: for (j = 0; j < NVCXBUFS; j++) { ! 1097: cp = &vs->vs_lst[j]; ! 1098: cp->c_fwd = &vs->vs_lst[j+1]; ! 1099: } ! 1100: vs->vs_avail = &vs->vs_lst[0]; ! 1101: cp->c_fwd = (struct vxcmd *)0; ! 1102: printf("vx%d: reset...", vx); ! 1103: vp->v_fault = 0; ! 1104: vp->v_vioc = V_BSY; ! 1105: vp->v_hdwre = V_RESET; /* generate reset interrupt */ ! 1106: timeout(vxinreset, (caddr_t)vx, hz*5); ! 1107: splx(s); ! 1108: } ! 1109: ! 1110: /* continue processing a reset on a vioc after an error (hopefully) */ ! 1111: vxinreset(vx) ! 1112: int vx; ! 1113: { ! 1114: register struct vxdevice *vp; ! 1115: int s = spl8(); ! 1116: ! 1117: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 1118: /* ! 1119: * See if the vioc has reset. ! 1120: */ ! 1121: if (vp->v_fault != VXF_READY) { ! 1122: printf("failed\n"); ! 1123: splx(s); ! 1124: return; ! 1125: } ! 1126: /* ! 1127: * Send a LIDENT to the vioc and mess with carrier flags ! 1128: * on parallel printer ports. ! 1129: */ ! 1130: vxinit(vx, 0); ! 1131: splx(s); ! 1132: } ! 1133: ! 1134: /* ! 1135: * Finish the reset on the vioc after an error (hopefully). ! 1136: * ! 1137: * Restore modem control, parameters and restart output. ! 1138: * Since the vioc can handle no more then 24 commands at a time ! 1139: * and we could generate as many as 48 commands, we must do this in ! 1140: * phases, issuing no more then 16 commands at a time. ! 1141: */ ! 1142: vxfnreset(vx, cp) ! 1143: register int vx; ! 1144: register struct vxcmd *cp; ! 1145: { ! 1146: register struct vx_softc *vs; ! 1147: register struct vxdevice *vp ; ! 1148: register struct tty *tp, *tp0; ! 1149: register int i; ! 1150: #ifdef notdef ! 1151: register int on; ! 1152: #endif ! 1153: extern int vxrestart(); ! 1154: int s = spl8(); ! 1155: ! 1156: vs = &vx_softc[vx]; ! 1157: vs->vs_loport = cp->par[5]; ! 1158: vs->vs_hiport = cp->par[7]; ! 1159: vrelease(vs, cp); ! 1160: vs->vs_nbr = vx; /* assign VIOC-X board number */ ! 1161: vs->vs_state = VXS_READY; ! 1162: ! 1163: vp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 1164: vp->v_vcid = 0; ! 1165: ! 1166: /* ! 1167: * Restore modem information and control. ! 1168: */ ! 1169: tp0 = &vx_tty[vx*16]; ! 1170: for (i = vs->vs_loport; i <= vs->vs_hiport; i++) { ! 1171: tp = tp0 + i; ! 1172: if (tp->t_state&(TS_ISOPEN|TS_WOPEN)) { ! 1173: tp->t_state &= ~TS_CARR_ON; ! 1174: vcmodem(tp->t_dev, VMOD_ON); ! 1175: if (tp->t_state&TS_CARR_ON) ! 1176: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 1177: else if (tp->t_state & TS_ISOPEN) ! 1178: (void)(*linesw[tp->t_line].l_modem)(tp, 0); ! 1179: } ! 1180: #ifdef notdef ! 1181: /* ! 1182: * If carrier has changed while we were resetting, ! 1183: * take appropriate action. ! 1184: */ ! 1185: on = vp->v_dcd & 1<<i; ! 1186: if (on && (tp->t_state&TS_CARR_ON) == 0) ! 1187: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 1188: else if (!on && tp->t_state&TS_CARR_ON) ! 1189: (void)(*linesw[tp->t_line].l_modem)(tp, 0); ! 1190: #endif ! 1191: } ! 1192: vs->vs_state = VXS_RESET; ! 1193: timeout(vxrestart, (caddr_t)vx, hz); ! 1194: splx(s); ! 1195: } ! 1196: ! 1197: /* ! 1198: * Restore a particular aspect of the VIOC. ! 1199: */ ! 1200: vxrestart(vx) ! 1201: int vx; ! 1202: { ! 1203: register struct tty *tp, *tp0; ! 1204: register struct vx_softc *vs; ! 1205: register int i, count; ! 1206: int s = spl8(); ! 1207: ! 1208: count = vx >> 8; ! 1209: vx &= 0xff; ! 1210: vs = &vx_softc[vx]; ! 1211: vs->vs_state = VXS_READY; ! 1212: tp0 = &vx_tty[vx*16]; ! 1213: for (i = vs->vs_loport; i <= vs->vs_hiport; i++) { ! 1214: tp = tp0 + i; ! 1215: if (count != 0) { ! 1216: tp->t_state &= ~(TS_BUSY|TS_TIMEOUT); ! 1217: if (tp->t_state&(TS_ISOPEN|TS_WOPEN)) ! 1218: vxstart(tp); /* restart pending output */ ! 1219: } else { ! 1220: if (tp->t_state&(TS_WOPEN|TS_ISOPEN)) ! 1221: vxcparam(tp->t_dev, 0); ! 1222: } ! 1223: } ! 1224: if (count == 0) { ! 1225: vs->vs_state = VXS_RESET; ! 1226: timeout(vxrestart, (caddr_t)(vx + 1*256), hz); ! 1227: } else ! 1228: printf("done\n"); ! 1229: splx(s); ! 1230: } ! 1231: ! 1232: vxreset(dev) ! 1233: dev_t dev; ! 1234: { ! 1235: ! 1236: vxstreset((int)VXUNIT(minor(dev))); /* completes asynchronously */ ! 1237: } ! 1238: ! 1239: #ifdef notdef ! 1240: vxfreset(vx) ! 1241: register int vx; ! 1242: { ! 1243: struct vba_device *vi; ! 1244: ! 1245: if ((unsigned)vx > NVX || (vi = vxinfo[vx]) == 0 || vi->ui_addr == 0) ! 1246: return (ENODEV); ! 1247: vx_softc[vx].vs_state = VXS_READY; ! 1248: vxstreset(vx); ! 1249: return (0); /* completes asynchronously */ ! 1250: } ! 1251: #endif ! 1252: ! 1253: vcmodem(dev, flag) ! 1254: dev_t dev; ! 1255: { ! 1256: struct tty *tp; ! 1257: register struct vxcmd *cp; ! 1258: register struct vx_softc *vs; ! 1259: register struct vxdevice *kp; ! 1260: register port; ! 1261: int unit; ! 1262: ! 1263: unit = minor(dev); ! 1264: tp = &vx_tty[unit]; ! 1265: vs = (struct vx_softc *)tp->t_addr; ! 1266: if (vs->vs_state != VXS_READY) ! 1267: return; ! 1268: cp = vobtain(vs); ! 1269: kp = (struct vxdevice *)((struct vba_device *)vxinfo[vs->vs_nbr])->ui_addr; ! 1270: ! 1271: port = unit & 017; ! 1272: /* ! 1273: * Issue MODEM command ! 1274: */ ! 1275: cp->cmd = VXC_MDMCTL; ! 1276: if (flag == VMOD_ON) { ! 1277: if (vs->vs_softCAR & (1 << port)) ! 1278: cp->par[0] = V_MANUAL | V_DTR_ON | V_RTS; ! 1279: else ! 1280: cp->par[0] = V_AUTO | V_DTR_ON | V_RTS; ! 1281: } else ! 1282: cp->par[0] = V_DTR_OFF; ! 1283: cp->par[1] = port; ! 1284: (void) vcmd((int)vs->vs_nbr, (caddr_t)&cp->cmd); ! 1285: if (vs->vs_softCAR & (1 << port)) ! 1286: kp->v_dcd |= (1 << port); ! 1287: if ((kp->v_dcd | vs->vs_softCAR) & (1 << port) && flag == VMOD_ON) ! 1288: tp->t_state |= TS_CARR_ON; ! 1289: } ! 1290: ! 1291: /* ! 1292: * VCMINTR called when an unsolicited interrup occurs signaling ! 1293: * some change of modem control state. ! 1294: */ ! 1295: vcmintr(vx) ! 1296: register vx; ! 1297: { ! 1298: register struct vxdevice *kp; ! 1299: register struct tty *tp; ! 1300: register port; ! 1301: register struct vx_softc *vs; ! 1302: ! 1303: kp = (struct vxdevice *)((struct vba_device *)vxinfo[vx])->ui_addr; ! 1304: port = kp->v_usdata[0] & 017; ! 1305: tp = &vx_tty[vx*16+port]; ! 1306: vs = &vx_softc[vx]; ! 1307: ! 1308: if (kp->v_ustat & DCD_ON) ! 1309: (void)(*linesw[tp->t_line].l_modem)(tp, 1); ! 1310: else if ((kp->v_ustat & DCD_OFF) && ! 1311: ((vs->vs_softCAR & (1 << port))) == 0 && ! 1312: (*linesw[tp->t_line].l_modem)(tp, 0) == 0) { ! 1313: register struct vcmds *cp; ! 1314: register struct vxcmd *cmdp; ! 1315: ! 1316: /* clear all pending transmits */ ! 1317: if (tp->t_state&(TS_BUSY|TS_FLUSH) && ! 1318: vs->vs_vers == VXV_NEW) { ! 1319: int i, cmdfound = 0; ! 1320: ! 1321: cp = &vs->vs_cmds; ! 1322: for (i = cp->v_empty; i != cp->v_fill; ) { ! 1323: cmdp = (struct vxcmd *)((long *)cp->cmdbuf[i]-1); ! 1324: if ((cmdp->cmd == VXC_XMITDTA || ! 1325: cmdp->cmd == VXC_XMITIMM) && ! 1326: ((struct vxmit *)cmdp->par)->line == port) { ! 1327: cmdfound++; ! 1328: cmdp->cmd = VXC_FDTATOX; ! 1329: cmdp->par[1] = port; ! 1330: } ! 1331: if (++i >= VC_CMDBUFL) ! 1332: i = 0; ! 1333: } ! 1334: if (cmdfound) ! 1335: tp->t_state &= ~(TS_BUSY|TS_FLUSH); ! 1336: /* cmd is already in vioc, have to flush it */ ! 1337: else { ! 1338: cmdp = vobtain(vs); ! 1339: cmdp->cmd = VXC_FDTATOX; ! 1340: cmdp->par[1] = port; ! 1341: (void) vcmd(vx, (caddr_t)&cmdp->cmd); ! 1342: } ! 1343: } ! 1344: } else if ((kp->v_ustat&BRK_CHR) && (tp->t_state&TS_ISOPEN)) { ! 1345: (*linesw[tp->t_line].l_rint)((tp->t_flags & RAW) ? ! 1346: 0 : tp->t_intrc, tp); ! 1347: return; ! 1348: } ! 1349: } ! 1350: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.