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