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