|
|
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
1.1.1.2 ! root 23:
1.1 root 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;
1.1.1.2 ! root 30: extern struct bsc bsc[];
1.1 root 31: #endif
32:
33: #define RSPquals 1
34:
1.1.1.2 ! root 35: struct vcx vcx[NVIOCX];
! 36: struct tty vx_tty[NVXPORTS];
! 37: extern struct vcmds v_cmds[];
! 38: struct vba_device *vxinfo[NVIOCX];
1.1 root 39:
1.1.1.2 ! root 40: int vxstart();
! 41: int ttrstrt();
1.1 root 42: caddr_t vtoph();
1.1.1.2 ! root 43: struct vxcmd *vobtain();
1.1 root 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[] */
1.1.1.2 ! root 56: char vxbbno = -1;
1.1 root 57: short vbtbl = -1;
1.1.1.2 ! root 58: int vx_cnt = NVXPORTS; /* needed by vmstat/iostat */
1.1 root 59: extern vbrall();
60:
61: vxprobe(reg)
1.1.1.2 ! root 62: caddr_t reg;
1.1 root 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:
1.1.1.2 ! root 71: if (badaddr(vp, 1))
1.1 root 72: return(0);
1.1.1.2 ! root 73: vp->v_fault = 0;
! 74: vp->v_vioc = V_BSY;
! 75: vp->v_hdwre = V_RESET; /* reset interrupt */
1.1 root 76:
77: DELAY(4000000);
1.1.1.2 ! root 78: if (vp->v_fault != VREADY)
! 79: return(0);
! 80: return(1);
1.1 root 81: }
82:
83: vxattach(ui)
1.1.1.2 ! root 84: register struct vba_device *ui;
1.1 root 85: {
86: VIOCBAS[ui->ui_unit] = ui->ui_addr;
1.1.1.2 ! root 87: vxinit(ui->ui_unit, 1);
1.1 root 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 */
1.1.1.2 ! root 97: register int d; /* minor device number */
! 98: register int error;
1.1 root 99:
100: d = minor(dev); /* get minor device number */
101: if (d >= NVXPORTS) /* validate minor device number */
1.1.1.2 ! root 102: return(ENXIO); /* set errno to indicate bad port # */
1.1 root 103: tp = &vx_tty[d]; /* index the tty structure for port */
104:
1.1.1.2 ! root 105: xp = &vcx[d>>4]; /* index VIOC-X info/cmd area */
1.1 root 106: d &= 017;
107:
1.1.1.2 ! root 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? */
1.1 root 130: ttychars(tp); /* set default control chars */
1.1.1.2 ! root 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 */
1.1 root 137: tp->t_flags |= (ODDP|EVENP|ECHO); /* default modes */
138: }
139: vxparam(dev); /* set parameters for this port */
140: }
1.1.1.2 ! root 141: /*
! 142: * If already open for exclusive use open fails unless caller is root.
! 143: */
1.1 root 144: if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
1.1.1.2 ! root 145: return(EBUSY); /* device is busy, sorry */
1.1 root 146:
147: d = spl8();
1.1.1.2 ! root 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);
1.1 root 163: }
164:
165: /*
166: * Close a VX line.
167: */
168: vxclose(dev, flag)
169: dev_t dev;
170: int flag;
171: {
1.1.1.2 ! root 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);
1.1 root 193: ttyclose(tp); /* let tty.c finish the close */
1.1.1.2 ! root 194: splx(s);
! 195: return(error);
1.1 root 196: }
197:
198: /*
199: * Read from a VX line.
200: */
201: vxread(dev, uio)
1.1.1.2 ! root 202: dev_t dev;
! 203: struct uio *uio;
1.1 root 204: {
1.1.1.2 ! root 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);
1.1 root 213: }
214:
215: /*
1.1.1.2 ! root 216: * Write on a VX line.
1.1 root 217: */
218: vxwrite(dev, uio)
1.1.1.2 ! root 219: dev_t dev;
! 220: struct uio *uio;
1.1 root 221: {
1.1.1.2 ! root 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);
1.1 root 226: }
227:
228: /*
229: * VIOCX unsolicited interrupt.
230: */
231: vxrint(n)
1.1.1.2 ! root 232: int n; /* mux number */
1.1 root 233: {
234: register struct tty *tp;
235: register struct vcx *xp;
236: register short *sp;
1.1.1.2 ! root 237: register int i;
! 238: register unsigned int c;
! 239: register int port;
! 240: struct tty *tp0;
! 241: struct vblok *kp;
1.1 root 242: short *savsilo;
243: struct silo {
1.1.1.2 ! root 244: char data;
! 245: unsigned char port;
1.1 root 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
1.1.1.2 ! root 258: switch (kp->v_uqual&037) {
1.1 root 259: #endif
260: case 0:
261: break;
262: case 2:
1.1.1.2 ! root 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: }
1.1 root 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:
1.1.1.2 ! root 277: printf(" ERR NBR %x\n", kp->v_uqual);
1.1 root 278: vpanic("vc: VC UQUAL ERR");
279: vxstreset(n);
280: return(0);
281: }
1.1.1.2 ! root 282:
! 283: /*
! 284: * Get the address of the silo in VIOC common memory.
! 285: */
! 286: sp = (short *)((char *)kp + *(short *)kp->v_usdata);
! 287:
1.1 root 288: nextsilo:
1.1.1.2 ! root 289:
! 290: /*
! 291: * See if the number of characters is reasonable.
! 292: */
1.1 root 293: i = *(savsilo = sp);
1.1.1.2 ! root 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: */
1.1 root 309: continue;
1.1.1.2 ! root 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: */
1.1 root 321: c = ((struct silo *)sp)->data;
1.1.1.2 ! root 322:
! 323: switch (((struct silo *)sp)->port&(PERROR|FERROR)) {
1.1 root 324: case PERROR:
325: case PERROR|FERROR:
1.1.1.2 ! root 326: if ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
! 327: (tp->t_flags&(EVENP|ODDP)) == ODDP)
1.1 root 328: continue;
1.1.1.2 ! root 329: if (!(((struct silo *)sp)->port&FERROR))
1.1 root 330: break;
1.1.1.2 ! root 331:
1.1 root 332: case FERROR:
1.1.1.2 ! root 333: if (tp->t_flags&RAW)
! 334: c = 0;
! 335: else
! 336: c = tp->t_intrc;
1.1 root 337: }
338: (*linesw[tp->t_line].l_rint)(c, tp);
339: }
340: *savsilo = 0;
341: return(1);
342: }
343:
344: /*
1.1.1.2 ! root 345: * stty/gtty for VX.
1.1 root 346: */
347: vxioctl(dev, cmd, data, flag)
1.1.1.2 ! root 348: int dev; /* major, minor device numbers */
! 349: int cmd; /* command */
1.1 root 350: caddr_t data;
1.1.1.2 ! root 351: int flag;
1.1 root 352: {
1.1.1.2 ! root 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: }
1.1 root 368:
369: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
370: if (error == 0)
1.1.1.2 ! root 371: return(error);
! 372: if ((error = ttioctl(tp, cmd, data, flag)) >= 0)
1.1 root 373: {
374: if (cmd==TIOCSETP||cmd==TIOCSETN)
375: vxparam(dev);
1.1.1.2 ! root 376: return(error);
1.1 root 377: } else
1.1.1.2 ! root 378: return(ENOTTY);
1.1 root 379: }
380:
381: vxparam(dev)
1.1.1.2 ! root 382: dev_t dev;
1.1 root 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)
1.1.1.2 ! root 392: dev_t dev; /* major, minor device numbers */
1.1 root 393: int wait; /* nonzero if we should wait for finish */
394: {
1.1.1.2 ! root 395: register struct tty *tp;
! 396: register struct vcx *xp;
! 397: register struct vxcmd *cp;
! 398: register int s = spl8();
1.1 root 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 */
1.1.1.2 ! root 402:
1.1 root 403: cp = vobtain(xp);
404: cp->cmd = LPARAX; /* set command to "load parameters" */
405: cp->par[1] = minor(dev)&017; /* port number */
406:
1.1.1.2 ! root 407: /*
! 408: * Check for XON/XOFF flow control.
! 409: */
1.1 root 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:
1.1.1.2 ! root 413: if (tp->t_flags&(RAW|LITOUT) ||
1.1 root 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 */
1.1.1.2 ! root 419: if ((tp->t_flags&(EVENP|ODDP)) == ODDP)
1.1 root 420: cp->par[7] = 1; /* odd parity */
1.1.1.2 ! root 421: else if ((tp->t_flags&(EVENP|ODDP)) == EVENP)
1.1 root 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;
1.1.1.2 ! root 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;
1.1 root 431:
432: if (vcmd(xp->v_nbr, &cp->cmd) && wait)
1.1.1.2 ! root 433: sleep(cp, TTIPRI);
1.1 root 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.
1.1.1.2 ! root 441: * This routine is called with spl8 from vcmdrsp().
1.1 root 442: */
1.1.1.2 ! root 443: vxxint(n, cp)
1.1 root 444: register int n; /* VIOC number */
1.1.1.2 ! root 445: register struct vxcmd *cp; /* command structure */
1.1 root 446: {
1.1.1.2 ! root 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;
1.1 root 452:
453: xp = &vcx[n];
1.1.1.2 ! root 454: cp = (struct vxcmd *)((long *)cp-1);
1.1 root 455: #if NVBSC > 0
1.1.1.2 ! root 456: switch (cp->cmd) {
1.1 root 457: case MDMCTL1: case HUNTMD1: case LPARAX1:
458: vrelease(xp, cp);
459: wakeup(cp);
460: return;
461: }
462: #endif
1.1.1.2 ! root 463: switch (cp->cmd&0xff00) {
1.1 root 464: case LIDENT: /* initialization complete */
1.1.1.2 ! root 465: if (xp->v_state&V_RESETTING)
! 466: vxfnreset(n, cp);
1.1 root 467: cp->cmd++;
468: return;
469: case XMITDTA: case XMITIMM:
470: break;
471: case LPARAX:
472: wakeup(cp);
1.1.1.2 ! root 473: case FDTATOX:
1.1 root 474: default: /* MDMCTL or FDTATOX */
475: vrelease(xp, cp);
476: return;
477: }
1.1.1.2 ! root 478: for (vp = (struct vxmit *)(cp->par + (cp->cmd&07)*sizvxmit);
1.1 root 479: vp >= (struct vxmit *)cp->par;
1.1.1.2 ! root 480: vp = (struct vxmit *) ((char *)vp - sizvxmit)) {
! 481: tp = &vx_tty[(vp->line&017)+(n<<4)];
1.1 root 482:
483: #if NVBSC > 0
484: port = vp->line;
485: if (tp->t_line == LDISP) {
1.1.1.2 ! root 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: */
1.1 root 491: bsctxd((xp->v_xmtcnt*NBSC)+port);
1.1.1.2 ! root 492: return;
1.1 root 493: }
494: if (bscport[(n<<4)+port] == BISYNC) {
495: printf("\nvxxint: int. after line closed. (cmd:%lx)",
496: cp->cmd&0xff);
1.1.1.2 ! root 497: vrelease(xp, cp);
! 498: return;
1.1 root 499: }
500: #endif
501: pvp = vp;
502: tp->t_state &= ~TS_BUSY;
1.1.1.2 ! root 503: if (tp->t_state&TS_FLUSH) {
1.1 root 504: tp->t_state &= ~TS_FLUSH;
1.1.1.2 ! root 505: wakeup((caddr_t)&tp->t_state);
1.1 root 506: }
507: else
508: ndflush(&tp->t_outq, vp->bcount+1);
509: }
510: xp->v_xmtcnt--;
1.1.1.2 ! root 511: vrelease(xp, cp);
! 512: vp = pvp;
! 513: vxstart(tp);
! 514: return;
1.1 root 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;
1.1.1.2 ! root 524: register struct vcx *xp;
1.1 root 525: register char *outb;
526: register full = 0;
1.1.1.2 ! root 527: int s, port;
1.1 root 528:
529: s = spl8();
1.1.1.2 ! root 530: port = minor(tp->t_dev)&017;
1.1 root 531: xp = (struct vcx *)tp->t_addr;
532: if (!(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))) {
1.1.1.2 ! root 533: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
1.1 root 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) {
1.1.1.2 ! root 539: selwakeup(tp->t_wsel, tp->t_state&TS_WCOLL);
1.1 root 540: tp->t_wsel = 0;
541: tp->t_state &= ~TS_WCOLL;
542: }
543: }
1.1.1.2 ! root 544: if (tp->t_outq.c_cc == 0) {
1.1 root 545: splx(s);
546: return(0);
547: }
548: #ifdef VXPERF
1.1.1.2 ! root 549: scope_out(3);
1.1 root 550: #endif VXPERF
1.1.1.2 ! root 551: if (!(tp->t_flags&(RAW|LITOUT)))
1.1 root 552: full = 0200;
1.1.1.2 ! root 553: if ((nch = ndqb(&tp->t_outq, full)) == 0) {
! 554: if (full) {
1.1 root 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;
1.1.1.2 ! root 563: vsend(xp, port, outb, nch);
1.1 root 564: }
565: }
566: splx(s);
1.1.1.2 ! root 567: return;
1.1 root 568: }
569:
570: /*
571: * Stop output on a line.
572: */
573: vxstop(tp)
574: register struct tty *tp;
575: {
1.1.1.2 ! root 576: register int s;
1.1 root 577:
578: s = spl8();
1.1.1.2 ! root 579: if (tp->t_state&TS_BUSY) {
1.1 root 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
1.1.1.2 ! root 591: * port numbers.
1.1 root 592: */
1.1.1.2 ! root 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;
1.1 root 603: char type;
1.1.1.2 ! root 604: #if NVBSC > 0
! 605: register struct bsc *bp; /* bsc change */
! 606: #endif
1.1 root 607:
1.1.1.2 ! root 608: /*
! 609: * Only initialize once.
! 610: */
1.1 root 611: if (vbtbl) {
1.1.1.2 ! root 612: for (j = 0;j < NVIOCX; j++)
! 613: vxbopno[j] = (char)-1;
1.1 root 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 */
1.1.1.2 ! root 619:
1.1 root 620: cpp = &v_cmds[i];
621: type = kp->v_ident;
1.1.1.2 ! root 622: vxtype[i] = 0; /* Type is VIOC-X */
! 623: switch (type) {
! 624: case PVIOCX:
1.1 root 625: case VIOCX:
1.1.1.2 ! root 626: printf("WARNING: Old vioc no longer supported.\n");
! 627: xp->v_loport = xp->v_hiport = 0;
! 628: return;
! 629:
1.1 root 630: case NWVIOCX:
631: case NPVIOCX:
1.1.1.2 ! root 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:
1.1 root 641: case VIOCB: /* old f/w, Bisync board */
1.1.1.2 ! root 642: if (wait) { /* Just boot up */
! 643: if (bscno >= NVBSC) {
! 644: printf("\nVIOCB no%ld is not configured in software", bscno);
! 645: break;
! 646: }
1.1 root 647: if (bscno >= MXVIOC_B) {
648: printf("\nvxinit: exceed max no of VIOC-B:%ld",
649: MXVIOC_B);
650: break;
1.1.1.2 ! root 651: }
1.1 root 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);
1.1.1.2 ! root 656: xp->v_vers = V_OLD;
1.1 root 657:
658: if (wait) /* Use v_xmtcnt to */
659: xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */
1.1.1.2 ! root 660: else
! 661: bscno = (long)xp->v_xmtcnt&0x7f;
1.1 root 662:
663: bp = &bsc[0+(bscno*4)];
1.1.1.2 ! root 664: for (ix = 0; ix < 4; ix++, bp++)
! 665: bp->b_devregs = (caddr_t)xp;
1.1 root 666: bscno++;
1.1.1.2 ! root 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;
1.1 root 673:
674: case NWVIOCB: /* new f/w, Bisync board */
1.1.1.2 ! root 675: if (wait) { /* Just boot up */
! 676: if (bscno >= NVBSC) {
! 677: printf("\nVIOCB no%ld is not configured in software", bscno);
! 678: break;
! 679: }
1.1 root 680: if (bscno >= MXVIOC_B) {
681: printf("\nvxinit: exceed max no of VIOC-B:%ld",
682: MXVIOC_B);
683: break;
684: }
1.1.1.2 ! root 685: }
! 686: xp->v_vers = V_NEW;
! 687: xp->v_silosiz = kp->v_maxsilo;
1.1 root 688:
689: if (wait) /* Use v_xmtcnt to */
690: xp->v_xmtcnt = (char)bscno; /* save VIOC-B ctlrno */
1.1.1.2 ! root 691: else
! 692: bscno = (long)xp->v_xmtcnt&0x7f;
1.1 root 693:
694: bp = &bsc[bscno*4];
1.1.1.2 ! root 695: for (ix = 0; ix < 4; ix++, bp++)
! 696: bp->b_devregs = (caddr_t)xp;
1.1 root 697: bscno++;
1.1.1.2 ! root 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:
1.1 root 705: case VBOPID: /* VIOC-BOP */
1.1.1.2 ! root 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:
1.1 root 713: default:
1.1.1.2 ! root 714: return; /* Not a viocx type */
1.1 root 715: }
1.1.1.2 ! root 716: xp->v_nbr = -1; /* no number for it yet */
! 717: xp->v_maxcmd = xp->v_vers == V_NEW ? 23 : 3;
1.1 root 718:
1.1.1.2 ! root 719: for (j = 0; j < NVCXBUFS; j++) {/* init all cmd buffers */
1.1 root 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:
1.1.1.2 ! root 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 */
1.1 root 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 */
1.1.1.2 ! root 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 */
1.1 root 754: return; /* try next VIOC-X */
755: }
756:
757: xp->v_loport = cp->par[5]; /* save low port number */
1.1.1.2 ! root 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 */
1.1 root 761: }
762:
763: /*
1.1.1.2 ! root 764: * Obtain a command buffer.
1.1 root 765: */
766: struct vxcmd *
767: vobtain(xp)
1.1.1.2 ! root 768: register struct vcx *xp;
1.1 root 769: {
1.1.1.2 ! root 770: register struct vxcmd *p;
! 771: register int s;
1.1 root 772:
773: s = spl8();
774: p = xp->vx_avail;
1.1.1.2 ! root 775: if (p == (struct vxcmd *)0) {
1.1 root 776: vpanic("vx: no buffs");
777: vxstreset(xp - vcx);
778: splx(s);
1.1.1.2 ! root 779: return(vobtain(xp)); /* guaranteed to work this time */
1.1 root 780: }
781: xp->vx_avail = (xp->vx_avail)->c_fwd;
782: splx(s);
1.1.1.2 ! root 783: return((struct vxcmd *)p);
1.1 root 784: }
785:
786: /*
1.1.1.2 ! root 787: * Release a command buffer.
1.1 root 788: */
1.1.1.2 ! root 789: vrelease(xp, cp)
! 790: register struct vcx *xp;
! 791: register struct vxcmd *cp;
1.1 root 792: {
1.1.1.2 ! root 793: register int s = spl8();
1.1 root 794:
795: cp->c_fwd = xp->vx_avail;
796: xp->vx_avail = cp;
797: splx(s);
798: }
799:
800: /*
1.1.1.2 ! root 801: * Arrange for "cnt" bytes from "addr" to be written to port number
! 802: * "port" on VIOC described by "xp".
1.1 root 803: */
1.1.1.2 ! root 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);
1.1 root 819:
1.1.1.2 ! root 820: /*
! 821: * Fill out the port information.
! 822: */
! 823: mp = (struct vxmit *)cp->par;
! 824: mp->bcount = cnt-1;
! 825: mp->line = port;
1.1 root 826:
1.1.1.2 ! root 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;
1.1 root 835: } else {
1.1.1.2 ! root 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);
1.1 root 843: }
844:
1.1.1.2 ! root 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;
1.1 root 855: }
856: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.