|
|
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.