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