4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
31 #pragma ident "%Z%%M% %I% %E% SMI"
38 extern void pkfail(), pkzero(), pkoutput(), pkreset(), pkcntl(), pkgetpack();
42 static void xlatestate(struct pack
*, int);
43 void xlatecntl(int, int);
46 * Code added to allow translation of states from numbers to
47 * letters, to be done in such a way as to be meaningful to
65 BADFRAME
, "Bad frame",
66 -1, "End of the line",
69 extern char _Protocol
[]; /* Protocol string with (options) */
72 int Connodata
= 0; /* Continuous Non Valid Data Count */
74 #define CONNODATA 20 /* Max Continuous Non Valid Data Count */
75 #define NTIMEOUT 50 /* This is not currently used, but maybe future */
77 extern jmp_buf Getjbuf
;
80 * start initial synchronization.
89 int windows
= WINDOWS
;
90 extern int xpacksize
, packsize
;
92 if ((pk
= (struct pack
*) calloc(1, sizeof (struct pack
))) == NULL
)
96 DEBUG(7, "Setting up protocol parameters '%s'\n", _Protocol
);
97 if ( _Protocol
[1] == '(' ) {
98 if (sscanf(_Protocol
, "%*c(%d,%d)", &windows
, &packsize
) == 0)
99 sscanf(_Protocol
, "%*c(,%d)", &packsize
);
100 windows
= ( windows
< MINWINDOWS
? WINDOWS
:
101 ( windows
> MAXWINDOWS
? WINDOWS
: windows
) );
102 packsize
= ( packsize
< MINPACKSIZE
? PACKSIZE
:
103 ( packsize
> MAXPACKSIZE
? PACKSIZE
: packsize
) );
105 if ( (_Protocol
[0] == 'g') && (packsize
> OLDPACKSIZE
) ) {
107 * We reset to OLDPACKSIZE to maintain compatibility
108 * with old limited implementations. Maybe we should
109 * just warn the administrator and continue?
111 packsize
= OLDPACKSIZE
;
113 pk
->p_xsize
= pk
->p_rsize
= xpacksize
= packsize
;
114 pk
->p_rwindow
= pk
->p_swindow
= windows
;
117 * allocate input window
119 for (i
= 0; i
< pk
->p_rwindow
; i
++) {
120 if ((bp
= (char **) malloc((unsigned) pk
->p_xsize
)) == NULL
)
122 *bp
= (char *) pk
->p_ipool
;
130 * start synchronization
132 pk
->p_msg
= pk
->p_rmsg
= M_INITA
;
135 for (i
= 0; i
< PKMAXSTMSG
; i
++) {
137 if ((pk
->p_state
& LIVE
) != 0)
148 * input framing and block checking.
149 * frame layout for most devices is:
151 * S|K|X|Y|C|Z| ... data ... |
153 * where S == initial synch byte
154 * K == encoded frame size (indexes pksizes[])
155 * X, Y == block check bytes
157 * Z == XOR of header (K^X^Y^C)
158 * data == 0 or more data bytes
174 int k
, tries
, ifn
, noise
;
179 * If we are known to be DOWN, or if we've received too many garbage
180 * packets or timeouts, give up without a fight.
182 if ((pk
->p_state
& DOWN
) || Connodata
> CONNODATA
|| Ntimeout
> NTIMEOUT
)
188 * Attempt no more than GETRIES times to read a packet. The only valid
189 * exit from this loop is a return. Break forces a failure.
191 for (tries
= 0; tries
< GETRIES
; tries
++) {
194 * First look for SYN. If more than 3 * packetsize characters
195 * go by w/o a SYN, request a retransmit.
200 if (pkcget(ifn
, p
, HDRSIZ
) != SUCCESS
) {
202 "Alarm while looking for SYN -- request RXMIT\n%s", "");
210 DEBUG(7, "first char not SYN (%x)\n", *p
&0xff);
211 if ((pp
= memchr(p
, SYN
, HDRSIZ
)) != NULL
) {
215 /* Now look for remainder of header */
216 if (pkcget(ifn
, p
, pend
- p
) !=
219 "Alarm while looking for header -- request RXMIT\n%s", "");
223 break; /* got entire header */
226 if ((noise
+= HDRSIZ
) > 3 * pk
->p_rsize
) {
228 "No SYN in %d characters -- request RXMIT\n", noise
);
232 /* Validate the header */
234 hdchk
= p
[1] ^ p
[2] ^ p
[3] ^ p
[4];
235 sum
= ((unsigned) p
[2] & 0377) | ((unsigned) p
[3] << 8);
238 if (hdchk
!= h
->ccntl
) {
240 DEBUG(7, "bad header checksum\n%s", "");
244 if (k
== 9) { /* control packet */
245 if (((h
->sum
+ h
->cntl
) & 0xffff) == CHECK
) {
250 DEBUG(7, "bad header (k == 9) 0%o\n", h
->cntl
&0xff);
251 pk
->p_state
|= BADFRAME
;
256 if (k
&& pksizes
[k
] != pk
->p_rsize
)
258 pk
->p_rpr
= h
->cntl
& MOD8
;
260 if ((bp
= pk
->p_ipool
) == NULL
) {
261 DEBUG(7, "bp NULL\n%s", "");
264 pk
->p_ipool
= (char **) *bp
;
265 /* Header checks out, go for data */
266 if (pkcget(pk
->p_ifn
, (char *) bp
, pk
->p_rsize
) == SUCCESS
) {
267 pkdata(h
->cntl
, h
->sum
, pk
, bp
);
271 DEBUG(7, "Alarm while reading data -- request RXMIT\n%s", "");
274 * Transmission error or excessive noise. Send a RXMIT
280 pk
->p_msg
|= pk
->p_rmsg
;
283 if ((pk
->p_state
& LIVE
) == LIVE
)
284 pk
->p_state
|= RXMIT
;
287 DEBUG(7, "pkgetpack failed after %d tries\n", tries
);
292 * Translate pk->p_state into something printable.
295 xlatestate(pk
, dbglvl
)
300 char delimc
= ' ', msgline
[80], *buf
= msgline
;
304 sprintf(buf
, "state -");
306 for(i
= 0; st_trans
[i
].state
!= -1; i
++) {
307 if (pk
->p_state
&st_trans
[i
].state
){
308 sprintf(buf
, "%c[%s]", delimc
, st_trans
[i
].msg
);
313 sprintf(buf
, " (0%o)\n", pk
->p_state
);
314 DEBUG(dbglvl
, "%s", msgline
);
319 pkdata(c
, sum
, pk
, bp
)
329 if (pk
->p_state
& DRAINO
|| !(pk
->p_state
& LIVE
)) {
330 pk
->p_msg
|= pk
->p_rmsg
;
335 for(x
=pk
->p_pr
; x
!=t
; x
= (x
-1)&7) {
336 if (pk
->p_is
[x
] == 0)
340 *bp
= (char *)pk
->p_ipool
;
349 pk
->p_ib
[x
] = (char *)bp
;
353 * Start transmission on output device associated with pk.
354 * For asynch devices (t_line==1) framing is
355 * imposed. For devices with framing and crc
356 * in the driver (t_line==2) the transfer is
357 * passed on to the driver.
360 pkxstart(pk
, cntl
, x
)
369 p
= (caddr_t
) &pk
->p_ohbuf
;
375 *p
++ = hdchk
= pk
->p_lpsize
;
376 checkword
= pk
->p_osum
[x
] ^ (unsigned)(cntl
& 0377);
378 checkword
= CHECK
- checkword
;
393 p
= (caddr_t
) & pk
->p_ohbuf
;
395 if ((*Write
)(pk
->p_ofn
, p
, HDRSIZ
) != HDRSIZ
) {
396 DEBUG(4, "pkxstart, write failed, %s\n",
398 logent(strerror(errno
), "PKXSTART WRITE");
403 char buf
[MAXPACKSIZE
+ HDRSIZ
];
405 memcpy(buf
, p
, HDRSIZ
);
406 memcpy(buf
+HDRSIZ
, pk
->p_ob
[x
], pk
->p_xsize
);
407 if ((*Write
)(pk
->p_ofn
, buf
, pk
->p_xsize
+ HDRSIZ
) !=
408 pk
->p_xsize
+ HDRSIZ
) {
409 DEBUG(4, "pkxstart, write failed, %s\n",
411 logent(strerror(errno
), "PKXSTART WRITE");
422 * get n characters from input
423 * b -> buffer for characters
424 * fn -> file descriptor
425 * n -> requested number of characters
427 * SUCCESS -> n chars successfully read
439 extern int linebaudrate
;
440 int donap
= (linebaudrate
> 0 && linebaudrate
< 4800);
441 #endif /* PKSPEEDUP */
445 if (setjmp(Getjbuf
)) {
447 DEBUG(4, "pkcget: alarm %d\n", Ntimeout
);
451 (void) alarm( (unsigned) ( 10 + (n
>> 7)) );
454 ret
= (*Read
)(fn
, b
, n
);
457 DEBUG(4, "pkcget, read failed, EOF\n", 0);
459 * Device has decided that the connection has no
460 * more data to send. Any further tries are futile...
461 * (The only other way to get a zero return value
462 * is to read a zero length message from a STREAM.
463 * However, uucp *never* sends zero length messages
464 * over any sort of channel...)
470 DEBUG(4, "pkcget, read failed, %s\n",
472 logent(strerror(errno
), "PKCGET READ");
480 #if defined(BSD4_2) || defined(ATTSVR4)
481 /* wait for more chars to come in */
482 nap((n
* HZ
* 10) / linebaudrate
); /* n char times */
487 #endif /* PKSPEEDUP */
489 (void) alarm( (unsigned) ( 10 + (n
>> 7)) );
500 xlatecntl(role
, cntl
)
504 static char *cntltype
[4] = {"CNTL, ", "ALT, ", "DATA, ", "SHORT, "};
505 static char *cntlxxx
[8] = {"ZERO, ", "CLOSE, ", "RJ, ", "SRJ, ",
506 "RR, ", "INITC, ", "INITB, ", "INITA, "};
511 strcpy(ptr
, role
? "send " : "recv ");
514 strcpy(ptr
, cntltype
[(cntl
&0300)>>6]);
520 sprintf(ptr
, "loc %o, rem %o\n", (cntl
& 070) >> 3, cntl
& 7);
522 sprintf(ptr
, "loc %o, rem %o\n", cntl
& 7, (cntl
& 070) >> 3);
525 strcpy(ptr
, cntlxxx
[(cntl
&070)>>3]);
527 sprintf(ptr
, "val %o\n", cntl
& 7);