Bell 32V release
[unix-history] / usr / src / cmd / uucp / pk1.c
CommitLineData
ca95affc
TL
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
11int Errorrate;
12int Conbad = 0;
13int Ntimeout = 0;
14#define CONBAD 5
15#define NTIMEOUT 50
16/*
17 * packet driver support routines
18 *
19 */
20
21struct pack *pklines[NPLINES];
22
23/*
24 * start initial synchronization.
25 */
26
27struct pack *
28pkopen(ifn, ofn)
29int 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
91int 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
100pkgetpack(ipk)
101struct 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
196pkdata(c, sum, pk, bp)
197char c;
198short sum;
199register struct pack *pk;
200char **bp;
201{
202register x;
203int t;
204char 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 }
216drop:
217 *bp = (char *)pk->p_ipool;
218 pk->p_ipool = bp;
219 return;
220
221slot:
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 */
235pkrstart(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 */
245pkxstart(pk, cntl, x)
246struct pack *pk;
247char cntl;
248register 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 */
274PKDEBUG(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
299pkmove(p1, p2, count, flag)
300char *p1, *p2;
301int 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
330jmp_buf Getjbuf;
331cgalarm() { longjmp(Getjbuf, 1); }
332
333pkcget(fn, b, n)
334int fn, n;
335char *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
361generror(p, s)
362char *p;
363int s;
364{
365 int r;
366 if (Errorrate != 0 && (rand() % Errorrate) == 0) {
367 r = rand() % s;
368fprintf(stderr, "gen err at %o, (%o), ", r, (unsigned) *(p + r));
369 *(p + r) += 1;
370 }
371 return;
372}
373
374