|
|
1.1 root 1: /*
2: * This software is provided solely for use with
3: * the National Instruments GPIB11-2.
4: *
5: * Copyright 1980, 1983 National Instruments
6: *
7: * Jeffrey Kodosky
8: * REV D: 10/30/83
9: * (4.1bsd mods)
10: *
11: * utterly hopeless
12: */
13: #include "sys/param.h"
14: #include "sys/conf.h"
15: #include "sys/user.h"
16: #include "sys/buf.h"
17: #include "sys/ubaddr.h"
18: #include "sys/ttyio.h"
19:
20: #include "sys/callout.h"
21:
22: static init(), irload(), lun(), wsetup(), rsetup(), ibdone(), gts(), tcs();
23: static unhold(), xfer(), ldaux(), wait100us();
24:
25: #define TRI 0 /* 4 for Three-state highspeed timing; 0 for Normal timing */
26: #define EXT 1 /* 2 for Extended; 1 for Normal GPIB addressing */
27: #define MSA 0140 /* Msa&037 for Extended; 0140 for Normal GPIB addressing */
28: #define MA 025 /* GPIB address */
29: #define DONE 0x0080 /* this is what they wanted */
30:
31:
32: #define SIGSRQ SIGINT
33:
34:
35: #define INACTIVE 0 /* Software controller states */
36: #define IDLE 1
37: #define INCHARGE 2
38: #define STANDBY 3
39:
40: #define GO 1 /* Control/status register bits */
41: #define OUT 2
42: #define SEL 4
43: #define ECC 010
44: #define XBA 060
45: #define IE 0100
46: #define LMR 0200
47: #define CIC 0400
48: #define ATN 01000
49: #define EOI 02000
50: #define OCSW 02000
51: #define TCS 04000
52: #define DAV 04000
53: #define SRQ_IE 010000
54: #define SRQ 010000
55: #define INT 020000
56: #define DMA_ENAB 020000
57: #define NEX 040000
58: #define REN 040000
59: #define IFC 0100000
60:
61: #define DIR 0 /* Internal register addresses */
62: #define DOR 0
63: #define ISR1 1
64: #define IMR1 1
65: #define ISR2 2
66: #define IMR2 2
67: #define SPS 3
68: #define SPM 3
69: #define ADS 4
70: #define ADM 4
71: #define CPT 5
72: #define AUX 5
73: #define AD0 6
74: #define ADR 6
75: #define AD1 7
76: #define EOS 7
77:
78: #define ERR_IE 4 /* Internal register bits */
79: #define END_IE 020
80: #define CPT_IE 0200
81: #define DMAI_ENAB 020
82: #define DMAO_ENAB 040
83: #define SRQS 0100
84: #define RSV 0100
85: #define TA 2
86: #define LA 4
87: #define LON 0100
88: #define TON 0200
89: #define DL 040
90: #define DT 0100
91: #define ARS 0200
92:
93: #define _CLKR 040 /* Hidden register addresses & offsets */
94: #define _PPR 0140
95: #define _AUXA 0200
96: #define _AUXB 0240
97: #define CLKR 0
98: #define PPR 1
99: #define AUXA 2
100: #define AUXB 3
101:
102: #define U 020 /* Hidden register bits */
103: #define BIN 020
104: #define S 010
105: #define REOS 4
106: #define HLDE 2
107: #define HLDA 1
108: #define CPT_ENAB 1
109: #define PACS 1 /* Software status bits */
110: #define MON 2
111:
112: #define IST 011 /* Special interface functions */
113: #define NIST 1
114: #define VSC 017
115: #define NVSC 7
116: #define SEOI 6
117: #define FH 3
118: #define IR 2
119: #define PON 0
120:
121: #define OK 1 /* Error codes */
122: #define ENONE -1 /* No command byte available (READCOMMAND) */
123: #define ECACFLT -2 /* ATN not unasserted after IFC sent (bus problem) */
124: #define ENOTCAC -3 /* Not Active Controller for operation requiring CAC (software problem) */
125: #define ENOTSAC -4 /* Not System Controller for operation requiring SAC (software problem) */
126: #define EIFCLR -5 /* IFC caused operation to abort (bus problem) */
127: #define ETIMO -6 /* Operation did not complete within allotted time (bus problem) */
128: #define ENOFUN -7 /* Non-existent function code (software problem) */
129: #define ETCTIMO -8 /* Take control not completed within allotted time (bus problem) */
130: #define ENOIBDEV -9 /* No Listeners addressed or no devices connected (bus problem) */
131: #define EIDMACNT -10 /* Internal DMA completed without bcr going to 0 (hardware problem) */
132: #define ENOPP -11 /* PP operation attempted on three-state GPIB (software problem) */
133: #define EITIMO -12 /* Internal DMA did not complete within allotted time (hardware problem) */
134: #define EINEXM -13 /* Internal DMA aborted due to non-existent memory (software/hardware problem) */
135: #define ENEXMEM -14 /* GPIB DMA aborted due to non-existent memory (software/hardware problem) */
136: #define ECNTRS -15 /* Bar and bcr are inconsistent following GPIB DMA (hardware problem) */
137:
138: #define RQC_STB (RSV | 1) /* Service request status bytes */
139: #define RQT_STB (RSV | 2)
140: #define RQL_STB (RSV | 4)
141:
142: #define RQC 1 /* Asynchronous op codes */
143: #define CAC 2
144: #define TAC 3
145: #define LAC 4
146: #define CWT 5
147: #define WSRQ 6
148:
149: #define TCT 011 /* GPIB multiline messages */
150: #define PPC 5
151: #define PPU 025
152: #define SCG 0140
153:
154: #define IN 0
155: #define ITIMO 25 /* Internal loopcount timeout */
156: #define GTIMO 10 /* Default GPIB timeout in seconds */
157: #define TCTIMO 100
158: #define MONHWAT 32
159:
160: #define RD (DMA_ENAB|TCS|IN|GO)
161: #define WT (DMA_ENAB|TCS|OUT|GO)
162: #define RDIR (DMA_ENAB|IN|SEL|GO)
163: #define WTIR (DMA_ENAB|OUT|SEL|GO)
164:
165: static struct buf ibbuf;
166: static short iboddc, ibodda;
167:
168: #define in(a) ib.addr->a
169: #define out(a,v) ib.addr->a=(v)
170: #define Exclude sps=spl5()
171: #define Unexclude splx(sps)
172: #define Try(f) if((x=(f))<0) return x
173:
174: struct ib {
175: short unsigned bcr, bar, csr, ccf; /* Unibus device registers */
176: char internal[8]; /* Internal registers */
177: char hidden[4]; /* Hidden registers */
178: char cstate, istr, op;
179: int ans;
180: int timo; /* Watchdog timer */
181: struct proc *owner; /* GPIB owning process */
182: short unsigned rdbcr, rdbar, rdcsr;
183: char rdinternal[8];
184: int arg[3];
185:
186: struct ib *addr;
187: int ubno;
188: ubm_t ubm, ioubm;
189: uaddr_t uaddr, iouaddr;
190: } ib;
191:
192: static int status(), spbyte();
193: static int command(), transfer(), clear(), remote(), local(), ppoll();
194: static int passctrl(), setstat(), monitor(), readcmd(), setparam(), testsrq();
195:
196: int (*ibfn[])() =
197: {
198: command, transfer, clear, remote, local, ppoll,
199: passctrl, setstat, monitor, readcmd, setparam, testsrq,
200: status, spbyte
201: };
202:
203: #define NFNS ((sizeof ibfn)/(sizeof ibfn[0]))
204:
205: /*
206: * config glue
207: */
208: int gpibopen(), gpibclose(), gpibread(), gpibwrite(), gpibioctl();
209:
210: extern struct ubaddr gpibaddr[];
211: extern int gpibcnt;
212: struct cdevsw gpibcdev =
213: cdinit(gpibopen, gpibclose, gpibread, gpibwrite, gpibioctl);
214:
215:
216: gpibopen(d, f)
217: {
218: register int dev, s;
219: register struct ib *p;
220:
221: if((dev = minor(d)) >= gpibcnt || gpibcnt > 1) {
222: u.u_error = ENODEV;
223: return;
224: }
225: if((p = &ib)->owner) {
226: u.u_error = EBUSY;
227: return;
228: }
229: if((p->addr = (struct ib *)ubaddr(&gpibaddr[dev])) == 0
230: || ubbadaddr(gpibaddr[dev].ubno, (caddr_t)p->addr, sizeof(u_short))) {
231: printf("gpib%d absent\n", dev);
232: u.u_error = ENODEV;
233: return;
234: }
235: p->ubno = gpibaddr[dev].ubno;
236: p->ubm = ubmalloc(p->ubno, sizeof(struct ib), USLP);
237: p->uaddr = ubmaddr(p->ubno, p, sizeof(struct ib), p->ubm);
238: s = spl5();
239: if((ib.ans=init())<0){
240: ubmfree(p->ubno, p->ubm);
241: u.u_error= EIO;
242: }
243: else ib.owner= u.u_procp;
244: splx(s);
245: }
246:
247: gpibclose(dev)
248: {
249: register int sps, x;
250:
251: Exclude;
252: ubmfree(ib.ubno, ib.ubm);
253: ib.cstate= INACTIVE;
254: ib.csr= 0;
255: out(csr,LMR);
256: ib.owner= 0;
257: Unexclude;
258: }
259:
260: gpibioctl(dev,cmd,addr)
261: caddr_t addr;
262: {
263: register int sps, x;
264:
265: Exclude;
266: switch(cmd){
267: case TIOCGETP:
268: ib.arg[0]= ib.ans;
269: ib.arg[1]= in(csr);
270: ib.arg[2]= in(bcr);
271: if(copyout(ib.arg,addr,sizeof ib.arg)) u.u_error= EFAULT;
272: break;
273: case TIOCSETP:
274: if(copyin(addr,ib.arg,sizeof ib.arg)){
275: u.u_error= EFAULT;
276: break;
277: }
278: if((x=ib.arg[0])<0 || x>=NFNS){
279: ib.ans= ENOFUN;
280: u.u_error= EIO;
281: }
282: else if((ib.ans= (*ibfn[x])())<0) u.u_error= EIO;
283: break;
284: default:
285: u.u_error= ENOTTY;
286: break;
287: }
288: Unexclude;
289: }
290:
291: static
292: command()
293: {
294: ib.op= CWT;
295: return OK;
296: }
297:
298: static
299: transfer()
300: {
301: return gts(EXT);
302: }
303:
304: static
305: clear()
306: {
307: register int x;
308:
309: Try(unhold());
310: out(csr, ib.csr | IFC);
311: wait100us();
312: if(in(csr)&ATN) return ECACFLT;
313: ib.cstate= INCHARGE;
314: out(csr, (ib.csr |= ATN | SRQ_IE | CIC));
315: return lun(TON);
316: }
317:
318: static
319: remote()
320: {
321: out(csr, (ib.csr |= REN));
322: return OK;
323: }
324:
325: static
326: local()
327: {
328: out(csr, (ib.csr &= ~REN));
329: return OK;
330: }
331:
332: static
333: ppoll()
334: {
335: register int x;
336:
337: Try(tcs());
338: Try(lun(LON));
339: out(csr, (ib.csr |= EOI));
340: Try(xfer(RDIR, &ib.rdinternal[CPT], 1, CPT));
341: out(csr, (ib.csr &= ~EOI));
342: return (ib.rdinternal[CPT]&0377|0400);
343: }
344:
345: static
346: passctrl()
347: {
348: return ENOIBDEV;
349: }
350:
351: static
352: setstat()
353: {
354: return OK;
355: }
356:
357: static
358: monitor()
359: {
360: return OK;
361: }
362:
363: static
364: readcmd()
365: {
366: return ENONE;
367: }
368:
369: static
370: setparam()
371: {
372: ib.timo= ib.arg[1];
373: ib.internal[0]= ib.arg[2];
374: ib.internal[EOS]= ib.arg[2]>>8;
375: return OK;
376: }
377:
378: static
379: testsrq()
380: {
381: int ibtimer();
382:
383: if(in(csr)&SRQ) return OK;
384: if(ib.csr&CIC) out(csr, (ib.csr |= SRQ_IE));
385: if(ib.arg[1]){
386: ib.op= WSRQ;
387: if(ib.timo)
388: timeout(ibtimer,0,ib.timo*HZ);
389: sleep(&ibbuf,10);
390: return ib.ans;
391: }
392: return ENONE;
393: }
394:
395: static
396: status()
397: {
398: register char *c;
399: register int ct;
400:
401: c= (caddr_t)&ib;
402: u.u_base= (caddr_t)ib.arg[1];
403: if((u.u_count=ib.arg[2]) > sizeof ib)
404: u.u_count= sizeof ib;
405: ct= u.u_count;
406: while(passc(*c++)>=0) ;
407: return ct;
408: }
409:
410: static
411: spbyte()
412: {
413: register int x;
414:
415: return OK;
416: }
417:
418: static
419: init()
420: {
421: register char *cp;
422: register int x;
423:
424: out(csr, LMR);
425: ib.csr= 0;
426: cp= &ib.hidden[0];
427: *cp++= _CLKR | 6;
428: *cp++= _PPR | U;
429: *cp++= _AUXA;
430: *cp++= _AUXB | TRI | CPT_ENAB;
431:
432: cp= &ib.internal[0];
433: *cp++= 0;
434: *cp++= CPT_IE | ERR_IE;
435: *cp++= 0;
436: *cp++= 0;
437: *cp++= EXT;
438: *cp++= ib.hidden[CLKR];
439: *cp++= ARS | MSA;
440: *cp++= 0;
441:
442: ib.istr= 0;
443: ib.op= 0;
444: ib.ans= 0;
445: ib.timo= GTIMO;
446: Try(irload());
447: ib.cstate= IDLE;
448: out(csr, ib.csr= IE);
449: return 0;
450: }
451:
452: static
453: ibstop()
454: {
455: register int x;
456:
457: out(csr, (ib.csr &= ~(DMA_ENAB|GO)));
458: ib.op= 0;
459: ibdone(&ibbuf);
460: return ETIMO;
461: }
462:
463: static
464: irload()
465: {
466: register int x;
467:
468: Try(xfer(WTIR,&ib.internal[ISR1],7,ISR1));
469: ib.internal[AUX]= ib.hidden[AUXA];
470: ib.internal[ADR]= MA;
471: Try(xfer(WTIR,&ib.internal[AUX],2,AUX));
472: Try(xfer(WTIR,&ib.hidden[AUXB],1,AUX));
473: x= ib.internal[ADM];
474: ib.internal[ADM]= 0;
475: return lun(x);
476: }
477:
478: static
479: lun(newadm)
480: char newadm;
481: { /* Note: rsv is cleared and not restored*/
482: register int x;
483:
484: if(ib.internal[ADM]==newadm) return OK;
485: ib.internal[ADM]= newadm;
486: ib.internal[AUX]= PON;
487: Try(xfer(WTIR,&ib.internal[ADM],2,ADM));
488: Try(xfer(WTIR,&ib.hidden[PPR],1,AUX));
489: return (ib.istr&S)? ldaux(IST): OK;
490: }
491:
492: gpibwrite(dev)
493: {
494: register int sps;
495: int ibstrategy();
496:
497: Exclude;
498: if((ib.ans=wsetup())>=0)
499: physio(ibstrategy, &ibbuf, dev, B_WRITE, minphys);
500: ib.op= 0;
501: if(ib.ans<0) u.u_error= EIO;
502: Unexclude;
503: }
504:
505: static
506: wsetup()
507: {
508: register x;
509:
510: ib.ccf= 0;
511: ib.csr &= ~ECC;
512: if(ib.op==CWT)
513: if((x=tcs())<0){
514: return x;
515: }
516: else {
517: Try(lun(TON));
518: ib.op= CAC;
519: }
520: else {
521: if((x=gts(TON))<0){
522: return x;
523: }
524: if(ib.internal[0]&2){
525: ib.ccf= SEOI;
526: ib.csr |= ECC;
527: }
528: ib.op= TAC;
529: }
530: ibodda= (int)u.u_base&1;
531: u.u_base -= ibodda;
532: iboddc= ((ibodda + u.u_count + 1)&~1) - u.u_count;
533: u.u_count += iboddc;
534: return OK;
535: }
536:
537: gpibread(dev)
538: {
539: register int sps;
540: int ibstrategy();
541:
542: Exclude;
543: if((ib.ans=rsetup())>=0)
544: physio(ibstrategy, &ibbuf, dev, B_READ, minphys);
545: ib.op= 0;
546: if(ib.ans<0) u.u_error= EIO;
547: Unexclude;
548: }
549:
550: static
551: rsetup()
552: {
553: register int x;
554:
555: ib.ccf= 0;
556: ib.csr &= ~ECC;
557: if((x=gts(LON))<0){
558: return x;
559: }
560: ib.hidden[AUXA] |= (ib.internal[0]&(2<<4)? REOS:0) | (ib.internal[0]&(1<<4)? BIN:0);
561: if(ib.internal[0]&(4<<4)) ib.internal[IMR1] &= ~END_IE;
562: else {
563: ib.internal[IMR1] |= END_IE;
564: if(ib.cstate==STANDBY) ib.hidden[AUXA] |= HLDE;
565: }
566: ib.internal[AUX]= ib.hidden[AUXA];
567: Try(xfer(WTIR, &ib.internal[IMR1], 7, IMR1));
568: if(ib.cstate==STANDBY){
569: ib.ccf= ib.hidden[AUXA]= ib.hidden[AUXA]&~HLDE|HLDA;
570: ib.csr |= ECC;
571: }
572: ib.op= LAC;
573: ibodda= (int)u.u_base&1;
574: u.u_base -= ibodda;
575: iboddc= ((ibodda + u.u_count + 1)&~1) - u.u_count;
576: u.u_count += iboddc;
577: return OK;
578: }
579:
580: ibstrategy(bp)
581: register struct buf *bp;
582: {
583: register int x, rw;
584:
585: ib.ioubm = ubmbuf(ib.ubno, bp, USLP);
586: ib.iouaddr = ubadbuf(ib.ubno, bp, ib.ioubm);
587: rw= bp->b_flags&B_READ? RD:(ib.op==RQC? OUT:WT);
588: if((x=xfer(rw, ib.iouaddr+ibodda, bp->b_bcount-iboddc, 0))<0){
589: ib.ans= x;
590: ibdone(bp);
591: }
592: }
593:
594: static
595: ibdone(bp)
596: register struct buf *bp;
597: {
598: register int x;
599:
600: iodone(bp);
601: ubmfree(ib.ubno, ib.ioubm);
602: }
603:
604:
605: static
606: gts(newadm)
607: char newadm;
608: {
609: register int x;
610:
611: Try(unhold());
612: if(ib.cstate==STANDBY)
613: return (ib.internal[ADM]==newadm)? OK : ENOIBDEV;
614: if(ib.cstate==IDLE) return ENOTCAC;
615: Try(lun(newadm));
616: out(csr, (ib.csr &= ~ATN));
617: ib.cstate= STANDBY;
618: return OK;
619: }
620:
621: static
622: tcs()
623: {
624: if(ib.cstate==INCHARGE) return OK;
625: if(ib.cstate==IDLE) return ENOTCAC;
626: out(csr, (ib.csr |= ATN));
627: ib.cstate= INCHARGE;
628: return unhold();
629: }
630:
631: static
632: unhold()
633: {
634: register int x;
635:
636: if(ib.hidden[AUXA]&(HLDE|HLDA)){
637: ib.hidden[AUXA]= _AUXA;
638: Try(ldaux(FH));
639: return xfer(WTIR, &ib.hidden[AUXA], 1, AUX);
640: }
641: return OK;
642: }
643:
644: static
645: xfer(rw,bp,n,fr)
646: { /* fr is internal reg addr */
647: register int i, x;
648: int ibtimer();
649:
650: if(n<=0) return OK;
651: if(rw&SEL){
652: out(bcr, (-n<<8) | fr & 7);
653: bp += ib.uaddr - (int)&ib;
654: out(bar, bp);
655: out(csr, ib.csr & (REN|SRQ_IE|EOI|ATN|CIC) | (bp>>12) & XBA | rw);
656: for(i=ITIMO; !((x=in(csr))&DONE); )
657: if(--i<=0) return EITIMO;
658: if(x&NEX) return EINEXM;
659: if(in(bcr)&0177400) return EIDMACNT;
660: out(csr, ib.csr & (REN|SRQ_IE|ATN|CIC|IE));
661: return n;
662: }
663: ib.internal[IMR2]= rw&OUT? DMAO_ENAB:DMAI_ENAB;
664: Try(xfer(WTIR,&ib.internal[IMR2],1,IMR2));
665: out(bcr, ib.bcr= -n);
666: out(bar, ib.bar= bp);
667: out(ccf, ib.ccf);
668: out(csr, (ib.csr= ib.csr & (REN|SRQ_IE|TCS|ATN|CIC|ECC) | (bp>>12) & XBA | IE | rw));
669: ib.ans= 0;
670: if(ib.timo) timeout(ibtimer,0,ib.timo*HZ);
671: return OK;
672: }
673:
674: static
675: ldaux(a)
676: {
677: ib.internal[AUX]= a;
678: return xfer(WTIR, &ib.internal[AUX], 1, AUX);
679: }
680:
681: ibtimer(id)
682: {
683: int sps;
684:
685: Exclude;
686: printf("timer (%o)\n",ibtimer);
687: ib.ans= ibstop();
688: Unexclude;
689: }
690:
691: gpib0int()
692: {
693: register int x, i;
694: register short unsigned y, z;
695:
696: ib.rdcsr= in(csr);
697: ib.rdbcr= in(bcr);
698: ib.rdbar= in(bar);
699: if((ib.rdcsr&SRQ) && (ib.csr&SRQ_IE)){
700: out(csr, (ib.csr &= ~SRQ_IE) & ~GO);
701: if(ib.op==WSRQ){
702: ib.op= 0;
703: ib.ans= OK;
704: untimeout(ibtimer,0);
705: wakeup(&ibbuf);
706: }
707: else if(ib.owner) psignal(ib.owner,SIGSRQ);
708: }
709: if(ib.rdcsr&INT){
710: out(csr, ib.csr & ~(DMA_ENAB|GO));
711: ib.rdcsr= in(csr);
712: ib.rdbcr= in(bcr);
713: ib.rdbar= in(bar);
714: if((x=xfer(RDIR, &ib.rdinternal[ISR1], 5, ISR1))<0) goto quit;
715: if(ib.rdinternal[ISR1]&ERR_IE) ib.ans= ENOIBDEV;
716: if(ib.internal[IMR1]&END_IE){
717: ib.internal[IMR1] &= ~END_IE;
718: if((x=xfer(WTIR,&ib.internal[IMR1],1,IMR1))<0) goto quit;
719: }
720: }
721: if((ib.rdcsr&DONE) && (ib.csr&GO)){
722: ib.csr &= ~GO;
723: if(ib.timo) untimeout(ibtimer,0);
724: if(ib.rdcsr&NEX) ib.ans= ENEXMEM;
725: x = y = ib.rdbcr - ib.bcr;
726: z = ib.rdbar - ib.bar; /* complete batshit */
727: if(z != y){
728: x= ECNTRS;
729: printf("\trdbcr,rdbar,rdcsr= %o %o %o\n",ib.rdbcr,ib.rdbar,ib.rdcsr);
730: printf("\tbcr,bar,csr= %o %o %o\n",ib.bcr,ib.bar,ib.csr);
731: }
732: ibbuf.b_resid= -ib.rdbcr;
733: if(ib.ans==0)
734: quit:
735: ib.ans= x;
736: ib.op= 0;
737: ibdone(&ibbuf);
738: }
739: }
740:
741: static
742: wait100us()
743: {
744: register int i;
745:
746: for(i=100; i-->0; ) ;
747: }
748:
749: untimeout(fn,arg)
750: register int (*fn)();
751: caddr_t arg;
752: {
753: register struct callout *p, *q;
754: int s;
755:
756: s= spl7();
757: for(p= &calltodo; q=p->c_next; p=q)
758: if(q->c_func==fn && q->c_arg==arg){
759: p->c_next= q->c_next;
760: q->c_next= callfree;
761: callfree= q;
762: if(p=p->c_next)
763: p->c_time += q->c_time;
764: break;
765: }
766: splx(s);
767: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.