|
|
1.1 root 1: #include "../chunix/chsys.h"
2: #include "../chunix/chconf.h"
3: #include "../chaos/chaos.h"
4: /*
5: * DR11-C Chaos driver.
6: * This driver does framing and a block check for each packet.
7: * The framing is similar to standard synchronous links, except that
8: * the "byte" is 16 bits. Basically a frame starts after 2 or more
9: * DRSYNC words, then the next word being a count and the next word being the
10: * complement of the count (both count and its complement must not be DRSYNC).
11: * Then the number of words specified by the count are the actual data,
12: * followed by an LRC-16. Data words equal to DRSYNC or DRESC are preceded by
13: * DRESC. The count does not include the inserted DRESC words, but the CRC
14: * word does. The LRC word does not include the initial DRSYNC's or the count.
15: * This framing scheme was thought up quickly and may well be overkill.
16: * The LRC is a simple XOR of all data words.
17: * Chaos N.C.P.'s that use this file must include <chaos/dr11c.h> in their
18: * chconf.h files.
19: * Keep in mind that the interrupt priority level of this driver maybe less
20: * than either the clock or the LOCK macro supplied by the user.
21: * Also remember that the block check is not to great.
22: */
23:
24: #define xc_draddr xc_info.xc_dr11c.dr_addr
25: #define xc_drtptr xc_info.xc_dr11c.dr_tptr
26: #define xc_drrptr xc_info.xc_dr11c.dr_rptr
27: #define xc_drtcnt xc_info.xc_dr11c.dr_tcnt
28: #define xc_drrcnt xc_info.xc_dr11c.dr_rcnt
29: #define xc_drrstate xc_info.xc_dr11c.dr_rstate
30: #define xc_drtstate xc_info.xc_dr11c.dr_tstate
31: #define xc_drrcheck xc_info.xc_dr11c.dr_rcheck
32: #define xc_drtcheck xc_info.xc_dr11c.dr_tcheck
33: #define xc_drintrup xc_info.xc_dr11c.dr_intrup
34:
35: struct chxcvr dr11cxcvr[NCHDR];
36:
37:
38: /*
39: * dr11-c initialization. Also does initialization to the static chxcvr
40: * structure since initialized unions don't work anyway.
41: */
42:
43: int chdrstart(), chdrreset();
44: /*
45: * Initialize all dr11c interfaces - called from low priority
46: */
47: chdrinit()
48: {
49: register struct chxcvr *xp;
50: register short *hp;
51: #ifdef VMUNIX
52: register int i = 0;
53: #else
54: register char *dp = (char *)DR11CBASE;/* must be char * to use DR11CINC */
55: #endif
56:
57: hp = &dr11chosts[0];
58: for (xp = &dr11cxcvr[0]; xp < &dr11cxcvr[NDR11C]; xp++) {
59: xp->xc_draddr =
60: #ifdef VMUNIX
61: (struct dr11c *) chdrdinfo[i++]->ui_addr;
62: #else
63: (struct dr11c *) dp;
64: dp += DR11CINC;
65: #endif
66: /*DEBUG*/ if (xp->xc_draddr == 0) panic("draddr");
67: xp->xc_start = chdrstart;
68: xp->xc_reset = chdrreset;
69: xp->xc_host = *hp++;
70: LOCK;
71: chdrreset(xp);
72: UNLOCK;
73: }
74: }
75: /*
76: * Check for hung interfaces - if so flush the packet.
77: * Assumed called at clock level.
78: */
79: chdrxtime()
80: {
81: register struct chxcvr *xp;
82:
83: for (xp = &dr11cxcvr[0]; xp < &dr11cxcvr[NDR11C]; xp++) {
84: if (xp->xc_drintrup)
85: continue;
86: if (xp->xc_rpkt != NOPKT &&
87: Chclock - xp->xc_rtime > DR11CHUNG) {
88: ch_free((char *)xp->xc_rpkt);
89: xp->xc_rpkt = NOPKT;
90: xp->xc_drrstate = DRIDLE;
91: debug(DABNOR, printf("Rec pkt timeout\n"));
92: }
93: if (xp->xc_tpkt != NOPKT &&
94: Chclock - xp->xc_ttime > DR11CHUNG) {
95: debug(DABNOR, printf("Trans pkt timeout\n"));
96: xp->xc_drtstate = DRTDONE;
97: chdrxint(xp - dr11cxcvr);
98: }
99: }
100: }
101:
102: /*
103: * Reset things from an unknown state (high priority)
104: * Basically enable interrupts and tell him we're ready for input.
105: * If he already has a word, take it right away.
106: */
107: chdrreset(xp)
108: register struct chxcvr *xp;
109: {
110: register struct dr11c *dp = xp->xc_draddr;
111:
112: xp->xc_drrstate = xp->xc_drtstate = DRIDLE;
113: dp->dr_csr = 0;
114: dp->dr_csr = DRIN|DROUT|DRIE|DROE;
115: }
116: /*
117: * Start output on an idle line - called when nothing happening
118: */
119: chdrstart(xp)
120: register struct chxcvr *xp;
121: {
122:
123: if (xp->xc_tpkt != NOPKT)
124: panic("chdrstart: already busy");
125: chdrxint(xp - dr11cxcvr);
126: }
127: /*
128: * Receiver interrupt
129: */
130: chdrrint(dev)
131: {
132: register unsigned short data; /* register short is dubious - be careful! */
133: register struct chxcvr *xp = &dr11cxcvr[dev];
134: register struct dr11c *dp = xp->xc_draddr;
135:
136: if ((dp->dr_csr & DRIRDY) == 0) {
137: debug(DABNOR, printf("extra dr11c rint\n"));
138: return;
139: }
140: dp->dr_csr &= ~DRIN;
141: data = dp->dr_ibuf;
142: dp->dr_csr |= DRIN; /* set his DRORDY, and cause his chdrxint */
143:
144: xp->xc_drintrup = 1;
145: switch(xp->xc_drrstate) {
146: case DRIDLE:
147: if (data == DRSYNC)
148: xp->xc_drrstate = DRSYN1;
149: break;
150: case DRSYN1:
151: xp->xc_drrstate = data == DRSYNC ? DRSYN2 : DRIDLE;
152: break;
153: case DRSYN2:
154: if (data != DRSYNC) {
155: xp->xc_drrcnt = data;
156: xp->xc_drrstate = DRCNT1;
157: }
158: break;
159: case DRCNT1:
160: xp->xc_drrstate = DRIDLE;
161: data = ~data;
162: debug(DTRANS,printf("Rec size=%d\n", data));
163: if (data != xp->xc_drrcnt)
164: debug(DABNOR, printf("Rec bad count\n"));
165: else if ((data <<= 1) < sizeof(struct pkt_header) ||
166: data > CHMAXDATA + sizeof(struct pkt_header))
167: debug(DABNOR, printf("Rec bad size: %d", data));
168: else {
169: LOCK; /* in case of clock interrupt */
170: if ((xp->xc_rpkt = (struct packet *)ch_alloc(
171: (int)data + sizeof(struct ncp_header) , 1))
172: != NOPKT) {
173: xp->xc_drrstate = DRDATA;
174: xp->xc_drrptr = (short *)&xp->xc_rpkt->pk_phead;
175: xp->xc_drrcheck = 0;
176: xp->xc_rtime = Chclock;
177: } else
178: debug(DABNOR, printf("Rec alloc fail: %d\n", data));
179: }
180: break;
181: case DRDATA:
182: if (data == DRESC) {
183: xp->xc_drrstate = DRESC1;
184: xp->xc_drrcheck ^= data;
185: break;
186: }
187: /* Falls into... */
188: case DRESC1:
189: xp->xc_drrcheck ^= data;
190: *xp->xc_drrptr++ = data;
191: if (--xp->xc_drrcnt == 0)
192: xp->xc_drrstate = DRCHECK;
193: else
194: xp->xc_drrstate = DRDATA;
195: break;
196: case DRCHECK:
197: xp->xc_drrstate = DRIDLE;
198: LOCK; /* raise to possibly higher priority */
199: if (data == xp->xc_drrcheck)
200: rcvpkt(xp->xc_rpkt);
201: else
202: ch_free((char *)xp->xc_rpkt);
203: xp->xc_rpkt = NOPKT;
204: }
205: xp->xc_drintrup = 0;
206: }
207: /*
208: * Transmit interrupt
209: */
210: chdrxint(dev)
211: {
212: register struct chxcvr *xp = &dr11cxcvr[dev];
213: register struct dr11c *dp = xp->xc_draddr;
214: register struct packet *pkt;
215: unsigned short data;
216:
217: if (xp->xc_tpkt != NOPKT && (dp->dr_csr & DRORDY) == 0) {
218: debug(DABNOR, printf("Extra dr11c xint\n"));
219: /*return;*/
220: }
221: dp->dr_csr &= ~DROUT;
222: xp->xc_drintrup = 1;
223: switch (xp->xc_drtstate) {
224: case DRIDLE:
225: xp->xc_tpkt = NOPKT;
226: case DRTDONE:
227: LOCK;
228: if ((pkt = xcvrdone(xp)) == NOPKT)
229: goto out;
230: xp->xc_ttime = Chclock;
231: data = sizeof(struct pkt_header) + pkt->pk_len;
232: data = (data + (sizeof(short) - 1)) >> 1;
233: xp->xc_drtcnt = data;
234: xp->xc_drtptr = (short *)&pkt->pk_phead;
235: debug(DTRANS,printf("Trans size=%d, %x\n",data, pkt));
236: data = DRSYNC;
237: xp->xc_drtstate = DRSYN1;
238: break;
239: case DRSYN1:
240: data = DRSYNC;
241: xp->xc_drtstate = DRSYN2;
242: break;
243: case DRSYN2:
244: data = xp->xc_drtcnt;
245: xp->xc_drtstate = DRCNT1;
246: break;
247: case DRCNT1:
248: data = ~xp->xc_drtcnt;
249: xp->xc_drtstate = DRDATA;
250: xp->xc_drtcheck = 0;
251: break;
252: case DRDATA:
253: if ((data = *xp->xc_drtptr) == DRESC || data == DRSYNC) {
254: data = DRESC;
255: xp->xc_drtcheck ^= data;
256: xp->xc_drtstate = DRESC1;
257: break;
258: }
259: /* Falls into... */
260: case DRESC1:
261: data = *xp->xc_drtptr++;
262: xp->xc_drtcheck ^= data;
263: if (--xp->xc_drtcnt == 0)
264: xp->xc_drtstate = DRCHECK;
265: else
266: xp->xc_drtstate = DRDATA;
267: break;
268: case DRCHECK:
269: data = xp->xc_drtcheck;
270: xp->xc_drtstate = DRTDONE;
271: }
272: dp->dr_obuf = data;
273: dp->dr_csr |= DROUT; /* set his DRIRDY, cause his chdrrint */
274: out:
275: xp->xc_drintrup = 0;
276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.