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