|
|
1.1 root 1: /*
2: * ibv.c - DEC IBV-11A IEEE INTERFACE DRIVER
3: * Version III (modified for portability, burst reads,
4: * and easier secondary addressing)
5: * DLA 8/1/85
6: *
7: *
8: changed for the Qbus VAX under
9: unix 10e T. Siegrist 19-Nov-94
10:
11: the base address is needed for two registers, the csr and ibs
12:
13: the board generates 4 interrupts:
14: - err error 420
15: - srq service request 424
16: - tlr talker 430
17: - lnr listener 434
18:
19: To Install:
20:
21: low core section:
22: . = ZERO + 420
23:
24: ibverr; br5
25: ibvsrq; br5
26: ibvtlr; br5
27: ibvlnr; br5
28:
29:
30: .globl _iberr
31: ibverr: jsr r0,call; jmp _iberr
32:
33: .globl _ibsrq
34: ibvsrq: jsr r0,call; jmp _ibsrq
35:
36: .globl _ibwint
37: ibvtlr: jsr r0,call; jmp _ibwint
38:
39: .globl _ibrint
40: ibvlnr: jsr r0,call; jmp _ibrint
41:
42: c.c section:
43: int ibopen(), ibclose(), ibread(), ibwrite(), ibioctl();
44: in cdevsw, add:
45: ibopen, ibclose, ibread, ibwrite, ibioctl, nulldev, 0,
46: then add other code
47:
48: Install ibv.h in /usr/include for user access to regular IEEE commands
49: */
50:
51:
52: /* define NOSDC for no SDC command sent with device open.
53: * allows full use of Shell - level I/O without resetting device
54: * each time. "friendly" systems only!
55: */
56: #define NOSDC
57:
58: /*
59: #include "../h/param.h"
60: #include "../h/dir.h"
61: #include "../h/user.h"
62: #include "../h/proc.h"
63: #include "../h/var.h"
64: */
65:
66: #include <sys/param.h>
67: #include <sys/dir.h>
68: #include <sys/user.h>
69: #include <sys/ubaddr.h>
70: #include <sys/proc.h>
71: #include <sys/systm.h>
72: #include <sys/ibv.h>
73:
74: #define IB_ADDR 0775000 /* IBV-11 base address */
75: #define IB_VEC 420 /* Interrupt vector */
76: #define NIBDEV 31 /* max devices on IEEE bus */
77: /* (Note the IBV-11 is limited to 15 devs online at a time, but
78: * minors for these may range 1-30. 0 will be for the raw bus.
79: * Attempting an open on any minor >= NIBDEV sends kill to all bus
80: * processes and unconditionally resets bus.)
81: */
82:
83: #define QMAX 75 /* max queue characters */
84: #define TTIME 1800 /* ibtimer return interval in system Hz */
85: #define IQLOOP 750 /* max untimed inqueue wait loop */
86: #define OQLOOP 750 /* max untimed outqueue wait loop */
87: /* Pri range while awaiting IEEE bus, > PZERO allows proc to be signaled.
88: * Range is reset to IBSPRI when IBHPRI is reached.
89: */
90: #define IBLPRI PZERO+5 /* multi-user low value */
91: #define IBSPRI PZERO+15 /* multi-user start value */
92: #define IBHPRI PZERO+25 /* multi-user high value */
93: #define IBXPRI IBLPRI+5 /* exclusive-use wait value */
94:
95:
96: /* IB STATUS FLAGS */
97: #define IBLOCK 001 /* locked */
98: #define IBATEOF 002 /* at EOF */
99: #define IBERR 010 /* bus error */
100: #define IBULOCK 070 /* unlocking mask - LOCK and EOF bits only! */
101:
102: /* HARDWARE CONTROL */
103: #define IBSRQ (1<<15) /* csr definitions: */
104: #define IBER2 (1<<14)
105: #define IBER1 (1<<13)
106: #define IBCMD (1<<10)
107: #define IBTKR (1<<9)
108: #define IBLNR (1<<8)
109: #define IBACC (1<<7)
110: #define IBIEN (1<<6)
111: #define IBTON (1<<5)
112: #define IBLON (1<<4)
113: #define IBIBC (1<<3)
114: #define IBREM (1<<2)
115: #define IBEOP (1<<1)
116: #define IBTCS (1<<0)
117:
118: #define BEOI (1<<15) /* ibs definitions: */
119: #define BATN (1<<14)
120: #define BIFC (1<<13)
121: #define BREN (1<<12)
122: #define BSRQ (1<<11)
123: #define BRFD (1<<10)
124: #define BDAV (1<<9)
125: #define BDAC (1<<8)
126:
127: #define IBATT (IBREM | IBIEN | IBTCS) /* IB11 take control */
128: #define IBTALK (IBREM | IBIEN | IBTON) /* IB11 talker */
129: #define IBLISTEN (IBREM | IBIEN | IBLON | IBACC) /* IB11 listener */
130: #define IBIFC (IBREM | IBIEN | IBIBC) /* IB11 send IFC */
131: #define IBWAIT (IBREM | IBIEN) /* IB11 standby */
132:
133:
134: /* structure definitions */
135: struct clist { /* standard character queue */
136: int c_cc; /* character count */
137: char *c_cf; /* pointer to first char */
138: char *c_cl; /* pointer to last char */
139: };
140:
141: struct ibdevs { /* bus devices */
142: short pid; /* proc id controlling dev */
143: short signo; /* sig no. to be sent on SRQ */
144: char sbyte; /* SRQ status return byte (returned as int) */
145: char pri; /* bus use priority penalty */
146: } bdev[NIBDEV];
147:
148: struct device { /* the IBV-11 hardware itself */
149: unsigned short csr; /* control & status register */
150: unsigned short ibs; /* instrument bus status register */
151: /* these are 16-bit registers */
152: };
153:
154: struct ib { /* IBV-11 driver */
155: unsigned state; /* current status flags */
156: int count; /* number of currently open devices */
157: struct clist iq; /* char in queue */
158: struct clist oq; /* char out queue */
159: } ib;
160:
161:
162: /* this is the absolute addressing scheme of the PDP/11
163: it is now replaced by a relative addressing scheme, where
164: the address is fetched from the address array ubaddr
165:
166: #define ibc ((struct device *)IB_ADDR) /* the IBV-11 card */
167: */
168:
169: #define TEST(flag) (ib.state & flag) /* shorthand */
170:
171: short ibrcount; /* read count */
172: short mtq; /* queue activity test flags */
173: short omtq;
174: short timer; /* timer active flag */
175: extern int ibtimer(); /* ib timeout routine */
176:
177:
178:
179: ibopen(dev,flag)
180: { register struct ibdevs *pbdev;
181: register s;
182:
183: if( minor(dev) >= NIBDEV ) /* unconditional bus reset */
184: { for( pbdev = bdev; pbdev < &bdev[NIBDEV]; pbdev++ )
185: { ibpsig( pbdev->pid, 9 ); /* SIGKILL all procs */
186: pbdev->pid = 0;
187: }
188: ib.state = 0;
189: ib.count = 0;
190: ibc->csr = 0;
191: wakeup((caddr_t)&ib.state);
192: err: u.u_error = ENXIO;
193: return;
194: }
195:
196: /* Check this bus dev not inuse. Note bdev[0] is interface itself,
197: * with a nonzero pid if exclusive use. Since ibpsig returns 0
198: * for a pid = 0, the double test is ok.
199: */
200: pbdev = &bdev[minor(dev)];
201: if( ibpsig(pbdev->pid, 0) || ibpsig(bdev[0].pid, 0) )
202: { u.u_error = EBUSY;
203: return;
204: }
205:
206: /*
207: * Since polling of IEEE devices is so device dependent, there is
208: * no general way to tell if a particular one is online. Send cmds
209: * to clear. If interrupt has set error, there are NONE active.
210: */
211:
212: pbdev->pri = IBLPRI; /* open gets highest priority */
213: if( minor(dev) ) /* address device for clear */
214: { bdev[0].pid = 0; /* should be! */
215: ibsetup(dev, 1); /* await free bus, setup to listen */
216: #ifndef NOSDC /* send SDC to dev, else just address & unaddress */
217: putc(SDC, &ib.oq);
218: #endif
219: } else /* exclusive: await bus empty */
220: { s = spl5(); /* allow to sleep before wakeup call */
221: while( ib.count || TEST(IBLOCK) )
222: sleep((caddr_t)&ib.state,IBXPRI);
223: ib.state = IBLOCK;
224: splx(s);
225: ibqdrain();
226: putc(UNTALK, &ib.oq);
227: }
228:
229: ib.state |= IBATEOF; /* flag to free after last output */
230:
231: if( ib.count ) s = IBATT; /* start command output */
232: else s = IBIFC; /* open with IFC */
233:
234: if( ibstart(s) ) /* iberr or timeout */
235: { printf("\nNo active IEEE devices");
236: return;
237: }
238:
239: pbdev->pid = u.u_procp->p_pid; /* this pid now owns dev */
240: pbdev->signo = 0; /* clear SRQ returned signal */
241: pbdev->sbyte = 0; /* clear SRQ status byte */
242: pbdev->pri = IBSPRI; /* set starting I/O priority */
243: ib.count++; /* update open count */
244: }
245:
246:
247: ibclose(dev)
248: { bdev[minor(dev)].pid = 0;
249: if( --ib.count == 0 ) wakeup((caddr_t)&ib.state);
250: }
251:
252:
253: ibread(dev)
254: { register c;
255:
256: ibsetup(dev, 0); /* steal and setup bus */
257: if( minor(dev) )
258: if( ibstart(IBATT) ) return; /* addressing sequence */
259:
260: /* ibrint() keeps track of count via ibrcount. If EOI observed
261: * on bus, ibrcount set to 0 to flag transaction complete.
262: */
263: ibrcount = u.u_count;
264:
265: do{ /* break if usr read filled or EOI on bus: */
266: if(ib.iq.c_cc == 0)
267: { if( ibrcount == 0 ) break;
268: if( ibstart(IBLISTEN) ) return;
269: }
270: } while( passc(getc(&ib.iq)) == 0 );
271:
272: if( minor(dev) )
273: { ib.state |= IBATEOF;
274: putc(UNTALK,&ib.oq);
275: ibstart(IBATT);
276: } else ibfree(); /* exclusive-use mode - no unaddressing */
277: }
278:
279:
280: ibwrite(dev)
281: { register c;
282: register s;
283:
284: ibsetup(dev, 1);
285: if( minor(dev) )
286: if( ibstart(IBATT) ) return;
287:
288: /* get chars from user buf. try at least once since u.u_count = 0
289: * is not necessarily EOF at start . cpass will set u.u_error if
290: * bad buffer read occurs.
291: */
292:
293: if( (c = cpass()) < 0 )
294: { putc(UNLISTEN, &ib.oq);
295: s = IBATT;
296: goto out;
297: }
298: s = IBTALK;
299: putc(c, &ib.oq);
300:
301: do { if( (c = cpass()) < 0 ) break;
302: if( ib.oq.c_cc > QMAX ) /* restart ints and sleep */
303: if( ibstart(IBTALK) ) return;
304:
305: putc(c, &ib.oq);
306: } while( u.u_count ) ;
307:
308: out: ib.state |= IBATEOF;
309: ibstart(s);
310: }
311:
312:
313:
314: ibioctl(dev, mode, arg, flag)
315: dev_t dev;
316: int mode;
317: caddr_t arg;
318: { register struct ibdevs *pbdev;
319: register s;
320: int cmd;
321:
322: pbdev = &bdev[minor(dev)];
323:
324: switch( mode )
325: { case IBSETPID: /* set new controlling pid */
326: if( copyin( arg, (caddr_t)&pbdev->pid,
327: sizeof(pbdev->pid)) )
328: {
329: err1: u.u_error = EFAULT;
330: return;
331: }
332: break;
333: case IBSETSIG: /* set SRQ return signal */
334: if( copyin( arg, (caddr_t)&pbdev->signo,
335: sizeof(pbdev->signo)) ) goto err1;
336: break;
337: case IBGETSTAT: /* return SRQ status byte */
338: /* insure no SRQ int while current byte is being
339: * cleared. sbyte is int for copyout() portability
340: */
341: s = spl5();
342: cmd = pbdev->sbyte;
343: if( copyout( (caddr_t)&cmd, arg, sizeof(cmd)) )
344: u.u_error = EFAULT;
345: else pbdev->sbyte = 0; /* clear status byte */
346: splx(s);
347: break;
348: case IBSENDC: /* send command */
349: ibsetup(dev, 1);
350: if( copyin( arg, (caddr_t)&cmd, sizeof(cmd)) )
351: { ibfree();
352: goto err1;
353: }
354: putc(cmd, &ib.oq);
355:
356: if( minor(dev) ) /* addr cmds (less TCT) only: */
357: { if( cmd & 020 || cmd == TCT )
358: { ibfree();
359: goto err2;
360: }
361: putc(UNLISTEN, &ib.oq);
362: } else /* "raw" bus mode: */
363: { if( cmd == TCT )
364: { /* release bus until EOI or signaled */
365: if( ibstart(IBATT) ) return;
366: ibc->csr = IBREM;
367: mtq++; /* allow timeout wakeups */
368: while( !(ibc->ibs & BEOI) && !issig() )
369: sleep((caddr_t)&mtq, IBLPRI);
370: } else
371: { /* if extended (2byte) cmd, add to queue: */
372: cmd >>= 8;
373: if( cmd ) putc(cmd,&ib.oq);
374: }
375: }
376: ib.state |= IBATEOF;
377: ibstart(IBATT);
378: break;
379: default:
380: err2: u.u_error = EINVAL;
381: }
382: }
383:
384:
385:
386: ibrint()
387: {
388: putc(ibc->ibs, &ib.iq);
389:
390: /* if not last char or buffer overflow, complete handshake
391: * and return. Otherwise, stop I/O by not completing handshake:
392: * ibstart() will complete and restart if more chars expected.
393: */
394:
395: if( ibc->ibs & BEOI ) ibrcount = 0; /* last byte from sender */
396: else ibrcount--;
397:
398: if( ibrcount && ib.iq.c_cc < QMAX )
399: { ibc->ibs = 0; /* complete DAC handshake */
400: mtq++; /* show activity to preclude timeout */
401: } else
402: { omtq = mtq = 0; /* invalidate timer */
403: wakeup((caddr_t)&mtq);
404: }
405:
406: }
407:
408:
409:
410: ibwint()
411: { if( ib.oq.c_cc == 0 ) /* empty queue - alert process */
412: { omtq = mtq = 0; /* invalidate timer */
413: wakeup((caddr_t)&mtq);
414: if( TEST(IBATEOF) ) ibfree();
415: return;
416: }
417:
418: mtq++; /* show activity */
419:
420: /* if last char on queue, set EOI and add UNLISTEN if reqd: */
421: if( (ib.oq.c_cc == 1) && TEST(IBATEOF) && !(ibc->ibs & BATN) )
422: { if( ibc->ibs & BEOI )
423: { /* previous was last data in normal-use mode,
424: * and UNLISTEN is char on queue.
425: * remove EOI, set ATT for UNLISTEN cmd
426: * and output next loop
427: */
428: ibc->csr = IBATT;
429: return;
430: } else
431: { /* last data: add EOI to output and queue
432: * UNLISTEN if normal use mode.
433: * Since ATEOF, bus will be freed afterwards
434: */
435: ibc->csr |= IBEOP;
436: if( !bdev[0].pid ) putc(UNLISTEN, &ib.oq);
437: }
438: }
439:
440: ibc->ibs = getc(&ib.oq) & 0377;
441: }
442:
443:
444:
445: iberr()
446: { if( ibc->csr & IBER1 ) printf("\nIEEE hardw error");
447: ibterror();
448: }
449:
450:
451: ibsrq()
452: { /* If bus locked, SRQ poll will be done during ibfree().
453: * Otherwise, if bus open call ibfree to do poll now.
454: * ibpollsrq will show bus locked when running.
455: */
456: if( !TEST(IBLOCK) && ib.count )
457: { ib.state |= IBLOCK;
458: ibfree(); /* run srq, etc */
459: }
460: }
461:
462:
463:
464: ibpollsrq() /* called from ibfree() to do SRQ serial poll */
465: { register struct ibdevs *pbdev;
466: register i, flag;
467: int s, twice;
468: char c;
469:
470: /* if exclusive-use, signal and return */
471: if( ibpsig( bdev[0].pid, bdev[0].signo) ) return;
472:
473: /* Serial poll active devices first. If SRQ, record status byte and
474: * signal process. If SRQ uncleared, try all devices. Timeouts are
475: * loops and spl is reset since poll might be called from interrupt.
476: */
477: ibc->csr = IBWAIT;
478: ib.state &= ~IBATEOF;
479: s = spl1();
480: ibqdrain();
481: ibunq();
482: putc(SPE, &ib.oq);
483: flag = 1;
484: twice = 0;
485:
486: loop: while( ibc->ibs & BSRQ )
487: { for(pbdev = &bdev[1], i = 1; i < NIBDEV; pbdev++, i++)
488: { if( flag )
489: { if( pbdev->pid == 0 ) continue;
490: } else if( pbdev->pid ) continue;
491: putc((i | TALK), &ib.oq);
492: mtq++;
493: ibc->csr = IBWAIT;
494: ibc->csr = IBATT;
495: if( iboqloop() ) break;
496: ibrcount = 1; /* 1 byte anticipated */
497: ibc->csr = IBLISTEN;
498: if( ibiqloop() ) continue; /* LISTEN timeout */
499:
500: if( (c = getc(&ib.iq)) & 0100 ) /* set bit = SRQ */
501: { if( twice == i ) /* bad device: */
502: { printf("\nIEEE bad dev %d",i);
503: flag = 0;
504: break;
505: }
506:
507: twice = i;
508: pbdev->sbyte = c; /* store status */
509: if( pbdev->signo ) /* send sig if wanted */
510: ibpsig(pbdev->pid, pbdev->signo);
511: goto loop; /* search for more SRQ's */
512: }
513: }
514: if(flag) flag = 0;
515: else
516: { printf("\nIEEE uncleared SRQ");
517: break;
518: }
519: }
520:
521: /* end poll. Note if SRQ has not been cleared, bus ops can
522: * continue, but runsrq will occur again at every ibfree().
523: */
524: putc(SPD, &ib.oq);
525: ibunq();
526: mtq++;
527: ibc->csr = IBWAIT;
528: ibc->csr = IBATT;
529: if( iboqloop() ) printf("\nIEEE bad SRQ poll");
530: splx(s);
531: }
532:
533:
534: ibsetup(dev, flag) /* await bus, setup, queue dev address */
535: dev_t dev;
536: int flag;
537: { register struct ibdevs *pbdev;
538: register s;
539:
540: pbdev = &bdev[minor(dev)];
541: if( pbdev->pri < IBHPRI ) pbdev->pri++; /* use penalty */
542: else pbdev->pri = IBSPRI; /* reset */
543:
544: s = spl5(); /* hold off intrs until test and sleep */
545: while( TEST(IBLOCK) )
546: { if( pbdev->pri > IBLPRI ) pbdev->pri--;
547: sleep((caddr_t)&ib.state, pbdev->pri);
548: }
549:
550: ib.state = IBLOCK; /* show now inuse */
551: splx(s);
552: ibqdrain();
553: if( minor(dev) ) /* not exclusive-use: q dev addr for I/O */
554: { ibunq(); /* queue bus UN- commands */
555: if(flag) putc((minor(dev) | LISTEN),&ib.oq);
556: else putc((minor(dev) | TALK),&ib.oq);
557: }
558: }
559:
560:
561:
562: ibstart(csr) /* start interrupts, sleep on mtq & test error */
563: int csr;
564: { register s;
565:
566: s = spl5(); /* disable ints until reallowed as part of sleep() */
567: if( timer == 0 ) /* start ibtimer if not running */
568: { timer++;
569: timeout( ibtimer, (caddr_t)0, TTIME);
570: }
571: omtq = mtq = 0; /* guarantee fresh timeout */
572: mtq++;
573: ib.state &= ~IBERR; /* clear ERR flag */
574: /* csr bits should not be toggled for LISTEN. toggling is
575: * required for TALK and ATT to trigger first interrupt.
576: * write 0 to ibc->ibs to complete a LISTEN handshake - reqd
577: * if listening interrupted due to buffer fill.
578: */
579: if( csr == IBLISTEN ) ibc->ibs = 0;
580: else ibc->csr = IBWAIT;
581:
582: ibc->csr = csr;
583: sleep((caddr_t)&mtq, PZERO); /* not awakened by signal */
584:
585: splx(s);
586: if( TEST(IBERR) ) /* timeout or iberr */
587: { u.u_error = ENXIO; /* default error */
588: return(1);
589: }
590:
591: return(0);
592: }
593:
594:
595:
596: ibtimer() /* timeout routine */
597: { if( TEST(IBLOCK) )
598: { if( mtq && (mtq == omtq) )
599: { printf("\nIEEE timeout ");
600: ibterror();
601: } else /* continue timer */
602: { omtq = mtq;
603: timeout( ibtimer, (caddr_t)0, TTIME);
604: return;
605: }
606: }
607: timer = 0; /* turn timer off */
608: }
609:
610:
611:
612: ibterror() /* bus or timeout error close routine */
613: { ib.state |= IBERR;
614: omtq = mtq = 0;
615: wakeup((caddr_t)&mtq);
616: if( TEST(IBLOCK) ) ibfree();
617: }
618:
619:
620:
621: ibqdrain() /* flush I/O queues */
622: { while( getc(&ib.iq) >= 0 ) ;
623: while( getc(&ib.oq) >= 0 ) ;
624: }
625:
626:
627: ibunq() /* add UN- bus commands to output queue */
628: { putc(UNTALK, &ib.oq);
629: putc(UNLISTEN, &ib.oq);
630: }
631:
632:
633:
634: iboqloop() /* loop timeout on outqueue activity */
635: { int i = 0;
636:
637: while( mtq )
638: if( i++ > OQLOOP ) return(1);
639: return(0);
640: }
641:
642: ibiqloop() /* loop timeout on inqueue activity */
643: { int i = 0;
644:
645: while( ib.iq.c_cc == 0 )
646: if( i++ > IQLOOP ) return(1);
647: return(0);
648: }
649:
650:
651: ibfree()
652: { if( ibc->ibs & BSRQ ) ibpollsrq(); /* service any SRQ request */
653: ib.state &= IBULOCK; /* clear EOF & LOCK flags */
654: ibc->csr = IBWAIT; /* leave csr in standby */
655: wakeup((caddr_t)&ib.state); /* alert any sleepers */
656: }
657:
658:
659: /* ibpsig() - checks pid active in sys proc table, sends sig if nonzero.
660: * returns 1 if process was found, 0 if not
661: */
662: ibpsig(pid, sig)
663: short pid;
664: short sig;
665: { register struct proc *pp;
666:
667: if( pid == 0 ) return(0);
668:
669: for(pp = &proc[0]; pp < u.u_procp; pp++) /* changed TSI*/
670: /* for(pp = &proc[0]; pp < maxproc; pp++) */
671: if( pp->p_pid == pid )
672: { if( sig ) psignal(pp, sig);
673: return(1);
674: }
675:
676: return(0);
677: }
678:
679:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.