|
|
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: return(0);
116: if (dkstate[chan] != DKOPEN)
117: return(0); /* closing channels can't reopen */
118: return(1);
119: }
120: dkp->dkrq = q;
121: q->ptr = (caddr_t)dkp;
122: WR(q)->ptr = (caddr_t)dkp;
123: dkp->flag = DKXCL;
124: dkp->icnt = 0;
125: dkp->isize = 0;
126: dkp->ibuf = 0;
127: dkp->ialloc = DKISML;
128: dkstate[chan] = DKOPEN;
129: return(1);
130: }
131:
132: /*
133: * Timer to recover from lost interrupt condition.
134: */
135: dkrecover(dev)
136: dev_t dev;
137: {
138: register int ps = spl5();
139:
140: if (DKADDR->csr & DKRDONE)
141: dk1int(dev);
142: splx(ps);
143:
144: timeout(dkrecover, (caddr_t)dev, HZ/2);
145: }
146:
147: /*
148: * close DK channel
149: */
150: dkclose(q)
151: register struct queue *q;
152: {
153: register struct dk *dkp;
154: register struct block *bp;
155:
156: dkp = (struct dk *)q->ptr;
157: dkp->dkrq = NULL;
158: dkp->flag = 0;
159: if (dkstate[dkp->chan] == DKRCLOSE || dkmodp->listnrq==NULL)
160: dkstate[dkp->chan] = DKCLOSED;
161: else if (dkstate[dkp->chan] == DKOPEN)
162: dkstate[dkp->chan] = DKLCLOSE;
163: if (dkmodp->listnrq)
164: putctl2(RD(dkmodp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
165: if (dkp->ibuf)
166: freeb(dkp->ibuf);
167: while ((bp = dkp->ofirst) != NULL) {
168: dkp->ofirst = bp->next;
169: freeb(bp);
170: }
171: dkp->ibuf = 0;
172: }
173:
174: /*
175: * DK receiver interrupt.
176: */
177:
178: #define PUTIN(bp, q) {\
179: dkstat.input += (bp)->wptr - (bp)->rptr;\
180: if (((q)->next->flag & QFULL) == 0)\
181: (*(q)->next->qinfo->putp)(q->next, bp);\
182: else\
183: freeb(bp);\
184: }
185:
186: #define DKSIZUP(dkp) {\
187: if (dkp->isize > DKITHRES) {\
188: dkp->ialloc = dkp->isize;\
189: dkp->icnt = 3;\
190: } else if (--dkp->icnt <= 0) {\
191: dkp->icnt = 0;\
192: dkp->ialloc = DKISML;\
193: }\
194: dkp->isize = 0;\
195: }
196:
197: dk1int(dev)
198: {
199: register struct queue *q;
200: register struct block *bp;
201: register struct dk *dkp;
202: register struct device *reg;
203: register c, nbytes;
204: register sane, chan;
205: register struct block **bpp;
206: struct block *blist[DKIPKT+2];
207:
208: if ((reg = DKADDR) == NULL)
209: return;
210: c = 0;
211: dkp = NULL;
212: while (reg->csr & DKRDONE) {
213: reg->csr = D_READ|ENABS;
214: if ((c & DKMARK) == 0) {
215: /* Search for channel number */
216: sane = 256;
217: do {
218: c = reg->dki;
219: if (c & DKMARK || --sane==0)
220: break;
221: } while (reg->csr & DKRDONE);
222: }
223: if ((c & DKMARK) == 0) {
224: dkstat.markflt++;
225: continue;
226: }
227: if ((c & DKPARITY) == 0) {
228: dkstat.markparity++;
229: c = 0;
230: continue;
231: }
232: /* check channel */
233: chan = c & 0777;
234: if (dkp && dkp->chan != chan) {
235: if ((bp = dkp->ibuf) != NULL)
236: PUTIN(bp, q);
237: DKSIZUP(dkp);
238: dkp->ibuf = NULL;
239: }
240: if (chan == 0 || chan >= dkcnt || (q = dk[chan].dkrq)==NULL) {
241: if (chan>0 && chan<dkcnt) {
242: if (dkmodp->listnrq)
243: putctl2(RD(dkmodp->listnrq),
244: M_PRICTL, DKMCLOSE, chan);
245: dkstat.closepack++;
246: } else if (chan == 0)
247: dkstat.pack0++;
248: else
249: dkstat.packstrange++;
250: for (nbytes=0; nbytes<DKIPKT; nbytes++) {
251: c = reg->dki;
252: if (c & DKMARK)
253: break;
254: }
255: continue;
256: }
257: dkp = (struct dk *)q->ptr;
258: if ((bp = dkp->ibuf) == NULL
259: && (bp = allocb(dkp->ialloc)) == NULL)
260: return;
261: bpp = blist;
262: for (nbytes=0; nbytes<DKIPKT; nbytes++) {
263: #ifdef SAFETY
264: if ((reg->csr&DKRDONE) == 0)
265: break;
266: #endif
267: c = reg->dki;
268: if ((c&(DKPARITY|DKMARK|DKDATA)) == (DKPARITY|DKDATA)) {
269: if (bp->wptr >= bp->lim) {
270: *bpp++ = bp;
271: if ((bp = allocb(DKISML)) == NULL)
272: break;
273: }
274: *bp->wptr++ = c;
275: dkp->isize++;
276: continue;
277: }
278: /*
279: * control or error
280: */
281: if (c & DKMARK) {
282: dkstat.shortpack++;
283: break;
284: }
285: if ((c & DKPARITY) == 0) {
286: dkstat.parity++;
287: break;
288: }
289: if ((c & 0377) == 0) /* control-null */
290: continue;
291: if (bp->wptr > bp->rptr) {
292: *bpp++ = bp;
293: if ((bp = allocb(DKISML)) == NULL)
294: break;
295: }
296: bp->type = M_CTL;
297: *bp->wptr++ = c;
298: }
299: if (bpp == blist && bp->type == M_DATA) {
300: dkp->ibuf = bp;
301: continue;
302: }
303: *bpp++ = bp;
304: *bpp = NULL;
305: bpp = blist;
306: while ((bp = *bpp++) != NULL)
307: PUTIN(bp, q);
308: DKSIZUP(dkp);
309: dkp->ibuf = NULL;
310: }
311: if (dkp && (bp = dkp->ibuf) != NULL) {
312: PUTIN(bp, q);
313: DKSIZUP(dkp);
314: dkp->ibuf = NULL;
315: }
316: }
317:
318: /*
319: * DK put procedure
320: */
321: dkput(q, bp)
322: register struct queue *q;
323: register struct block *bp;
324: {
325: register n;
326: register bn;
327: int s;
328: register struct device *reg = DKADDR;
329: register struct dk *dkp;
330:
331: dkp = (struct dk *)q->ptr;
332: if (dkp == NULL) {
333: freeb(bp);
334: return;
335: }
336: switch (bp->type) {
337:
338: case M_IOCTL:
339: bp->type = M_IOCACK;
340: switch (stiocom(bp)) {
341: case DIOCNXCL:
342: dkp->flag &=~ DKXCL;
343: bp->wptr = bp->rptr;
344: bp->type = M_IOCACK;
345: break;
346:
347: default:
348: bp->type = M_IOCNAK;
349: break;
350: }
351: qreply(q, bp);
352: return;
353:
354: case M_CTL:
355: case M_DATA:
356: s = spl6();
357: bp->next = NULL;
358: if (dkp->ofirst == NULL)
359: dkp->ofirst = bp;
360: else
361: dkp->olast->next = bp;
362: dkp->olast = bp;
363: if ((bp->class&S_DELIM)==0 || dkalive == 0) {
364: splx(s);
365: return;
366: }
367: /*
368: * S_DELIM:
369: * push out data
370: */
371: n = DKOPKT;
372: reg->csr = D_WRITE + ENABS;
373: reg->dko = DKMARK + dkp->chan;
374: while ((bp = dkp->ofirst) != NULL) {
375: dkp->ofirst = bp->next;
376: if (bp->wptr == bp->rptr) {
377: freeb(bp);
378: continue;
379: }
380: dkstat.output += bp->wptr - bp->rptr;
381: if (n <= 0) {
382: reg->csr = D_XPACK + ENABS;
383: reg->dko = 0;
384: n = DKOPKT;
385: reg->csr = D_WRITE + ENABS;
386: reg->dko = DKMARK + dkp->chan;
387: }
388: --n;
389: reg->dko = *bp->rptr++ | ((bp->type==M_DATA)?DKDATA:0);
390: while ((bn = bp->wptr - bp->rptr) > 0) {
391: if (bn > n)
392: bn = n;
393: n -= bn;
394: while (--bn >= 0)
395: reg->dko = *bp->rptr++ | DKDATA;
396: if (n <= 0) {
397: reg->csr = D_XPACK + ENABS;
398: reg->dko = 0;
399: n = DKOPKT;
400: reg->csr = D_WRITE + ENABS;
401: reg->dko = DKMARK + dkp->chan;
402: }
403: }
404: freeb(bp);
405: }
406: reg->csr = D_XPACK + ENABS;
407: reg->dko = 0;
408: splx(s);
409: return;
410:
411: case M_PRICTL:
412: switch (*bp->rptr) {
413: case DKMCLOSE:
414: n = bp->rptr[1];
415: if (n < dkcnt) {
416: if (dkstate[n] == DKOPEN) {
417: dkstate[n] = DKRCLOSE;
418: putctl(dk[n].dkrq->next, M_HANGUP);
419: } else if (dkstate[n] == DKLCLOSE)
420: dkstate[n] = DKCLOSED;
421: }
422: freeb(bp);
423: return;
424:
425: case DKMXINIT:
426: n = bp->rptr[1];
427: if (n < dkcnt && dkstate[n] == DKOPEN)
428: (*dk[n].dkrq->next->qinfo->putp)(dk[n].dkrq->next, bp);
429: else
430: freeb(bp);
431: return;
432:
433: default:
434: freeb(bp);
435: return;
436: }
437:
438: default:
439: freeb(bp);
440: return;
441: }
442: }
443:
444: /*
445: * transmit interrupt
446: */
447:
448: dk0int(dev)
449: int dev;
450: {
451: printf("dk%d xmit stray\n", dev);
452: }
453:
454: /*
455: * unibus reset
456: */
457: dkreset()
458: {
459: if (DKADDR)
460: DKADDR->csr = ENABS;
461: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.