|
|
1.1 ! root 1: #include "vx.h" ! 2: #if NVX > 0 ! 3: /* ! 4: * VIOC-X driver ! 5: */ ! 6: ! 7: #include "../h/param.h" ! 8: #include "../h/ioctl.h" ! 9: #include "../h/tty.h" ! 10: #include "../h/dir.h" ! 11: #include "../h/user.h" ! 12: #include "../h/map.h" ! 13: #include "../machine/pte.h" ! 14: #include "../h/buf.h" ! 15: #include "../vba/vbavar.h" ! 16: #include "../h/conf.h" ! 17: #include "../h/file.h" ! 18: #include "../h/uio.h" ! 19: #include "../vba/vioc.h" ! 20: #ifdef VXPERF ! 21: #include "../vba/scope.h" ! 22: #endif VXPERF ! 23: ! 24: #include "vbsc.h" ! 25: #if NVBSC > 0 ! 26: #include "../bsc/bscio.h" ! 27: #include "../bsc/bsc.h" ! 28: char bscport[NVXPORTS]; ! 29: long bscno = 0; ! 30: extern struct bsc bsc[]; ! 31: #endif ! 32: ! 33: #define RSPquals 1 ! 34: ! 35: struct vcx vcx[NVIOCX]; ! 36: struct tty vx_tty[NVXPORTS]; ! 37: extern struct vcmds v_cmds[]; ! 38: struct vba_device *vxinfo[NVIOCX]; ! 39: ! 40: int vxstart(); ! 41: int ttrstrt(); ! 42: caddr_t vtoph(); ! 43: struct vxcmd *vobtain(); ! 44: ! 45: /* ! 46: * Driver information for auto-configuration stuff. ! 47: * (not tested and probably should be changed) ! 48: */ ! 49: int vxprobe(), vxattach(), vxrint(); ! 50: long vxstd[] = { 0 }; ! 51: struct vba_driver vxdriver = ! 52: { vxprobe, 0, vxattach, 0, vxstd, "VIOC ", vxinfo }; ! 53: ! 54: char vxtype[NVIOCX]; /* 0: viox-x/vioc-b; 1: vioc-bop */ ! 55: char vxbopno[NVIOCX]; /* BOP board no. if indicated by vxtype[] */ ! 56: char vxbbno = -1; ! 57: short vbtbl = -1; ! 58: int vx_cnt = NVXPORTS; /* needed by vmstat/iostat */ ! 59: extern vbrall(); ! 60: ! 61: vxprobe(reg) ! 62: caddr_t reg; ! 63: { ! 64: register int br, cvec; ! 65: register struct vblok *vp = (struct vblok *)reg; ! 66: ! 67: #ifdef lint ! 68: br = 0; cvec = br; br = cvec; ! 69: #endif ! 70: ! 71: if (badaddr(vp, 1)) ! 72: return(0); ! 73: vp->v_fault = 0; ! 74: vp->v_vioc = V_BSY; ! 75: vp->v_hdwre = V_RESET; /* reset interrupt */ ! 76: ! 77: DELAY(4000000); ! 78: if (vp->v_fault != VREADY) ! 79: return(0); ! 80: return(1); ! 81: } ! 82: ! 83: vxattach(ui) ! 84: register struct vba_device *ui; ! 85: { ! 86: VIOCBAS[ui->ui_unit] = ui->ui_addr; ! 87: vxinit(ui->ui_unit, 1); ! 88: } ! 89: ! 90: /* ! 91: * Open a VX line. ! 92: */ ! 93: vxopen(dev, flag) ! 94: { ! 95: register struct tty *tp; /* pointer to tty struct for port */ ! 96: register struct vcx *xp; /* pointer to VIOC-X info/cmd buffer */ ! 97: register int d; /* minor device number */ ! 98: register int error; ! 99: ! 100: d = minor(dev); /* get minor device number */ ! 101: if (d >= NVXPORTS) /* validate minor device number */ ! 102: return(ENXIO); /* set errno to indicate bad port # */ ! 103: tp = &vx_tty[d]; /* index the tty structure for port */ ! 104: ! 105: xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */ ! 106: d &= 017; ! 107: ! 108: /* ! 109: * If we are resetting the VIOC, wait until the LIDENT has ! 110: * completed. ! 111: */ ! 112: while (xp->v_state&V_RESETTING) ! 113: sleep((caddr_t)&xp->v_state); ! 114: ! 115: if (xp->v_hiport == xp->v_loport || /* no ports on this board */ ! 116: d < xp->v_loport || d > xp->v_hiport)/* not in the range of ports */ ! 117: return(ENXIO); /* bad minor device number */ ! 118: ! 119: if (isprinter(xp, d)) ! 120: /* ! 121: * Printers have different semantics than tty ports. ! 122: * They have a fixed output transliteration, no read, ! 123: * only one process may open them at a time, they always ! 124: * have carrier and processes cannot be attached to them. ! 125: */ ! 126: if (tp->t_state&TS_ISOPEN) ! 127: return(EBUSY); ! 128: ! 129: if ((tp->t_state&(TS_ISOPEN|TS_WOPEN))==0){/* is device already open? */ ! 130: ttychars(tp); /* set default control chars */ ! 131: tp->t_addr = (caddr_t)xp;/* store addr of VIOC-X info */ ! 132: tp->t_oproc = vxstart; /* store address of startup routine */ ! 133: tp->t_dev = dev; /* store major/minor device numbers */ ! 134: if (tp->t_ispeed == 0) {/* if no default speeds set them */ ! 135: tp->t_ispeed = SSPEED;/* default input baud */ ! 136: tp->t_ospeed = SSPEED;/* default output baud */ ! 137: tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */ ! 138: } ! 139: vxparam(dev); /* set parameters for this port */ ! 140: } ! 141: /* ! 142: * If already open for exclusive use open fails unless caller is root. ! 143: */ ! 144: if (tp->t_state&TS_XCLUDE && u.u_uid!=0) ! 145: return(EBUSY); /* device is busy, sorry */ ! 146: ! 147: d = spl8(); ! 148: tp->t_state |= TS_WOPEN; /* mark device as waiting for open */ ! 149: /* ! 150: * Check for carrier ! 151: */ ! 152: if (vcmodem(dev, VMOD_ON)) ! 153: tp->t_state |= TS_CARR_ON; ! 154: else ! 155: tp->t_state &= ~TS_CARR_ON; ! 156: while ((tp->t_state&TS_CARR_ON) == 0) { ! 157: tp->t_state |= TS_WOPEN; ! 158: sleep(&tp->t_canq, TTIPRI); ! 159: } ! 160: error = (*linesw[tp->t_line].l_open)(dev, tp);/*let tty.c finish open */ ! 161: splx(d); ! 162: return(error); ! 163: } ! 164: ! 165: /* ! 166: * Close a VX line. ! 167: */ ! 168: vxclose(dev, flag) ! 169: dev_t dev; ! 170: int flag; ! 171: { ! 172: register int d = minor(dev); ! 173: register struct tty *tp = &vx_tty[d]; ! 174: register int s = spl8(); ! 175: register int error; ! 176: ! 177: error = (*linesw[tp->t_line].l_close)(tp); ! 178: if ((tp->t_state&TS_ISOPEN) && (tp->t_state&TS_HUPCLS)) { ! 179: register int flags = tp->t_flags; ! 180: ! 181: /* ! 182: ** Turn off echo to prevent infinite flushing ! 183: ** Flush output queue then turn off clear to send. ! 184: ** Always restore flags so line disipline will not change. ! 185: */ ! 186: tp->t_flags &= ~ECHO; ! 187: ttywait(tp); ! 188: tp->t_flags = flags; ! 189: vcmodem(dev, VMOD_OFF); ! 190: } ! 191: while ((tp->t_state&TS_FLUSH) && (tp->t_state&TS_BUSY)) ! 192: sleep((caddr_t)&tp->t_state, TTOPRI); ! 193: ttyclose(tp); /* let tty.c finish the close */ ! 194: splx(s); ! 195: return(error); ! 196: } ! 197: ! 198: /* ! 199: * Read from a VX line. ! 200: */ ! 201: vxread(dev, uio) ! 202: dev_t dev; ! 203: struct uio *uio; ! 204: { ! 205: register int d = minor(dev); ! 206: register struct tty *tp = &vx_tty[d]; ! 207: register struct vcx *xp = &vcx[d>>4]; ! 208: ! 209: d &= 0xf; ! 210: if (isprinter(xp, d)) ! 211: return(ENODEV); ! 212: return(*linesw[tp->t_line].l_read)(tp, uio); ! 213: } ! 214: ! 215: /* ! 216: * Write on a VX line. ! 217: */ ! 218: vxwrite(dev, uio) ! 219: dev_t dev; ! 220: struct uio *uio; ! 221: { ! 222: register int d = minor(dev); ! 223: register struct tty *tp = &vx_tty[d]; ! 224: ! 225: return(*linesw[tp->t_line].l_write)(tp, uio); ! 226: } ! 227: ! 228: /* ! 229: * VIOCX unsolicited interrupt. ! 230: */ ! 231: vxrint(n) ! 232: int n; /* mux number */ ! 233: { ! 234: register struct tty *tp; ! 235: register struct vcx *xp; ! 236: register short *sp; ! 237: register int i; ! 238: register unsigned int c; ! 239: register int port; ! 240: struct tty *tp0; ! 241: struct vblok *kp; ! 242: short *savsilo; ! 243: struct silo { ! 244: char data; ! 245: unsigned char port; ! 246: }; ! 247: ! 248: kp = VBAS(n); ! 249: xp = &vcx[n]; ! 250: #if VX_TESTING ! 251: c = kp->v_uqual&037; ! 252: if (vx_test&VX_PROC_ERR_DEBUG) ! 253: c = 2; ! 254: else if (vx_test&VX_UQUAL_ERR_DEBUG) ! 255: c = 5; ! 256: switch (c) { ! 257: #else ! 258: switch (kp->v_uqual&037) { ! 259: #endif ! 260: case 0: ! 261: break; ! 262: case 2: ! 263: printf(" ERR NBR %x\n", kp->v_ustat); ! 264: if (kp->v_ustat == 0x40) { ! 265: printf("VIOC %x lost some read data\n", n); ! 266: return(0); ! 267: } ! 268: vpanic("vc: VC PROC ERR"); ! 269: vxstreset(n); ! 270: return(0); ! 271: case 3: ! 272: vcmintr(n); ! 273: return(1); ! 274: case 4: ! 275: return(1); ! 276: default: ! 277: printf(" ERR NBR %x\n", kp->v_uqual); ! 278: vpanic("vc: VC UQUAL ERR"); ! 279: vxstreset(n); ! 280: return(0); ! 281: } ! 282: ! 283: /* ! 284: * Get the address of the silo in VIOC common memory. ! 285: */ ! 286: sp = (short *)((char *)kp + *(short *)kp->v_usdata); ! 287: ! 288: nextsilo: ! 289: ! 290: /* ! 291: * See if the number of characters is reasonable. ! 292: */ ! 293: i = *(savsilo = sp); ! 294: if (i > xp->v_silosiz) { ! 295: printf("vx: %d exceeds silo size\n", i); ! 296: i = xp->v_silosiz; ! 297: } ! 298: ! 299: /* ! 300: * Drain the silo. ! 301: */ ! 302: tp0 = &vx_tty[n<<4]; ! 303: for (sp++; i > 0; i--, sp++) { ! 304: port = ((struct silo *)sp)->port&017; ! 305: if (port < xp->v_loport || port > xp->v_hiport) ! 306: /* ! 307: * Not a valid port. ! 308: */ ! 309: continue; ! 310: ! 311: tp = tp0 + port; ! 312: if ((tp->t_state&TS_ISOPEN) == 0) ! 313: /* ! 314: * Nobody is listening. ! 315: */ ! 316: continue; ! 317: ! 318: /* ! 319: * Fetch the character from vioc memory. ! 320: */ ! 321: c = ((struct silo *)sp)->data; ! 322: ! 323: switch (((struct silo *)sp)->port&(PERROR|FERROR)) { ! 324: case PERROR: ! 325: case PERROR|FERROR: ! 326: if ((tp->t_flags&(EVENP|ODDP)) == EVENP || ! 327: (tp->t_flags&(EVENP|ODDP)) == ODDP) ! 328: continue; ! 329: if (!(((struct silo *)sp)->port&FERROR)) ! 330: break; ! 331: ! 332: case FERROR: ! 333: if (tp->t_flags&RAW) ! 334: c = 0; ! 335: else ! 336: c = tp->t_intrc; ! 337: } ! 338: (*linesw[tp->t_line].l_rint)(c, tp); ! 339: } ! 340: *savsilo = 0; ! 341: return(1); ! 342: } ! 343: ! 344: /* ! 345: * stty/gtty for VX. ! 346: */ ! 347: vxioctl(dev, cmd, data, flag) ! 348: int dev; /* major, minor device numbers */ ! 349: int cmd; /* command */ ! 350: caddr_t data; ! 351: int flag; ! 352: { ! 353: register int d = minor(dev); ! 354: register struct tty *tp = &vx_tty[d]; ! 355: register int error; ! 356: ! 357: switch (cmd) { ! 358: case VCMANUAL: ! 359: case VCGRS232: ! 360: case VCSRS232: ! 361: /* ! 362: * Intercept device specific commands. ! 363: */ ! 364: return(vcumodem(dev, cmd, data, flag)); ! 365: default: ! 366: break; ! 367: } ! 368: ! 369: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag); ! 370: if (error == 0) ! 371: return(error); ! 372: if ((error = ttioctl(tp, cmd, data, flag)) >= 0) ! 373: { ! 374: if (cmd==TIOCSETP||cmd==TIOCSETN) ! 375: vxparam(dev); ! 376: return(error); ! 377: } else ! 378: return(ENOTTY); ! 379: } ! 380: ! 381: vxparam(dev) ! 382: dev_t dev; ! 383: { ! 384: vxcparam(dev, 1); ! 385: } ! 386: ! 387: /* ! 388: * Set parameters from open or stty into the VX hardware ! 389: * registers. ! 390: */ ! 391: vxcparam(dev, wait) ! 392: dev_t dev; /* major, minor device numbers */ ! 393: int wait; /* nonzero if we should wait for finish */ ! 394: { ! 395: register struct tty *tp; ! 396: register struct vcx *xp; ! 397: register struct vxcmd *cp; ! 398: register int s = spl8(); ! 399: ! 400: tp = &vx_tty[minor(dev)]; /* pointer to tty structure for port */ ! 401: xp = (struct vcx *)tp->t_addr; /* pointer to VIOCX info/cmd buffer */ ! 402: ! 403: cp = vobtain(xp); ! 404: cp->cmd = LPARAX; /* set command to "load parameters" */ ! 405: cp->par[1] = minor(dev)&017; /* port number */ ! 406: ! 407: /* ! 408: * Check for XON/XOFF flow control. ! 409: */ ! 410: cp->par[2] = (tp->t_flags&RAW)? 0 : tp->t_startc; /* XON char */ ! 411: cp->par[3] = (tp->t_flags&RAW)? 0 : tp->t_stopc; /* XOFF char */ ! 412: ! 413: if (tp->t_flags&(RAW|LITOUT) || ! 414: (tp->t_flags&(EVENP|ODDP)) == (EVENP|ODDP)) { ! 415: cp->par[4] = 0xc0; /* 8 bits of data */ ! 416: cp->par[7] = 0; /* no parity */ ! 417: } else { ! 418: cp->par[4] = 0x40; /* 7 bits of data */ ! 419: if ((tp->t_flags&(EVENP|ODDP)) == ODDP) ! 420: cp->par[7] = 1; /* odd parity */ ! 421: else if ((tp->t_flags&(EVENP|ODDP)) == EVENP) ! 422: cp->par[7] = 3; /* even parity */ ! 423: else ! 424: cp->par[7] = 0; /* no parity */ ! 425: } ! 426: cp->par[5] = (tp->t_stopbits == 0) ? 4 : tp->t_stopbits; ! 427: if (tp->t_ospeed == EXTA || tp->t_ospeed == EXTB) ! 428: cp->par[6] = 19; /* 19200 BAUD */ ! 429: else ! 430: cp->par[6] = tp->t_ospeed; ! 431: ! 432: if (vcmd(xp->v_nbr, &cp->cmd) && wait) ! 433: sleep(cp, TTIPRI); ! 434: splx(s); ! 435: } ! 436: ! 437: /* ! 438: * VIOCX command response interrupt. ! 439: * For transmission, restart output to any active port. ! 440: * For all other commands, just clean up. ! 441: * This routine is called with spl8 from vcmdrsp(). ! 442: */ ! 443: vxxint(n, cp) ! 444: register int n; /* VIOC number */ ! 445: register struct vxcmd *cp; /* command structure */ ! 446: { ! 447: register struct vxmit *vp, *pvp; ! 448: register struct tty *tp; ! 449: register struct vcx *xp; ! 450: register struct tty *hp; ! 451: register int port; ! 452: ! 453: xp = &vcx[n]; ! 454: cp = (struct vxcmd *)((long *)cp-1); ! 455: #if NVBSC > 0 ! 456: switch (cp->cmd) { ! 457: case MDMCTL1: case HUNTMD1: case LPARAX1: ! 458: vrelease(xp, cp); ! 459: wakeup(cp); ! 460: return; ! 461: } ! 462: #endif ! 463: switch (cp->cmd&0xff00) { ! 464: case LIDENT: /* initialization complete */ ! 465: if (xp->v_state&V_RESETTING) ! 466: vxfnreset(n, cp); ! 467: cp->cmd++; ! 468: return; ! 469: case XMITDTA: case XMITIMM: ! 470: break; ! 471: case LPARAX: ! 472: wakeup(cp); ! 473: case FDTATOX: ! 474: default: /* MDMCTL or FDTATOX */ ! 475: vrelease(xp, cp); ! 476: return; ! 477: } ! 478: for (vp = (struct vxmit *)(cp->par + (cp->cmd&07)*sizvxmit); ! 479: vp >= (struct vxmit *)cp->par; ! 480: vp = (struct vxmit *) ((char *)vp - sizvxmit)) { ! 481: tp = &vx_tty[(vp->line&017)+(n<<4)]; ! 482: ! 483: #if NVBSC > 0 ! 484: port = vp->line; ! 485: if (tp->t_line == LDISP) { ! 486: vrelease(xp, cp); ! 487: /* ! 488: * Call bsctxd with logical bscport no; 0,1..4,5. ! 489: * v_xmtcnt was set to BISYNC ctlr no in vxinit(). ! 490: */ ! 491: bsctxd((xp->v_xmtcnt*NBSC)+port); ! 492: return; ! 493: } ! 494: if (bscport[(n<<4)+port] == BISYNC) { ! 495: printf("\nvxxint: int. after line closed. (cmd:%lx)", ! 496: cp->cmd&0xff); ! 497: vrelease(xp, cp); ! 498: return; ! 499: } ! 500: #endif ! 501: pvp = vp; ! 502: tp->t_state &= ~TS_BUSY; ! 503: if (tp->t_state&TS_FLUSH) { ! 504: tp->t_state &= ~TS_FLUSH; ! 505: wakeup((caddr_t)&tp->t_state); ! 506: } ! 507: else ! 508: ndflush(&tp->t_outq, vp->bcount+1); ! 509: } ! 510: xp->v_xmtcnt--; ! 511: vrelease(xp, cp); ! 512: vp = pvp; ! 513: vxstart(tp); ! 514: return; ! 515: } ! 516: ! 517: /* ! 518: * Start (restart) transmission on the given VX line. ! 519: */ ! 520: vxstart(tp) ! 521: register struct tty *tp; ! 522: { ! 523: register short nch; ! 524: register struct vcx *xp; ! 525: register char *outb; ! 526: register full = 0; ! 527: int s, port; ! 528: ! 529: s = spl8(); ! 530: port = minor(tp->t_dev)&017; ! 531: xp = (struct vcx *)tp->t_addr; ! 532: if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) { ! 533: if (tp->t_outq.c_cc <= TTLOWAT(tp)) { ! 534: if (tp->t_state&TS_ASLEEP) { ! 535: tp->t_state &= ~TS_ASLEEP; ! 536: wakeup((caddr_t)&tp->t_outq); ! 537: } ! 538: if (tp->t_wsel) { ! 539: selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL); ! 540: tp->t_wsel = 0; ! 541: tp->t_state &= ~TS_WCOLL; ! 542: } ! 543: } ! 544: if (tp->t_outq.c_cc == 0) { ! 545: splx(s); ! 546: return(0); ! 547: } ! 548: #ifdef VXPERF ! 549: scope_out(3); ! 550: #endif VXPERF ! 551: if (!(tp->t_flags&(RAW|LITOUT))) ! 552: full = 0200; ! 553: if ((nch = ndqb(&tp->t_outq, full)) == 0) { ! 554: if (full) { ! 555: nch = getc(&tp->t_outq); ! 556: timeout(ttrstrt, (caddr_t)tp, (nch&0177) +6); ! 557: tp->t_state |= TS_TIMEOUT; ! 558: full = 0; ! 559: } ! 560: } else { ! 561: outb = (char *)tp->t_outq.c_cf; ! 562: tp->t_state |= TS_BUSY; ! 563: vsend(xp, port, outb, nch); ! 564: } ! 565: } ! 566: splx(s); ! 567: return; ! 568: } ! 569: ! 570: /* ! 571: * Stop output on a line. ! 572: */ ! 573: vxstop(tp) ! 574: register struct tty *tp; ! 575: { ! 576: register int s; ! 577: ! 578: s = spl8(); ! 579: if (tp->t_state&TS_BUSY) { ! 580: if ((tp->t_state&TS_TTSTOP)==0) { ! 581: tp->t_state |= TS_FLUSH; ! 582: } ! 583: } ! 584: splx(s); ! 585: } ! 586: ! 587: /* ! 588: * VIOCX Initialization. Makes free lists of command buffers. ! 589: * Resets all viocx's. Issues a LIDENT command to each ! 590: * viocx which establishes interrupt vectors and logical ! 591: * port numbers. ! 592: */ ! 593: vxinit(i, wait) ! 594: register int i; ! 595: int wait; ! 596: { ! 597: register struct vcx *xp; /* ptr to VIOC-X info/cmd buffer */ ! 598: register struct vblok *kp; /* pointer to VIOC-X control block */ ! 599: register struct vxcmd *cp; /* pointer to a command buffer */ ! 600: register char *resp; /* pointer to response buffer */ ! 601: register int j, ix; ! 602: register struct vcmds *cpp; ! 603: char type; ! 604: #if NVBSC > 0 ! 605: register struct bsc *bp; /* bsc change */ ! 606: #endif ! 607: ! 608: /* ! 609: * Only initialize once. ! 610: */ ! 611: if (vbtbl) { ! 612: for (j = 0;j < NVIOCX; j++) ! 613: vxbopno[j] = (char)-1; ! 614: vbtbl = 0; ! 615: } ! 616: ! 617: kp = VBAS(i); /* get base adr of cntl blok for VIOC */ ! 618: xp = &vcx[i]; /* index info/command buffers */ ! 619: ! 620: cpp = &v_cmds[i]; ! 621: type = kp->v_ident; ! 622: vxtype[i] = 0; /* Type is VIOC-X */ ! 623: switch (type) { ! 624: case PVIOCX: ! 625: case VIOCX: ! 626: printf("WARNING: Old vioc no longer supported.\n"); ! 627: xp->v_loport = xp->v_hiport = 0; ! 628: return; ! 629: ! 630: case NWVIOCX: ! 631: case NPVIOCX: ! 632: xp->v_vers = V_NEW; ! 633: xp->v_silosiz = kp->v_maxsilo; ! 634: /* ! 635: * Initialize the port types. ! 636: */ ! 637: for (j = 0; j < 16; j++) ! 638: xp->vx_type[j] = kp->v_portyp[j]; ! 639: break; ! 640: ! 641: case VIOCB: /* old f/w, Bisync board */ ! 642: if (wait) { /* Just boot up */ ! 643: if (bscno >= NVBSC) { ! 644: printf("\nVIOCB no%ld is not configured in software", bscno); ! 645: break; ! 646: } ! 647: if (bscno >= MXVIOC_B) { ! 648: printf("\nvxinit: exceed max no of VIOC-B:%ld", ! 649: MXVIOC_B); ! 650: break; ! 651: } ! 652: } ! 653: printf("(kp:%lx)(xp:%lx): %lx---%x OLD VIOC-B, ", ! 654: (long)kp, (long)xp,(int)kp->v_ident, ! 655: (int)kp->v_fault); ! 656: xp->v_vers = V_OLD; ! 657: ! 658: if (wait) /* Use v_xmtcnt to */ ! 659: xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */ ! 660: else ! 661: bscno = (long)xp->v_xmtcnt&0x7f; ! 662: ! 663: bp = &bsc[0+(bscno*4)]; ! 664: for (ix = 0; ix < 4; ix++, bp++) ! 665: bp->b_devregs = (caddr_t)xp; ! 666: bscno++; ! 667: bscport[(i<<4)+0] = BISYNC; ! 668: bscport[(i<<4)+1] = BISYNC; ! 669: bscport[(i<<4)+2] = BISYNC; ! 670: bscport[(i<<4)+3] = BISYNC; ! 671: printf(" Bisync initialized\n"); ! 672: break; ! 673: ! 674: case NWVIOCB: /* new f/w, Bisync board */ ! 675: if (wait) { /* Just boot up */ ! 676: if (bscno >= NVBSC) { ! 677: printf("\nVIOCB no%ld is not configured in software", bscno); ! 678: break; ! 679: } ! 680: if (bscno >= MXVIOC_B) { ! 681: printf("\nvxinit: exceed max no of VIOC-B:%ld", ! 682: MXVIOC_B); ! 683: break; ! 684: } ! 685: } ! 686: xp->v_vers = V_NEW; ! 687: xp->v_silosiz = kp->v_maxsilo; ! 688: ! 689: if (wait) /* Use v_xmtcnt to */ ! 690: xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */ ! 691: else ! 692: bscno = (long)xp->v_xmtcnt&0x7f; ! 693: ! 694: bp = &bsc[bscno*4]; ! 695: for (ix = 0; ix < 4; ix++, bp++) ! 696: bp->b_devregs = (caddr_t)xp; ! 697: bscno++; ! 698: bscport[(i<<4)+0] = BISYNC; ! 699: bscport[(i<<4)+1] = BISYNC; ! 700: bscport[(i<<4)+2] = BISYNC; ! 701: bscport[(i<<4)+3] = BISYNC; ! 702: printf(" Bisync initialized\n"); ! 703: break; ! 704: ! 705: case VBOPID: /* VIOC-BOP */ ! 706: if (vxtype[i] == 0) { /* don't increment if already seen */ ! 707: vxbbno++; ! 708: vxtype[i] = 1; ! 709: vxbopno[i] = vxbbno; ! 710: } ! 711: printf(" VIOC-BOP initialized\n"); ! 712: ! 713: default: ! 714: return; /* Not a viocx type */ ! 715: } ! 716: xp->v_nbr = -1; /* no number for it yet */ ! 717: xp->v_maxcmd = xp->v_vers == V_NEW ? 23 : 3; ! 718: ! 719: for (j = 0; j < NVCXBUFS; j++) {/* init all cmd buffers */ ! 720: cp = &xp->vx_lst[j]; /* index a buffer */ ! 721: cp->c_fwd = &xp->vx_lst[j+1]; /* point to next buf */ ! 722: } ! 723: xp->vx_avail = &xp->vx_lst[0]; /* set idx to 1st free buf */ ! 724: cp->c_fwd = (struct vxcmd *)0; /* mark last buf in free list */ ! 725: ! 726: /* ! 727: * Assures proper state when reinit. in case of INT. ERR ! 728: */ ! 729: cpp->v_cmdsem = cpp->v_curcnt = cpp->v_fill = 0; ! 730: cpp->v_empty = cpp->v_itrfill = cpp->v_itrempt = 0; ! 731: ! 732: cp = vobtain(xp); /* grap the control block */ ! 733: cp->cmd = LIDENT; /* set command type */ ! 734: cp->par[0] = i * 4 + VCVECT; /* ack vector */ ! 735: cp->par[1] = cp->par[0] + 1; /* cmd resp vector */ ! 736: cp->par[3] = cp->par[0] + 2; /* unsol intr vector */ ! 737: cp->par[4] = 15; /* max ports, no longer used */ ! 738: cp->par[5] = 0; /* set 1st port number */ ! 739: vcmd(i, &cp->cmd); /* initialize the VIOC-X */ ! 740: if (!wait) ! 741: return; ! 742: ! 743: while (cp->cmd == LIDENT) /* wait for command completion */ ! 744: ; ! 745: ! 746: /* ! 747: * Calculate address of response buffer. ! 748: */ ! 749: resp = (char *)kp; ! 750: resp += kp->v_rspoff&0x3FFF; ! 751: ! 752: if (resp[0] != 0 && (resp[0]&0177) != 3) { /* did init work? */ ! 753: vrelease(xp, cp); /* init failed */ ! 754: return; /* try next VIOC-X */ ! 755: } ! 756: ! 757: xp->v_loport = cp->par[5]; /* save low port number */ ! 758: xp->v_hiport = cp->par[7]; /* VIOC knows high port numbr */ ! 759: vrelease(xp, cp); /* done with this control block */ ! 760: xp->v_nbr = i; /* assign VIOC-X board number */ ! 761: } ! 762: ! 763: /* ! 764: * Obtain a command buffer. ! 765: */ ! 766: struct vxcmd * ! 767: vobtain(xp) ! 768: register struct vcx *xp; ! 769: { ! 770: register struct vxcmd *p; ! 771: register int s; ! 772: ! 773: s = spl8(); ! 774: p = xp->vx_avail; ! 775: if (p == (struct vxcmd *)0) { ! 776: vpanic("vx: no buffs"); ! 777: vxstreset(xp - vcx); ! 778: splx(s); ! 779: return(vobtain(xp)); /* guaranteed to work this time */ ! 780: } ! 781: xp->vx_avail = (xp->vx_avail)->c_fwd; ! 782: splx(s); ! 783: return((struct vxcmd *)p); ! 784: } ! 785: ! 786: /* ! 787: * Release a command buffer. ! 788: */ ! 789: vrelease(xp, cp) ! 790: register struct vcx *xp; ! 791: register struct vxcmd *cp; ! 792: { ! 793: register int s = spl8(); ! 794: ! 795: cp->c_fwd = xp->vx_avail; ! 796: xp->vx_avail = cp; ! 797: splx(s); ! 798: } ! 799: ! 800: /* ! 801: * Arrange for "cnt" bytes from "addr" to be written to port number ! 802: * "port" on VIOC described by "xp". ! 803: */ ! 804: vsend(xp, port, addr, cnt) ! 805: register struct vcx *xp;/* points to vioc control structure for this port */ ! 806: int port; /* port number to get the data */ ! 807: caddr_t addr; /* beginning address of the block */ ! 808: register int cnt; /* size of the block of characters */ ! 809: { ! 810: register struct vxcmd *cp; ! 811: register struct vxmit *mp; ! 812: register int i; ! 813: register char *src, *dst; ! 814: ! 815: /* ! 816: * Get a command. ! 817: */ ! 818: cp = vobtain(xp); ! 819: ! 820: /* ! 821: * Fill out the port information. ! 822: */ ! 823: mp = (struct vxmit *)cp->par; ! 824: mp->bcount = cnt-1; ! 825: mp->line = port; ! 826: ! 827: if (cnt <= 6) { ! 828: /* ! 829: * If small enough, we can give the data directly to ! 830: * the vioc, eliminating the need for DMA. ! 831: */ ! 832: cp->cmd = XMITIMM; ! 833: src = addr; ! 834: i = cnt; ! 835: } else { ! 836: /* ! 837: * Get the physical address of the block to DMA. ! 838: */ ! 839: cp->cmd = XMITDTA; ! 840: addr = vtoph(0, (caddr_t)addr); ! 841: src = (char *)&addr; ! 842: i = sizeof(addr); ! 843: } ! 844: ! 845: /* ! 846: * Copy the data or address into the command. ! 847: */ ! 848: dst = mp->ostream; ! 849: while (--i >= 0) ! 850: *dst++ = *src++; ! 851: ! 852: xp->v_xmtcnt++; ! 853: vcmd(xp->v_nbr, (char *)&cp->cmd); ! 854: return; ! 855: } ! 856: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.