|
|
1.1 root 1: #define USER 1
2: #include <stdio.h>
3: #include <sys/pk.p>
4: #include <sys/param.h>
5: #include <sys/pk.h>
6: #include <sys/buf.h>
7: #include <setjmp.h>
8: #include <signal.h>
9:
10: #define PKTIME 10
11: int Errorrate;
12: int Conbad = 0;
13: int Ntimeout = 0;
14: #define CONBAD 5
15: #define NTIMEOUT 50
16: /*
17: * packet driver support routines
18: *
19: */
20:
21: struct pack *pklines[NPLINES];
22:
23: /*
24: * start initial synchronization.
25: */
26:
27: struct pack *
28: pkopen(ifn, ofn)
29: int ifn, ofn;
30: {
31: struct pack *pk;
32: char **bp;
33: int i;
34:
35: if (++pkactive >= NPLINES)
36: return(NULL);
37: if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL)
38: return(NULL);
39: pkzero((caddr_t) pk, sizeof (struct pack));
40: pk->p_ifn = ifn;
41: pk->p_ofn = ofn;
42: pk->p_xsize = pk->p_rsize = PACKSIZE;
43: pk->p_rwindow = pk->p_swindow = WINDOWS;
44: /* allocate input windows */
45: for (i = 0; i < pk->p_rwindow; i++) {
46: if ((bp = (char **) GETEPACK) == NULL)
47: break;
48: *bp = (char *) pk->p_ipool;
49: pk->p_ipool = bp;
50: }
51: if (i == 0)
52: return(NULL);
53: pk->p_rwindow = i;
54:
55: /* start synchronization */
56: pk->p_msg = pk->p_rmsg = M_INITA;
57: for (i = 0; i < NPLINES; i++) {
58: if (pklines[i] == NULL) {
59: pklines[i] = pk;
60: break;
61: }
62: }
63: if (i >= NPLINES)
64: return(NULL);
65: pkoutput(pk);
66:
67: while ((pk->p_state & LIVE) == 0) {
68: PKGETPKT(pk);
69: }
70:
71: pkreset(pk);
72: return(pk);
73: }
74:
75:
76: /*
77: * input framing and block checking.
78: * frame layout for most devices is:
79: *
80: * S|K|X|Y|C|Z| ... data ... |
81: *
82: * where S == initial synch byte
83: * K == encoded frame size (indexes pksizes[])
84: * X, Y == block check bytes
85: * C == control byte
86: * Z == XOR of header (K^X^Y^C)
87: * data == 0 or more data bytes
88: *
89: */
90:
91: int pksizes[] = {
92: 1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1
93: };
94:
95: #define GETRIES 5
96: /*
97: * Pseudo-dma byte collection.
98: */
99:
100: pkgetpack(ipk)
101: struct pack *ipk;
102: {
103: int ret, k, tries;
104: register char *p;
105: struct pack *pk;
106: struct header *h;
107: unsigned short sum;
108: int ifn;
109: char **bp;
110: char hdchk;
111:
112: if (Conbad > CONBAD /* || Ntimeout > NTIMEOUT */)
113: pkfail();
114: pk = PADDR;
115: ifn = pk->p_ifn;
116:
117: /* find HEADER */
118: for (tries = 0; tries < GETRIES; ) {
119: p = (caddr_t) &pk->p_ihbuf;
120: if ((ret = pkcget(ifn, p, 1)) < 0) {
121: /* set up retransmit or REJ */
122: tries++;
123: pk->p_msg |= pk->p_rmsg;
124: if (pk->p_msg == 0)
125: pk->p_msg |= M_RR;
126: if ((pk->p_state & LIVE) == LIVE)
127: pk->p_state |= RXMIT;
128: pkoutput(pk);
129: continue;
130: }
131: if (*p != SYN)
132: continue;
133: p++;
134: ret = pkcget(ifn, p, HDRSIZ - 1);
135: if (ret == -1)
136: continue;
137: break;
138: }
139: if (tries >= GETRIES) {
140: PKDEBUG(4, "tries = %d\n", tries);
141: pkfail();
142: }
143:
144: h = (struct header * ) &pk->p_ihbuf;
145: p = (caddr_t) h;
146: hdchk = p[1] ^ p[2] ^ p[3] ^ p[4];
147: p += 2;
148: sum = (unsigned) *p++ & 0377;
149: sum |= (unsigned) *p << 8;
150: h->sum = sum;
151: PKDEBUG(7, "rec h->cntl %o\n", (unsigned) h->cntl);
152: k = h->ksize;
153: if (hdchk != h->ccntl) {
154: /* bad header */
155: PKDEBUG(7, "bad header %o,", hdchk);
156: PKDEBUG(7, "h->ccntl %o\n", h->ccntl);
157: Conbad++;
158: return;
159: }
160: if (k == 9) {
161: if (h->sum + h->cntl == CHECK) {
162: pkcntl(h->cntl, pk);
163: Conbad = 0;
164: PKDEBUG(7, "state - %o\n", pk->p_state);
165: }
166: else {
167: /* bad header */
168: Conbad++;
169: PKDEBUG(7, "bad header %o\n", h->cntl);
170: pk->p_state |= BADFRAME;
171: }
172: return;
173: }
174: if (k && pksizes[k] == pk->p_rsize) {
175: pk->p_rpr = h->cntl & MOD8;
176: pksack(pk);
177: Conbad = 0;
178: bp = pk->p_ipool;
179: pk->p_ipool = (char **) *bp;
180: if (bp == NULL) {
181: PKDEBUG(7, "bp NULL %s\n", "");
182: return;
183: }
184: }
185: else {
186: Conbad++;
187: return;
188: }
189: ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize);
190: PKASSERT(ret != -1, "PKGETPKT CAN't READ %d", ret);
191: pkdata(h->cntl, h->sum, pk, (char *) bp);
192: return;
193: }
194:
195:
196: pkdata(c, sum, pk, bp)
197: char c;
198: short sum;
199: register struct pack *pk;
200: char **bp;
201: {
202: register x;
203: int t;
204: char m;
205:
206: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) {
207: pk->p_msg |= pk->p_rmsg;
208: pkoutput(pk);
209: goto drop;
210: }
211: t = next[pk->p_pr];
212: for(x=pk->p_pr; x!=t; x = (x-1)&7) {
213: if (pk->p_is[x] == 0)
214: goto slot;
215: }
216: drop:
217: *bp = (char *)pk->p_ipool;
218: pk->p_ipool = bp;
219: return;
220:
221: slot:
222: m = mask[x];
223: pk->p_imap |= m;
224: pk->p_is[x] = c;
225: pk->p_isum[x] = sum;
226: pk->p_ib[x] = (char *)bp;
227: return;
228: }
229:
230:
231:
232: /*
233: * setup input transfers
234: */
235: pkrstart(pk)
236: {}
237:
238: /*
239: * Start transmission on output device associated with pk.
240: * For asynch devices (t_line==1) framing is
241: * imposed. For devices with framing and crc
242: * in the driver (t_line==2) the transfer is
243: * passed on to the driver.
244: */
245: pkxstart(pk, cntl, x)
246: struct pack *pk;
247: char cntl;
248: register x;
249: {
250: register char *p;
251: int ret;
252: short checkword;
253: char hdchk;
254:
255: p = (caddr_t) &pk->p_ohbuf;
256: *p++ = SYN;
257: if (x < 0) {
258: *p++ = hdchk = 9;
259: checkword = cntl;
260: }
261: else {
262: *p++ = hdchk = pk->p_lpsize;
263: checkword = pk->p_osum[x] ^ (unsigned)(cntl&0377);
264: }
265: checkword = CHECK - checkword;
266: *p = checkword;
267: hdchk ^= *p++;
268: *p = checkword>>8;
269: hdchk ^= *p++;
270: *p = cntl;
271: hdchk ^= *p++;
272: *p = hdchk;
273: /* writes */
274: PKDEBUG(7, "send %o\n", (unsigned) cntl);
275: p = (caddr_t) & pk->p_ohbuf;
276: if (x < 0) {
277: GENERROR(p, HDRSIZ);
278: ret = write(pk->p_ofn, p, HDRSIZ);
279: PKASSERT(ret == HDRSIZ, "PKXSTART ret %d", ret);
280: }
281: else {
282: char buf[PACKSIZE + HDRSIZ], *b;
283: int i;
284: for (i = 0, b = buf; i < HDRSIZ; i++)
285: *b++ = *p++;
286: for (i = 0, p = pk->p_ob[x]; i < pk->p_rsize; i++)
287: *b++ = *p++;
288: GENERROR(buf, pk->p_rsize + HDRSIZ);
289: ret = write(pk->p_ofn, buf, pk->p_rsize + HDRSIZ);
290: PKASSERT(ret == pk->p_rsize + HDRSIZ,
291: "PKXSTART ret %d", ret);
292: }
293: if (pk->p_msg)
294: pkoutput(pk);
295: return;
296: }
297:
298:
299: pkmove(p1, p2, count, flag)
300: char *p1, *p2;
301: int count, flag;
302: {
303: char *s, *d;
304: int i;
305: if (flag == B_WRITE) {
306: s = p2;
307: d = p1;
308: }
309: else {
310: s = p1;
311: d = p2;
312: }
313: for (i = 0; i < count; i++)
314: *d++ = *s++;
315: return;
316: }
317:
318:
319: /***
320: * pkcget(fn, b, n) get n characters from input
321: * char *b; - buffer for characters
322: * int fn; - file descriptor
323: * int n; - requested number of characters
324: *
325: * return codes:
326: * n - number of characters returned
327: * 0 - end of file
328: */
329:
330: jmp_buf Getjbuf;
331: cgalarm() { longjmp(Getjbuf, 1); }
332:
333: pkcget(fn, b, n)
334: int fn, n;
335: char *b;
336: {
337: int nchars, ret;
338:
339: if (setjmp(Getjbuf)) {
340: Ntimeout++;
341: PKDEBUG(4, "alarm %d\n", Ntimeout);
342: return(-1);
343: }
344: signal(SIGALRM, cgalarm);
345:
346: for (nchars = 0; nchars < n; nchars += ret) {
347: alarm(PKTIME);
348: ret = read(fn, b, n - nchars);
349: if (ret == 0) {
350: alarm(0);
351: return(-1);
352: }
353: PKASSERT(ret > 0, "PKCGET READ %d", ret);
354: b += ret;
355: }
356: alarm(0);
357: return(0);
358: }
359:
360:
361: generror(p, s)
362: char *p;
363: int s;
364: {
365: int r;
366: if (Errorrate != 0 && (rand() % Errorrate) == 0) {
367: r = rand() % s;
368: fprintf(stderr, "gen err at %o, (%o), ", r, (unsigned) *(p + r));
369: *(p + r) += 1;
370: }
371: return;
372: }
373:
374:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.