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