|
|
1.1 root 1: #define BSD41
2: #define VAXONE
3: #define TIMEOUT
4:
5: #ifdef MARVIN
6: #define TXDRIVER
7: #endif
8: #ifdef CANTOR
9: #define TXDRIVER
10: #endif
11: #ifdef HILBERT
12: #define TXDRIVER
13: #endif
14: #ifdef DAISY
15: #define TXDRIVER
16: #endif
17:
18: #ifdef USG5
19: #define NSN 1
20: #else
21: #include "sn.h"
22: #endif
23: #if NSN > 0
24:
25: #ifdef BSD41
26: #include "../h/param.h"
27: #include "../h/systm.h"
28: #include "../h/buf.h"
29: #include "../h/conf.h"
30: #include "../h/dir.h"
31: #include "../h/user.h"
32: #include "../h/pte.h"
33: #include "../h/map.h"
34: #include "../h/vm.h"
35: #include "../h/dk.h"
36: #include "../h/cmap.h"
37: #include "../h/ubareg.h"
38: #include "../h/ubavar.h"
39: #include "../h/cpu.h"
40: #include "../h/proc.h"
41: #include "../h/snet.h"
42: #include "../h/packet.h"
43: #include "../h/channel.h"
44: #include "../h/status.h"
45: #endif
46:
47: #ifdef SNDEBUG
48: int sndebug = 1;
49: #else
50: int sndebug = 0;
51: #endif
52:
53: /* flags for status */
54: #define INPUT 1
55: #define OUTPUT 2
56:
57: #define min(x,y) ((x) < (y) ? (x) : (y))
58: #define swab(x) (unsigned short)((((x)>>8)&0xff) | ((x) << 8))
59:
60: #define SNPRI 28
61:
62: #define CHKINIT 0xbf37
63:
64: struct device {
65: short drcs;
66: short drout;
67: short drin;
68: };
69:
70: /* Command and Status word */
71: #define CSR0 0x1
72: #define CSR1 0x2
73: #define RIE 0x20
74: #define TIE 0x40
75: #define TEMPTY 0x80
76: #define RFULL 0x8000
77:
78: /*
79: * CSR1 CSR0
80: * 0 0 Write Data
81: * 0 1 Write EOP
82: * 1 0 Write Command
83: * 1 1 Read Status
84: */
85: #define DATA_MODE (RIE)
86: #define EOP_MODE (CSR0 | RIE)
87: #define CMD_MODE (CSR1 | RIE)
88: #define STATUS_MODE (CSR0 | CSR1 | RIE)
89:
90: /* Command word format
91: *
92: * +-----------------------------------------------+
93: * | |B |R |A | | | |
94: * | |C |S |B | DID | | FCN |
95: * | |T |T |T | | | |
96: * +-----------------------------------------------+
97: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
98: */
99: /* Function codes */
100: #define NOP 0x0
101: #define BOARD_RESET 0x5
102: #define MASTER_CLEAR 0x6
103:
104: #define ABORT(did) (0x1000 | (did))
105: #define RESET(did) (0x2000 | (did))
106: #define BROAD_CAST(did) (0x4000 | (did))
107:
108:
109: /* SNET status word bits
110: *
111: * +-----------------------------------------------+
112: * | |E |S |I |O | | |
113: * | |O |N |B |B | | |
114: * | |P |K |E |E | | |
115: * +-----------------------------------------------+
116: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
117: */
118: #define OUTBUF_E 0x4
119: #define INBUF_E 0x8
120: #define SNACK 0x10 /* transmitter error */
121: #define EOP 0x20 /* we have read and EOP frame */
122:
123: static int sn_multiplex;
124:
125: struct openwait sn_openwait[NUMDEV];
126: struct openwait *sn_owhead, *sn_owtail;
127:
128: #define SNFILE(dev) (minor(dev) & 0x3f)
129: #define SNUNIT(dev) ((minor(dev) & 0xc0) >> 6)
130:
131: struct chdat sn_chans[NUMLCH];
132: #define MAXMSGLEN (512+8)
133: struct sn_buffers {
134: short inbuf[MAXMSGLEN];
135: short outbuf[MAXMSGLEN];
136: } sn_buffers[NUMLCH];
137:
138: #define NOPDID -1
139:
140: #ifdef TIMEOUT
141: #define CKFUZZ 4 /* number of timeouts we wait for a response */
142: #ifdef USG5
143: #define CKTICKS (HZ/4) /* number of ticks per timeout */
144: #else
145: #define CKTICKS (hz/4) /* number of ticks per timeout */
146: #endif
147:
148: int sn_state;
149: #define OPEN 1 /* set if at least one sn? is open */
150: #define TIMER 2 /* set if at timer is running */
151:
152: int cktimchk();
153: int sn_opncnt;
154: #endif TIMEOUT
155:
156: struct snmach snmach[NUMDEV] = {
157: { 1, 255 },
158: { 2, 254 },
159: { 3, 253 },
160: { 4, 252 },
161: { 5, 251 },
162: { 6, 250 },
163: { 7, 249 },
164: { 8, 248 } };
165:
166: int sn_once;
167:
168: #ifdef BSD42
169: #define RETURN(x) {return(x);}
170: #define ARGS(x) args->x
171: #else
172: #define RETURN(x) {u.u_error = x; return;}
173: #define ARGS(x) args.x
174: #endif
175:
176: #ifdef USG5
177: extern struct sninfo sn_sninfo[];
178: extern int sn_cnt;
179: extern struct device *sn_addr[];
180: #else
181: struct sninfo sn_sninfo[NSN];
182: int snprobe(), snattach();
183: struct uba_device *sndinfo[NSN];
184: u_short snstd[] = {0};
185: struct uba_driver sndriver =
186: { snprobe, 0, snattach, 0, snstd, "sn", sndinfo};
187:
188: snprobe(reg)
189: caddr_t reg;
190: {
191: register int br, cvec; /* value result */
192: register struct device *snaddr = (struct device *)reg;
193:
194: br = 0x15;
195: #ifdef VAXONE
196: cvec = 0510;
197: #else
198: #ifdef CANTOR
199: if (((int)snaddr & 017777) == 007770)
200: cvec = 0504;
201: if (((int)snaddr & 017777) == 007750)
202: cvec = 0464;
203: #else
204: cvec = 0504;
205: #endif
206: #endif
207: #ifdef BSD41
208: return(1);
209: #endif
210: #ifdef BSD42
211: return(sizeof(struct device));
212: #endif
213: }
214:
215: /*ARGSUSED*/
216: snattach(ui)
217: register struct uba_device *ui;
218: {
219: }
220: #endif
221:
222: snopen(dev, rw)
223: dev_t dev;
224: int rw;
225: {
226: register struct device *draddr;
227: #ifndef USG5
228: struct uba_device *ui;
229: #endif
230: register struct sninfo *sninfop;
231: int mdev = SNFILE(dev);
232: int unit = SNUNIT(dev);
233:
234: if( sndebug )
235: printf("snopen(%x,%x)\n", dev, rw);
236:
237: #ifdef USG5
238: if ( mdev > NUMDEV || unit >= sn_cnt) {
239: RETURN ( ENXIO );
240: }
241: draddr = sn_addr[unit];
242: #else
243: if (mdev > NUMDEV || unit >= NSN ||
244: (ui = sndinfo[unit]) == 0 || ui->ui_alive == 0) {
245: RETURN ( ENXIO );
246: }
247: draddr = (struct device *)ui->ui_addr;
248: #endif
249:
250: if ( sn_once == 0 ) {
251: struct chdat *cp = sn_chans;
252:
253: sn_once++;
254: for( ; cp<&sn_chans[NUMLCH]; cp++) {
255: cp->lchnum = -1;
256: cp->dlchnum = -1;
257: }
258: sn_owhead = sn_owtail = sn_openwait;
259: }
260:
261: sninfop = &sn_sninfo[unit];
262: spl6();
263: if (sninfop->sndevlock[mdev]++ != 0) {
264: spl0();
265: RETURN ( EBUSY );
266: }
267: #ifdef TIMEOUT
268: sn_opncnt++;
269: sn_state |= OPEN;
270: if ((sn_state & TIMER) == 0) {
271: sn_state |= TIMER;
272: timeout(cktimchk, (caddr_t)0, CKTICKS);
273: }
274: #endif TIMEOUT
275: if( sninfop->snlock++ == 0 ) {
276: #ifdef TXDRIVER
277: {
278: extern struct txinfo tx_sninfo[];
279:
280: if (tx_sninfo[unit].snlock != 0) {
281: spl0();
282: return;
283: }
284: }
285: #endif
286: draddr->drcs = CMD_MODE;
287: draddr->drout = 0;
288: draddr->drout = BOARD_RESET;
289: draddr->drout = 0;
290: draddr->drcs = DATA_MODE;
291: }
292:
293: spl0();
294: return(0);
295: }
296:
297: snclose(dev)
298: {
299: register struct chdat *cp;
300: #ifndef USG5
301: struct uba_device *ui;
302: #endif
303: register struct sninfo *sninfop;
304: register struct device *draddr;
305: int mdev = SNFILE(dev);
306: int unit = SNUNIT(dev);
307: int resetmachno;
308: struct openwait *curtail;
309:
310: if( sndebug )
311: printf("snclose(%x)\n", dev);
312: #ifdef USG5
313: if ( unit >= sn_cnt) {
314: RETURN ( ENXIO );
315: }
316: draddr = sn_addr[unit];
317: #else
318: if ( unit >= NSN) {
319: RETURN ( ENXIO );
320: }
321: ui = sndinfo[unit];
322: draddr = (struct device *)ui->ui_addr;
323: #endif
324:
325: sninfop = &sn_sninfo[unit];
326: spl6();
327: if( sninfop->snlock == 0 || mdev > NUMDEV
328: || sninfop->sndevlock[mdev] == 0 ) {
329: spl0();
330: RETURN ( ENXIO );
331: }
332:
333: resetmachno = -1;
334: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) {
335: if (cp->pdid == NOPDID)
336: resetmachno = cp->machno;
337: chclose(cp);
338: }
339: if (resetmachno != -1) {
340: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) {
341: if (cp->pdid == NOPDID && cp->machno == resetmachno)
342: goto noreset;
343: }
344: draddr->drcs = CMD_MODE;
345: draddr->drout = RESET(resetmachno << 8);
346: draddr->drcs = EOP_MODE;
347: draddr->drout = 0;
348: draddr->drcs = DATA_MODE;
349: }
350:
351: noreset:
352: for (curtail = sn_owtail; curtail != sn_owhead;
353: curtail = ownext(curtail)) {
354: if (curtail->pid == u.u_procp->p_pid) {
355: curtail->pid = 0;
356: goto nowakeup;
357: }
358: }
359: while (sn_owtail != sn_owhead) {
360: curtail = sn_owtail;
361: sn_owtail = ownext(sn_owtail);
362: if (curtail->pid) {
363: wakeup(curtail);
364: break;
365: }
366: }
367:
368: nowakeup:
369: sninfop->snlink[mdev] = 0;
370: sninfop->sndevlock[mdev] = 0;
371: #ifdef TIMEOUT
372: if (--sn_opncnt <= 0) {
373: sn_state &= ~OPEN;
374: sn_opncnt = 0;
375: }
376: #endif TIMEOUT
377: if (--sninfop->snlock == 0 ) {
378: #ifdef TXDRIVER
379: {
380: if (tx_sninfo[unit].snlock != 0)
381: return;
382: }
383: #endif
384: draddr->drcs &= ~RIE;
385: }
386: spl0();
387: return(0);
388: }
389:
390: static short ratshole[MAXMSGLEN];
391: static struct chdat ratschan;
392:
393: #ifdef USG5
394: snintr(unit)
395: #else
396: snrint(unit)
397: #endif
398: int unit;
399: {
400: register struct chdat *cp;
401: register short *sp, *dp;
402: register int i;
403: register struct sninfo *sninfop;
404: register struct device *draddr;
405: unsigned short chksum, xchk;
406: short len;
407: unsigned short chan;
408: short *osp;
409: #ifndef USG5
410: struct uba_device *ui;
411: #endif
412:
413: #ifdef USG5
414: draddr = sn_addr[unit];
415: #else
416: ui = sndinfo[unit];
417: draddr = (struct device *)ui->ui_addr;
418: #endif
419: dp = &draddr->drin;
420:
421: sninfop = &sn_sninfo[unit];
422: sninfop->snrcnt++;
423:
424: loop:
425: chksum = CHKINIT;
426:
427: chan = *dp;
428: #ifdef TXDRIVER
429: /* unusual process numbers go to tx driver */
430: if ((chan & 0xff) <= 200 || ((unsigned int)chan) >= 0x2000 ) {
431: txintrmt(unit, chan);
432: goto getstatus;
433: }
434: #endif
435: chksum ^= chan;
436: chan = swab(chan);
437: len = *dp;
438: chksum ^= len;
439: len = swab(len);
440: if( len > MAXMSGLEN ) {
441: sninfop->snnbadlen++;
442: goto getstatus;
443: }
444: sninfop->sninbytes += len+4;
445:
446: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++)
447: if( cp->xchan == chan && cp->snunit == unit ) {
448: if( cp->input.done == 0 && len <= cp->input.len )
449: osp = sp = cp->input.buf;
450: else
451: osp = sp = ratshole;
452: goto found;
453: }
454: osp = sp = ratshole;
455: cp = &ratschan;
456: sninfop->snnnolc++;
457: found:
458:
459: for(i=len; i>0; i-=8) {
460: switch( i ) {
461: default:
462: *sp = *dp;
463: chksum ^= *sp++;
464: case 7:
465: *sp = *dp;
466: chksum ^= *sp++;
467: case 6:
468: *sp = *dp;
469: chksum ^= *sp++;
470: case 5:
471: *sp = *dp;
472: chksum ^= *sp++;
473: case 4:
474: *sp = *dp;
475: chksum ^= *sp++;
476: case 3:
477: *sp = *dp;
478: chksum ^= *sp++;
479: case 2:
480: *sp = *dp;
481: chksum ^= *sp++;
482: case 1:
483: *sp = *dp;
484: chksum ^= *sp++;
485: }
486: }
487: if( (i = ((len < 0 ? 0 : len) + 3)&0xf) != 0 ) {
488: for(i^=0xf; i-->=0; )
489: chksum ^= *dp;
490: }
491: if( chksum != (xchk = *dp) ) {
492: sninfop->snnchksum++;
493: if( sndebug ) {
494: short *usp = osp;
495: int x = len;
496:
497: printf("snchksum (%x, %x):", chan, len);
498: for(; --x>=0; )
499: printf(" %x", *usp++);
500: printf(" %x (%x)\n", xchk, chksum);
501: }
502: } else if( len > 0 ) {
503: if( osp == ratshole ) {
504: cp->flags |= SENTRNR;
505: snxstart(unit, cp, RNR);
506: sninfop->snsrnr++;
507: } else {
508: sninfop->snndata++;
509: cp->input.done = 1;
510: cp->input.len = len;
511: snxstart(unit, cp, ACK);
512: sninfop->snsack++;
513: wakeup((caddr_t)cp->input.buf);
514: if( cp->flags&MULTIPLEX )
515: wakeup((caddr_t)&sn_multiplex);
516: }
517: } else {
518: switch( len ) {
519: case ACK:
520: sninfop->snnack++;
521: cp->flags &= ~SENTDATA;
522: cp->output.done = 1;
523: wakeup((caddr_t)cp->output.buf);
524: break;
525:
526: case RDY:
527: sninfop->snnrdy++;
528: snxstart(unit, cp, RACK);
529: if( cp->output.done == 0 && cp->output.len > 0 ) {
530: snxstart(unit, cp, DATA);
531: sninfop->snrout++;
532: }
533: break;
534:
535: case RNR:
536: sninfop->snnrnr++;
537: cp->flags &= ~SENTDATA;
538: break;
539:
540: case RACK:
541: sninfop->snnrack++;
542: cp->flags &= ~SENTRDY;
543: break;
544:
545: default:
546: printf("snrint: unit %d, bad type %d\n", unit, len);
547: break;
548: }
549: }
550:
551: getstatus:
552: draddr->drcs = STATUS_MODE;
553: i = *dp;
554: draddr->drcs = DATA_MODE;
555: if ((i&INBUF_E) == 0) {
556: sninfop->sninloop++;
557: goto loop;
558: }
559: }
560:
561: snxstart(unit, cp, type)
562: int unit;
563: register struct chdat *cp;
564: int type;
565: {
566: register short *sp, *dp;
567: register struct sninfo *sninfop;
568: register struct device *draddr;
569: register int i;
570: unsigned short chksum;
571: #ifndef USG5
572: struct uba_device *ui;
573: #endif
574: int len, numretry;
575:
576: #ifdef USG5
577: draddr = sn_addr[unit];
578: #else
579: ui = sndinfo[unit];
580: draddr = (struct device *)ui->ui_addr;
581: #endif
582: dp = &draddr->drout;
583:
584: sninfop = &sn_sninfo[unit];
585:
586: if( type == DATA ) {
587: len = cp->output.len;
588: sninfop->snoutbytes += len+4;
589: } else {
590: len = type;
591: sninfop->snoutbytes += 4;
592: }
593: draddr->drcs = STATUS_MODE;
594:
595: i = draddr->drin;
596: if ( (i&OUTBUF_E) == 0 ) {
597: sninfop->snoutfull++;
598: do {
599: i = draddr->drin;
600: sninfop->sncntoutfull++;
601: } while( (i&OUTBUF_E) == 0 );
602: }
603:
604: numretry = 0;
605: sninfop->snxcnt++;
606: retry:
607: sp = cp->output.buf;
608: chksum = CHKINIT;
609: if (cp->pdid == NOPDID) {
610: draddr->drcs = CMD_MODE;
611: *dp = cp->machno<<8;
612: draddr->drcs = DATA_MODE;
613: *dp = i = swab(cp->dlchnum);
614: } else {
615: draddr->drcs = CMD_MODE;
616: *dp = cp->pdid<<8;
617: draddr->drcs = DATA_MODE;
618: *dp = i = (cp->dlchnum<<8) | cp->machno;
619: }
620: chksum ^= (unsigned short)i;
621: *dp = i = swab(len);
622: chksum ^= (unsigned short)i;
623: for( i=len; i>0; i-=8 ) {
624: switch( i ) {
625: default:
626: chksum ^= *sp;
627: *dp = *sp++;
628: case 7:
629: chksum ^= *sp;
630: *dp = *sp++;
631: case 6:
632: chksum ^= *sp;
633: *dp = *sp++;
634: case 5:
635: chksum ^= *sp;
636: *dp = *sp++;
637: case 4:
638: chksum ^= *sp;
639: *dp = *sp++;
640: case 3:
641: chksum ^= *sp;
642: *dp = *sp++;
643: case 2:
644: chksum ^= *sp;
645: *dp = *sp++;
646: case 1:
647: chksum ^= *sp;
648: *dp = *sp++;
649: }
650: }
651: if( (i = ((len < 0 ? 0 : len) + 3)&0xf) != 0 ) {
652: for(i^=0xf; i-->=0; )
653: *dp = 0;
654: }
655: draddr->drcs = EOP_MODE;
656: *dp = chksum;
657: draddr->drcs = STATUS_MODE;
658: i = draddr->drin;
659: draddr->drcs = DATA_MODE;
660: if( i&SNACK ) {
661: sninfop->snsnack++;
662: if( ++numretry < 100 )
663: goto retry;
664: sninfop->snlost++;
665: }
666: cp->ckticks = CKFUZZ;
667: if( type == DATA ) {
668: cp->flags |= SENTDATA;
669: }
670: }
671:
672: snioctl(dev, cmd, addr, flag)
673: caddr_t addr;
674: dev_t dev;
675: {
676: register struct chdat *cp;
677: register struct reqinfo *rp;
678: register struct sninfo *sninfop;
679: register struct bufinfo *bp;
680: register struct chdat *dp;
681: struct status status;
682: int i;
683: struct status *ustatus;
684: char *usaddr;
685: int ulen;
686: int error;
687: int mdev = SNFILE(dev);
688: int unit = SNUNIT(dev);
689:
690: #ifdef USG5
691: if ( unit >= sn_cnt) {
692: RETURN ( ENXIO );
693: }
694: #else
695: if ( unit >= NSN) {
696: RETURN ( ENXIO );
697: }
698: #endif
699: sninfop = &sn_sninfo[unit];
700:
701: switch( cmd ) {
702: case NIOOPEN: {
703: #ifdef BSD42
704: struct oargs *args = (struct oargs *)addr;
705: #else
706: struct oargs args;
707:
708: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
709: RETURN ( EFAULT );
710: }
711: #endif
712: spl6();
713: for(cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++)
714: if( cp->lchnum == -1 && cp->dlchnum == -1 )
715: break;
716: if( cp >= &sn_chans[NUMLCH] ) {
717: spl0();
718: RETURN( ENFILE );
719: }
720: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++)
721: if( dp->lchnum != -1 && dp->lmachno == ARGS(lmachno)
722: && dp->lchnum == ARGS(lchno)
723: && dp->snunit == unit ) {
724: spl0();
725: RETURN( EEXIST );
726: }
727: cp->lchnum = ARGS(lchno);
728: cp->dlchnum = ARGS(dlchno);
729: spl0();
730: cp->lmachno = ARGS(lmachno);
731: cp->machno = ARGS(dmachno);
732: cp->xchan = (cp->lmachno<<8)|cp->lchnum;
733: cp->snunit = unit;
734: cp->pdid = NOPDID;
735: bp = &cp->input;
736: i = cp-sn_chans;
737: bp->buf = sn_buffers[i].inbuf;
738: bp->len = MAXMSGLEN;
739: bp->done = 0;
740: bp = &cp->output;
741: bp->buf = sn_buffers[i].outbuf;
742: bp->len = bp->done = 0;
743: cp->flags = 0;
744: cp->link = sninfop->snlink[mdev];
745: sninfop->snlink[mdev] = cp;
746: return(0);
747: }
748:
749: case NIOXOPEN: {
750: struct snmach *snmachp;
751: struct openwait *nexthead, *thishead;
752: #ifdef BSD42
753: struct oargs *args = (struct oargs *)addr;
754: #else
755: struct oargs args;
756:
757: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
758: RETURN ( EFAULT );
759: }
760: #endif
761: for (;;) {
762: for (snmachp = &snmach[0];
763: snmachp < &snmach[NUMDEV] &&
764: snmachp->machno;
765: snmachp++) {
766: spl6();
767: for (cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++)
768: if( cp->lchnum == -1 &&
769: cp->dlchnum == -1 )
770: break;
771: if( cp >= &sn_chans[NUMLCH] ) {
772: goto xopensleep;
773: }
774: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++) {
775: if( dp->lchnum != -1
776: && dp->lmachno == snmachp->lmachno
777: && dp->lchnum == ARGS(lchno)
778: && dp->snunit == unit ) {
779: /* Channel already in use */
780: break;
781: }
782: }
783: if( dp >= &sn_chans[NUMLCH] )
784: goto okmachp;
785: spl0();
786: }
787: xopensleep:
788: nexthead = ownext(sn_owhead);
789: if (nexthead == sn_owtail) {
790: RETURN ( ENXIO );
791: }
792: thishead = sn_owhead;
793: thishead->pid = u.u_procp->p_pid;
794: sn_owhead = nexthead;
795: sleep((caddr_t)thishead, SNPRI);
796: }
797: okmachp:
798: cp->lchnum = ARGS(lchno);
799: cp->lmachno = snmachp->lmachno;
800: spl0();
801: cp->dlchnum = ARGS(dlchno);
802: cp->machno = snmachp->machno;
803: cp->xchan = (cp->lmachno<<8)|cp->lchnum;
804: cp->snunit = unit;
805: cp->pdid = NOPDID;
806: bp = &cp->input;
807: i = cp-sn_chans;
808: bp->buf = sn_buffers[i].inbuf;
809: bp->len = MAXMSGLEN;
810: bp->done = 0;
811: bp = &cp->output;
812: bp->buf = sn_buffers[i].outbuf;
813: bp->len = bp->done = 0;
814: cp->flags = 0;
815: cp->link = sninfop->snlink[mdev];
816: sninfop->snlink[mdev] = cp;
817:
818: ARGS(lmachno) = snmachp->lmachno;
819: ARGS(dmachno) = snmachp->machno;
820: #ifndef BSD42
821: if (copyout((caddr_t)&args, addr, sizeof(args))) {
822: RETURN ( EFAULT );
823: }
824: #endif
825: return(0);
826: }
827:
828: case NIOPOPEN: {
829: #ifdef BSD42
830: struct voargs *args = (struct voargs *)addr;
831: #else
832: struct voargs args;
833:
834: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
835: RETURN ( EFAULT );
836: }
837: #endif
838: spl6();
839: for(cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++)
840: if( cp->lchnum == -1 && cp->dlchnum == -1 )
841: break;
842: if( cp >= &sn_chans[NUMLCH] ) {
843: spl0();
844: RETURN( ENFILE );
845: }
846: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++)
847: if( dp->lchnum != -1 && dp->lmachno == ARGS(lmachno)
848: && dp->lchnum == ARGS(lchno)
849: && dp->snunit == unit ) {
850: spl0();
851: RETURN( EEXIST );
852: }
853: cp->lchnum = ARGS(lchno);
854: cp->lmachno = ARGS(lmachno);
855: spl0();
856: cp->dlchnum = ARGS(dlchno);
857: cp->machno = ARGS(dmachno);
858: cp->xchan = (cp->lmachno<<8)|cp->lchnum;
859: cp->snunit = unit;
860: cp->pdid = ARGS(pdid);
861: bp = &cp->input;
862: i = cp-sn_chans;
863: bp->buf = sn_buffers[i].inbuf;
864: bp->len = MAXMSGLEN;
865: bp->done = 0;
866: bp = &cp->output;
867: bp->buf = sn_buffers[i].outbuf;
868: bp->len = bp->done = 0;
869: cp->flags = 0;
870: cp->link = sninfop->snlink[mdev];
871: sninfop->snlink[mdev] = cp;
872: return(0);
873: }
874:
875: case NIOCLOSE: {
876: #ifdef BSD42
877: struct cargs *args = (struct cargs *)addr;
878: #else
879: struct cargs args;
880:
881: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
882: RETURN ( EFAULT );
883: }
884: #endif
885: for(cp=sninfop->snlink[mdev], dp=0; cp; dp=cp, cp=cp->link)
886: if( cp->lmachno == ARGS(lmachno)
887: && cp->lchnum == ARGS(lchno) ) {
888: /* TIMING !!! */
889: if( dp )
890: dp->link = cp->link;
891: else
892: sninfop->snlink[mdev] = cp->link;
893: chclose(cp);
894: return(0);
895: }
896: RETURN( EBADF );
897: }
898:
899: case NIOGET:
900: case NIOPUT:
901: {
902: #ifdef BSD42
903: struct gpargs *args = (struct gpargs *)addr;
904: #else
905: struct gpargs args;
906:
907: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
908: RETURN ( EFAULT );
909: }
910: #endif
911: status.lchdir = (cmd == NIOGET ? INPUT : OUTPUT);
912: status.lchnum = ARGS(lch);
913: ustatus = ARGS(status);
914: usaddr = ARGS(addr);
915: ulen = ARGS(len);
916: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) {
917: if( cp->lchnum == ARGS(lch)
918: && cp->lmachno == ARGS(lmachno)) {
919: do_getput:
920: bp = (cmd == NIOGET ? &cp->input : &cp->output);
921: if( cmd == NIOPUT ) {
922: copyin(usaddr, bp->buf, ulen);
923: spl5();
924: bp->len = (ulen+1)/2;
925: snxstart(unit, cp, DATA);
926: sninfop->snsdata++;
927: } else {
928: spl5();
929: /*
930: * The following may be
931: * unnecessary in light of
932: * the later check.
933: */
934: if( bp->done == 0 && cp->flags&SENTRNR ) {
935: cp->flags &= ~SENTRNR;
936: cp->flags |= SENTRDY;
937: snxstart(unit, cp, RDY);
938: sninfop->sns1rdy++;
939: }
940: }
941: for (;;) {
942: spl5();
943: if (bp->done) break;
944: sleep((caddr_t)bp->buf, SNPRI);
945: #ifdef TIMEOUT
946: spl6();
947: if (cp->flags & RETRY) {
948: cp->flags &= ~RETRY;
949: sninfop->sntimeout++;
950: snxstart(unit, cp, (cp->flags&SENTDATA) ? DATA : RDY);
951: }
952: #endif TIMEOUT
953: }
954: status.code = ST_OK;
955: status.len = 2*bp->len;
956: if( cmd == NIOGET ) {
957: spl0();
958: copyout(bp->buf, usaddr, 2*bp->len);
959: spl5();
960: bp->len = MAXMSGLEN;
961: /*
962: * Believe it or not, we must check
963: * this here. This is because
964: * we lowered the ipl to do the
965: * copyout(). During that time
966: * another message may have tried
967: * to sneak in.
968: */
969: if( cp->flags&SENTRNR ) {
970: cp->flags &= ~SENTRNR;
971: snxstart(unit, cp, RDY);
972: sninfop->snsrdy++;
973: }
974: } else
975: bp->len = 0;
976: bp->done = 0;
977: spl0();
978: error = 0;
979: goto cpyout;
980: }
981: }
982: status.code = ST_IARGS;
983: error = EIO;
984: cpyout:
985: copyout((caddr_t)&status, (caddr_t)ustatus, sizeof(status));
986: RETURN ( error );
987: }
988:
989: case NIOGETM:
990: {
991: struct pair pair;
992: struct chdat *lchns[MAXMUX+1];
993: register struct chdat **chp = lchns, **chpe = lchns;
994: #ifdef BSD42
995: struct gmargs *args = (struct gmargs *)addr;
996: #else
997: struct gmargs args;
998:
999: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
1000: RETURN ( EFAULT );
1001: }
1002: #endif
1003: status.lchdir = INPUT;
1004: ustatus = ARGS(status);
1005: usaddr = ARGS(addr);
1006: ulen = ARGS(len);
1007: for(i=0; i<MAXMUX; i++) {
1008: if (copyin((caddr_t)ARGS(pairp++), (caddr_t)&pair,
1009: sizeof(struct pair))) {
1010: RETURN ( EFAULT );
1011: }
1012: if( pair.lchno == -1 )
1013: break;
1014: if (pair.lchno < 0 || pair.lchno >= 512
1015: || pair.lmachno < 0 || pair.lmachno >= 512) {
1016: RETURN ( EBADF );
1017: }
1018: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) {
1019: if( cp->lchnum == pair.lchno
1020: && cp->lmachno == pair.lmachno ) {
1021: *chpe++ = cp;
1022: break;
1023: }
1024: }
1025: if( cp >= &sn_chans[NUMLCH] ) {
1026: RETURN ( EBADF );
1027: }
1028: }
1029: spl5();
1030: for(chp=lchns; chp<chpe; chp++) {
1031: if( (*chp)->flags&MULTIPLEX ) {
1032: spl0();
1033: RETURN ( EBUSY );
1034: }
1035: }
1036: for(chp=lchns; chp<chpe; chp++)
1037: (*chp)->flags |= MULTIPLEX;
1038:
1039: loop:
1040: spl5();
1041: for(chp=lchns; chp<chpe; chp++) {
1042: if( (*chp)->input.done ) {
1043: goto gotone;
1044: }
1045: }
1046: sleep((caddr_t)&sn_multiplex, SNPRI);
1047: goto loop;
1048:
1049: gotone:
1050: cp = *chp;
1051: for(chp=lchns; chp<chpe; chp++)
1052: (*chp)->flags &= ~MULTIPLEX;
1053: spl0();
1054: status.lchnum = cp->lchnum;
1055: cmd = NIOGET;
1056: goto do_getput;
1057: }
1058:
1059: case NIOABORT:
1060: case NIORESET: {
1061: struct device *draddr;
1062: #ifndef USG5
1063: struct uba_device *ui;
1064: #endif
1065: #ifdef BSD42
1066: struct raargs *args = (struct raargs *)addr;
1067: #else
1068: struct raargs args;
1069:
1070: if (copyin(addr, (caddr_t)&args, sizeof(args))) {
1071: RETURN ( EFAULT );
1072: }
1073: #endif
1074:
1075: #ifdef USG5
1076: draddr = sn_addr[unit];
1077: #else
1078: ui = sndinfo[unit];
1079: draddr = (struct device *)ui->ui_addr;
1080: #endif
1081:
1082: spl5();
1083: i = ARGS(machno) << 8;
1084: draddr->drcs = CMD_MODE;
1085: draddr->drout = (cmd == NIOABORT ? ABORT(i) : RESET(i));
1086: draddr->drcs = EOP_MODE;
1087: draddr->drout = 0;
1088: draddr->drcs = DATA_MODE;
1089: spl0();
1090: return(0);
1091: }
1092:
1093: case NIOREADSTATUS:
1094: #ifdef BSD42
1095: copyout((caddr_t)sninfop, *(caddr_t *)addr,
1096: sizeof sn_sninfo[0]);
1097: #else
1098: copyout((caddr_t)sninfop, (caddr_t)addr,
1099: sizeof sn_sninfo[0]);
1100: #endif
1101: return(0);
1102:
1103: case NIOCHSTATUS: {
1104:
1105: struct chinfo chinfo;
1106:
1107: chinfo.numlch = NUMLCH;
1108: chinfo.chanaddr = &sn_chans[0];
1109: #ifdef BSD42
1110: copyout((caddr_t)&chinfo, *(caddr_t *)addr,
1111: sizeof chinfo);
1112: copyout((caddr_t)chinfo.chanaddr,
1113: (*(caddr_t *)addr)+sizeof chinfo,
1114: NUMLCH*sizeof sn_chans[0]);
1115: #else
1116: copyout((caddr_t)&chinfo, (caddr_t)addr,
1117: sizeof chinfo);
1118: copyout((caddr_t)chinfo.chanaddr,
1119: (caddr_t)(addr+sizeof chinfo),
1120: NUMLCH*sizeof sn_chans[0]);
1121: #endif
1122: return(0);
1123: }
1124:
1125: case NIOSETMACH:
1126: #ifdef BSD42
1127: copyin(*(caddr_t *)addr, (caddr_t)snmach, sizeof snmach);
1128: #else
1129: copyin((caddr_t)addr, (caddr_t)snmach, sizeof snmach);
1130: #endif
1131: return(0);
1132:
1133:
1134: case NIOGETMACH:
1135: #ifdef BSD42
1136: copyout((caddr_t)snmach, *(caddr_t *)addr, sizeof snmach);
1137: #else
1138: copyout((caddr_t)snmach, (caddr_t)addr, sizeof snmach);
1139: #endif
1140: return(0);
1141:
1142:
1143: case NIOQSTATUS: {
1144: struct openinfo openinfo;
1145:
1146: openinfo.owaddr = sn_openwait;
1147: openinfo.head = sn_owhead;
1148: openinfo.tail = sn_owtail;
1149:
1150: #ifdef BSD42
1151: copyout((caddr_t)&openinfo, *(caddr_t *)addr, sizeof openinfo);
1152: copyout((caddr_t)sn_openwait,
1153: (*(caddr_t *)addr)+sizeof openinfo,
1154: NUMDEV*sizeof sn_openwait[0]);
1155: #else
1156: copyout((caddr_t)&openinfo, (caddr_t)addr, sizeof openinfo);
1157: copyout((caddr_t)sn_openwait, (caddr_t)(addr+sizeof openinfo),
1158: NUMDEV*sizeof sn_openwait[0]);
1159: #endif
1160: return(0);
1161: }
1162:
1163: case NIOZEROSTAT:
1164: {
1165:
1166: register char *p, *low, *high;
1167:
1168: low = (char *) &sn_sninfo[0];
1169: #ifdef USG5
1170: high = low + sn_cnt*sizeof (struct sninfo);
1171: #else
1172: high = low + NSN*sizeof (struct sninfo);
1173: #endif
1174:
1175: for (p=low; p<high; p++)
1176: *p = '\0';
1177: return(0);
1178: }
1179: case NIOCHECK:
1180: case NIOWAIT:
1181: case NIOPURGE:
1182: case NIOSETVEC:
1183: ;
1184: }
1185: }
1186:
1187: static
1188: chclose(cp)
1189: register struct chdat *cp;
1190: {
1191: cp->lchnum = cp->dlchnum = cp->machno = -1;
1192: cp->flags = cp->xchan = cp->input.len = 0;
1193: }
1194:
1195: #ifdef TIMEOUT
1196: cktimchk()
1197: {
1198: register struct chdat *cp;
1199: register struct sninfo *sninfop;
1200: int unit;
1201: int s;
1202:
1203: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) {
1204: if( cp->flags&(SENTDATA|SENTRDY) && --cp->ckticks == 0 ) {
1205: unit = cp->snunit;
1206: sninfop = &sn_sninfo[unit];
1207: sninfop->snsched++;
1208: sninfop->snenqlost[cp->machno]++;
1209: cp->flags |= RETRY;
1210: if (cp->flags & SENTDATA) {
1211: wakeup((caddr_t)cp->output.buf);
1212: } else {
1213: wakeup((caddr_t)cp->input.buf);
1214: }
1215: }
1216: }
1217: s = spl6();
1218: if (sn_state & OPEN) {
1219: timeout(cktimchk, (caddr_t)0, CKTICKS);
1220: } else {
1221: sn_state &= ~TIMER;
1222: }
1223: splx(s);
1224: }
1225: #endif TIMEOUT
1226:
1227: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.