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 xlatecntl();
39 extern void pkcntl(), pkoutput(), pkclose(), pkreset(), pkzero(),
40 pkgetpack(), pkxstart();
41 extern int pkread(), pkwrite(), pksack();
42 static int pksize(), chksum(), pkaccept();
44 extern int Connodata
; /* Continuous No Valid Data Count */
48 * receive control messages
49 * c -> message type fields
50 * pk -> line control unit
63 logent("PK0", "not cntl");
73 pk
->p_xsize
= xpacksize
= pksizes
[val
];
76 if (pk
->p_state
& LIVE
) {
81 if ((pk
->p_state
& INITa
)==0) {
84 pk
->p_rmsg
&= ~M_INITA
;
89 if ((pk
->p_state
&INITab
)==INITab
) {
91 pk
->p_rmsg
&= ~M_INITB
;
98 if (val
==0 && pk
->p_state
&LIVE
) {
99 logent("PK0", "alloc change not implemented");
103 pk
->p_state
|= INITa
;
104 pk
->p_msg
|= M_INITB
;
105 pk
->p_rmsg
|= M_INITB
;
110 pk
->p_state
|= RXMIT
;
112 DEBUG(9, "pkcntl: RJ: Connodata=%d\n", Connodata
);
119 pk
->p_state
= DOWN
+RCLOSE
;
131 char m
, cntl
, *p
, imask
, **bp
;
132 int bad
,accept
,skip
,t
,cc
;
136 bad
= accept
= skip
= 0;
142 while ((imask
=pk
->p_imap
) == 0 && pk
->p_rcount
==0) {
149 * determine input window in m.
151 t
= (~(-1<<pk
->p_rwindow
)) <<x
;
157 * mark newly accepted input buffers
161 if ((imask
& mask
[x
]) == 0)
164 if (((cntl
=pk
->p_is
[x
])&0200)==0) {
167 bp
= (char **)pk
->p_ib
[x
];
168 *bp
= (char *)pk
->p_ipool
;
174 pk
->p_is
[x
] = (char) ~(B_COPY
+B_MARK
);
175 sum
= (unsigned)chksum(pk
->p_ib
[x
], pk
->p_rsize
) ^ (unsigned)(cntl
&0377);
176 sum
+= pk
->p_isum
[x
];
178 seq
= (cntl
>>3) & MOD8
;
180 if (pk
->p_is
[seq
] & (B_COPY
| B_MARK
)) {
188 pk
->p_ib
[x
] = pk
->p_ib
[seq
];
189 pk
->p_is
[x
] = pk
->p_is
[seq
];
192 pk
->p_is
[seq
] = B_MARK
;
196 pk
->p_is
[seq
] = B_MARK
+B_SHORT
;
198 cc
= (unsigned)*p
++ & 0377;
204 pk
->p_isum
[seq
] = pk
->p_rsize
- cc
;
215 * scan window again turning marked buffers into
216 * COPY buffers and looking for missing sequence
220 for(x
=next
[pk
->p_pr
],t
= -1; m
& mask
[x
]; x
= next
[x
]) {
221 if (pk
->p_is
[x
] & B_MARK
)
222 pk
->p_is
[x
] |= B_COPY
;
224 if (pk
->p_is
[x
] & B_COPY
) {
226 bp
= (char **)pk
->p_ib
[x
];
227 *bp
= (char *)pk
->p_ipool
;
245 pk
->p_rcount
= accept
;
263 while (pkaccept()==0)
265 Connodata
= 0; /* accecpted a packet -- good data */
274 cc
= MIN(pk
->p_isum
[x
], icount
);
288 memcpy(ibuf
, cp
, cc
);
294 if (pk
->p_isum
[x
] == 0) {
296 bp
= (char **)pk
->p_ib
[x
];
297 *bp
= (char *)pk
->p_ipool
;
304 pk
->p_is
[x
] |= B_RESID
;
315 /* return number of bytes writtten */
317 pkwrite(ibuf
, icount
)
328 if (pk
->p_state
&DOWN
|| !pk
->p_state
&LIVE
) {
334 while (pk
->p_xcount
>=pk
->p_swindow
) {
338 x
= next
[pk
->p_pscopy
];
339 while (pk
->p_os
[x
]!=B_NULL
) {
342 pk
->p_os
[x
] = B_MARK
;
346 cp
= pk
->p_ob
[x
] = (caddr_t
) malloc((unsigned) pk
->p_xsize
);
348 if ((int)icount
< pk
->p_xsize
) {
350 fc
= pk
->p_xsize
- cc
;
360 memcpy(cp
, ibuf
, cc
);
363 pk
->p_osum
[x
] = chksum(pk
->p_ob
[x
], pk
->p_xsize
);
364 pk
->p_os
[x
] = B_READY
+partial
;
378 for(x
=pk
->p_ps
; x
!=pk
->p_rpr
; ) {
380 if (pk
->p_os
[x
]&B_SENT
) {
383 pk
->p_os
[x
] = B_NULL
;
384 pk
->p_state
&= ~WAITO
;
386 free((char *) pk
->p_ob
[x
]);
409 * find seq number and buffer state
410 * of next output packet
412 if (pk
->p_state
&RXMIT
)
413 pk
->p_nxtps
= next
[pk
->p_rpr
];
415 bstate
= pk
->p_os
[x
];
419 * Send control packet if indicated
422 if (pk
->p_msg
& ~M_RR
|| !(bstate
&B_READY
) ) {
439 x
+= pksize(pk
->p_rsize
);
449 pk
->p_msg
&= ~mask
[i
];
457 * Don't send data packets if line is marked dead.
459 if (pk
->p_state
&DOWN
) {
464 * Start transmission (or retransmission) of data packets.
466 if (bstate
& (B_READY
|B_SENT
)) {
471 pk
->p_nxtps
= next
[x
];
473 x
= 0200+pk
->p_pr
+(seq
<<3);
474 if (bstate
& B_SHORT
)
476 pkxstart(pk
, x
, seq
);
477 pk
->p_os
[seq
] = bstate
;
478 pk
->p_state
&= ~RXMIT
;
484 * enable timeout if there's nothing to send
485 * and transmission buffers are languishing
489 pk
->p_state
|= WAITO
;
491 pk
->p_state
&= ~WAITO
;
497 * shut down line by ignoring new input
498 * letting output drain
510 pk
->p_state
|= DRAINO
;
513 * try to flush output
517 while (pk
->p_xcount
&& pk
->p_state
&LIVE
) {
518 if (pk
->p_state
&(RCLOSE
+DOWN
) || ++i
> 2)
526 * try to exchange CLOSE messages
529 while ((pk
->p_state
&RCLOSE
)==0 && i
<2) {
541 if (pk
->p_os
[i
]!=B_NULL
) {
542 free((char *) pk
->p_ob
[i
]);
545 if (pk
->p_is
[i
]!=B_NULL
) {
546 free((char *) pk
->p_ib
[i
]);
550 while (pk
->p_ipool
!= NULL
) {
552 pk
->p_ipool
= (char **)*bp
;
556 if (rcheck
!= pk
->p_rwindow
) {
557 logent("PK0", "pkclose rcheck != p_rwindow");
568 pk
->p_ps
= pk
->p_pr
= pk
->p_rpr
= 0;
591 sum
+= (unsigned)*s
++ & 0377;
593 if ((unsigned short)sum
<= t
) {
608 for(k
=0; n
>>= 1; k
++);