|
|
1.1 ! root 1: #include "vx.h" ! 2: #if NVX > 0 ! 3: /* ! 4: * VIOC driver ! 5: */ ! 6: #include "../h/param.h" ! 7: #include "../h/file.h" ! 8: #include "../h/ioctl.h" ! 9: #include "../h/tty.h" ! 10: #include "../h/errno.h" ! 11: #include "../h/time.h" ! 12: #include "../h/kernel.h" ! 13: #include "../vba/vioc.h" ! 14: #include "../sna/snadebug.h" ! 15: #ifdef VXPERF ! 16: #include "../vba/scope.h" ! 17: #endif VXPERF ! 18: ! 19: #define CMDquals 0 ! 20: #define RSPquals 1 ! 21: #define UNSquals 2 ! 22: ! 23: long reinit = 0; ! 24: extern struct vcx vcx[] ; ! 25: extern struct tty vx_tty[]; ! 26: struct vcmds v_cmds[NVIOCX] ; ! 27: ! 28: extern char vxtype[]; ! 29: extern char vxbbno; ! 30: extern char vxbopno[]; ! 31: ! 32: #if defined(NVSNA) | defined(NSD) ! 33: extern vbrall(); ! 34: #else ! 35: vbrall() {}; ! 36: #endif ! 37: ! 38: extern struct vxcmd *vobtain(); ! 39: ! 40: #ifdef VX_DEBUG ! 41: #include "../vba/vxdebug.h" ! 42: #endif ! 43: ! 44: /* ! 45: * Write a command out to the VIOC ! 46: */ ! 47: vcmd(n, cmdad) ! 48: register int n ; ! 49: register caddr_t cmdad ; /* command address */ ! 50: { ! 51: ! 52: register struct vcmds *cp ; ! 53: register struct vcx *xp; ! 54: int s ; ! 55: ! 56: s = spl8() ; ! 57: cp = &v_cmds[n] ; ! 58: xp = &vcx[n]; ! 59: if (xp->v_state&V_RESETTING && cmdad != NULL) { ! 60: /* ! 61: * When the vioc is resetting, don't process ! 62: * anything other than LIDENT commands. ! 63: */ ! 64: register struct vxcmd *cp = (struct vxcmd *) ! 65: ((char *)cmdad - sizeof(cp->c_fwd)); ! 66: if (cp->cmd != LIDENT) { ! 67: vrelease(xp, cp); ! 68: return(0); ! 69: } ! 70: } ! 71: if (cmdad != (caddr_t) 0) { ! 72: #ifdef VX_DEBUG ! 73: if ((*((short *)cmdad) == FDTATOX) && (vxdebug & VXVCC)) ! 74: printf("vcmd: FDTATOX queued to VIOC%d\n",n); ! 75: #endif ! 76: cp->cmdbuf[cp->v_fill] = cmdad ; ! 77: if( ++cp->v_fill >= VC_CMDBUFL ) cp->v_fill = 0 ; ! 78: if(cp->v_fill == cp->v_empty) { ! 79: vpanic("vc: CMD Q OVFLO") ; ! 80: vxstreset(n); ! 81: splx(s); ! 82: return(0); ! 83: } ! 84: cp->v_cmdsem++; ! 85: } ! 86: if(cp->v_cmdsem && cp->v_curcnt < vcx[n].v_maxcmd) { ! 87: cp->v_cmdsem--; ! 88: cp->v_curcnt++; ! 89: vinthandl(n, ((V_BSY | CMDquals) << 8) | V_INTR ) ; ! 90: } ! 91: splx(s) ; ! 92: } ! 93: ! 94: /* ! 95: * VIOC acknowledge interrupt. The VIOC has received the new ! 96: * command. If no errors, the new command becomes one of 16 (max) ! 97: * current commands being executed. ! 98: */ ! 99: vackint(n) ! 100: register n ; /* VIOC number */ ! 101: { ! 102: ! 103: register struct vblok *vp ; ! 104: register struct vcmds *cp ; ! 105: register s; ! 106: ! 107: #ifdef VXPERF ! 108: scope_out(5); ! 109: #endif VXPERF ! 110: if (vxtype[n]) { /* Its a BOP */ ! 111: vbrall(n); /* Int. from BOP, port 0 */ ! 112: return; ! 113: } ! 114: s = spl8(); ! 115: vp = VBAS(n) ; ! 116: cp = &v_cmds[n] ; ! 117: if( vp->v_vcid & V_ERR ) { ! 118: register char *resp; ! 119: register i; ! 120: printf ("INTR ERR type = %x VIOC = %x, v_dcd: %lx\n", ! 121: vp->v_vcid & 07, n, vp->v_dcd & 0xff); ! 122: /* resp = (char *)vp + (vp->v_rspoff & 0x7FFF); */ ! 123: resp = (char *)(&vcx[n])->v_mricmd; ! 124: for(i=0; i<16; i++) ! 125: printf("%x ", resp[i]&0xff); ! 126: vpanic( "\nvcc: vackint") ; ! 127: splx(s); ! 128: vxstreset(n); ! 129: return ; ! 130: } else ! 131: if((vp->v_hdwre&017) == CMDquals) { ! 132: #ifdef VX_DEBUG ! 133: if (vxintr4 & VXERR4) { /* causes VIOC INTR ERR 4 */ ! 134: register struct vxcmd *cp1; ! 135: register struct vxcmd *cp0 = (struct vxcmd *) ! 136: ((long)cp->cmdbuf[cp->v_empty] - 4); ! 137: if ((cp0->cmd == XMITDTA) || (cp0->cmd == XMITIMM)) { ! 138: cp1 = vobtain(&vcx[n]); ! 139: *cp1 = *cp0; ! 140: vxintr4 &= ~VXERR4; ! 141: vcmd(n,&cp1->cmd); ! 142: } ! 143: } ! 144: #endif ! 145: cp->v_curcmd[vp->v_vcid & VCMDLEN-1] = cp->cmdbuf[cp->v_empty] ; ! 146: if( ++cp->v_empty >= VC_CMDBUFL ) cp->v_empty = 0 ; ! 147: } ! 148: if( ++cp->v_itrempt >= VC_IQLEN ) cp->v_itrempt = 0 ; ! 149: vintempt(n) ; ! 150: splx(s); ! 151: vcmd(n, 0); /* queue next cmd, if any */ ! 152: } ! 153: ! 154: /* ! 155: * Command Response interrupt. The Vioc has completed ! 156: * a command. The command may now be returned to ! 157: * the appropriate device driver . ! 158: */ ! 159: vcmdrsp(n) ! 160: register n ; ! 161: { ! 162: ! 163: register struct vblok *vp ; ! 164: register struct vcmds *cp ; ! 165: register caddr_t cmd ; ! 166: register char *resp ; ! 167: register k ; ! 168: register int s ; ! 169: ! 170: #ifdef VXPERF ! 171: scope_out(6); ! 172: #endif VXPERF ! 173: if (vxtype[n]) { /* Its a BOP */ ! 174: printf("vcmdrsp: stray interrupt from BOP at VIOC%d...\n",n); ! 175: return; ! 176: } ! 177: s = spl8(); ! 178: vp = VBAS(n) ; ! 179: cp = &v_cmds[n] ; ! 180: resp = (char *)vp; ! 181: resp += vp->v_rspoff & 0x7FFF; ! 182: ! 183: if ( ! 184: #if VX_TESTING ! 185: (vx_test&VX_CMDRESP_DEBUG) == 0 && ! 186: #endif ! 187: (k=resp[1]) & V_UNBSY ) { ! 188: k &= VCMDLEN-1; ! 189: cmd = cp->v_curcmd[k]; ! 190: cp->v_curcmd[k] = (caddr_t)0; ! 191: cp->v_curcnt--; ! 192: k = *((short *)&resp[4]); /* cmd operation code */ ! 193: if((k & 0xFF00) == LIDENT) { /* want hiport number */ ! 194: for(k=0; k<VRESPLEN; k++) ! 195: cmd[k] = resp[k+4]; ! 196: } ! 197: resp[1] = 0; ! 198: vxxint(n, cmd) ; ! 199: if ((&vcx[n])->v_state == V_RESETTING) return; ! 200: } ! 201: else { ! 202: vpanic( "vc, cmdresp debug") ; ! 203: splx(s); ! 204: vxstreset(n); ! 205: return; ! 206: } ! 207: ! 208: vinthandl(n, ( (V_BSY | RSPquals) << 8 ) | V_INTR ) ; ! 209: splx(s); ! 210: ! 211: } ! 212: ! 213: ! 214: /* ! 215: * Unsolicited interrupt. ! 216: */ ! 217: vunsol(n) ! 218: register(n) ; ! 219: { ! 220: ! 221: register struct vblok *vp ; ! 222: register s; ! 223: ! 224: #ifdef VXPERF ! 225: scope_out(1); ! 226: #endif VXPERF ! 227: if (vxtype[n]) { /* Its a BOP */ ! 228: printf("vunsol: stray interrupt from BOP at VIOC%d...\n",n); ! 229: return; ! 230: } ! 231: s = spl8(); ! 232: vp = VBAS(n) ; ! 233: if ( ! 234: #if VX_TESTING ! 235: (vx_test&VX_UNSOL_INT_DEBUG) == 0 && ! 236: #endif ! 237: vp->v_uqual & V_UNBSY) { ! 238: if (vxrint(n)) ! 239: vinthandl(n, ( (V_BSY | UNSquals) << 8 ) | V_INTR ) ; ! 240: splx(s); ! 241: } ! 242: else { ! 243: vpanic("vc: UNSOL INT ERR") ; ! 244: splx(s); ! 245: vxstreset(n); ! 246: } ! 247: } ! 248: ! 249: /* ! 250: * Enqueue an interrupt ! 251: */ ! 252: vinthandl(n, item) ! 253: register int n ; ! 254: register item ; ! 255: { ! 256: ! 257: register struct vcmds *cp ; ! 258: register int empflag = 0 ; ! 259: ! 260: cp = &v_cmds[n] ; ! 261: if( cp->v_itrfill == cp->v_itrempt ) empflag++ ; ! 262: cp->v_itrqueu[cp->v_itrfill] = item ; ! 263: if( ++cp->v_itrfill >= VC_IQLEN ) cp->v_itrfill = 0 ; ! 264: if(cp->v_itrfill == cp->v_itrempt) { ! 265: vpanic( "vc: INT Q OVFLO" ) ; ! 266: vxstreset(n); ! 267: } ! 268: else if( empflag ) vintempt(n) ; ! 269: } ! 270: ! 271: vintempt(n) ! 272: register int n ; ! 273: { ! 274: register struct vcmds *cp ; ! 275: register struct vblok *vp ; ! 276: register short item ; ! 277: register short *intr ; ! 278: ! 279: vp = VBAS(n) ; ! 280: if(vp->v_vioc & V_BSY) return ; ! 281: cp = &v_cmds[n] ; ! 282: if(cp->v_itrempt == cp->v_itrfill) return ; ! 283: item = cp->v_itrqueu[cp->v_itrempt] ; ! 284: intr = (short *)&vp->v_vioc ; ! 285: switch( (item >> 8) & 03 ) { ! 286: ! 287: case CMDquals: /* command */ ! 288: { ! 289: int phys; ! 290: ! 291: if(cp->v_empty == cp->v_fill || vp->v_vcbsy&V_BSY) ! 292: break; ! 293: (&vcx[n])->v_mricmd = (caddr_t)cp->cmdbuf[cp->v_empty]; ! 294: phys = vtoph(0, cp->cmdbuf[cp->v_empty]) ; /* should be a sys address */ ! 295: vp->v_vcp[0] = ((short *)&phys)[0]; ! 296: vp->v_vcp[1] = ((short *)&phys)[1]; ! 297: vp->v_vcbsy = V_BSY ; ! 298: *intr = item ; ! 299: } ! 300: #ifdef VXPERF ! 301: scope_out(4); ! 302: #endif VXPERF ! 303: break ; ! 304: ! 305: case RSPquals: /* command response */ ! 306: *intr = item ; ! 307: #ifdef VXPERF ! 308: scope_out(7); ! 309: #endif VXPERF ! 310: break ; ! 311: ! 312: case UNSquals: /* unsolicited interrupt */ ! 313: vp->v_uqual = 0 ; ! 314: *intr = item ; ! 315: #ifdef VXPERF ! 316: scope_out(2); ! 317: #endif VXPERF ! 318: break ; ! 319: } ! 320: } ! 321: ! 322: ! 323: /* start a reset on a vioc after error (hopefully) */ ! 324: vxstreset(n) ! 325: register n; ! 326: { ! 327: register struct vcx *xp; ! 328: register struct vblok *vp ; ! 329: register struct vxcmd *cp; ! 330: register int j; ! 331: extern int vxinreset(); ! 332: int s ; ! 333: ! 334: s = spl8() ; ! 335: vp = VBAS(n); ! 336: xp = &vcx[n]; ! 337: ! 338: #if VX_TESTING ! 339: vx_test = 0; ! 340: #endif ! 341: if (xp->v_state&V_RESETTING) ! 342: /* ! 343: * Avoid infinite recursion. ! 344: */ ! 345: return; ! 346: ! 347: /* ! 348: * Zero out the vioc structures, mark the vioc as being ! 349: * reset, reinitialize the free command list, reset the vioc ! 350: * and start a timer to check on the progress of the reset. ! 351: */ ! 352: bzero(&v_cmds[n], sizeof(struct vcmds)); ! 353: bzero(xp, sizeof(struct vcx)); ! 354: ! 355: /* ! 356: * Setting V_RESETTING prevents others from issuing ! 357: * commands while allowing currently queued commands to ! 358: * be passed to the VIOC. ! 359: */ ! 360: xp->v_state |= V_RESETTING; ! 361: for(j=0; j<NVCXBUFS; j++) /* init all cmd buffers */ ! 362: { ! 363: cp = &xp->vx_lst[j]; /* index a buffer */ ! 364: cp->c_fwd = &xp->vx_lst[j+1]; /* point to next buf */ ! 365: } ! 366: xp->vx_avail = &xp->vx_lst[0]; /* set idx to 1st free buf */ ! 367: cp->c_fwd = (struct vxcmd *)0; /* mark last buf in free list */ ! 368: ! 369: printf("resetting VIOC %x .. ", n); ! 370: ! 371: vp->v_fault = 0 ; ! 372: vp->v_vioc = V_BSY ; ! 373: vp->v_hdwre = V_RESET ; /* reset interrupt */ ! 374: ! 375: timeout(vxinreset, (caddr_t)n, hz*5); ! 376: splx(s); ! 377: return; ! 378: } ! 379: ! 380: /* continue processing a reset on a vioc after an error (hopefully) */ ! 381: vxinreset(vioc) ! 382: caddr_t vioc; ! 383: { ! 384: register struct vcx *xp; ! 385: register struct vblok *vp ; ! 386: register int n = (int)vioc; ! 387: int s = spl8(); ! 388: printf("vxinreset "); ! 389: ! 390: vp = VBAS(n); ! 391: xp = &vcx[n]; ! 392: ! 393: /* ! 394: * See if the vioc has reset. ! 395: */ ! 396: if (vp->v_fault != VREADY) { ! 397: printf("failed\n"); ! 398: splx(s); ! 399: return; ! 400: } ! 401: ! 402: /* ! 403: * Send a LIDENT to the vioc and mess with carrier flags ! 404: * on parallel printer ports. ! 405: */ ! 406: vxinit(n, 0); ! 407: splx(s); ! 408: } ! 409: ! 410: /* ! 411: * Restore modem control, parameters and restart output. ! 412: * Since the vioc can handle no more then 24 commands at a time ! 413: * and we could generate as many as 48 commands, we must do this in ! 414: * phases, issuing no more then 16 commands at a time. ! 415: */ ! 416: /* finish the reset on the vioc after an error (hopefully) */ ! 417: vxfnreset(n, cp) ! 418: register int n; ! 419: register struct vxcmd *cp; ! 420: { ! 421: register struct vcx *xp; ! 422: register struct vblok *vp ; ! 423: register struct tty *tp; ! 424: register int i; ! 425: register int on; ! 426: extern int vxrestart(); ! 427: int s = spl8(); ! 428: printf("vxfnreset "); ! 429: ! 430: vp = VBAS(n); ! 431: xp = &vcx[n]; ! 432: ! 433: xp->v_loport = cp->par[5]; /* save low port number */ ! 434: xp->v_hiport = cp->par[7];/* VIOC knows high port numbr */ ! 435: vrelease(xp,cp); /* done with this control block */ ! 436: xp->v_nbr = n; /* assign VIOC-X board number */ ! 437: ! 438: xp->v_state &= ~V_RESETTING; ! 439: ! 440: vp->v_vcid = 0; ! 441: ! 442: /* ! 443: * Restore modem information and control. ! 444: */ ! 445: for(i=xp->v_loport; i<=xp->v_hiport; i++) { ! 446: tp = &vx_tty[i+n*16]; ! 447: if (tp->t_state&(TS_ISOPEN|TS_WOPEN)) { ! 448: tp->t_state &= ~TS_CARR_ON; ! 449: vcmodem(tp->t_dev, VMOD_ON); ! 450: if (tp->t_state&TS_CARR_ON) { ! 451: wakeup((caddr_t)&tp->t_canq) ; ! 452: } ! 453: else { ! 454: if(tp->t_state & TS_ISOPEN) { ! 455: ttyflush(tp, FREAD|FWRITE); ! 456: if(tp->t_state&TS_FLUSH) ! 457: wakeup((caddr_t)&tp->t_state) ; ! 458: if((tp->t_flags&NOHANG)==0) { ! 459: gsignal(tp->t_pgrp, SIGHUP) ; ! 460: gsignal(tp->t_pgrp, SIGCONT); ! 461: } ! 462: } ! 463: } ! 464: } ! 465: /* ! 466: * If carrier has changed while we were resetting, ! 467: * take appropriate action. ! 468: */ ! 469: /* ! 470: on = vp->v_dcd & 1<<i; ! 471: if (on && (tp->t_state&TS_CARR_ON) == 0) { ! 472: tp->t_state |= TS_CARR_ON ; ! 473: wakeup((caddr_t)&tp->t_canq) ; ! 474: } else if (!on && tp->t_state&TS_CARR_ON) { ! 475: tp->t_state &= ~TS_CARR_ON ; ! 476: if(tp->t_state & TS_ISOPEN) { ! 477: ttyflush(tp, FREAD|FWRITE); ! 478: if(tp->t_state&TS_FLUSH) ! 479: wakeup((caddr_t)&tp->t_state) ; ! 480: if((tp->t_flags&NOHANG)==0) { ! 481: gsignal(tp->t_pgrp, SIGHUP) ; ! 482: gsignal(tp->t_pgrp, SIGCONT); ! 483: } ! 484: } ! 485: } ! 486: */ ! 487: } ! 488: ! 489: xp->v_state |= V_RESETTING; ! 490: ! 491: timeout(vxrestart, (caddr_t)n, hz); ! 492: splx(s); ! 493: } ! 494: ! 495: /* ! 496: * Restore a particular aspect of the VIOC. ! 497: */ ! 498: vxrestart(vioc) ! 499: caddr_t vioc; ! 500: { ! 501: register struct tty *tp, *tp0; ! 502: register struct vcx *xp; ! 503: register int i, cnt; ! 504: register int n = (int)vioc; ! 505: int s = spl8(); ! 506: ! 507: cnt = n>>8; ! 508: printf("vxrestart %d ",cnt); ! 509: n &= 0xff; ! 510: ! 511: tp0 = &vx_tty[n*16]; ! 512: xp = &vcx[n]; ! 513: ! 514: xp->v_state &= ~V_RESETTING; ! 515: ! 516: for(i=xp->v_loport; i<=xp->v_hiport; i++) { ! 517: tp = tp0 + i; ! 518: if (cnt != 0) { ! 519: tp->t_state &= ~(TS_BUSY|TS_TIMEOUT); ! 520: if(tp->t_state&(TS_ISOPEN|TS_WOPEN)) /* restart pending output */ ! 521: vxstart(tp); ! 522: } else { ! 523: if (tp->t_state&(TS_WOPEN|TS_ISOPEN)) ! 524: vxcparam(tp->t_dev, 0); ! 525: } ! 526: } ! 527: ! 528: if (cnt == 0) { ! 529: xp->v_state |= V_RESETTING; ! 530: timeout(vxrestart, (caddr_t)(n + 1*256), hz); ! 531: } else ! 532: printf("done\n"); ! 533: splx(s); ! 534: } ! 535: ! 536: vxreset(dev) ! 537: dev_t dev; ! 538: { ! 539: vxstreset(minor(dev)>>4); /* completes asynchronously */ ! 540: } ! 541: ! 542: vxfreset(n) ! 543: register int n; ! 544: { ! 545: register struct vblok *vp; ! 546: ! 547: if (n < 0 || n > NVX || VBAS(n) == NULL) ! 548: return(ENODEV); ! 549: vcx[n].v_state &= ~V_RESETTING; ! 550: vxstreset(n); ! 551: return(0); /* completes asynchronously */ ! 552: } ! 553: #endif ! 554:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.