|
|
1.1 root 1: /* Jupiter driver -- both 8 bit programmed i/o and 16 bit dma i/o */
2:
3: #include "ju.h"
4: #if NJU>0
5: #include "../h/param.h"
6: #include "../h/dir.h"
7: #include "../h/user.h"
8: #include "../h/buf.h"
9: #include "../h/pte.h"
10: #include "../h/ubavar.h"
11: #include "../h/ubareg.h"
12: #include "../h/systm.h"
13:
14: #define JUPRI PZERO+10
15: #define JULOWAT 50
16:
17: struct judevice {
18: unsigned short jucsr, /* interface card csr */
19: jutc, /* transfer count */
20: juba, /* bus address */
21: juxba, /* extended bus address */
22: judcsr, /* device csr */
23: judcw, /* device command word */
24: judsw, /* device status word */
25: juvec; /* interrupt vector */
26: };
27:
28: #define JBUFSIZ 512
29: #define JUSIZ (2*JBUFSIZ)
30:
31: #define JNTRIES 2000
32: #define MAXSAME 60
33: struct ju {
34: unsigned char jucbuf[JUSIZ]; /* one buffer */
35: unsigned char *jur, *juw; /* two chasing pointers */
36: int jucc; /* char count to dismbiguate */
37: unsigned short flag; /* the case of jur == juw */
38: unsigned int writes, lastwrite;
39: unsigned short samewrite;
40: int waitcount;
41: } jutab[NJU];
42:
43: int jutimeout;
44: int waitpoke, timerpoke;
45: /* FLAG BITS */
46: #define OPEN 010
47: #define DIWAIT 020
48: #define DEBUG 040
49: #define ASLP 0100
50: #define ESLP 0200
51: #define DMA 0400
52: #define TIWAIT 01000
53:
54: /* I/O LOCATIONS */
55: #define DA 0777320
56: #define CSR DA+0
57: #define TC DA+02
58: #define BA DA+04
59: #define XBA DA+06
60: #define DCSR DA+010
61: #define DCW DA+012
62: #define DSW DA+014
63: #define VEC DA+016
64: /*
65: DA device base address
66: CSR csr for interface card
67: TC transfer count
68: BA bus address
69: XBA extended bus address
70: DCSR csr for device
71: DCW command word to device
72: DSW status word from device
73: VEC interrupt vector
74: */
75:
76: /* BIT DEFINITIONS: */
77:
78: /* interface csr register */
79: #define C_GO 1
80: #define C_DFD 2
81: #define C_BY 020
82: #define C_DIR 040
83: #define C_TIE 0100
84: #define C_DON 0200
85: #define C_FIFO 01400
86: #define C_WDF 02000
87: #define C_PGE 010000
88: #define C_VE 020000
89: #define C_MTO 040000
90: #define C_ERR 0100000
91: /*
92: C_GO dma go bit
93: C_DFD data flag done
94: C_BY byte mode
95: C_DIR xfer direction (1 for read from device)
96: C_TIE enable transfer complete interrupt
97: C_DON transfer done
98: C_FIFO fifo level
99: C_WDF waiting for data flag
100: C_PGE program error
101: C_VE vector error
102: C_MTO memory timeout
103: C_ERR any error
104: */
105:
106: /* device csr register */
107: #define D_RST 1
108: #define D_SNS 2
109: #define D_DIE 0100
110: #define D_DIR 0200
111: /*
112: D_RST reset terminal
113: D_SNS sense line
114: D_DIE enable devive interrupt
115: D_DIR device interrupt request
116: */
117:
118: /* device command word */
119: #define DC_SI 01000
120: #define DC_RST 0400
121: /*
122: DC_SI suppress interrupt from terminal
123: DC_RST reset terminal
124: */
125: /* device status word */
126: #define DS_BSY 0100000
127: #define DS_PBR 040000
128: #define DS_KSR 020000
129: /*
130: DS_BSY device busy
131: DS_PBR parallel byte ready
132: DS_KSR keystroke ready
133: */
134:
135: int juattach(), juprobe(), judgo(), judintr(), jutintr();
136: int justrategy(), justart();
137:
138: struct uba_ctlr *jucinfo[NJU];
139: struct uba_ctlr juctlr[NJU]; /* juattach() sets jucinfo to point to this */
140: struct uba_device *judinfo[NJU];
141: u_short justd[] = { 0 };
142: struct uba_driver judriver =
143: { juprobe, 0, juattach, judgo, justd, "ju", judinfo ,"ju", jucinfo };
144:
145: #define ui_open ui_type
146: struct buf jubuf[NJU];
147: struct buf judtab[NJU];
148: juprobe(reg)
149: caddr_t reg;
150: {
151: register int br, cvec;
152: register struct judevice *juaddr = (struct judevice *)reg;
153:
154: juaddr->juvec = 0500; /* set interrupt vector xxx ? */
155: /*
156: juaddr->judcsr &= ~D_DIR; |* clear interrupt request bit *|
157: juaddr->judcsr |= D_DIE; |* enable interrupt, the one that *|
158: |* happens when terminal is ready *|
159: juaddr->judcsr |= D_DIR; |*cause an interrupt *|
160: DELAY(10000);
161: */
162: br = 0x14; /* BR Level 14 = UNIBUS 4 */
163: cvec = 0500;
164: return(1);
165: }
166:
167: juattach(ui) /* initialization on system boot */
168: register struct uba_device *ui;
169: {
170: register struct uba_ctlr *um;
171: register int unit;
172:
173: unit = ui->ui_unit;
174:
175: um = &juctlr[unit];
176: jucinfo[unit] = um;
177: ui->ui_ctlr = unit;
178: ui->ui_mi = um;
179: um->um_driver = ui->ui_driver;
180: um->um_ctlr = unit;
181: um->um_ubanum = ui->ui_ubanum;
182: um->um_alive = 1;
183: um->um_intr = ui->ui_intr;
184: um->um_addr = ui->ui_addr;
185: um->um_hd = ui->ui_hd;
186: }
187:
188: static int jerror,
189: entries,direntries,breturns,oreturns,
190: impossible, jutotali, jubytes;
191: static int jwrites, jwaits, jwritepokes, jfullpokes, jreads;
192: juopen(dev, flag)
193: dev_t dev;
194: {
195: register int s;
196: register unit, d;
197: int jutimer();
198: register struct ju *ju;
199: register struct uba_device *ui;
200:
201: d = minor(dev);
202: unit = d&07;
203: ju = &jutab[unit];
204: ui = judinfo[unit];
205: if(unit >= NJU || ui->ui_alive == 0 || (ju->flag & OPEN)) {
206: u.u_error = ENXIO;
207: return;
208: }
209: jerror=waitpoke=timerpoke=0;
210: entries=direntries=breturns=oreturns=0;
211: jwrites=jwaits=jwritepokes=jfullpokes=jreads=0;
212: jubytes=jutotali=impossible=0;
213: ju->flag = (d&077)|OPEN;
214: ju->juw = ju->jur = ju->jucbuf;
215: ju->jucc = 0;
216:
217: ui->ui_open++;
218: while(((struct judevice *)ui->ui_addr)->judsw&DS_BSY)
219: sleep((caddr_t)&lbolt,JUPRI);
220: if(jutimeout == 0) { /* i.e. there is not a timer already going */
221: jutimeout++;
222: timeout(jutimer, (caddr_t)0, 60);
223: }
224:
225: }
226:
227: jutimer()
228: {
229: register struct ju *ju;
230: register unit, flag, ps;
231: register struct judevice *juaddr;
232:
233: for (unit=flag=0; unit < NJU; unit++) {
234: ju = &jutab[unit];
235: if (ju->flag&OPEN==0) {
236: continue;
237: }
238: juaddr = (struct judevice *)(judinfo[unit]->ui_addr);
239: flag++; /* unit is active */
240: ps = spl4();
241: if (ju->flag & TIWAIT) {
242: if (ju->writes == ju->lastwrite) {
243: if (++(ju->samewrite) > MAXSAME) {
244: if(ju->flag & DEBUG)printf("timer TIWAIT\n");
245: juaddr->jucsr &= ~C_GO;
246: jutintr(unit);
247: }
248: } else
249: ju->lastwrite = ju->writes;
250: }
251: if (ju->flag&DIWAIT) {
252: /* judintr thinks it has work to do, */
253: /* is waiting for a device interrupt */
254: if ((juaddr->judsw & DS_BSY) == 0) {
255: /* device is not busy! */
256: timerpoke++;
257: judintr(unit);
258: }
259: }
260: splx(ps);
261: }
262: if(flag) { /* keep timer going */
263: timeout(jutimer, (caddr_t)0, 60);
264: } else { /* no active devices, shut down timer */
265: jutimeout = 0;
266: }
267: }
268: #define DEBUGON (('J'<<8)|1)
269: #define DEBUGOFF (('J'<<8)|2)
270: #define DMAON (('J'<<8)|3)
271: #define DMAOFF (('J'<<8)|4)
272: #define READREGS (('J'<<8)|6)
273:
274: struct juregs {
275: unsigned short jucsr,
276: judcsr,
277: judsw;
278: };
279:
280: juioctl(dev, cmd, addr)
281: register dev_t dev;
282: register struct juregs *addr;
283: register cmd;
284: {
285: int unit;
286: struct ju *ju;
287: struct judevice *juaddr;
288:
289: unit = minor(dev)&07;
290: ju = &jutab[unit];
291: juaddr = (struct judevice *)judinfo[unit]->ui_addr;
292:
293: switch(cmd){
294: case DMAON:
295: if(ju->jucc > 0)juwait(ju,0); /* flush pg buffer */
296: ju->flag |= DMA;
297: if(ju->flag & DEBUG)printf("ju: DMAON\n");
298: break;
299: case DMAOFF:
300: ju->flag &= ~DMA;
301: break;
302: case READREGS:
303: addr->jucsr = juaddr->jucsr;
304: addr->judcsr = juaddr->judcsr;
305: addr->judsw = juaddr->judsw;
306: break;
307: case DEBUGON:
308: ju->flag |= DEBUG;
309: printf("ju: DEBUGON\n");
310: break;
311: case DEBUGOFF:
312: ju->flag &= ~DEBUG;
313: break;
314: default:
315: u.u_error = EFAULT;
316: }
317: }
318: juclose(dev)
319: register dev_t dev;
320: {
321: register unit;
322: register struct ju *ju;
323:
324: unit = minor(dev)&07;
325: ju = &jutab[unit];
326:
327: ju->flag &= ~OPEN; /* to shut off timer */
328: juwait(ju,0);
329: ((struct judevice *)judinfo[unit]->ui_addr)->jucsr = 0;
330: ((struct judevice *)judinfo[unit]->ui_addr)->judcsr = 0;
331:
332: judinfo[unit]->ui_open = 0;
333: if(ju->flag&DEBUG) {
334: printf("juclose: errors %d waitpokes %d timerpokes %d\n",
335: jerror,waitpoke,timerpoke);
336: printf(" judintr: %d entries, of which %d had D_DIR set\n",
337: entries, direntries);
338: printf(" %d returns on busy, %d out bottom\n",
339: breturns, oreturns);
340: printf("%d writes, %d reads, %d writepokes, %d fullpokes, %d waits\n",
341: jwrites,jreads,jwritepokes,jfullpokes,jwaits);
342: if(jubytes)
343: printf("totali %d on %d bytes sent, %d average\n",jutotali,jubytes,
344: jutotali/jubytes);
345: }
346: ju->flag = 0;
347: }
348:
349: juwait(ju, count)
350: register struct ju *ju;
351: register count;
352: {
353: register int s, times;
354: register r;
355:
356: jwaits++;
357: times = 60;
358: ju->waitcount = count;
359: while(ju->jucc > count){
360: ju->flag |= ASLP;
361: r = tsleep((caddr_t)ju, JUPRI, 1);
362: if(r == TS_TIME) { /* timed out */
363: if ((ju->flag&DIWAIT) == 0) {
364: /* oddly enough judintr doesn't think it has */
365: /* any work to do */
366: s = spl4();
367: waitpoke++;
368: judintr(ju-jutab);
369: splx(s);
370: }
371: times--;
372: if(times==0) {
373: printf("jupiter timeout, buffer flushed\n");
374: goto flush;
375: }
376: }
377: if (r==TS_SIG) {
378: flush:
379: ju->jur = ju->juw = ju->jucbuf;
380: ju->jucc = 0;
381: }
382: }
383: }
384:
385: unsigned short jcheck(addr,bitmask,value)
386: register unsigned short *addr;
387: register unsigned int bitmask, value;
388: {
389: register int times;
390: unsigned short data;
391:
392: times = 0;
393: while (((data = *addr) & bitmask) != value)
394: if (times++ >= JNTRIES) {
395: times = 0;
396: if (tsleep((caddr_t)addr, JUPRI, 1) == TS_SIG)
397: return 0;
398: }
399:
400: return data;
401: }
402:
403: juread(dev)
404: {
405: register struct judevice *addr;
406: register struct ju *ju;
407: register int unit, count;
408: register unsigned char *bptr;
409:
410: unit = dev & 07;
411: ju = &jutab[unit];
412: addr = (struct judevice *)judinfo[unit]->ui_addr;
413: jreads++;
414:
415: if (ju->jucc)
416: juwait(ju, 0);
417: if(ju->flag&DMA) {
418: if(ju->flag&DEBUG)
419: printf("attempting dma read to ju\n");
420: ju->flag |= TIWAIT;
421: physio(justrategy,&jubuf[unit],dev,B_READ,minphys);
422: return;
423: }
424: count = u.u_count;
425: bptr = ju->jucbuf;
426:
427: addr->judcsr &= ~D_DIR;
428: if(ju->flag&DEBUG)printf("DSW address %o\n",&(addr->judsw));
429: while (count--) {
430: *bptr++ = (unsigned char)(jcheck(&(addr->judsw),DS_PBR, DS_PBR)
431: &0xFF) ;
432: if(ju->flag&DEBUG)printf("DSW is %x\n",(unsigned int)addr->judsw);
433: jcheck(&(addr->judsw), DS_PBR, 0);
434: /* send PBA command */
435: jcheck(&(addr->judsw), DS_BSY, 0);
436: addr->judcw = 033;
437: if(ju->flag & DEBUG)printf("end of read loop, data %x\n",
438: (int)(*(bptr-1)));
439: }
440:
441: iomove(ju->jucbuf, u.u_count, B_READ);
442: }
443:
444: juwrite(dev)
445: {
446: register struct ju *ju;
447: register unsigned char *p;
448: register c, cc;
449: register s;
450: register unsigned char *jur;
451: register int unit;
452:
453: unit = minor(dev) & 07;
454: ju = &jutab[unit];
455: ju->writes++;
456: jwrites++;
457:
458: if(ju->flag&DMA) {
459: if(ju->flag&DEBUG)
460: printf("attempting dma write to ju\n");
461: ju->flag |= TIWAIT;
462: physio(justrategy,&jubuf[unit],dev,B_WRITE,minphys);
463: }
464: else {
465: while(u.u_count) {
466: jur = ju->jur;
467: if(jur > ju->juw)
468: cc = jur - ju->juw;
469: else if (jur == ju->juw && ju->jucc != 0)
470: cc = 0; /* buffer full */
471: else /* from juw to end of buffer */
472: cc = ju->jucbuf + JUSIZ - ju->juw;
473: if(u.u_count < cc)
474: cc = u.u_count;
475: if(cc == 0) { /* the buffer must be full */
476: s = spl4(); /* correct priority?xxx */
477: if ((ju->flag&DIWAIT) == 0) {
478: jfullpokes++;
479: judintr(unit);
480: }
481: splx(s);
482: juwait(ju,JULOWAT);
483: }
484: else { /* queue up some characters */
485: iomove(ju->juw, cc, B_WRITE);
486: if((ju->juw += cc) >= ju->jucbuf + JUSIZ)
487: ju->juw = ju->jucbuf;
488: s = spl4();
489: ju->jucc += cc;
490: if (( ju->flag&DIWAIT) == 0) {
491: jwritepokes++;
492: judintr(unit);
493: }
494: splx(s);
495: }
496: }
497: }
498: }
499:
500: /* Since justrategy is currently called only by juwrite
501: via physio, there will be only one transaction in each
502: DMA-U's queue at a given time. So we tack the given buffer
503: header pointer on at the end of the queue, and call justart
504: */
505: justrategy(bp)
506: register struct buf *bp;
507: {
508: register struct uba_device *ui;
509: register struct uba_ctlr *um;
510: register struct buf *dp;
511: register judvma;
512: dev_t unit;
513: int ps;
514:
515: ps = spl4();
516: unit = minor(bp->b_dev);
517: ui = judinfo[unit];
518: um = ui->ui_mi; /* ctlr pointer */
519: dp = &judtab[unit];
520: dp->b_actf = bp;
521: dp->b_actl = bp;
522: bp->av_forw = NULL;
523: um->um_tab.b_actf = dp;
524: um->um_tab.b_actl = dp;
525: um->um_cmd = C_TIE | C_GO;
526: if (bp->b_flags & B_READ)
527: um->um_cmd |= C_DIR;
528:
529: justart(um);
530: splx(ps);
531: }
532:
533: justart(um)
534: register struct uba_ctlr *um;
535: {
536: register struct buf *bp, *dp;
537: register struct judevice *juaddr;
538:
539: dp = um->um_tab.b_actf;
540: bp = dp->b_actf;
541: um->um_tab.b_active++;
542: juaddr = (struct judevice *)um->um_addr;
543: jcheck(&(juaddr->judsw), DS_BSY, 0);
544: juaddr->jutc = -bp->b_bcount / sizeof(short);
545: juaddr->judcsr = juaddr->jucsr = 0;
546: (void) ubago(judinfo[minor(bp->b_dev)]);
547: }
548:
549: judgo(um)
550: register struct uba_ctlr *um;
551: {
552: register struct judevice *juaddr = (struct judevice *)um->um_addr;
553:
554: juaddr->juba = um->um_ubinfo;
555: juaddr->juxba = (um->um_ubinfo>>16) & 3;
556: juaddr->jucsr = um->um_cmd;
557: }
558: jutintr(dev)
559: register dev_t dev;
560: {
561: register struct buf *bp, *dp;
562: register struct judevice *juaddr;
563: register struct uba_ctlr *um;
564: register unit;
565: register struct ju *ju;
566:
567: unit = minor(dev) & 07;
568: um = jucinfo[unit];
569:
570: ju = &jutab[unit];
571: ju->flag &= ~TIWAIT;
572: ju->samewrite = 0;
573: juaddr = (struct judevice *)um->um_addr;
574: juaddr->jucsr = 0;
575: if(um->um_tab.b_active == 0)
576: return;
577:
578: dp = um->um_tab.b_actf;
579: bp = dp->b_actf;
580:
581: /* should check for errors? */
582:
583: um->um_tab.b_active = 0;
584: um->um_tab.b_errcnt = 0;
585: um->um_tab.b_actf = dp->b_forw;
586: dp->b_errcnt = 0;
587: dp->b_active = 0;
588: bp->b_resid = (-juaddr->jutc * sizeof(short));
589: ubadone(um);
590: iodone(bp);
591: }
592:
593: static int jcount;
594: judintr(dev)
595: register dev_t dev;
596: {
597: register struct ju *ju;
598: register struct judevice *addr;
599: register c, cc, unit;
600:
601: unit = minor(dev) & 07;
602: ju = &jutab[unit];
603: ju->flag &= ~DIWAIT;
604: addr = (struct judevice *)judinfo[unit]->ui_addr;
605:
606: entries++; if(addr->judcsr&D_DIR)direntries++;
607:
608: if (addr->jucsr&C_ERR) {
609: printf("error: ju %d %x\n",dev,(int)addr->jucsr);
610: addr->jucsr &= ~C_ERR;
611: ju->flag &= ~DIWAIT;
612: ju->flag |= ESLP;
613: jerror++;
614: return;
615: }
616:
617: cc = 0;
618: while (ju->jucc > 0) {
619: addr->judcsr &= ~D_DIR; /* clear interrupt request bit */
620: for(jcount=0;jcount<JNTRIES;jcount++)
621: if( (addr->judsw&DS_BSY) == 0 )goto putout;
622: /* busy too long -- sleep */
623: addr->judcsr |= D_DIE;
624: ju->flag |= DIWAIT;
625: if(ju->flag&ASLP && ju->jucc <= ju->waitcount){
626: ju->flag &= ~ASLP;
627: wakeup((caddr_t)ju);
628: }
629: breturns++;
630: return;
631: putout: /* not busy: output a byte */
632: addr->judcw = *(ju->jur)++;
633: if (ju->jur == ju->jucbuf + JUSIZ)
634: ju->jur = ju->jucbuf;
635: ju->jucc--;
636: cc++;
637: jutotali += jcount;
638: jubytes++;
639: }
640:
641:
642: out: if(cc && ju->flag&ASLP && ju->jucc <= ju->waitcount) {
643: ju->flag &= ~ASLP;
644: wakeup ((caddr_t)ju);
645: }
646: oreturns++;
647: }
648: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.