|
|
1.1 root 1: /*
2: * Datakit driver
3: */
4: #include "sys/param.h"
5: #include "sys/systm.h"
6: #include "sys/stream.h"
7: #include "sys/dkio.h"
8: #include "sys/ubaddr.h"
9: #include "sys/conf.h"
10: #include "sys/dk.h"
11: #include "sys/dkstat.h"
12: #include "sys/dkmod.h"
13:
14: #define SAFETY 1 /* turn off doubtful speed hack */
15:
16: struct device {
17: unsigned short csr;
18: unsigned short dko;
19: unsigned short dki;
20: };
21:
22: struct device *DKADDR; /* assume one addr for now */
23:
24: extern struct dk dk[];
25: extern int dkcnt;
26: extern char dkstate[];
27:
28: #define DKXCL 01
29:
30: int dkalive;
31: struct dkstat dkstat;
32: extern struct dkmodule dkmod[];
33: struct dkmodule *dkmodp;
34:
35: /*
36: * Hardware control bits
37: */
38: #define DKTENAB 0100
39: #define DKRENAB 040
40: #define ENABS (DKRENAB)
41: #define DKTDONE 0200
42: #define DKRDONE 0100000
43: #define D_OSEQ 0
44: #define D_READ 01
45: #define D_WRITE 02
46: #define D_XPACK 03
47: #define DKMARK 01000
48: #define DKDATA 0400
49: #define DKPARITY 0100000
50:
51: #define DKOPKT 16 /* biggest output packet */
52: #define DKIPKT 16 /* biggest input packet */
53: #define DKISML 16 /* smallest interesting allocation */
54: #define DKITHRES 200
55:
56: int dkclose(), dkput();
57: long dkopen();
58:
59: static struct qinit dkrinit = { noput, NULL, dkopen, dkclose, 0, 0 };
60: struct qinit dkwinit = { dkput, NULL, dkopen, dkclose, 0, 0 };
61: struct streamtab dkinfo = { &dkrinit, &dkwinit };
62: struct cdevsw dkcdev = cstrinit(&dkinfo);
63: extern struct ubaddr dkaddr[];
64:
65: /*
66: * open DK channel
67: */
68: long
69: dkopen(q, dev)
70: register struct queue *q;
71: register dev_t dev;
72: {
73: register struct dk *dkp;
74: static opened, badtime;
75: register chan;
76:
77: chan = minor(dev);
78: if (chan<=0 || chan>=dkcnt)
79: return(0);
80: if (!opened) {
81: register i;
82:
83: if ((DKADDR = (struct device *)ubaddr(&dkaddr[0])) == NULL
84: || badaddr(DKADDR, 2)) {
85: printf("dk0 absent\n");
86: return (0);
87: }
88: DKADDR->csr = D_OSEQ;
89: DKADDR->dko = 0; /* Clear fifo's */
90: i = 256; /* sanity count */
91: DELAY(1000); /* wait for board to reset */
92: do {
93: if (DKADDR->csr & DKTDONE) {
94: dkalive = 0;
95: if (time > badtime + 300) {
96: badtime = time;
97: printf("DK interface bad\n");
98: }
99: return(0);
100: }
101: } while (--i);
102: if ((dkmodp = dkmodall(dev, 0, dkcnt)) == NULL)
103: return (0);
104: dkmodp->dkstate = dkstate;
105: dkalive = 1;
106: for (dkp = dk, i = 0; i < dkcnt; dkp++, i++)
107: dkp->chan = i;
108: DKADDR->csr = ENABS;
109: opened++;
110: dkrecover(chan);
111: }
112: dkp = &dk[chan];
113: if (dkstate[chan] != DKCLOSED) { /* already open */
114: if (dkp->flag & DKXCL) {
115: /* printf("DK XCL chan %d state %o flag %o\n", chan, dkstate[chan], dkp->flag); */
116: return(0);
117: }
118: if (dkstate[chan] != DKOPEN) {
119: /* printf("DK XCL chan %d state %o flag %o\n", chan, dkstate[chan], dkp->flag); */
120: return(0); /* closing channels can't reopen */
121: }
122: return(1);
123: }
124: dkp->dkrq = q;
125: q->ptr = (caddr_t)dkp;
126: WR(q)->ptr = (caddr_t)dkp;
127: dkp->flag = DKXCL;
128: dkp->icnt = 0;
129: dkp->isize = 0;
130: dkp->ibuf = 0;
131: dkp->ialloc = DKISML;
132: dkstate[chan] = DKOPEN;
133: return(1);
134: }
135:
136: /*
137: * Timer to recover from lost interrupt condition.
138: */
139: dkrecover(dev)
140: dev_t dev;
141: {
142: register int ps = spl5();
143:
144: if (DKADDR->csr & DKRDONE)
145: dk1int(dev);
146: splx(ps);
147:
148: timeout(dkrecover, (caddr_t)dev, HZ/2);
149: }
150:
151: /*
152: * close DK channel
153: */
154: dkclose(q)
155: register struct queue *q;
156: {
157: register struct dk *dkp;
158: register struct block *bp;
159:
160: dkp = (struct dk *)q->ptr;
161: dkp->dkrq = NULL;
162: dkp->flag = 0;
163: if (dkstate[dkp->chan] == DKRCLOSE || dkmodp->listnrq==NULL)
164: dkstate[dkp->chan] = DKCLOSED;
165: else if (dkstate[dkp->chan] == DKOPEN)
166: dkstate[dkp->chan] = DKLCLOSE;
167: if (dkmodp->listnrq)
168: putctl2(RD(dkmodp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
169: if (dkp->ibuf)
170: freeb(dkp->ibuf);
171: while ((bp = dkp->ofirst) != NULL) {
172: dkp->ofirst = bp->next;
173: freeb(bp);
174: }
175: dkp->ibuf = 0;
176: }
177:
178: /*
179: * DK receiver interrupt.
180: */
181:
182: #define PUTIN(bp, q) {\
183: dkstat.input += (bp)->wptr - (bp)->rptr;\
184: if (((q)->next->flag & QFULL) == 0)\
185: (*(q)->next->qinfo->putp)(q->next, bp);\
186: else\
187: freeb(bp);\
188: }
189:
190: #define DKSIZUP(dkp) {\
191: if (dkp->isize > DKITHRES) {\
192: dkp->ialloc = dkp->isize;\
193: dkp->icnt = 3;\
194: } else if (--dkp->icnt <= 0) {\
195: dkp->icnt = 0;\
196: dkp->ialloc = DKISML;\
197: }\
198: dkp->isize = 0;\
199: }
200:
201: dk1int(dev)
202: {
203: register struct queue *q;
204: register struct block *bp;
205: register struct dk *dkp;
206: register struct device *reg;
207: register c, nbytes;
208: register sane, chan;
209: register struct block **bpp;
210: struct block *blist[DKIPKT+2];
211:
212: if ((reg = DKADDR) == NULL)
213: return;
214: c = 0;
215: dkp = NULL;
216: while (reg->csr & DKRDONE) {
217: reg->csr = D_READ|ENABS;
218: if ((c & DKMARK) == 0) {
219: /* Search for channel number */
220: sane = 256;
221: do {
222: c = reg->dki;
223: if (c & DKMARK || --sane==0)
224: break;
225: } while (reg->csr & DKRDONE);
226: }
227: if ((c & DKMARK) == 0) {
228: dkstat.markflt++;
229: continue;
230: }
231: if ((c & DKPARITY) == 0) {
232: dkstat.markparity++;
233: c = 0;
234: continue;
235: }
236: /* check channel */
237: chan = c & 0777;
238: if (dkp && dkp->chan != chan) {
239: if ((bp = dkp->ibuf) != NULL)
240: PUTIN(bp, q);
241: DKSIZUP(dkp);
242: dkp->ibuf = NULL;
243: }
244: if (chan == 0 || chan >= dkcnt || (q = dk[chan].dkrq)==NULL) {
245: if (chan>0 && chan<dkcnt)
246: dkstat.closepack++;
247: else if (chan == 0)
248: dkstat.pack0++;
249: else
250: dkstat.packstrange++;
251: for (nbytes=0; nbytes<DKIPKT; nbytes++) {
252: c = reg->dki;
253: if (c & DKMARK)
254: break;
255: }
256: continue;
257: }
258: dkp = (struct dk *)q->ptr;
259: if ((bp = dkp->ibuf) == NULL
260: && (bp = allocb(dkp->ialloc)) == NULL)
261: return;
262: bpp = blist;
263: for (nbytes=0; nbytes<DKIPKT; nbytes++) {
264: #ifdef SAFETY
265: if ((reg->csr&DKRDONE) == 0)
266: break;
267: #endif
268: c = reg->dki;
269: if ((c&(DKPARITY|DKMARK|DKDATA)) == (DKPARITY|DKDATA)) {
270: if (bp->wptr >= bp->lim) {
271: *bpp++ = bp;
272: if ((bp = allocb(DKISML)) == NULL)
273: break;
274: }
275: *bp->wptr++ = c;
276: dkp->isize++;
277: continue;
278: }
279: /*
280: * control or error
281: */
282: if (c & DKMARK) {
283: dkstat.shortpack++;
284: break;
285: }
286: if ((c & DKPARITY) == 0) {
287: dkstat.parity++;
288: break;
289: }
290: if ((c & 0377) == 0) /* control-null */
291: continue;
292: if (bp->wptr > bp->rptr) {
293: *bpp++ = bp;
294: if ((bp = allocb(DKISML)) == NULL)
295: break;
296: }
297: bp->type = M_CTL;
298: *bp->wptr++ = c;
299: }
300: if (bpp == blist && bp->type == M_DATA) {
301: dkp->ibuf = bp;
302: continue;
303: }
304: *bpp++ = bp;
305: *bpp = NULL;
306: bpp = blist;
307: while ((bp = *bpp++) != NULL)
308: PUTIN(bp, q);
309: DKSIZUP(dkp);
310: dkp->ibuf = NULL;
311: }
312: if (dkp && (bp = dkp->ibuf) != NULL) {
313: PUTIN(bp, q);
314: DKSIZUP(dkp);
315: dkp->ibuf = NULL;
316: }
317: }
318:
319: /*
320: * DK put procedure
321: */
322: dkput(q, bp)
323: register struct queue *q;
324: register struct block *bp;
325: {
326: register n;
327: register bn;
328: int s;
329: register struct device *reg = DKADDR;
330: register struct dk *dkp;
331:
332: dkp = (struct dk *)q->ptr;
333: if (dkp == NULL) {
334: freeb(bp);
335: return;
336: }
337: switch (bp->type) {
338:
339: case M_IOCTL:
340: bp->type = M_IOCACK;
341: switch (stiocom(bp)) {
342: case DIOCNXCL:
343: dkp->flag &=~ DKXCL;
344: bp->wptr = bp->rptr;
345: bp->type = M_IOCACK;
346: break;
347:
348: default:
349: bp->type = M_IOCNAK;
350: break;
351: }
352: qreply(q, bp);
353: return;
354:
355: case M_CTL:
356: case M_DATA:
357: s = spl6();
358: bp->next = NULL;
359: if (dkp->ofirst == NULL)
360: dkp->ofirst = bp;
361: else
362: dkp->olast->next = bp;
363: dkp->olast = bp;
364: if ((bp->class&S_DELIM)==0 || dkalive == 0) {
365: splx(s);
366: return;
367: }
368: /*
369: * S_DELIM:
370: * push out data
371: */
372: n = DKOPKT;
373: reg->csr = D_WRITE + ENABS;
374: reg->dko = DKMARK + dkp->chan;
375: while ((bp = dkp->ofirst) != NULL) {
376: dkp->ofirst = bp->next;
377: if (bp->wptr == bp->rptr) {
378: freeb(bp);
379: continue;
380: }
381: dkstat.output += bp->wptr - bp->rptr;
382: if (n <= 0) {
383: reg->csr = D_XPACK + ENABS;
384: reg->dko = 0;
385: n = DKOPKT;
386: reg->csr = D_WRITE + ENABS;
387: reg->dko = DKMARK + dkp->chan;
388: }
389: --n;
390: reg->dko = *bp->rptr++ | ((bp->type==M_DATA)?DKDATA:0);
391: while ((bn = bp->wptr - bp->rptr) > 0) {
392: if (bn > n)
393: bn = n;
394: n -= bn;
395: while (--bn >= 0)
396: reg->dko = *bp->rptr++ | DKDATA;
397: if (n <= 0) {
398: reg->csr = D_XPACK + ENABS;
399: reg->dko = 0;
400: n = DKOPKT;
401: reg->csr = D_WRITE + ENABS;
402: reg->dko = DKMARK + dkp->chan;
403: }
404: }
405: freeb(bp);
406: }
407: reg->csr = D_XPACK + ENABS;
408: reg->dko = 0;
409: splx(s);
410: return;
411:
412: case M_PRICTL:
413: switch (*bp->rptr) {
414: case DKMCLOSE:
415: n = bp->rptr[1];
416: if (n < dkcnt) {
417: if (dkstate[n] == DKOPEN) {
418: dkstate[n] = DKRCLOSE;
419: putctl(dk[n].dkrq->next, M_HANGUP);
420: } else if (dkstate[n] == DKLCLOSE)
421: dkstate[n] = DKCLOSED;
422: }
423: freeb(bp);
424: return;
425:
426: case DKMXINIT:
427: n = bp->rptr[1];
428: if (n < dkcnt && dkstate[n] == DKOPEN)
429: (*dk[n].dkrq->next->qinfo->putp)(dk[n].dkrq->next, bp);
430: else
431: freeb(bp);
432: return;
433:
434: default:
435: freeb(bp);
436: return;
437: }
438:
439: default:
440: freeb(bp);
441: return;
442: }
443: }
444:
445: /*
446: * transmit interrupt
447: */
448:
449: dk0int(dev)
450: int dev;
451: {
452: printf("dk%d xmit stray\n", dev);
453: }
454:
455: /*
456: * unibus reset
457: */
458: dkreset()
459: {
460: if (DKADDR)
461: DKADDR->csr = ENABS;
462: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.